10 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
11 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
13 #define TWOBLUECUBES_CATCH_HPP_INCLUDED
16 #pragma clang diagnostic ignored "-Wno-global-constructors"
18 #pragma clang diagnostic push
19 #pragma clang diagnostic ignored "-Wpadded"
23 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
26 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
28 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
29 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
30 #define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
32 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
33 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
36 #define CATCH_ATTRIBUTE_NORETURN __attribute__ ((noreturn))
38 #define CATCH_ATTRIBUTE_NORETURN
48 NonCopyable(
const NonCopyable& );
49 void operator = (
const NonCopyable& );
52 virtual ~NonCopyable();
57 typedef void (SafeBool::*type)()
const;
59 static type makeSafe(
bool value ) {
60 return value ? &SafeBool::trueValue : 0;
63 void trueValue()
const {}
66 template<
typename ContainerT>
67 inline void deleteAll( ContainerT& container ) {
68 typename ContainerT::const_iterator it = container.begin();
69 typename ContainerT::const_iterator itEnd = container.end();
70 for(; it != itEnd; ++it )
75 template<
typename AssociativeContainerT>
76 inline void deleteAllValues( AssociativeContainerT& container ) {
77 typename AssociativeContainerT::const_iterator it = container.begin();
78 typename AssociativeContainerT::const_iterator itEnd = container.end();
79 for(; it != itEnd; ++it )
85 template<
typename ContainerT,
typename Function>
86 inline void forEach( ContainerT& container, Function
function ) {
87 std::for_each( container.begin(), container.end(), function );
90 template<
typename ContainerT,
typename Function>
91 inline void forEach(
const ContainerT& container, Function
function ) {
92 std::for_each( container.begin(), container.end(), function );
95 inline bool startsWith(
const std::string& s,
const std::string& prefix ) {
96 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
98 inline bool endsWith(
const std::string& s,
const std::string& suffix ) {
99 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
101 inline bool contains(
const std::string& s,
const std::string& infix ) {
102 return s.find( infix ) != std::string::npos;
106 pluralise( std::size_t count,
const std::string& label )
111 friend std::ostream& operator << ( std::ostream& os,
const pluralise& pluraliser ) {
112 os << pluraliser.m_count <<
" " << pluraliser.m_label;
113 if( pluraliser.m_count != 1 )
122 struct SourceLineInfo {
124 SourceLineInfo() : line( 0 ){}
125 SourceLineInfo(
const std::string& _file, std::size_t _line )
129 SourceLineInfo(
const std::string& _function,
const std::string& _file, std::size_t _line )
130 :
function( _function ),
134 SourceLineInfo(
const SourceLineInfo& other )
135 : file( other.file ),
138 void swap( SourceLineInfo& other ){
139 file.swap( other.file );
140 std::swap( line, other.line );
143 std::string
function;
148 inline std::ostream& operator << ( std::ostream& os,
const SourceLineInfo& info ) {
150 os << info.file <<
"(" << info.line <<
"): ";
152 os << info.file <<
":" << info.line <<
": ";
158 inline void throwLogicError(
const std::string& message,
const SourceLineInfo& locationInfo ) {
159 std::ostringstream oss;
160 oss <<
"Internal Catch error: '" << message <<
"' at: " << locationInfo;
161 throw std::logic_error( oss.str() );
165 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
166 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
172 class NotImplementedException :
public std::exception
175 NotImplementedException(
const SourceLineInfo& lineInfo );
177 virtual ~NotImplementedException()
throw() {}
179 virtual const char* what()
const throw();
183 SourceLineInfo m_lineInfo;
189 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
192 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
195 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
201 struct IGeneratorInfo {
202 virtual ~IGeneratorInfo();
203 virtual bool moveNext() = 0;
204 virtual std::size_t getCurrentIndex()
const = 0;
207 struct IGeneratorsForTest {
208 virtual ~IGeneratorsForTest();
210 virtual IGeneratorInfo& getGeneratorInfo(
const std::string& fileInfo, std::size_t size ) = 0;
211 virtual bool moveNext() = 0;
214 IGeneratorsForTest* createGeneratorsForTest();
225 struct IResultCapture;
227 struct IGeneratorsForTest;
230 class StreamBufBase :
public std::streambuf {
232 virtual ~StreamBufBase();
239 virtual IResultCapture& getResultCapture() = 0;
240 virtual IRunner& getRunner() = 0;
241 virtual size_t getGeneratorIndex(
const std::string& fileInfo,
size_t totalSize ) = 0;
242 virtual bool advanceGeneratorsForCurrentTest() = 0;
243 virtual const IConfig* getConfig()
const = 0;
246 struct IMutableContext : IContext
248 virtual ~IMutableContext();
249 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
250 virtual void setRunner( IRunner* runner ) = 0;
251 virtual void setConfig(
const IConfig*
config ) = 0;
254 IContext& getCurrentContext();
255 IMutableContext& getCurrentMutableContext();
256 void cleanUpContext();
257 std::streambuf* createStreamBuf(
const std::string& streamName );
262 #define TWOBLUECUBES_CATCH_REGISTRY_HPP_INCLUDED
265 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
268 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
278 Ptr() : m_p( NULL ){}
279 Ptr( T* p ) : m_p( p ){
283 Ptr(
const Ptr& other ) : m_p( other.m_p ){
291 Ptr& operator = ( T* p ){
296 Ptr& operator = (
const Ptr& other ){
301 void swap( Ptr& other ){
302 std::swap( m_p, other.m_p );
308 const T*
get()
const{
312 T& operator*()
const {
316 T* operator->()
const {
320 bool operator !()
const {
328 struct IShared : NonCopyable {
330 virtual void addRef() = 0;
331 virtual void release() = 0;
335 struct SharedImpl : T {
337 SharedImpl() : m_rc( 0 ){}
339 virtual void addRef(){
342 virtual void release(){
356 class TestCaseFilters;
358 struct ITestCase : IShared {
359 virtual void invoke ()
const = 0;
361 virtual ~ITestCase();
366 struct ITestCaseRegistry {
367 virtual ~ITestCaseRegistry();
368 virtual const std::vector<TestCaseInfo>& getAllTests()
const = 0;
369 virtual std::vector<TestCaseInfo> getMatchingTestCases(
const std::string& rawTestSpec )
const = 0;
376 class MethodTestCase :
public SharedImpl<ITestCase> {
379 MethodTestCase(
void (C::*method)() ) : m_method( method ) {}
381 virtual void invoke()
const {
387 virtual ~MethodTestCase() {}
389 void (C::*m_method)();
392 typedef void(*TestFunction)();
396 AutoReg( TestFunction
function,
398 const char* description,
399 const SourceLineInfo& lineInfo );
402 AutoReg(
void (C::*method)(),
404 const char* description,
405 const SourceLineInfo& lineInfo ) {
406 registerTestCase(
new MethodTestCase<C>( method ), name, description, lineInfo );
409 void registerTestCase( ITestCase* testCase,
411 const char* description,
412 const SourceLineInfo& lineInfo );
417 AutoReg(
const AutoReg& );
418 void operator= (
const AutoReg& );
424 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
425 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )(); \
426 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\
427 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
430 #define INTERNAL_CATCH_TESTCASE_NORETURN( Name, Desc ) \
431 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )() CATCH_ATTRIBUTE_NORETURN; \
432 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ ), Name, Desc, CATCH_INTERNAL_LINEINFO ); }\
433 static void INTERNAL_CATCH_UNIQUE_NAME( TestCaseFunction_catch_internal_ )()
436 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
437 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, Name, Desc, CATCH_INTERNAL_LINEINFO ); }
440 #define TEST_CASE_METHOD( ClassName, TestName, Desc )\
442 struct INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ ) : ClassName{ \
445 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test, TestName, Desc, CATCH_INTERNAL_LINEINFO ); \
447 void INTERNAL_CATCH_UNIQUE_NAME( TestCaseMethod_catch_internal_ )::test()
450 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
453 #define TWOBLUECUBES_CATCH_EXPRESSION_BUILDER_HPP_INCLUDED
456 #define TWOBLUECUBES_CATCH_EXPRESSION_HPP_INCLUDED
459 #define TWOBLUECUBES_CATCH_RESULTINFO_BUILDER_H_INCLUDED
462 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
468 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
470 #import <Foundation/Foundation.h>
473 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
475 #define CATCH_ARC_ENABLED 0
478 void arcSafeRelease( NSObject* obj );
479 id performOptionalSelector(
id obj,
SEL sel );
481 #if !CATCH_ARC_ENABLED
482 inline void arcSafeRelease( NSObject* obj ) {
485 inline id performOptionalSelector(
id obj,
SEL sel ) {
486 if( [obj respondsToSelector: sel] )
487 return [obj performSelector: sel];
490 #define CATCH_UNSAFE_UNRETAINED
491 #define CATCH_ARC_STRONG
493 inline void arcSafeRelease( NSObject* ){}
494 inline id performOptionalSelector(
id obj,
SEL sel ) {
496 #pragma clang diagnostic push
497 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
499 if( [obj respondsToSelector: sel] )
500 return [obj performSelector: sel];
502 #pragma clang diagnostic pop
506 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
507 #define CATCH_ARC_STRONG __strong
515 struct NonStreamable {
516 template<
typename T> NonStreamable(
const T& ){}
521 inline std::ostream& operator << ( std::ostream& ss, NonStreamable ){
526 inline std::string makeString(
const T& value ) {
527 std::ostringstream oss;
533 inline std::string makeString( T* p ) {
536 std::ostringstream oss;
542 inline std::string makeString(
const T* p ) {
545 std::ostringstream oss;
560 std::string toString(
const T& value ) {
561 return Detail::makeString( value );
566 inline std::string toString(
const std::string& value ) {
567 return "\"" + value +
"\"";
570 inline std::string toString(
const std::wstring& value ) {
571 std::ostringstream oss;
573 for(
size_t i = 0; i < value.size(); ++i )
574 oss << static_cast<char>( value[i] <= 0xff ? value[i] :
'?');
579 inline std::string toString(
const char*
const value ) {
580 return value ? Catch::toString( std::string( value ) ) : std::string(
"{null string}" );
583 inline std::string toString(
char*
const value ) {
584 return Catch::toString( static_cast<const char*>( value ) );
587 inline std::string toString(
int value ) {
588 std::ostringstream oss;
593 inline std::string toString(
unsigned long value ) {
594 std::ostringstream oss;
596 oss <<
"0x" << std::hex << value;
602 inline std::string toString(
unsigned int value ) {
603 return toString( static_cast<unsigned long>( value ) );
606 inline std::string toString(
const double value ) {
607 std::ostringstream oss;
612 inline std::string toString(
bool value ) {
613 return value ?
"true" :
"false";
616 inline std::string toString(
char value ) {
618 ? toString( (
unsigned int)value )
619 : Detail::makeString( value );
622 inline std::string toString(
signed char value ) {
623 return toString( static_cast<char>( value ) );
626 #ifdef CATCH_CONFIG_CPP11_NULLPTR
627 inline std::string toString( std::nullptr_t ) {
633 inline std::string toString( NSString
const *
const& nsstring ) {
634 return std::string(
"@\"" ) + [nsstring UTF8String] +
"\"";
636 inline std::string toString( NSString * CATCH_ARC_STRONG
const& nsstring ) {
637 return std::string(
"@\"" ) + [nsstring UTF8String] +
"\"";
639 inline std::string toString( NSObject*
const& nsObject ) {
640 return toString( [nsObject description] );
647 #define TWOBLUECUBES_CATCH_RESULT_INFO_H_INCLUDED
651 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
655 struct ResultWas {
enum OfType {
663 ExpressionFailed = FailureBit | 1,
664 ExplicitFailure = FailureBit | 2,
666 Exception = 0x100 | FailureBit,
668 ThrewException = Exception | 1,
669 DidntThrowException = Exception | 2
673 struct ResultAction {
enum Value {
688 ResultInfo(
const char* expr,
689 ResultWas::OfType result,
691 const SourceLineInfo& lineInfo,
692 const char* macroName,
693 const char* message );
697 ResultWas::OfType getResultType()
const;
698 bool hasExpression()
const;
699 bool hasMessage()
const;
700 std::string getExpression()
const;
701 bool hasExpandedExpression()
const;
702 std::string getExpandedExpression()
const;
703 std::string getMessage()
const;
704 std::string getFilename()
const;
705 std::size_t getLine()
const;
706 std::string getTestMacroName()
const;
710 std::string getExpandedExpressionInternal()
const;
711 bool isNotExpression(
const char* expr );
714 std::string m_macroName;
715 SourceLineInfo m_lineInfo;
716 std::string m_expr, m_lhs, m_rhs, m_op;
717 std::string m_message;
718 ResultWas::OfType m_result;
725 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
736 IsGreaterThanOrEqualTo
739 template<Operator Op>
struct OperatorTraits {
static const char* getName(){
return "*error*"; } };
740 template<>
struct OperatorTraits<IsEqualTo> {
static const char* getName(){
return "=="; } };
741 template<>
struct OperatorTraits<IsNotEqualTo> {
static const char* getName(){
return "!="; } };
742 template<>
struct OperatorTraits<IsLessThan> {
static const char* getName(){
return "<"; } };
743 template<>
struct OperatorTraits<IsGreaterThan> {
static const char* getName(){
return ">"; } };
744 template<>
struct OperatorTraits<IsLessThanOrEqualTo> {
static const char* getName(){
return "<="; } };
745 template<>
struct OperatorTraits<IsGreaterThanOrEqualTo>{
static const char* getName(){
return ">="; } };
749 template<
typename T1,
typename T2, Operator Op>
752 template<
typename T1,
typename T2>
753 struct Evaluator<T1, T2, IsEqualTo> {
754 static bool evaluate(
const T1& lhs,
const T2& rhs) {
755 return const_cast<T1&
>( lhs ) == const_cast<T2&>( rhs );
758 template<
typename T1,
typename T2>
759 struct Evaluator<T1, T2, IsNotEqualTo> {
760 static bool evaluate(
const T1& lhs,
const T2& rhs ) {
761 return const_cast<T1&
>( lhs ) != const_cast<T2&>( rhs );
764 template<
typename T1,
typename T2>
765 struct Evaluator<T1, T2, IsLessThan> {
766 static bool evaluate(
const T1& lhs,
const T2& rhs ) {
767 return const_cast<T1&
>( lhs ) < const_cast<T2&>( rhs );
770 template<
typename T1,
typename T2>
771 struct Evaluator<T1, T2, IsGreaterThan> {
772 static bool evaluate(
const T1& lhs,
const T2& rhs ) {
773 return const_cast<T1&
>( lhs ) > const_cast<T2&>( rhs );
776 template<
typename T1,
typename T2>
777 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
778 static bool evaluate(
const T1& lhs,
const T2& rhs ) {
779 return const_cast<T1&
>( lhs ) >= const_cast<T2&>( rhs );
782 template<
typename T1,
typename T2>
783 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
784 static bool evaluate(
const T1& lhs,
const T2& rhs ) {
785 return const_cast<T1&
>( lhs ) <= const_cast<T2&>( rhs );
789 template<Operator Op,
typename T1,
typename T2>
790 bool applyEvaluator(
const T1& lhs,
const T2& rhs ) {
791 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
795 template<Operator Op,
typename T1,
typename T2>
796 bool compare(
const T1& lhs,
const T2& rhs ) {
797 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
801 template<Operator Op>
bool compare(
unsigned int lhs,
int rhs ) {
802 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
804 template<Operator Op>
bool compare(
unsigned long lhs,
int rhs ) {
805 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
807 template<Operator Op>
bool compare(
unsigned char lhs,
int rhs ) {
808 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
812 template<Operator Op>
bool compare(
unsigned int lhs,
long rhs ) {
813 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
815 template<Operator Op>
bool compare(
unsigned long lhs,
long rhs ) {
816 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
818 template<Operator Op>
bool compare(
unsigned char lhs,
long rhs ) {
819 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
823 template<Operator Op>
bool compare(
int lhs,
unsigned int rhs ) {
824 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
826 template<Operator Op>
bool compare(
int lhs,
unsigned long rhs ) {
827 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
829 template<Operator Op>
bool compare(
int lhs,
unsigned char rhs ) {
830 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
834 template<Operator Op>
bool compare(
long lhs,
unsigned int rhs ) {
835 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
837 template<Operator Op>
bool compare(
long lhs,
unsigned long rhs ) {
838 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
840 template<Operator Op>
bool compare(
long lhs,
unsigned char rhs ) {
841 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
845 template<Operator Op,
typename T>
846 bool compare(
long lhs,
const T* rhs ) {
847 return Evaluator<const T*, const T*, Op>::evaluate( reinterpret_cast<const T*>( lhs ), rhs );
850 template<Operator Op,
typename T>
851 bool compare(
long lhs, T* rhs ) {
852 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
855 template<Operator Op,
typename T>
856 bool compare(
const T* lhs,
long rhs ) {
857 return Evaluator<const T*, const T*, Op>::evaluate( lhs, reinterpret_cast<const T*>( rhs ) );
860 template<Operator Op,
typename T>
861 bool compare( T* lhs,
long rhs ) {
862 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
866 template<Operator Op,
typename T>
867 bool compare(
int lhs,
const T* rhs ) {
868 return Evaluator<const T*, const T*, Op>::evaluate( reinterpret_cast<const T*>( lhs ), rhs );
871 template<Operator Op,
typename T>
872 bool compare(
int lhs, T* rhs ) {
873 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
876 template<Operator Op,
typename T>
877 bool compare(
const T* lhs,
int rhs ) {
878 return Evaluator<const T*, const T*, Op>::evaluate( lhs, reinterpret_cast<const T*>( rhs ) );
881 template<Operator Op,
typename T>
882 bool compare( T* lhs,
int rhs ) {
883 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
891 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
893 class ResultInfoBuilder :
public ResultInfo {
899 ResultInfoBuilder(
const char* expr,
901 const SourceLineInfo& lineInfo,
902 const char* macroName,
903 const char* message =
"" );
905 void setResultType( ResultWas::OfType result );
906 void setMessage(
const std::string& message );
907 void setLineInfo(
const SourceLineInfo& lineInfo );
908 void setLhs(
const std::string& lhs );
909 void setRhs(
const std::string& rhs );
910 void setOp(
const std::string& op );
912 template<
typename RhsT>
913 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator ||
918 template<
typename RhsT>
919 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator &&
925 friend class ExpressionBuilder;
926 template<
typename T>
friend class Expression;
928 template<
typename T>
friend class PtrExpression;
930 ResultInfoBuilder& captureBoolExpression(
bool result );
932 template<Internal::Operator Op,
typename T1,
typename T2>
933 ResultInfoBuilder& captureExpression(
const T1& lhs,
const T2& rhs ) {
934 setResultType( Internal::compare<Op>( lhs, rhs ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
935 m_lhs = Catch::toString( lhs );
936 m_rhs = Catch::toString( rhs );
937 m_op = Internal::OperatorTraits<Op>::getName();
941 template<Internal::Operator Op,
typename T>
942 ResultInfoBuilder& captureExpression(
const T* lhs,
int rhs ) {
943 return captureExpression<Op>( lhs,
reinterpret_cast<const T*
>( rhs ) );
953 void operator = (
const Expression& );
956 Expression( ResultInfoBuilder& result, T lhs )
957 : m_result( result ),
961 template<
typename RhsT>
962 ResultInfoBuilder& operator == (
const RhsT& rhs ) {
963 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
966 template<
typename RhsT>
967 ResultInfoBuilder& operator != (
const RhsT& rhs ) {
968 return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
971 template<
typename RhsT>
972 ResultInfoBuilder& operator < (
const RhsT& rhs ) {
973 return m_result.captureExpression<Internal::IsLessThan>( m_lhs, rhs );
976 template<
typename RhsT>
977 ResultInfoBuilder& operator > (
const RhsT& rhs ) {
978 return m_result.captureExpression<Internal::IsGreaterThan>( m_lhs, rhs );
981 template<
typename RhsT>
982 ResultInfoBuilder& operator <= (
const RhsT& rhs ) {
983 return m_result.captureExpression<Internal::IsLessThanOrEqualTo>( m_lhs, rhs );
986 template<
typename RhsT>
987 ResultInfoBuilder& operator >= (
const RhsT& rhs ) {
988 return m_result.captureExpression<Internal::IsGreaterThanOrEqualTo>( m_lhs, rhs );
991 ResultInfoBuilder& operator == (
bool rhs ) {
992 return m_result.captureExpression<Internal::IsEqualTo>( m_lhs, rhs );
995 ResultInfoBuilder& operator != (
bool rhs ) {
996 return m_result.captureExpression<Internal::IsNotEqualTo>( m_lhs, rhs );
999 operator ResultInfoBuilder& () {
1000 return m_result.captureBoolExpression( m_lhs );
1003 template<
typename RhsT>
1004 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + (
const RhsT& );
1006 template<
typename RhsT>
1007 STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - (
const RhsT& );
1010 ResultInfoBuilder& m_result;
1020 class ExpressionBuilder {
1023 ExpressionBuilder(
const SourceLineInfo& lineInfo,
1024 const char* macroName,
1025 const char* expr =
"",
1026 bool isNot =
false )
1027 : m_result( expr, isNot, lineInfo, macroName ),
1031 template<
typename T>
1032 Expression<const T&> operator->* (
const T & operand ) {
1033 Expression<const T&> expr( m_result, operand );
1037 Expression<bool> operator->* (
bool value ) {
1038 Expression<bool> expr( m_result, value );
1042 template<
typename T>
1043 ExpressionBuilder& operator << (
const T & value ) {
1044 m_messageStream << Catch::toString( value );
1048 template<
typename MatcherT,
typename ArgT>
1049 ExpressionBuilder& acceptMatcher(
const MatcherT& matcher,
1051 const std::string& matcherCallAsString ) {
1052 std::string matcherAsString = Catch::toString( matcher );
1053 if( matcherAsString ==
"{?}" )
1054 matcherAsString = matcherCallAsString;
1055 m_result.setLhs( Catch::toString( arg ) );
1056 m_result.setRhs( matcherAsString );
1057 m_result.setOp(
"matches" );
1058 m_result.setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
1062 template<
typename MatcherT,
typename ArgT>
1063 ExpressionBuilder& acceptMatcher(
const MatcherT& matcher,
1065 const std::string& matcherCallAsString ) {
1066 std::string matcherAsString = Catch::toString( matcher );
1067 if( matcherAsString ==
"{?}" )
1068 matcherAsString = matcherCallAsString;
1069 m_result.setLhs( Catch::toString( arg ) );
1070 m_result.setRhs( matcherAsString );
1071 m_result.setOp(
"matches" );
1072 m_result.setResultType( matcher( arg ) ? ResultWas::Ok : ResultWas::ExpressionFailed );
1076 ExpressionBuilder& setResultType( ResultWas::OfType resultType ) {
1077 m_result.setResultType( resultType );
1081 operator ResultInfoBuilder&() {
1082 m_result.setMessage( m_messageStream.str() );
1087 ResultInfoBuilder m_result;
1088 std::ostringstream m_messageStream;
1094 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1098 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1103 Counts() : passed( 0 ), failed( 0 ) {}
1105 Counts operator - (
const Counts& other )
const {
1107 diff.passed = passed - other.passed;
1108 diff.failed = failed - other.failed;
1111 Counts& operator += (
const Counts& other ) {
1112 passed += other.passed;
1113 failed += other.failed;
1117 std::size_t total()
const {
1118 return passed + failed;
1127 Totals operator - (
const Totals& other )
const {
1129 diff.assertions = assertions - other.assertions;
1130 diff.testCases = testCases - other.testCases;
1134 Totals delta(
const Totals& prevTotals )
const {
1135 Totals diff = *
this - prevTotals;
1136 if( diff.assertions.failed > 0 )
1137 ++diff.testCases.failed;
1139 ++diff.testCases.passed;
1143 Totals& operator += (
const Totals& other ) {
1144 assertions += other.assertions;
1145 testCases += other.testCases;
1159 class ResultInfoBuilder;
1162 struct IResultCapture {
1164 virtual ~IResultCapture();
1166 virtual void testEnded(
const ResultInfo& result ) = 0;
1167 virtual bool sectionStarted(
const std::string& name,
1168 const std::string& description,
1169 const SourceLineInfo& lineInfo,
1170 Counts& assertions ) = 0;
1171 virtual void sectionEnded(
const std::string& name,
const Counts& assertions ) = 0;
1172 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) = 0;
1173 virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0;
1174 virtual bool shouldDebugBreak()
const = 0;
1176 virtual ResultAction::Value acceptResult(
bool result ) = 0;
1177 virtual ResultAction::Value acceptResult( ResultWas::OfType result ) = 0;
1178 virtual ResultAction::Value acceptExpression(
const ResultInfoBuilder& resultInfo ) = 0;
1179 virtual void acceptMessage(
const std::string& msg ) = 0;
1181 virtual std::string getCurrentTestName()
const = 0;
1182 virtual const ResultInfo* getLastResult()
const = 0;
1187 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
1191 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1192 #define CATCH_PLATFORM_MAC
1193 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1194 #define CATCH_PLATFORM_IPHONE
1195 #elif defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1196 #define CATCH_PLATFORM_WINDOWS
1199 #ifdef CATCH_PLATFORM_MAC
1202 #include <stdbool.h>
1203 #include <sys/types.h>
1205 #include <sys/sysctl.h>
1218 struct kinfo_proc info;
1224 info.kp_proc.p_flag = 0;
1231 mib[2] = KERN_PROC_PID;
1236 size =
sizeof(info);
1237 junk = sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size, NULL, 0);
1242 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
1249 #if defined(__ppc64__) || defined(__ppc__)
1250 #define BreakIntoDebugger() \
1251 if( Catch::isDebuggerActive() ) { \
1252 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1253 : : : "memory","r0","r3","r4" ); \
1256 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1262 #elif defined(_MSC_VER)
1263 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1264 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); }
1266 return IsDebuggerPresent() != 0;
1268 #elif defined(__MINGW32__)
1269 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
1270 extern "C"
__declspec(dllimport)
void __stdcall DebugBreak();
1271 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); }
1273 return IsDebuggerPresent() != 0;
1280 #ifdef CATCH_PLATFORM_WINDOWS
1281 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const
char* );
1283 ::OutputDebugStringA( text.c_str() );
1290 #endif // CATCH_PLATFORM_WINDOWS
1296 struct TestFailureException{};
1300 ScopedInfo() : m_oss() {
1301 getCurrentContext().getResultCapture().pushScopedInfo(
this );
1305 getCurrentContext().getResultCapture().popScopedInfo(
this );
1308 template<
typename T>
1309 ScopedInfo& operator << (
const T& value ) {
1314 std::string getInfo ()
const {
1319 std::ostringstream m_oss;
1323 inline bool isTrue(
bool value ){
return value; }
1328 #define INTERNAL_CATCH_ACCEPT_EXPR( expr, stopOnFailure, originalExpr ) \
1329 if( Catch::ResultAction::Value internal_catch_action = Catch::getCurrentContext().getResultCapture().acceptExpression( expr ) ) { \
1330 if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \
1331 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
1332 if( Catch::isTrue( stopOnFailure ) ) throw Catch::TestFailureException(); \
1333 if( Catch::isTrue( false ) ){ bool this_is_here_to_invoke_warnings = ( originalExpr ); Catch::isTrue( this_is_here_to_invoke_warnings ); } \
1337 #define INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ) \
1339 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr, isNot )->*expr ), stopOnFailure, expr ); \
1340 } catch( Catch::TestFailureException& ) { \
1343 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, expr ); \
1345 } } while( Catch::isTrue( false ) )
1348 #define INTERNAL_CATCH_IF( expr, isNot, stopOnFailure, macroName ) \
1349 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
1350 if( Catch::getCurrentContext().getResultCapture().getLastResult()->ok() )
1353 #define INTERNAL_CATCH_ELSE( expr, isNot, stopOnFailure, macroName ) \
1354 INTERNAL_CATCH_TEST( expr, isNot, stopOnFailure, macroName ); \
1355 if( !Catch::getCurrentContext().getResultCapture().getLastResult()->ok() )
1358 #define INTERNAL_CATCH_NO_THROW( expr, stopOnFailure, macroName ) \
1361 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
1364 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \
1368 #define INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1370 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
1372 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::DidntThrowException ), stopOnFailure, false ); \
1375 catch( Catch::TestFailureException& ) { \
1378 catch( exceptionType ) { \
1379 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ).setResultType( Catch::ResultWas::Ok ), stopOnFailure, false ); \
1383 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, stopOnFailure, macroName ) \
1384 INTERNAL_CATCH_THROWS( expr, exceptionType, stopOnFailure, macroName ) \
1386 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #expr ) << Catch::getRegistryHub().getExceptionTranslatorRegistry() ).setResultType( Catch::ResultWas::ThrewException ), stopOnFailure, false ); \
1390 #define INTERNAL_CATCH_MSG( reason, resultType, stopOnFailure, macroName ) \
1391 Catch::getCurrentContext().getResultCapture().acceptExpression( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName ) << reason ).setResultType( resultType ) );
1394 #define INTERNAL_CATCH_SCOPED_INFO( log ) \
1395 Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \
1396 INTERNAL_CATCH_UNIQUE_NAME( info ) << log
1399 #define INTERNAL_CHECK_THAT( arg, matcher, stopOnFailure, macroName ) \
1401 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher, false ).acceptMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), stopOnFailure, false ); \
1402 } catch( Catch::TestFailureException& ) { \
1405 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionBuilder( CATCH_INTERNAL_LINEINFO, macroName, #arg " " #matcher ) << Catch::getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() ).setResultType( Catch::ResultWas::ThrewException ), false, false ); \
1407 }}while( Catch::isTrue( false ) )
1410 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
1418 Section(
const std::string& name,
1419 const std::string& description,
1420 const SourceLineInfo& lineInfo )
1422 m_sectionIncluded( getCurrentContext().getResultCapture().sectionStarted( name, description, lineInfo, m_assertions ) )
1426 if( m_sectionIncluded )
1427 getCurrentContext().getResultCapture().sectionEnded( m_name, m_assertions );
1432 return m_sectionIncluded;
1438 Counts m_assertions;
1439 bool m_sectionIncluded;
1444 #define INTERNAL_CATCH_SECTION( name, desc ) \
1445 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( name, desc, CATCH_INTERNAL_LINEINFO ) )
1448 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
1457 template<
typename T>
1459 virtual ~IGenerator() {}
1460 virtual T getValue( std::size_t index )
const = 0;
1461 virtual std::size_t size ()
const = 0;
1464 template<
typename T>
1465 class BetweenGenerator :
public IGenerator<T> {
1467 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
1469 virtual T getValue( std::size_t index )
const {
1470 return m_from+
static_cast<T
>( index );
1473 virtual std::size_t size()
const {
1474 return static_cast<std::size_t
>( 1+m_to-m_from );
1483 template<
typename T>
1484 class ValuesGenerator :
public IGenerator<T> {
1488 void add( T value ) {
1489 m_values.push_back( value );
1492 virtual T getValue( std::size_t index )
const {
1493 return m_values[index];
1496 virtual std::size_t size()
const {
1497 return m_values.size();
1501 std::vector<T> m_values;
1504 template<
typename T>
1505 class CompositeGenerator {
1507 CompositeGenerator() : m_totalSize( 0 ) {}
1510 CompositeGenerator( CompositeGenerator& other )
1511 : m_fileInfo( other.m_fileInfo ),
1517 CompositeGenerator& setFileInfo(
const char* fileInfo ) {
1518 m_fileInfo = fileInfo;
1522 ~CompositeGenerator() {
1523 deleteAll( m_composed );
1526 operator T ()
const {
1527 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
1529 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
1530 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
1531 for(
size_t index = 0; it != itEnd; ++it )
1533 const IGenerator<T>* generator = *it;
1534 if( overallIndex >= index && overallIndex < index + generator->size() )
1536 return generator->getValue( overallIndex-index );
1538 index += generator->size();
1544 void add(
const IGenerator<T>* generator ) {
1545 m_totalSize += generator->size();
1546 m_composed.push_back( generator );
1549 CompositeGenerator& then( CompositeGenerator& other ) {
1554 CompositeGenerator& then( T value ) {
1555 ValuesGenerator<T>* valuesGen =
new ValuesGenerator<T>();
1556 valuesGen->add( value );
1563 void move( CompositeGenerator& other ) {
1564 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
1565 m_totalSize += other.m_totalSize;
1566 other.m_composed.clear();
1569 std::vector<const IGenerator<T>*> m_composed;
1570 std::string m_fileInfo;
1574 namespace Generators
1576 template<
typename T>
1577 CompositeGenerator<T> between( T from, T to ) {
1578 CompositeGenerator<T> generators;
1579 generators.add(
new BetweenGenerator<T>( from, to ) );
1583 template<
typename T>
1584 CompositeGenerator<T> values( T val1, T val2 ) {
1585 CompositeGenerator<T> generators;
1586 ValuesGenerator<T>* valuesGen =
new ValuesGenerator<T>();
1587 valuesGen->add( val1 );
1588 valuesGen->add( val2 );
1589 generators.add( valuesGen );
1593 template<
typename T>
1594 CompositeGenerator<T> values( T val1, T val2, T val3 ){
1595 CompositeGenerator<T> generators;
1596 ValuesGenerator<T>* valuesGen =
new ValuesGenerator<T>();
1597 valuesGen->add( val1 );
1598 valuesGen->add( val2 );
1599 valuesGen->add( val3 );
1600 generators.add( valuesGen );
1604 template<
typename T>
1605 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
1606 CompositeGenerator<T> generators;
1607 ValuesGenerator<T>* valuesGen =
new ValuesGenerator<T>();
1608 valuesGen->add( val1 );
1609 valuesGen->add( val2 );
1610 valuesGen->add( val3 );
1611 valuesGen->add( val4 );
1612 generators.add( valuesGen );
1618 using namespace Generators;
1622 #define INTERNAL_CATCH_LINESTR2( line ) #line
1623 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
1625 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
1628 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTIONS_H_INCLUDED
1632 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
1635 #define TWOBLUECUBES_CATCH_IREPORTERREGISTRY_INCLUDED
1638 #define TWOBLUECUBES_CATCH_RUNNERCONFIG_HPP_INCLUDED
1641 #define TWOBLUECUBES_CATCH_TESTSPEC_H_INCLUDED
1644 #define TWOBLUECUBES_CATCH_TESTCASEINFO_H_INCLUDED
1652 class TestCaseInfo {
1656 TestCaseInfo( ITestCase* testCase,
1658 const char* description,
1659 const SourceLineInfo& lineInfo );
1661 TestCaseInfo(
const TestCaseInfo& other,
const std::string& name );
1662 TestCaseInfo(
const TestCaseInfo& other );
1664 void invoke()
const;
1665 const std::string& getName()
const;
1666 const std::string& getDescription()
const;
1667 const SourceLineInfo& getLineInfo()
const;
1668 bool isHidden()
const;
1670 void swap( TestCaseInfo& other );
1671 bool operator == (
const TestCaseInfo& other )
const;
1672 bool operator < (
const TestCaseInfo& other )
const;
1673 TestCaseInfo& operator = (
const TestCaseInfo& other );
1676 Ptr<ITestCase> m_test;
1678 std::string m_description;
1679 SourceLineInfo m_lineInfo;
1688 struct IfFilterMatches{
enum DoWhat {
1693 class TestCaseFilter {
1694 enum WildcardPosition {
1696 WildcardAtStart = 1,
1698 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
1702 TestCaseFilter(
const std::string& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::IncludeTests )
1703 : m_stringToMatch( testSpec ),
1704 m_filterType( matchBehaviour ),
1705 m_wildcardPosition( NoWildcard )
1707 if( m_stringToMatch[0] ==
'*' ) {
1708 m_stringToMatch = m_stringToMatch.substr( 1 );
1709 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
1711 if( m_stringToMatch[m_stringToMatch.size()-1] ==
'*' ) {
1712 m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
1713 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
1717 IfFilterMatches::DoWhat getFilterType()
const {
1718 return m_filterType;
1721 bool shouldInclude(
const TestCaseInfo& testCase )
const {
1722 return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
1727 #pragma clang diagnostic push
1728 #pragma clang diagnostic ignored "-Wunreachable-code"
1731 bool isMatch(
const TestCaseInfo& testCase )
const {
1732 const std::string& name = testCase.getName();
1734 switch( m_wildcardPosition ) {
1736 return m_stringToMatch == name;
1737 case WildcardAtStart:
1738 return endsWith( name, m_stringToMatch );
1740 return startsWith( name, m_stringToMatch );
1741 case WildcardAtBothEnds:
1742 return contains( name, m_stringToMatch );
1744 throw std::logic_error(
"Unhandled wildcard type" );
1748 #pragma clang diagnostic pop
1751 std::string m_stringToMatch;
1752 IfFilterMatches::DoWhat m_filterType;
1753 WildcardPosition m_wildcardPosition;
1756 class TestCaseFilters {
1758 TestCaseFilters(
const std::string& name ) : m_name( name ) {}
1760 std::string getName()
const {
1764 void addFilter(
const TestCaseFilter& filter ) {
1765 if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
1766 m_exclusionFilters.push_back( filter );
1768 m_inclusionFilters.push_back( filter );
1771 bool shouldInclude(
const TestCaseInfo& testCase )
const {
1772 if( !m_inclusionFilters.empty() ) {
1773 std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
1774 std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
1775 for(; it != itEnd; ++it )
1776 if( it->shouldInclude( testCase ) )
1781 std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
1782 std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
1783 for(; it != itEnd; ++it )
1784 if( !it->shouldInclude( testCase ) )
1789 std::vector<TestCaseFilter> m_inclusionFilters;
1790 std::vector<TestCaseFilter> m_exclusionFilters;
1797 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
1805 virtual bool allowThrows()
const = 0;
1816 struct Include {
enum WhichResults {
1821 struct List{
enum What {
1840 struct WarnAbout {
enum What {
1846 : listSpec( List::None ),
1847 shouldDebugBreak( false ),
1848 includeWhichResults( Include::FailedOnly ),
1850 allowThrows( true ),
1851 warnings( WarnAbout::Nothing )
1854 std::string reporter;
1855 std::string outputFilename;
1856 List::What listSpec;
1857 std::vector<TestCaseFilters> filters;
1858 bool shouldDebugBreak;
1860 Include::WhichResults includeWhichResults;
1864 WarnAbout::What warnings;
1867 class Config :
public IConfig {
1869 Config(
const Config& other );
1870 Config& operator = (
const Config& other );
1871 virtual void dummy();
1875 : m_streambuf( NULL ),
1876 m_os( std::cout.rdbuf() )
1879 Config(
const ConfigData&
data )
1881 m_streambuf( NULL ),
1882 m_os( std::cout.rdbuf() )
1886 m_os.rdbuf( std::cout.rdbuf() );
1890 void setFilename(
const std::string& filename ) {
1891 m_data.outputFilename = filename;
1894 List::What getListSpec(
void )
const {
1895 return m_data.listSpec;
1898 const std::string& getFilename()
const {
1899 return m_data.outputFilename ;
1902 List::What listWhat()
const {
1903 return static_cast<List::What
>( m_data.listSpec & List::WhatMask );
1906 List::What listAs()
const {
1907 return static_cast<List::What
>( m_data.listSpec & List::AsMask );
1910 std::string getName()
const {
1914 bool shouldDebugBreak()
const {
1915 return m_data.shouldDebugBreak;
1918 virtual std::ostream& stream()
const {
1922 void setStreamBuf( std::streambuf* buf ) {
1923 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
1926 void useStream(
const std::string& streamName ) {
1927 std::streambuf* newBuf = createStreamBuf( streamName );
1928 setStreamBuf( newBuf );
1930 m_streambuf = newBuf;
1933 virtual bool includeSuccessfulResults()
const {
1934 return m_data.includeWhichResults == Include::SuccessfulResults;
1937 int getCutoff()
const {
1938 return m_data.cutoff;
1941 virtual bool allowThrows()
const {
1942 return m_data.allowThrows;
1945 const ConfigData&
data()
const {
1948 ConfigData&
data() {
1956 std::streambuf* m_streambuf;
1957 mutable std::ostream m_os;
1968 struct ReporterConfig
1970 ReporterConfig(
const std::string& _name,
1971 std::ostream& _stream,
1972 bool _includeSuccessfulResults,
1973 const ConfigData& _fullConfig )
1976 includeSuccessfulResults( _includeSuccessfulResults ),
1977 fullConfig( _fullConfig )
1981 std::ostream& stream;
1982 bool includeSuccessfulResults;
1983 ConfigData fullConfig;
1989 struct IReporter : IShared {
1990 virtual ~IReporter();
1991 virtual bool shouldRedirectStdout()
const = 0;
1992 virtual void StartTesting() = 0;
1993 virtual void EndTesting(
const Totals& totals ) = 0;
1994 virtual void StartGroup(
const std::string& groupName ) = 0;
1995 virtual void EndGroup(
const std::string& groupName,
const Totals& totals ) = 0;
1996 virtual void StartSection(
const std::string& sectionName,
const std::string& description ) = 0;
1997 virtual void NoAssertionsInSection(
const std::string& sectionName ) = 0;
1998 virtual void NoAssertionsInTestCase(
const std::string& testName ) = 0;
1999 virtual void EndSection(
const std::string& sectionName,
const Counts& assertions ) = 0;
2000 virtual void StartTestCase(
const TestCaseInfo& testInfo ) = 0;
2001 virtual void Aborted() = 0;
2002 virtual void EndTestCase(
const TestCaseInfo& testInfo,
const Totals& totals,
const std::string& stdOut,
const std::string& stdErr ) = 0;
2003 virtual void Result(
const ResultInfo& result ) = 0;
2006 struct IReporterFactory {
2007 virtual ~IReporterFactory();
2008 virtual IReporter* create(
const ReporterConfig&
config )
const = 0;
2009 virtual std::string getDescription()
const = 0;
2012 struct IReporterRegistry {
2013 typedef std::map<std::string, IReporterFactory*> FactoryMap;
2015 virtual ~IReporterRegistry();
2016 virtual IReporter* create(
const std::string& name,
const ReporterConfig&
config )
const = 0;
2017 virtual const FactoryMap& getFactories()
const = 0;
2020 inline std::string trim(
const std::string& str ) {
2021 std::string::size_type start = str.find_first_not_of(
"\n\r\t " );
2022 std::string::size_type end = str.find_last_not_of(
"\n\r\t " );
2024 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
2033 struct ITestCaseRegistry;
2034 struct IExceptionTranslatorRegistry;
2035 struct IExceptionTranslator;
2037 struct IRegistryHub {
2038 virtual ~IRegistryHub();
2040 virtual const IReporterRegistry& getReporterRegistry()
const = 0;
2041 virtual const ITestCaseRegistry& getTestCaseRegistry()
const = 0;
2042 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2045 struct IMutableRegistryHub {
2046 virtual ~IMutableRegistryHub();
2047 virtual void registerReporter(
const std::string& name, IReporterFactory* factory ) = 0;
2048 virtual void registerTest(
const TestCaseInfo& testInfo ) = 0;
2049 virtual void registerTranslator(
const IExceptionTranslator* translator ) = 0;
2052 IRegistryHub& getRegistryHub();
2053 IMutableRegistryHub& getMutableRegistryHub();
2060 typedef std::string(*exceptionTranslateFunction)();
2062 struct IExceptionTranslator {
2063 virtual ~IExceptionTranslator();
2064 virtual std::string translate()
const = 0;
2067 struct IExceptionTranslatorRegistry {
2068 virtual ~IExceptionTranslatorRegistry();
2070 virtual std::string translateActiveException()
const = 0;
2073 class ExceptionTranslatorRegistrar {
2074 template<
typename T>
2075 class ExceptionTranslator :
public IExceptionTranslator {
2078 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2079 : m_translateFunction( translateFunction )
2082 virtual std::string translate()
const {
2087 return m_translateFunction( ex );
2092 std::string(*m_translateFunction)( T& );
2096 template<
typename T>
2097 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
2098 getMutableRegistryHub().registerTranslator
2099 (
new ExceptionTranslator<T>( translateFunction ) );
2105 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2106 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2107 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2108 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2111 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2121 explicit Approx (
double value )
2122 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2127 Approx(
const Approx& other )
2128 : m_epsilon( other.m_epsilon ),
2129 m_scale( other.m_scale ),
2130 m_value( other.m_value )
2133 static Approx custom() {
2137 Approx operator()(
double value ) {
2138 Approx approx( value );
2139 approx.epsilon( m_epsilon );
2140 approx.scale( m_scale );
2144 friend bool operator == (
double lhs,
const Approx& rhs ) {
2146 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2149 friend bool operator == (
const Approx& lhs,
double rhs ) {
2150 return operator==( rhs, lhs );
2153 friend bool operator != (
double lhs,
const Approx& rhs ) {
2154 return !operator==( lhs, rhs );
2157 friend bool operator != (
const Approx& lhs,
double rhs ) {
2158 return !operator==( rhs, lhs );
2161 Approx& epsilon(
double newEpsilon ) {
2162 m_epsilon = newEpsilon;
2166 Approx& scale(
double newScale ) {
2171 std::string toString()
const {
2172 std::ostringstream oss;
2173 oss <<
"Approx( " << m_value <<
")";
2185 inline std::string toString<Detail::Approx>(
const Detail::Approx& value ) {
2186 return value.toString();
2192 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
2195 namespace Matchers {
2197 namespace StdString {
2200 Equals(
const std::string& str ) : m_str( str ){}
2202 bool operator()(
const std::string& str )
const
2204 return str == m_str;
2207 friend std::ostream& operator<<( std::ostream& os,
const Equals& matcher )
2209 os <<
"equals: \"" << matcher.m_str <<
"\"";
2216 Contains(
const std::string& substr ) : m_substr( substr ){}
2218 bool operator()(
const std::string& str )
const
2220 return str.find( m_substr ) != std::string::npos;
2223 friend std::ostream& operator<<( std::ostream& os,
const Contains& matcher )
2225 os <<
"contains: \"" << matcher.m_substr <<
"\"";
2228 std::string m_substr;
2232 StartsWith(
const std::string& substr ) : m_substr( substr ){}
2234 bool operator()(
const std::string& str )
const
2236 return str.find( m_substr ) == 0;
2239 friend std::ostream& operator<<( std::ostream& os,
const StartsWith& matcher )
2241 os <<
"starts with: \"" << matcher.m_substr <<
"\"";
2244 std::string m_substr;
2248 EndsWith(
const std::string& substr ) : m_substr( substr ){}
2250 bool operator()(
const std::string& str )
const
2252 return str.find( m_substr ) == str.size() - m_substr.size();
2255 friend std::ostream& operator<<( std::ostream& os,
const EndsWith& matcher )
2257 os <<
"ends with: \"" << matcher.m_substr <<
"\"";
2260 std::string m_substr;
2265 inline Impl::StdString::Equals Equals(
const std::string& str ){
return Impl::StdString::Equals( str ); }
2266 inline Impl::StdString::Contains Contains(
const std::string& substr ){
return Impl::StdString::Contains( substr ); }
2267 inline Impl::StdString::StartsWith StartsWith(
const std::string& substr ){
return Impl::StdString::StartsWith( substr ); }
2268 inline Impl::StdString::EndsWith EndsWith(
const std::string& substr ){
return Impl::StdString::EndsWith( substr ); }
2272 using namespace Matchers;
2279 #define TWOBLUECUBES_INTERNAL_CATCH_INTERFACES_RUNNER_H_INCLUDED
2294 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2296 #import <objc/runtime.h>
2318 class OcMethod :
public SharedImpl<ITestCase> {
2321 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2323 virtual void invoke()
const {
2324 id obj = [[m_cls alloc] init];
2326 performOptionalSelector( obj,
@selector(setUp) );
2327 performOptionalSelector( obj, m_sel );
2328 performOptionalSelector( obj,
@selector(tearDown) );
2330 arcSafeRelease( obj );
2333 virtual ~OcMethod() {}
2341 inline bool startsWith(
const std::string& str,
const std::string& sub ) {
2342 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
2345 inline std::string getAnnotation( Class cls,
2346 const std::string& annotationName,
2347 const std::string& testCaseName ) {
2348 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2349 SEL sel = NSSelectorFromString( selStr );
2350 arcSafeRelease( selStr );
2351 id value = performOptionalSelector( cls, sel );
2353 return [(NSString*)value UTF8String];
2358 inline size_t registerTestMethods() {
2359 size_t noTestMethods = 0;
2360 int noClasses = objc_getClassList( NULL, 0 );
2362 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc(
sizeof(Class) * noClasses);
2363 objc_getClassList( classes, noClasses );
2365 for(
int c = 0; c < noClasses; c++ ) {
2366 Class cls = classes[c];
2369 Method* methods = class_copyMethodList( cls, &count );
2370 for( u_int m = 0; m < count ; m++ ) {
2371 SEL selector = method_getName(methods[m]);
2372 std::string methodName = sel_getName(selector);
2373 if( Detail::startsWith( methodName,
"Catch_TestCase_" ) ) {
2374 std::string testCaseName = methodName.substr( 15 );
2375 std::string name = Detail::getAnnotation( cls,
"Name", testCaseName );
2376 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
2378 getMutableRegistryHub().registerTest( TestCaseInfo(
new OcMethod( cls, selector ), name.c_str(), desc.c_str(), SourceLineInfo() ) );
2385 return noTestMethods;
2388 namespace Matchers {
2390 namespace NSStringMatchers {
2392 struct StringHolder {
2393 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2395 arcSafeRelease( m_substr );
2401 struct Equals : StringHolder {
2402 Equals( NSString* substr ) : StringHolder( substr ){}
2404 bool operator()( NSString* str )
const {
2405 return [str isEqualToString:m_substr];
2408 friend std::ostream& operator<<( std::ostream& os,
const Equals& matcher ) {
2409 os <<
"equals string: " << Catch::toString( matcher.m_substr );
2414 struct Contains : StringHolder {
2415 Contains( NSString* substr ) : StringHolder( substr ){}
2417 bool operator()( NSString* str )
const {
2418 return [str rangeOfString:m_substr].location != NSNotFound;
2421 friend std::ostream& operator<<( std::ostream& os,
const Contains& matcher ) {
2422 os <<
"contains: " << Catch::toString( matcher.m_substr );
2427 struct StartsWith : StringHolder {
2428 StartsWith( NSString* substr ) : StringHolder( substr ){}
2430 bool operator()( NSString* str )
const {
2431 return [str rangeOfString:m_substr].location == 0;
2434 friend std::ostream& operator<<( std::ostream& os,
const StartsWith& matcher ) {
2435 os <<
"starts with: " << Catch::toString( matcher.m_substr );
2439 struct EndsWith : StringHolder {
2440 EndsWith( NSString* substr ) : StringHolder( substr ){}
2442 bool operator()( NSString* str )
const {
2443 return [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2446 friend std::ostream& operator<<( std::ostream& os,
const EndsWith& matcher ) {
2447 os <<
"ends with: " << Catch::toString( matcher.m_substr );
2455 inline Impl::NSStringMatchers::Equals
2456 Equals( NSString* substr ){
return Impl::NSStringMatchers::Equals( substr ); }
2458 inline Impl::NSStringMatchers::Contains
2459 Contains( NSString* substr ){
return Impl::NSStringMatchers::Contains( substr ); }
2461 inline Impl::NSStringMatchers::StartsWith
2462 StartsWith( NSString* substr ){
return Impl::NSStringMatchers::StartsWith( substr ); }
2464 inline Impl::NSStringMatchers::EndsWith
2465 EndsWith( NSString* substr ){
return Impl::NSStringMatchers::EndsWith( substr ); }
2469 using namespace Matchers;
2474 #define OC_TEST_CASE( name, desc )\
2475 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
2479 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
2483 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2487 #if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
2494 #pragma clang diagnostic push
2495 #pragma clang diagnostic ignored "-Wweak-vtables"
2499 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
2502 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2510 explicit Command(
const std::string& name ) : m_name( name ) {
2513 Command& operator += (
const std::string& arg ) {
2514 m_args.push_back( arg );
2518 std::copy( other.m_args.begin(), other.m_args.end(), std::back_inserter( m_args ) );
2519 if( m_name.empty() )
2520 m_name = other.m_name;
2525 newCommand += other;
2529 operator SafeBool::type()
const {
2530 return SafeBool::makeSafe( !m_name.empty() || !m_args.empty() );
2533 std::string name()
const {
return m_name; }
2534 std::string operator[]( std::size_t i )
const {
return m_args[i]; }
2535 std::size_t argsCount()
const {
return m_args.size(); }
2538 void raiseError(
const std::string& message )
const {
2539 std::ostringstream oss;
2540 if( m_name.empty() )
2541 oss <<
"Error while parsing " << m_name <<
". " << message <<
".";
2543 oss <<
"Error while parsing arguments. " << message <<
".";
2545 if( m_args.size() > 0 )
2546 oss <<
" Arguments were:";
2547 for( std::size_t i = 0; i < m_args.size(); ++i )
2548 oss << " " << m_args[i];
2549 throw std::domain_error( oss.str() );
2555 std::vector<std::string> m_args;
2558 class CommandParser {
2560 CommandParser(
int argc,
char const *
const * argv ) : m_argc( static_cast<std::size_t>( argc ) ), m_argv( argv ) {}
2562 Command find(
const std::string& arg1,
const std::string& arg2,
const std::string& arg3 )
const {
2563 return find( arg1 ) + find( arg2 ) + find( arg3 );
2566 Command find(
const std::string& shortArg,
const std::string& longArg )
const {
2567 return find( shortArg ) + find( longArg );
2569 Command find(
const std::string& arg )
const {
2571 return getArgs(
"", 1 );
2573 for( std::size_t i = 1; i < m_argc; ++i )
2574 if( m_argv[i] == arg )
2575 return getArgs( m_argv[i], i+1 );
2578 Command getDefaultArgs()
const {
2579 return getArgs(
"", 1 );
2583 Command getArgs(
const std::string& cmdName, std::size_t from )
const {
2585 for( std::size_t i = from; i < m_argc && m_argv[i][0] !=
'-'; ++i )
2591 char const *
const * m_argv;
2594 class OptionParser :
public SharedImpl<IShared> {
2596 OptionParser(
int minArgs = 0,
int maxArgs = 0 )
2597 : m_minArgs( minArgs ), m_maxArgs( maxArgs )
2600 virtual ~OptionParser() {}
2602 Command find(
const CommandParser& parser )
const {
2604 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
2605 it != m_optionNames.end();
2607 cmd += parser.find( *it );
2611 void validateArgs(
const Command& args )
const {
2612 if( tooFewArgs( args ) || tooManyArgs( args ) ) {
2613 std::ostringstream oss;
2614 if( m_maxArgs == -1 )
2615 oss <<
"Expected at least " << pluralise( static_cast<std::size_t>( m_minArgs ),
"argument" );
2616 else if( m_minArgs == m_maxArgs )
2617 oss <<
"Expected " << pluralise( static_cast<std::size_t>( m_minArgs ),
"argument" );
2619 oss <<
"Expected between " << m_minArgs <<
" and " << m_maxArgs <<
" argument";
2620 args.raiseError( oss.str() );
2624 void parseIntoConfig(
const CommandParser& parser, ConfigData&
config ) {
2625 if(
Command cmd = find( parser ) ) {
2626 validateArgs( cmd );
2627 parseIntoConfig( cmd, config );
2631 virtual void parseIntoConfig(
const Command& cmd, ConfigData& config ) = 0;
2632 virtual std::string argsSynopsis()
const = 0;
2633 virtual std::string optionSummary()
const = 0;
2635 std::string optionNames()
const {
2637 for( std::vector<std::string>::const_iterator it = m_optionNames.begin();
2638 it != m_optionNames.end();
2640 if( !it->empty() ) {
2641 if( !names.empty() )
2646 names =
"[" + names;
2649 if( names[0] ==
'[' )
2656 bool tooFewArgs(
const Command& args )
const {
2657 return args.argsCount() <
static_cast<std::size_t
>( m_minArgs );
2659 bool tooManyArgs(
const Command& args )
const {
2660 return m_maxArgs >= 0 && args.argsCount() >
static_cast<std::size_t
>( m_maxArgs );
2662 std::vector<std::string> m_optionNames;
2669 class HelpOptionParser :
public OptionParser {
2671 HelpOptionParser() {
2672 m_optionNames.push_back(
"-?" );
2673 m_optionNames.push_back(
"-h" );
2674 m_optionNames.push_back(
"--help" );
2676 virtual std::string argsSynopsis()
const {
2679 virtual std::string optionSummary()
const {
2680 return "Shows this usage summary";
2683 virtual void parseIntoConfig(
const Command&, ConfigData& ) {
2688 class TestCaseOptionParser :
public OptionParser {
2690 TestCaseOptionParser() : OptionParser( 1, -1 ) {
2691 m_optionNames.push_back(
"-t" );
2692 m_optionNames.push_back(
"--test" );
2693 m_optionNames.push_back(
"" );
2695 virtual std::string argsSynopsis()
const {
2696 return "<testspec> [<testspec>...]";
2698 virtual std::string optionSummary()
const {
2699 return "Specify which test case or cases to run";
2702 virtual void parseIntoConfig(
const Command& cmd, ConfigData& config ) {
2703 std::string groupName;
2704 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
2707 groupName += cmd[i];
2709 TestCaseFilters filters( groupName );
2710 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
2711 if( Catch::startsWith( cmd[i],
"exclude:" ) )
2712 filters.addFilter( TestCaseFilter( cmd[i].substr( 8 ), IfFilterMatches::ExcludeTests ) );
2713 else if( Catch::startsWith( cmd[i],
"~" ) )
2714 filters.addFilter( TestCaseFilter( cmd[i].substr( 1 ), IfFilterMatches::ExcludeTests ) );
2716 filters.addFilter( TestCaseFilter( cmd[i] ) );
2718 config.filters.push_back( filters );
2722 class ListOptionParser :
public OptionParser {
2724 ListOptionParser() : OptionParser( 0, 2 ) {
2725 m_optionNames.push_back(
"-l" );
2726 m_optionNames.push_back(
"--list" );
2728 virtual std::string argsSynopsis()
const {
2729 return "[all | tests | reporters [xml]]";
2731 virtual std::string optionSummary()
const {
2735 virtual void parseIntoConfig(
const Command& cmd, ConfigData& config ) {
2736 config.listSpec = List::TestNames;
2737 if( cmd.argsCount() >= 1 ) {
2738 if( cmd[0] ==
"all" )
2739 config.listSpec = List::All;
2740 else if( cmd[0] ==
"tests" )
2741 config.listSpec = List::Tests;
2742 else if( cmd[0] ==
"reporters" )
2743 config.listSpec = List::Reports;
2745 cmd.raiseError(
"Expected [tests] or [reporters]" );
2747 if( cmd.argsCount() >= 2 ) {
2748 if( cmd[1] ==
"xml" )
2749 config.listSpec =
static_cast<List::What
>( config.listSpec | List::AsXml );
2750 else if( cmd[1] ==
"text" )
2751 config.listSpec =
static_cast<List::What
>( config.listSpec | List::AsText );
2753 cmd.raiseError(
"Expected [xml] or [text]" );
2758 class ReporterOptionParser :
public OptionParser {
2760 ReporterOptionParser() : OptionParser( 1, 1 ) {
2761 m_optionNames.push_back(
"-r" );
2762 m_optionNames.push_back(
"--reporter" );
2764 virtual std::string argsSynopsis()
const {
2765 return "<reporter name>";
2767 virtual std::string optionSummary()
const {
2771 virtual void parseIntoConfig(
const Command& cmd, ConfigData& config ) {
2772 config.reporter = cmd[0];
2776 class OutputOptionParser :
public OptionParser {
2778 OutputOptionParser() : OptionParser( 1, 1 ) {
2779 m_optionNames.push_back(
"-o" );
2780 m_optionNames.push_back(
"--out" );
2782 virtual std::string argsSynopsis()
const {
2783 return "<file name>|<%stream name>";
2785 virtual std::string optionSummary()
const {
2789 virtual void parseIntoConfig(
const Command& cmd, ConfigData& config ) {
2790 if( cmd[0][0] ==
'%' )
2791 config.stream = cmd[0].substr( 1 );
2793 config.outputFilename = cmd[0];
2797 class SuccesssOptionParser :
public OptionParser {
2799 SuccesssOptionParser() {
2800 m_optionNames.push_back(
"-s" );
2801 m_optionNames.push_back(
"--success" );
2803 virtual std::string argsSynopsis()
const {
2806 virtual std::string optionSummary()
const {
2810 virtual void parseIntoConfig(
const Command&, ConfigData& config ) {
2811 config.includeWhichResults = Include::SuccessfulResults;
2815 class DebugBreakOptionParser :
public OptionParser {
2817 DebugBreakOptionParser() {
2818 m_optionNames.push_back(
"-b" );
2819 m_optionNames.push_back(
"--break" );
2821 virtual std::string argsSynopsis()
const {
2824 virtual std::string optionSummary()
const {
2828 virtual void parseIntoConfig(
const Command&, ConfigData& config ) {
2829 config.shouldDebugBreak =
true;
2833 class NameOptionParser :
public OptionParser {
2835 NameOptionParser() : OptionParser( 1, 1 ) {
2836 m_optionNames.push_back(
"-n" );
2837 m_optionNames.push_back(
"--name" );
2839 virtual std::string argsSynopsis()
const {
2842 virtual std::string optionSummary()
const {
2846 virtual void parseIntoConfig(
const Command& cmd, ConfigData& config ) {
2847 config.name = cmd[0];
2851 class AbortOptionParser :
public OptionParser {
2853 AbortOptionParser() : OptionParser( 0, 1 ) {
2854 m_optionNames.push_back(
"-a" );
2855 m_optionNames.push_back(
"--abort" );
2857 virtual std::string argsSynopsis()
const {
2860 virtual std::string optionSummary()
const {
2864 virtual void parseIntoConfig(
const Command& cmd, ConfigData& config ) {
2866 if( cmd.argsCount() == 1 ) {
2867 std::stringstream ss;
2870 if( ss.fail() || threshold <= 0 )
2871 cmd.raiseError(
"threshold must be a number greater than zero" );
2873 config.cutoff = threshold;
2877 class NoThrowOptionParser :
public OptionParser {
2879 NoThrowOptionParser() {
2880 m_optionNames.push_back(
"-nt" );
2881 m_optionNames.push_back(
"--nothrow" );
2883 virtual std::string argsSynopsis()
const {
2886 virtual std::string optionSummary()
const {
2890 virtual void parseIntoConfig(
const Command&, ConfigData& config ) {
2891 config.allowThrows =
false;
2895 class WarningsOptionParser :
public OptionParser {
2897 WarningsOptionParser() : OptionParser( 1, -1 ) {
2898 m_optionNames.push_back(
"-w" );
2899 m_optionNames.push_back(
"--warnings" );
2901 virtual std::string argsSynopsis()
const {
2904 virtual std::string optionSummary()
const {
2908 virtual void parseIntoConfig(
const Command& cmd, ConfigData& config ) {
2909 for( std::size_t i = 0; i < cmd.argsCount(); ++i ) {
2910 if( cmd[i] ==
"NoAssertions" )
2911 config.warnings = (ConfigData::WarnAbout::What)( config.warnings | ConfigData::WarnAbout::NoAssertions );
2913 cmd.raiseError(
"Unrecognised warning: " + cmd[i] );
2922 typedef std::vector<Ptr<OptionParser> > Parsers;
2923 typedef Parsers::const_iterator const_iterator;
2924 typedef Parsers::const_iterator iterator;
2927 add<Options::TestCaseOptionParser>();
2929 add<Options::ListOptionParser>();
2930 add<Options::ReporterOptionParser>();
2931 add<Options::OutputOptionParser>();
2932 add<Options::SuccesssOptionParser>();
2933 add<Options::DebugBreakOptionParser>();
2934 add<Options::NameOptionParser>();
2935 add<Options::AbortOptionParser>();
2936 add<Options::NoThrowOptionParser>();
2937 add<Options::WarningsOptionParser>();
2939 add<Options::HelpOptionParser>();
2942 void parseIntoConfig(
const CommandParser& parser, ConfigData& config ) {
2943 for( const_iterator it = m_parsers.begin(); it != m_parsers.end(); ++it )
2944 (*it)->parseIntoConfig( parser, config );
2947 const_iterator begin()
const {
2948 return m_parsers.begin();
2950 const_iterator end()
const {
2951 return m_parsers.end();
2955 template<
typename T>
2957 m_parsers.push_back(
new T() );
2966 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
2971 inline bool matchesFilters(
const std::vector<TestCaseFilters>& filters,
const TestCaseInfo& testCase ) {
2972 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
2973 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
2974 for(; it != itEnd; ++it )
2975 if( !it->shouldInclude( testCase ) )
2979 inline void List(
const ConfigData& config ) {
2981 if( config.listSpec & List::Reports ) {
2982 std::cout <<
"Available reports:\n";
2983 IReporterRegistry::FactoryMap::const_iterator it = getRegistryHub().getReporterRegistry().getFactories().begin();
2984 IReporterRegistry::FactoryMap::const_iterator itEnd = getRegistryHub().getReporterRegistry().getFactories().end();
2985 for(; it != itEnd; ++it ) {
2987 std::cout <<
"\t" << it->first <<
"\n\t\t'" << it->second->getDescription() <<
"'\n";
2989 std::cout << std::endl;
2992 if( config.listSpec & List::Tests ) {
2993 if( config.filters.empty() )
2994 std::cout <<
"All available test cases:\n";
2996 std::cout <<
"Matching test cases:\n";
2997 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
2998 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
2999 std::size_t matchedTests = 0;
3000 for(; it != itEnd; ++it ) {
3001 if( matchesFilters( config.filters, *it ) ) {
3004 std::cout <<
"\t" << it->getName() <<
"\n";
3005 if( ( config.listSpec & List::TestNames ) != List::TestNames )
3006 std::cout <<
"\t\t '" << it->getDescription() <<
"'\n";
3009 if( config.filters.empty() )
3010 std::cout << pluralise( matchedTests,
"test case" ) << std::endl;
3012 std::cout << pluralise( matchedTests,
"matching test case" ) << std::endl;
3015 if( ( config.listSpec & List::All ) == 0 ) {
3016 std::ostringstream oss;
3017 oss <<
"Unknown list type";
3018 throw std::domain_error( oss.str() );
3025 #define TWOBLUECUBES_INTERNAL_CATCH_RUNNER_HPP_INCLUDED
3028 #define TWOBLUECUBES_INTERNAL_CATCH_RUNNING_TEST_HPP_INCLUDED
3031 #define TWOBLUECUBES_INTERNAL_CATCH_SECTION_INFO_HPP_INCLUDED
3049 SectionInfo( SectionInfo* parent )
3050 : m_status( Unknown ),
3060 deleteAllValues( m_subSections );
3063 bool shouldRun()
const {
3064 return m_status < TestedBranch;
3068 if( m_status < Branch ) {
3069 m_status = TestedLeaf;
3075 bool isBranch()
const {
3076 return m_status == Branch;
3079 void ranToCompletion() {
3080 if( m_status == Branch && !hasUntestedSections() )
3081 m_status = TestedBranch;
3084 SectionInfo* findSubSection(
const std::string& name ) {
3085 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.find( name );
3086 return it != m_subSections.end()
3091 SectionInfo* addSubSection(
const std::string& name ) {
3092 SectionInfo* subSection =
new SectionInfo(
this );
3093 m_subSections.insert( std::make_pair( name, subSection ) );
3098 SectionInfo* getParent() {
3102 bool hasUntestedSections()
const {
3103 if( m_status == Unknown )
3106 std::map<std::string, SectionInfo*>::const_iterator it = m_subSections.begin();
3107 std::map<std::string, SectionInfo*>::const_iterator itEnd = m_subSections.end();
3108 for(; it != itEnd; ++it ) {
3109 if( it->second->hasUntestedSections() )
3117 std::map<std::string, SectionInfo*> m_subSections;
3118 SectionInfo* m_parent;
3128 EncounteredASection,
3129 RanAtLeastOneSection,
3130 RanToCompletionWithSections,
3131 RanToCompletionWithNoSections
3135 explicit RunningTest(
const TestCaseInfo* info = NULL )
3137 m_runStatus( RanAtLeastOneSection ),
3138 m_currentSection( &m_rootSection ),
3142 bool wasSectionSeen()
const {
3143 return m_runStatus == RanAtLeastOneSection ||
3144 m_runStatus == RanToCompletionWithSections;
3147 bool isBranchSection()
const {
3148 return m_currentSection &&
3149 m_currentSection->isBranch();
3152 bool hasSections()
const {
3153 return m_runStatus == RanAtLeastOneSection ||
3154 m_runStatus == RanToCompletionWithSections ||
3155 m_runStatus == EncounteredASection;
3159 m_runStatus = NothingRun;
3161 m_lastSectionToRun = NULL;
3164 void ranToCompletion() {
3165 if( m_runStatus == RanAtLeastOneSection ||
3166 m_runStatus == EncounteredASection ) {
3167 m_runStatus = RanToCompletionWithSections;
3168 if( m_lastSectionToRun ) {
3169 m_lastSectionToRun->ranToCompletion();
3174 m_runStatus = RanToCompletionWithNoSections;
3178 bool addSection(
const std::string& name ) {
3179 if( m_runStatus == NothingRun )
3180 m_runStatus = EncounteredASection;
3182 SectionInfo* thisSection = m_currentSection->findSubSection( name );
3183 if( !thisSection ) {
3184 thisSection = m_currentSection->addSubSection( name );
3188 if( !wasSectionSeen() && thisSection->shouldRun() ) {
3189 m_currentSection = thisSection;
3190 m_lastSectionToRun = NULL;
3196 void endSection(
const std::string& ) {
3197 if( m_currentSection->ran() ) {
3198 m_runStatus = RanAtLeastOneSection;
3201 else if( m_runStatus == EncounteredASection ) {
3202 m_runStatus = RanAtLeastOneSection;
3203 m_lastSectionToRun = m_currentSection;
3205 m_currentSection = m_currentSection->getParent();
3208 const TestCaseInfo& getTestCaseInfo()
const {
3212 bool hasUntestedSections()
const {
3213 return m_runStatus == RanAtLeastOneSection ||
3214 ( m_rootSection.hasUntestedSections() && m_changed );
3218 const TestCaseInfo* m_info;
3219 RunStatus m_runStatus;
3220 SectionInfo m_rootSection;
3221 SectionInfo* m_currentSection;
3222 SectionInfo* m_lastSectionToRun;
3232 class StreamRedirect {
3235 StreamRedirect( std::ostream& stream, std::string& targetString )
3236 : m_stream( stream ),
3237 m_prevBuf( stream.rdbuf() ),
3238 m_targetString( targetString )
3240 stream.rdbuf( m_oss.rdbuf() );
3244 m_targetString += m_oss.str();
3245 m_stream.rdbuf( m_prevBuf );
3249 std::ostream& m_stream;
3250 std::streambuf* m_prevBuf;
3251 std::ostringstream m_oss;
3252 std::string& m_targetString;
3257 class Runner :
public IResultCapture,
public IRunner {
3259 Runner(
const Runner& );
3260 void operator =(
const Runner& );
3264 explicit Runner(
const Config& config,
const Ptr<IReporter>& reporter )
3265 : m_context( getCurrentMutableContext() ),
3266 m_runningTest( NULL ),
3268 m_reporter( reporter ),
3269 m_prevRunner( &m_context.getRunner() ),
3270 m_prevResultCapture( &m_context.getResultCapture() ),
3271 m_prevConfig( m_context.getConfig() )
3273 m_context.setRunner(
this );
3274 m_context.setConfig( &m_config );
3275 m_context.setResultCapture(
this );
3276 m_reporter->StartTesting();
3280 m_reporter->EndTesting( m_totals );
3281 m_context.setRunner( m_prevRunner );
3282 m_context.setConfig( NULL );
3283 m_context.setResultCapture( m_prevResultCapture );
3284 m_context.setConfig( m_prevConfig );
3287 Totals runMatching(
const std::string& testSpec ) {
3289 std::vector<TestCaseInfo> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec );
3293 m_reporter->StartGroup( testSpec );
3295 std::vector<TestCaseInfo>::const_iterator it = matchingTests.begin();
3296 std::vector<TestCaseInfo>::const_iterator itEnd = matchingTests.end();
3297 for(; it != itEnd; ++it )
3298 totals += runTest( *it );
3301 m_reporter->EndGroup( testSpec, totals );
3305 Totals runTest(
const TestCaseInfo& testInfo ) {
3306 Totals prevTotals = m_totals;
3308 std::string redirectedCout;
3309 std::string redirectedCerr;
3311 m_reporter->StartTestCase( testInfo );
3313 m_runningTest =
new RunningTest( &testInfo );
3317 m_currentResult.setLineInfo( m_runningTest->getTestCaseInfo().getLineInfo() );
3318 runCurrentTest( redirectedCout, redirectedCerr );
3320 while( m_runningTest->hasUntestedSections() && !aborting() );
3322 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
3324 delete m_runningTest;
3325 m_runningTest = NULL;
3327 Totals deltaTotals = m_totals.delta( prevTotals );
3328 m_totals.testCases += deltaTotals.testCases;
3329 m_reporter->EndTestCase( testInfo, deltaTotals, redirectedCout, redirectedCerr );
3333 const Config&
config()
const {
3339 virtual ResultAction::Value acceptResult(
bool result ) {
3340 return acceptResult( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
3343 virtual ResultAction::Value acceptResult( ResultWas::OfType result ) {
3344 m_currentResult.setResultType( result );
3345 return actOnCurrentResult();
3348 virtual ResultAction::Value acceptExpression(
const ResultInfoBuilder& resultInfo ) {
3349 m_currentResult = resultInfo;
3350 return actOnCurrentResult();
3353 virtual void acceptMessage(
const std::string& msg ) {
3354 m_currentResult.setMessage( msg );
3357 virtual void testEnded(
const ResultInfo& result ) {
3358 if( result.getResultType() == ResultWas::Ok ) {
3359 m_totals.assertions.passed++;
3361 else if( !result.ok() ) {
3362 m_totals.assertions.failed++;
3364 std::vector<ResultInfo>::const_iterator it = m_info.begin();
3365 std::vector<ResultInfo>::const_iterator itEnd = m_info.end();
3366 for(; it != itEnd; ++it )
3367 m_reporter->
Result( *it );
3371 if( result.getResultType() == ResultWas::Info )
3372 m_info.push_back( result );
3374 m_reporter->Result( result );
3377 virtual bool sectionStarted (
3378 const std::string& name,
3379 const std::string& description,
3380 const SourceLineInfo& lineInfo,
3384 std::ostringstream oss;
3385 oss << name <<
"@" << lineInfo;
3387 if( !m_runningTest->addSection( oss.str() ) )
3390 m_currentResult.setLineInfo( lineInfo );
3391 m_reporter->StartSection( name, description );
3392 assertions = m_totals.assertions;
3397 virtual void sectionEnded(
const std::string& name,
const Counts& prevAssertions ) {
3398 Counts assertions = m_totals.assertions - prevAssertions;
3399 if( assertions.total() == 0 &&
3400 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
3401 !m_runningTest->isBranchSection() ) {
3402 m_reporter->NoAssertionsInSection( name );
3403 m_totals.assertions.failed++;
3404 assertions.failed++;
3406 m_runningTest->endSection( name );
3407 m_reporter->EndSection( name, assertions );
3410 virtual void pushScopedInfo( ScopedInfo* scopedInfo ) {
3411 m_scopedInfos.push_back( scopedInfo );
3414 virtual void popScopedInfo( ScopedInfo* scopedInfo ) {
3415 if( m_scopedInfos.back() == scopedInfo )
3416 m_scopedInfos.pop_back();
3419 virtual bool shouldDebugBreak()
const {
3420 return m_config.shouldDebugBreak();
3423 virtual std::string getCurrentTestName()
const {
3424 return m_runningTest
3425 ? m_runningTest->getTestCaseInfo().getName()
3429 virtual const ResultInfo* getLastResult()
const {
3430 return &m_lastResult;
3435 bool aborting()
const {
3436 return m_totals.assertions.failed ==
static_cast<std::size_t
>( m_config.getCutoff() );
3441 ResultAction::Value actOnCurrentResult() {
3442 testEnded( m_currentResult );
3443 m_lastResult = m_currentResult;
3445 m_currentResult = ResultInfoBuilder();
3447 ResultAction::Value action = ResultAction::None;
3449 if( !m_lastResult.ok() ) {
3450 action = ResultAction::Failed;
3451 if( shouldDebugBreak() )
3452 action = (ResultAction::Value)( action | ResultAction::Debug );
3454 action = (ResultAction::Value)( action | ResultAction::Abort );
3459 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
3461 m_runningTest->reset();
3462 Counts prevAssertions = m_totals.assertions;
3463 if( m_reporter->shouldRedirectStdout() ) {
3464 StreamRedirect coutRedir( std::cout, redirectedCout );
3465 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
3466 m_runningTest->getTestCaseInfo().invoke();
3469 m_runningTest->getTestCaseInfo().invoke();
3471 Counts assertions = m_totals.assertions - prevAssertions;
3472 if( assertions.total() == 0 &&
3473 ( m_config.data().warnings & ConfigData::WarnAbout::NoAssertions ) &&
3474 !m_runningTest->hasSections() ) {
3475 m_totals.assertions.failed++;
3476 m_reporter->NoAssertionsInTestCase( m_runningTest->getTestCaseInfo().getName() );
3478 m_runningTest->ranToCompletion();
3480 catch( TestFailureException& ) {
3484 acceptMessage( getRegistryHub().getExceptionTranslatorRegistry().translateActiveException() );
3485 acceptResult( ResultWas::ThrewException );
3491 IMutableContext& m_context;
3492 RunningTest* m_runningTest;
3493 ResultInfoBuilder m_currentResult;
3494 ResultInfo m_lastResult;
3496 const Config& m_config;
3498 Ptr<IReporter> m_reporter;
3499 std::vector<ScopedInfo*> m_scopedInfos;
3500 std::vector<ResultInfo> m_info;
3501 IRunner* m_prevRunner;
3502 IResultCapture* m_prevResultCapture;
3503 const IConfig* m_prevConfig;
3517 Runner2( Config& configWrapper )
3518 : m_configWrapper( configWrapper ),
3519 m_config( configWrapper.
data() )
3527 std::vector<TestCaseFilters> filterGroups = m_config.filters;
3528 if( filterGroups.empty() ) {
3529 TestCaseFilters filterGroup(
"" );
3530 filterGroup.addFilter( TestCaseFilter(
"./*", IfFilterMatches::ExcludeTests ) );
3531 filterGroups.push_back( filterGroup );
3534 Runner context( m_configWrapper, m_reporter );
3537 std::vector<TestCaseFilters>::const_iterator it = filterGroups.begin();
3538 std::vector<TestCaseFilters>::const_iterator itEnd = filterGroups.end();
3539 for(; it != itEnd; ++it ) {
3540 m_reporter->StartGroup( it->getName() );
3541 totals += runTestsForGroup( context, *it );
3542 if( context.aborting() )
3543 m_reporter->Aborted();
3544 m_reporter->EndGroup( it->getName(), totals );
3549 Totals runTestsForGroup( Runner& context,
const TestCaseFilters& filterGroup ) {
3551 std::vector<TestCaseInfo>::const_iterator it = getRegistryHub().getTestCaseRegistry().getAllTests().begin();
3552 std::vector<TestCaseInfo>::const_iterator itEnd = getRegistryHub().getTestCaseRegistry().getAllTests().end();
3553 int testsRunForGroup = 0;
3554 for(; it != itEnd; ++it ) {
3555 if( filterGroup.shouldInclude( *it ) ) {
3557 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
3559 if( context.aborting() )
3562 totals += context.runTest( *it );
3563 m_testsAlreadyRun.insert( *it );
3567 if( testsRunForGroup == 0 )
3568 std::cerr <<
"\n[No test cases matched with: " << filterGroup.getName() <<
"]" << std::endl;
3574 void resolveStream() {
3575 if( !m_config.stream.empty() ) {
3576 if( m_config.stream[0] ==
'%' )
3577 m_configWrapper.useStream( m_config.stream.substr( 1 ) );
3579 m_configWrapper.setFilename( m_config.stream );
3582 if( !m_config.outputFilename.empty() ) {
3583 m_ofs.open( m_config.outputFilename.c_str() );
3584 if( m_ofs.fail() ) {
3585 std::ostringstream oss;
3586 oss <<
"Unable to open file: '" << m_config.outputFilename <<
"'";
3587 throw std::domain_error( oss.str() );
3589 m_configWrapper.setStreamBuf( m_ofs.rdbuf() );
3592 void makeReporter() {
3593 std::string reporterName = m_config.reporter.empty()
3594 ? std::string(
"basic")
3595 : m_config.reporter;
3597 ReporterConfig reporterConfig( m_config.name, m_configWrapper.stream(), m_config.includeWhichResults == Include::SuccessfulResults, m_config );
3599 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, reporterConfig );
3601 std::ostringstream oss;
3602 oss <<
"No reporter registered with name: '" << reporterName <<
"'";
3603 throw std::domain_error( oss.str() );
3608 Config& m_configWrapper;
3609 const ConfigData& m_config;
3610 std::ofstream m_ofs;
3611 Ptr<IReporter> m_reporter;
3612 std::set<TestCaseInfo> m_testsAlreadyRun;
3615 inline int Main( Config& configWrapper ) {
3619 Runner2 runner( configWrapper );
3621 const ConfigData& config = configWrapper.data();
3624 if( config.listSpec != List::None ) {
3629 result =
static_cast<int>( runner.runTests().assertions.failed );
3632 catch( std::exception& ex ) {
3633 std::cerr << ex.what() << std::endl;
3634 result = (std::numeric_limits<int>::max)();
3641 inline void showUsage( std::ostream& os ) {
3643 for( AllOptions::const_iterator it = options.begin(); it != options.end(); ++it ) {
3644 OptionParser& opt = **it;
3645 os <<
" " << opt.optionNames() <<
" " << opt.argsSynopsis() <<
"\n";
3647 os <<
"\nFor more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line\n" << std::endl;
3649 inline void showHelp( std::string exeName ) {
3650 std::string::size_type pos = exeName.find_last_of(
"/\\" );
3651 if( pos != std::string::npos ) {
3652 exeName = exeName.substr( pos+1 );
3655 std::cout << exeName <<
" is a CATCH host application. Options are as follows:\n\n";
3656 showUsage( std::cout );
3659 inline int Main(
int argc,
char*
const argv[], Config& config ) {
3662 CommandParser parser( argc, (
char const *
const * ) argv );
3664 if(
Command cmd = Options::HelpOptionParser().find( parser ) ) {
3665 if( cmd.argsCount() != 0 )
3666 cmd.raiseError(
"Does not accept arguments" );
3668 showHelp( argv[0] );
3675 options.parseIntoConfig( parser, config.data() );
3677 catch( std::exception& ex ) {
3678 std::cerr << ex.what() <<
"\n\nUsage: ...\n\n";
3679 showUsage( std::cerr );
3681 return (std::numeric_limits<int>::max)();
3684 return Main( config );
3687 inline int Main(
int argc,
char*
const argv[] ) {
3692 return Main( argc, argv, config );
3708 class TestRegistry :
public ITestCaseRegistry {
3710 TestRegistry() : m_unnamedCount( 0 ) {}
3711 virtual ~TestRegistry();
3713 virtual void registerTest(
const TestCaseInfo& testInfo ) {
3714 if( testInfo.getName() ==
"" ) {
3715 std::ostringstream oss;
3716 oss << testInfo.getName() <<
"unnamed/" << ++m_unnamedCount;
3717 return registerTest( TestCaseInfo( testInfo, oss.str() ) );
3720 if( m_functions.find( testInfo ) == m_functions.end() ) {
3721 m_functions.insert( testInfo );
3722 m_functionsInOrder.push_back( testInfo );
3723 if( !testInfo.isHidden() )
3724 m_nonHiddenFunctions.push_back( testInfo );
3727 const TestCaseInfo& prev = *m_functions.find( testInfo );
3728 std::cerr <<
"error: TEST_CASE( \"" << testInfo.getName() <<
"\" ) already defined.\n"
3729 <<
"\tFirst seen at " << SourceLineInfo( prev.getLineInfo() ) <<
"\n"
3730 <<
"\tRedefined at " << SourceLineInfo( testInfo.getLineInfo() ) << std::endl;
3735 virtual const std::vector<TestCaseInfo>& getAllTests()
const {
3736 return m_functionsInOrder;
3739 virtual const std::vector<TestCaseInfo>& getAllNonHiddenTests()
const {
3740 return m_nonHiddenFunctions;
3744 virtual std::vector<TestCaseInfo> getMatchingTestCases(
const std::string& rawTestSpec )
const {
3745 std::vector<TestCaseInfo> matchingTests;
3746 getMatchingTestCases( rawTestSpec, matchingTests );
3747 return matchingTests;
3751 virtual void getMatchingTestCases(
const std::string& rawTestSpec, std::vector<TestCaseInfo>& matchingTestsOut )
const {
3752 TestCaseFilter filter( rawTestSpec );
3754 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
3755 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
3756 for(; it != itEnd; ++it ) {
3757 if( filter.shouldInclude( *it ) ) {
3758 matchingTestsOut.push_back( *it );
3762 virtual void getMatchingTestCases(
const TestCaseFilters& filters, std::vector<TestCaseInfo>& matchingTestsOut )
const {
3763 std::vector<TestCaseInfo>::const_iterator it = m_functionsInOrder.begin();
3764 std::vector<TestCaseInfo>::const_iterator itEnd = m_functionsInOrder.end();
3766 for(; it != itEnd; ++it )
3767 if( filters.shouldInclude( *it ) )
3768 matchingTestsOut.push_back( *it );
3773 std::set<TestCaseInfo> m_functions;
3774 std::vector<TestCaseInfo> m_functionsInOrder;
3775 std::vector<TestCaseInfo> m_nonHiddenFunctions;
3776 size_t m_unnamedCount;
3781 class FreeFunctionTestCase :
public SharedImpl<ITestCase> {
3784 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
3786 virtual void invoke()
const {
3791 virtual ~FreeFunctionTestCase();
3798 AutoReg::AutoReg( TestFunction
function,
3800 const char* description,
3801 const SourceLineInfo& lineInfo ) {
3802 registerTestCase(
new FreeFunctionTestCase(
function ), name, description, lineInfo );
3805 AutoReg::~AutoReg() {}
3807 void AutoReg::registerTestCase( ITestCase* testCase,
3809 const char* description,
3810 const SourceLineInfo& lineInfo ) {
3811 getMutableRegistryHub().registerTest( TestCaseInfo( testCase, name, description, lineInfo ) );
3817 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
3823 class ReporterRegistry :
public IReporterRegistry {
3827 virtual ~ReporterRegistry() {
3828 deleteAllValues( m_factories );
3831 virtual IReporter* create(
const std::string& name,
const ReporterConfig& config )
const {
3832 FactoryMap::const_iterator it = m_factories.find( name );
3833 if( it == m_factories.end() )
3835 return it->second->create( config );
3838 void registerReporter(
const std::string& name, IReporterFactory* factory ) {
3839 m_factories.insert( std::make_pair( name, factory ) );
3842 const FactoryMap& getFactories()
const {
3847 FactoryMap m_factories;
3852 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_HPP_INCLUDED
3855 #import "Foundation/Foundation.h"
3860 class ExceptionTranslatorRegistry :
public IExceptionTranslatorRegistry {
3862 ~ExceptionTranslatorRegistry() {
3863 deleteAll( m_translators );
3866 virtual void registerTranslator(
const IExceptionTranslator* translator ) {
3867 m_translators.push_back( translator );
3870 virtual std::string translateActiveException()
const {
3877 @catch (NSException *exception) {
3878 return toString( [exception description] );
3884 catch( std::exception& ex ) {
3887 catch( std::string& msg ) {
3890 catch(
const char* msg ) {
3894 return tryTranslators( m_translators.begin() );
3898 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it )
const {
3899 if( it == m_translators.end() )
3900 return "Unknown exception";
3903 return (*it)->translate();
3906 return tryTranslators( it+1 );
3911 std::vector<const IExceptionTranslator*> m_translators;
3919 class RegistryHub :
public IRegistryHub,
public IMutableRegistryHub {
3921 RegistryHub(
const RegistryHub& );
3922 void operator=(
const RegistryHub& );
3927 virtual const IReporterRegistry& getReporterRegistry()
const {
3928 return m_reporterRegistry;
3930 virtual const ITestCaseRegistry& getTestCaseRegistry()
const {
3931 return m_testCaseRegistry;
3933 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
3934 return m_exceptionTranslatorRegistry;
3938 virtual void registerReporter(
const std::string& name, IReporterFactory* factory ) {
3939 m_reporterRegistry.registerReporter( name, factory );
3941 virtual void registerTest(
const TestCaseInfo& testInfo ) {
3942 m_testCaseRegistry.registerTest( testInfo );
3944 virtual void registerTranslator(
const IExceptionTranslator* translator ) {
3945 m_exceptionTranslatorRegistry.registerTranslator( translator );
3949 TestRegistry m_testCaseRegistry;
3950 ReporterRegistry m_reporterRegistry;
3951 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
3955 inline RegistryHub*& getTheRegistryHub() {
3956 static RegistryHub* theRegistryHub = NULL;
3957 if( !theRegistryHub )
3958 theRegistryHub =
new RegistryHub();
3959 return theRegistryHub;
3963 IRegistryHub& getRegistryHub() {
3964 return *getTheRegistryHub();
3966 IMutableRegistryHub& getMutableRegistryHub() {
3967 return *getTheRegistryHub();
3970 delete getTheRegistryHub();
3971 getTheRegistryHub() = NULL;
3977 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
3983 NotImplementedException::NotImplementedException(
const SourceLineInfo& lineInfo )
3984 : m_lineInfo( lineInfo ) {
3985 std::ostringstream oss;
3986 oss << lineInfo <<
"function ";
3987 if( !lineInfo.function.empty() )
3988 oss << lineInfo.function <<
" ";
3989 oss <<
"not implemented";
3993 const char* NotImplementedException::what()
const throw() {
3994 return m_what.c_str();
4002 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
4004 #include <stdexcept>
4009 template<
typename WriterF,
size_t bufferSize=256>
4010 class StreamBufImpl :
public StreamBufBase {
4011 char data[bufferSize];
4024 int overflow(
int c ) {
4028 if( pbase() == epptr() )
4029 m_writer( std::string( 1, static_cast<char>( c ) ) );
4031 sputc( static_cast<char>( c ) );
4037 if( pbase() != pptr() ) {
4038 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
4039 setp( pbase(), epptr() );
4047 struct OutputDebugWriter {
4049 void operator()(
const std::string &str ) {
4057 class Context :
public IMutableContext {
4059 Context() : m_config( NULL ) {}
4060 Context(
const Context& );
4061 void operator=(
const Context& );
4064 virtual IResultCapture& getResultCapture() {
4065 return *m_resultCapture;
4067 virtual IRunner& getRunner() {
4070 virtual size_t getGeneratorIndex(
const std::string& fileInfo,
size_t totalSize ) {
4071 return getGeneratorsForCurrentTest()
4072 .getGeneratorInfo( fileInfo, totalSize )
4075 virtual bool advanceGeneratorsForCurrentTest() {
4076 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
4077 return generators && generators->moveNext();
4080 virtual const IConfig* getConfig()
const {
4085 virtual void setResultCapture( IResultCapture* resultCapture ) {
4086 m_resultCapture = resultCapture;
4088 virtual void setRunner( IRunner* runner ) {
4091 virtual void setConfig(
const IConfig* config ) {
4095 friend IMutableContext& getCurrentMutableContext();
4098 IGeneratorsForTest* findGeneratorsForCurrentTest() {
4099 std::string testName = getResultCapture().getCurrentTestName();
4101 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
4102 m_generatorsByTestName.find( testName );
4103 return it != m_generatorsByTestName.end()
4108 IGeneratorsForTest& getGeneratorsForCurrentTest() {
4109 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
4111 std::string testName = getResultCapture().getCurrentTestName();
4112 generators = createGeneratorsForTest();
4113 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
4120 IResultCapture* m_resultCapture;
4121 const IConfig* m_config;
4122 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
4126 Context* currentContext = NULL;
4128 IMutableContext& getCurrentMutableContext() {
4129 if( !currentContext )
4130 currentContext =
new Context();
4131 return *currentContext;
4133 IContext& getCurrentContext() {
4134 return getCurrentMutableContext();
4137 std::streambuf* createStreamBuf(
const std::string& streamName ) {
4138 if( streamName ==
"stdout" )
return std::cout.rdbuf();
4139 if( streamName ==
"stderr" )
return std::cerr.rdbuf();
4140 if( streamName ==
"debug" )
return new StreamBufImpl<OutputDebugWriter>;
4142 throw std::domain_error(
"Unknown stream: " + streamName );
4145 void cleanUpContext() {
4146 delete currentContext;
4147 currentContext = NULL;
4151 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
4154 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4158 struct ConsoleColourImpl;
4160 class TextColour : NonCopyable {
4174 ReconstructedExpression
4177 TextColour( Colours colour = None );
4178 void set( Colours colour );
4182 ConsoleColourImpl* m_impl;
4187 #ifdef CATCH_PLATFORM_WINDOWS
4189 #include <windows.h>
4195 WORD mapConsoleColour( TextColour::Colours colour ) {
4197 case TextColour::FileName:
4198 return FOREGROUND_INTENSITY;
4199 case TextColour::ResultError:
4200 return FOREGROUND_RED | FOREGROUND_INTENSITY;
4201 case TextColour::ResultSuccess:
4202 return FOREGROUND_GREEN | FOREGROUND_INTENSITY;
4203 case TextColour::Error:
4204 return FOREGROUND_RED;
4205 case TextColour::Success:
4206 return FOREGROUND_GREEN;
4207 case TextColour::OriginalExpression:
4208 return FOREGROUND_BLUE | FOREGROUND_GREEN;
4209 case TextColour::ReconstructedExpression:
4210 return FOREGROUND_RED | FOREGROUND_GREEN;
4216 struct ConsoleColourImpl {
4219 : hStdout( GetStdHandle(STD_OUTPUT_HANDLE) ),
4222 GetConsoleScreenBufferInfo( hStdout, &csbiInfo );
4223 wOldColorAttrs = csbiInfo.wAttributes;
4226 ~ConsoleColourImpl() {
4227 SetConsoleTextAttribute( hStdout, wOldColorAttrs );
4230 void set( TextColour::Colours colour ) {
4231 WORD consoleColour = Catch::mapConsoleColour( colour );
4232 if( consoleColour > 0 )
4233 SetConsoleTextAttribute( hStdout, consoleColour );
4237 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
4238 WORD wOldColorAttrs;
4241 TextColour::TextColour( Colours colour )
4242 : m_impl( new ConsoleColourImpl() )
4245 m_impl->set( colour );
4248 TextColour::~TextColour() {
4252 void TextColour::set( Colours colour ) {
4253 m_impl->set( colour );
4261 TextColour::TextColour( Colours ){}
4262 TextColour::~TextColour(){}
4263 void TextColour::set( Colours ){}
4270 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
4278 struct GeneratorInfo : IGeneratorInfo {
4280 GeneratorInfo( std::size_t size )
4286 if( ++m_currentIndex == m_size ) {
4293 std::size_t getCurrentIndex()
const {
4294 return m_currentIndex;
4298 std::size_t m_currentIndex;
4303 class GeneratorsForTest :
public IGeneratorsForTest {
4306 ~GeneratorsForTest() {
4307 deleteAll( m_generatorsInOrder );
4310 IGeneratorInfo& getGeneratorInfo(
const std::string& fileInfo, std::size_t size ) {
4311 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
4312 if( it == m_generatorsByName.end() ) {
4313 IGeneratorInfo* info =
new GeneratorInfo( size );
4314 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
4315 m_generatorsInOrder.push_back( info );
4322 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
4323 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
4324 for(; it != itEnd; ++it ) {
4325 if( (*it)->moveNext() )
4332 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
4333 std::vector<IGeneratorInfo*> m_generatorsInOrder;
4336 IGeneratorsForTest* createGeneratorsForTest()
4338 return new GeneratorsForTest();
4344 #define TWOBLUECUBES_CATCH_RESULT_INFO_HPP_INCLUDED
4348 ResultInfo::ResultInfo()
4355 m_result( ResultWas::Unknown ),
4359 ResultInfo::ResultInfo(
const char* expr,
4360 ResultWas::OfType result,
4362 const SourceLineInfo& lineInfo,
4363 const char* macroName,
4364 const char* message )
4365 : m_macroName( macroName ),
4366 m_lineInfo( lineInfo ),
4370 m_op( isNotExpression( expr ) ?
"!" :
"" ),
4371 m_message( message ),
4376 m_expr =
"!" + m_expr;
4379 ResultInfo::~ResultInfo() {}
4381 bool ResultInfo::ok()
const {
4382 return ( m_result & ResultWas::FailureBit ) != ResultWas::FailureBit;
4385 ResultWas::OfType ResultInfo::getResultType()
const {
4389 bool ResultInfo::hasExpression()
const {
4390 return !m_expr.empty();
4393 bool ResultInfo::hasMessage()
const {
4394 return !m_message.empty();
4397 std::string ResultInfo::getExpression()
const {
4401 bool ResultInfo::hasExpandedExpression()
const {
4402 return hasExpression() && getExpandedExpressionInternal() != m_expr;
4405 std::string ResultInfo::getExpandedExpression()
const {
4406 return hasExpression() ? getExpandedExpressionInternal() : std::string(
"");
4409 std::string ResultInfo::getMessage()
const {
4413 std::string ResultInfo::getFilename()
const {
4414 return m_lineInfo.file;
4417 std::size_t ResultInfo::getLine()
const {
4418 return m_lineInfo.line;
4421 std::string ResultInfo::getTestMacroName()
const {
4425 std::string ResultInfo::getExpandedExpressionInternal()
const {
4426 if( m_op ==
"" || m_isNot )
4427 return m_lhs.empty() ? m_expr : m_op + m_lhs;
4428 else if( m_op ==
"matches" )
4429 return m_lhs + " " + m_rhs;
4430 else if( m_op !=
"!" )
4432 if( m_lhs.size() + m_rhs.size() < 30 )
4433 return m_lhs + " " + m_op + " " + m_rhs;
4434 else if( m_lhs.size() < 70 && m_rhs.size() < 70 )
4435 return "\n\t" + m_lhs +
"\n\t" + m_op +
"\n\t" + m_rhs;
4437 return "\n" + m_lhs + "\n" + m_op + "\n" + m_rhs + "\n\n";
4440 return "{can't expand - use " + m_macroName + "_FALSE( " + m_expr.substr(1) + " ) instead of " + m_macroName + "( " + m_expr + " ) for better diagnostics}";
4443 bool ResultInfo::isNotExpression(
const char* expr ) {
4444 return expr && expr[0] ==
'!';
4450 #define TWOBLUECUBES_CATCH_RESULTINFO_BUILDER_HPP_INCLUDED
4454 ResultInfoBuilder::ResultInfoBuilder() {}
4456 ResultInfoBuilder::ResultInfoBuilder(
const char* expr,
4458 const SourceLineInfo& lineInfo,
4459 const char* macroName,
4460 const char* message )
4461 : ResultInfo( expr, ResultWas::Unknown, isNot, lineInfo, macroName, message )
4464 void ResultInfoBuilder::setResultType( ResultWas::OfType result ) {
4466 if( m_isNot && result == ResultWas::Ok )
4467 m_result = ResultWas::ExpressionFailed;
4468 else if( m_isNot && result == ResultWas::ExpressionFailed )
4469 m_result = ResultWas::Ok;
4474 void ResultInfoBuilder::setMessage(
const std::string& message ) {
4475 m_message = message;
4478 void ResultInfoBuilder::setLineInfo(
const SourceLineInfo& lineInfo ) {
4479 m_lineInfo = lineInfo;
4482 void ResultInfoBuilder::setLhs(
const std::string& lhs ) {
4486 void ResultInfoBuilder::setRhs(
const std::string& rhs ) {
4490 void ResultInfoBuilder::setOp(
const std::string& op ) {
4494 ResultInfoBuilder& ResultInfoBuilder::captureBoolExpression(
bool result ) {
4495 m_lhs = Catch::toString( result );
4496 m_op = m_isNot ?
"!" :
"";
4497 setResultType( result ? ResultWas::Ok : ResultWas::ExpressionFailed );
4504 #define TWOBLUECUBES_CATCH_TESTCASEINFO_HPP_INCLUDED
4508 TestCaseInfo::TestCaseInfo( ITestCase* testCase,
4510 const char* description,
4511 const SourceLineInfo& lineInfo )
4512 : m_test( testCase ),
4514 m_description( description ),
4515 m_lineInfo( lineInfo )
4518 TestCaseInfo::TestCaseInfo()
4524 TestCaseInfo::TestCaseInfo(
const TestCaseInfo& other,
const std::string& name )
4525 : m_test( other.m_test ),
4527 m_description( other.m_description ),
4528 m_lineInfo( other.m_lineInfo )
4531 TestCaseInfo::TestCaseInfo(
const TestCaseInfo& other )
4532 : m_test( other.m_test ),
4533 m_name( other.m_name ),
4534 m_description( other.m_description ),
4535 m_lineInfo( other.m_lineInfo )
4538 void TestCaseInfo::invoke()
const {
4542 const std::string& TestCaseInfo::getName()
const {
4546 const std::string& TestCaseInfo::getDescription()
const {
4547 return m_description;
4550 const SourceLineInfo& TestCaseInfo::getLineInfo()
const {
4554 bool TestCaseInfo::isHidden()
const {
4555 return m_name.size() >= 2 && m_name[0] ==
'.' && m_name[1] ==
'/';
4558 void TestCaseInfo::swap( TestCaseInfo& other ) {
4559 m_test.swap( other.m_test );
4560 m_name.swap( other.m_name );
4561 m_description.swap( other.m_description );
4562 m_lineInfo.swap( other.m_lineInfo );
4565 bool TestCaseInfo::operator == (
const TestCaseInfo& other )
const {
4566 return m_test.get() == other.m_test.get() && m_name == other.m_name;
4569 bool TestCaseInfo::operator < (
const TestCaseInfo& other )
const {
4570 return m_name < other.m_name;
4572 TestCaseInfo& TestCaseInfo::operator = (
const TestCaseInfo& other ) {
4573 TestCaseInfo temp( other );
4580 #define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED
4583 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
4587 template<
typename T>
4588 class ReporterRegistrar {
4590 class ReporterFactory :
public IReporterFactory {
4592 virtual IReporter* create(
const ReporterConfig& config )
const {
4593 return new T( config );
4596 virtual std::string getDescription()
const {
4597 return T::getDescription();
4603 ReporterRegistrar(
const std::string& name ) {
4604 getMutableRegistryHub().registerReporter( name,
new ReporterFactory() );
4609 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
4610 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name );
4614 class BasicReporter :
public SharedImpl<IReporter> {
4622 SpanInfo(
const std::string& spanName )
4627 SpanInfo(
const SpanInfo& other )
4628 : name( other.name ),
4629 emitted( other.emitted )
4637 BasicReporter(
const ReporterConfig& config )
4638 : m_config( config ),
4639 m_firstSectionInTestCase( true ),
4643 virtual ~BasicReporter();
4645 static std::string getDescription() {
4646 return "Reports test results as lines of text";
4651 void ReportCounts(
const std::string& label,
const Counts& counts,
const std::string& allPrefix =
"All " ) {
4653 m_config.stream << counts.failed <<
" of " << counts.total() <<
" " << label <<
"s failed";
4655 m_config.stream << ( counts.failed > 1 ? allPrefix : std::string(
"") ) << pluralise( counts.failed, label ) <<
" failed";
4658 void ReportCounts(
const Totals& totals,
const std::string& allPrefix =
"All " ) {
4659 if( totals.assertions.total() == 0 ) {
4660 m_config.stream <<
"No tests ran";
4662 else if( totals.assertions.failed ) {
4663 TextColour colour( TextColour::ResultError );
4664 ReportCounts(
"test case", totals.testCases, allPrefix );
4665 if( totals.testCases.failed > 0 ) {
4666 m_config.stream <<
" (";
4667 ReportCounts(
"assertion", totals.assertions, allPrefix );
4668 m_config.stream <<
")";
4672 TextColour colour( TextColour::ResultSuccess );
4673 m_config.stream << allPrefix <<
"tests passed ("
4674 << pluralise( totals.assertions.passed,
"assertion" ) <<
" in "
4675 << pluralise( totals.testCases.passed,
"test case" ) <<
")";
4681 virtual bool shouldRedirectStdout()
const {
4685 virtual void StartTesting() {
4686 m_testingSpan = SpanInfo();
4689 virtual void Aborted() {
4693 virtual void EndTesting(
const Totals& totals ) {
4696 m_config.stream <<
"\n[Testing aborted. ";
4697 ReportCounts( totals,
"The first " );
4700 m_config.stream <<
"\n[Testing completed. ";
4701 ReportCounts( totals );
4703 m_config.stream <<
"]\n" << std::endl;
4706 virtual void StartGroup(
const std::string& groupName ) {
4707 m_groupSpan = groupName;
4710 virtual void EndGroup(
const std::string& groupName,
const Totals& totals ) {
4711 if( m_groupSpan.emitted && !groupName.empty() ) {
4712 m_config.stream <<
"[End of group: '" << groupName <<
"'. ";
4713 ReportCounts( totals );
4714 m_config.stream <<
"]\n" << std::endl;
4715 m_groupSpan = SpanInfo();
4719 virtual void StartTestCase(
const TestCaseInfo& testInfo ) {
4720 m_testSpan = testInfo.getName();
4723 virtual void StartSection(
const std::string& sectionName,
const std::string& ) {
4724 m_sectionSpans.push_back( SpanInfo( sectionName ) );
4727 virtual void NoAssertionsInSection(
const std::string& sectionName ) {
4729 TextColour colour( TextColour::ResultError );
4730 m_config.stream <<
"\nNo assertions in section, '" << sectionName <<
"'\n" << std::endl;
4732 virtual void NoAssertionsInTestCase(
const std::string& testName ) {
4734 TextColour colour( TextColour::ResultError );
4735 m_config.stream <<
"\nNo assertions in test case, '" << testName <<
"'\n" << std::endl;
4738 virtual void EndSection(
const std::string& sectionName,
const Counts& assertions ) {
4740 SpanInfo& sectionSpan = m_sectionSpans.back();
4741 if( sectionSpan.emitted && !sectionSpan.name.empty() ) {
4742 m_config.stream <<
"[End of section: '" << sectionName <<
"' ";
4744 if( assertions.failed ) {
4745 TextColour colour( TextColour::ResultError );
4746 ReportCounts(
"assertion", assertions);
4749 TextColour colour( TextColour::ResultSuccess );
4750 m_config.stream << ( assertions.passed > 1 ?
"All " :
"" )
4751 << pluralise( assertions.passed,
"assertion" ) <<
" passed" ;
4753 m_config.stream <<
"]\n" << std::endl;
4755 m_sectionSpans.pop_back();
4758 virtual void Result(
const ResultInfo& resultInfo ) {
4759 if( !m_config.includeSuccessfulResults && resultInfo.getResultType() == ResultWas::Ok )
4764 if( !resultInfo.getFilename().empty() ) {
4765 TextColour colour( TextColour::FileName );
4766 m_config.stream << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
4769 if( resultInfo.hasExpression() ) {
4770 TextColour colour( TextColour::OriginalExpression );
4771 m_config.stream << resultInfo.getExpression();
4772 if( resultInfo.ok() ) {
4773 TextColour successColour( TextColour::Success );
4774 m_config.stream <<
" succeeded";
4777 TextColour errorColour( TextColour::Error );
4778 m_config.stream <<
" failed";
4781 switch( resultInfo.getResultType() ) {
4782 case ResultWas::ThrewException:
4784 TextColour colour( TextColour::Error );
4785 if( resultInfo.hasExpression() )
4786 m_config.stream <<
" with unexpected";
4788 m_config.stream <<
"Unexpected";
4789 m_config.stream <<
" exception with message: '" << resultInfo.getMessage() <<
"'";
4792 case ResultWas::DidntThrowException:
4794 TextColour colour( TextColour::Error );
4795 if( resultInfo.hasExpression() )
4796 m_config.stream <<
" because no exception was thrown where one was expected";
4798 m_config.stream <<
"No exception thrown where one was expected";
4801 case ResultWas::Info:
4802 streamVariableLengthText(
"info", resultInfo.getMessage() );
4804 case ResultWas::Warning:
4805 m_config.stream <<
"warning:\n'" << resultInfo.getMessage() <<
"'";
4807 case ResultWas::ExplicitFailure:
4809 TextColour colour( TextColour::Error );
4810 m_config.stream <<
"failed with message: '" << resultInfo.getMessage() <<
"'";
4813 case ResultWas::Unknown:
4815 case ResultWas::FailureBit:
4816 case ResultWas::ExpressionFailed:
4817 case ResultWas::Exception:
4818 if( !resultInfo.hasExpression() ) {
4819 if( resultInfo.ok() ) {
4820 TextColour colour( TextColour::Success );
4821 m_config.stream <<
" succeeded";
4824 TextColour colour( TextColour::Error );
4825 m_config.stream <<
" failed";
4831 if( resultInfo.hasExpandedExpression() ) {
4832 m_config.stream <<
" for: ";
4833 TextColour colour( TextColour::ReconstructedExpression );
4834 m_config.stream << resultInfo.getExpandedExpression();
4836 m_config.stream << std::endl;
4839 virtual void EndTestCase(
const TestCaseInfo& testInfo,
4840 const Totals& totals,
4841 const std::string& stdOut,
4842 const std::string& stdErr ) {
4843 if( !stdOut.empty() ) {
4845 streamVariableLengthText(
"stdout", stdOut );
4848 if( !stdErr.empty() ) {
4850 streamVariableLengthText(
"stderr", stdErr );
4853 if( m_testSpan.emitted ) {
4854 m_config.stream <<
"[Finished: '" << testInfo.getName() <<
"' ";
4855 ReportCounts( totals );
4856 m_config.stream <<
"]" << std::endl;
4862 void StartSpansLazily() {
4863 if( !m_testingSpan.emitted ) {
4864 if( m_config.name.empty() )
4865 m_config.stream <<
"[Started testing]" << std::endl;
4867 m_config.stream <<
"[Started testing: " << m_config.name <<
"]" << std::endl;
4868 m_testingSpan.emitted =
true;
4871 if( !m_groupSpan.emitted && !m_groupSpan.name.empty() ) {
4872 m_config.stream <<
"[Started group: '" << m_groupSpan.name <<
"']" << std::endl;
4873 m_groupSpan.emitted =
true;
4876 if( !m_testSpan.emitted ) {
4877 m_config.stream << std::endl <<
"[Running: " << m_testSpan.name <<
"]" << std::endl;
4878 m_testSpan.emitted =
true;
4881 if( !m_sectionSpans.empty() ) {
4882 SpanInfo& sectionSpan = m_sectionSpans.back();
4883 if( !sectionSpan.emitted && !sectionSpan.name.empty() ) {
4884 if( m_firstSectionInTestCase ) {
4885 m_config.stream <<
"\n";
4886 m_firstSectionInTestCase =
false;
4888 std::vector<SpanInfo>::iterator it = m_sectionSpans.begin();
4889 std::vector<SpanInfo>::iterator itEnd = m_sectionSpans.end();
4890 for(; it != itEnd; ++it ) {
4891 SpanInfo& prevSpan = *it;
4892 if( !prevSpan.emitted && !prevSpan.name.empty() ) {
4893 m_config.stream <<
"[Started section: '" << prevSpan.name <<
"']" << std::endl;
4894 prevSpan.emitted =
true;
4901 void streamVariableLengthText(
const std::string& prefix,
const std::string& text ) {
4902 std::string trimmed = trim( text );
4903 if( trimmed.find_first_of(
"\r\n" ) == std::string::npos ) {
4904 m_config.stream <<
"[" << prefix <<
": " << trimmed <<
"]\n";
4907 m_config.stream <<
"\n[" << prefix <<
"] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed
4908 <<
"\n[end of " << prefix <<
"] <<<<<<<<<<<<<<<<<<<<<<<<\n";
4913 ReporterConfig m_config;
4914 bool m_firstSectionInTestCase;
4916 SpanInfo m_testingSpan;
4917 SpanInfo m_groupSpan;
4918 SpanInfo m_testSpan;
4919 std::vector<SpanInfo> m_sectionSpans;
4926 #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
4929 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
4940 class ScopedElement {
4942 ScopedElement( XmlWriter* writer )
4943 : m_writer( writer )
4946 ScopedElement(
const ScopedElement& other )
4947 : m_writer( other.m_writer ){
4948 other.m_writer = NULL;
4953 m_writer->endElement();
4956 ScopedElement& writeText(
const std::string& text ) {
4957 m_writer->writeText( text );
4961 template<
typename T>
4962 ScopedElement& writeAttribute(
const std::string& name,
const T& attribute ) {
4963 m_writer->writeAttribute( name, attribute );
4968 mutable XmlWriter* m_writer;
4972 : m_tagIsOpen( false ),
4973 m_needsNewline( false ),
4977 XmlWriter( std::ostream& os )
4978 : m_tagIsOpen( false ),
4979 m_needsNewline( false ),
4984 while( !m_tags.empty() )
4988 XmlWriter& operator = (
const XmlWriter& other ) {
4989 XmlWriter temp( other );
4994 void swap( XmlWriter& other ) {
4995 std::swap( m_tagIsOpen, other.m_tagIsOpen );
4996 std::swap( m_needsNewline, other.m_needsNewline );
4997 std::swap( m_tags, other.m_tags );
4998 std::swap( m_indent, other.m_indent );
4999 std::swap( m_os, other.m_os );
5002 XmlWriter& startElement(
const std::string& name ) {
5004 newlineIfNecessary();
5005 stream() << m_indent <<
"<" << name;
5006 m_tags.push_back( name );
5012 ScopedElement scopedElement(
const std::string& name ) {
5013 ScopedElement scoped(
this );
5014 startElement( name );
5018 XmlWriter& endElement() {
5019 newlineIfNecessary();
5020 m_indent = m_indent.substr( 0, m_indent.size()-2 );
5023 m_tagIsOpen =
false;
5026 stream() << m_indent <<
"</" << m_tags.back() <<
">\n";
5032 XmlWriter& writeAttribute(
const std::string& name,
const std::string& attribute ) {
5033 if( !name.empty() && !attribute.empty() ) {
5034 stream() <<
" " << name <<
"=\"";
5035 writeEncodedText( attribute );
5041 XmlWriter& writeAttribute(
const std::string& name,
bool attribute ) {
5042 stream() <<
" " << name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
"\"";
5046 template<
typename T>
5047 XmlWriter& writeAttribute(
const std::string& name,
const T& attribute ) {
5049 stream() <<
" " << name <<
"=\"" << attribute <<
"\"";
5053 XmlWriter& writeText(
const std::string& text ) {
5054 if( !text.empty() ){
5055 bool tagWasOpen = m_tagIsOpen;
5058 stream() << m_indent;
5059 writeEncodedText( text );
5060 m_needsNewline =
true;
5065 XmlWriter& writeComment(
const std::string& text ) {
5067 stream() << m_indent <<
"<!--" << text <<
"-->";
5068 m_needsNewline =
true;
5072 XmlWriter& writeBlankLine() {
5080 std::ostream& stream() {
5084 void ensureTagClosed() {
5087 m_tagIsOpen =
false;
5091 void newlineIfNecessary() {
5092 if( m_needsNewline ) {
5094 m_needsNewline =
false;
5098 void writeEncodedText(
const std::string& text ) {
5099 static const char* charsToEncode =
"<&\"";
5100 std::string mtext = text;
5101 std::string::size_type pos = mtext.find_first_of( charsToEncode );
5102 while( pos != std::string::npos ) {
5103 stream() << mtext.substr( 0, pos );
5105 switch( mtext[pos] ) {
5110 stream() <<
"&";
5113 stream() <<
""";
5116 mtext = mtext.substr( pos+1 );
5117 pos = mtext.find_first_of( charsToEncode );
5123 bool m_needsNewline;
5124 std::vector<std::string> m_tags;
5125 std::string m_indent;
5131 class XmlReporter :
public SharedImpl<IReporter> {
5133 XmlReporter(
const ReporterConfig& config ) : m_config( config ) {}
5135 static std::string getDescription() {
5136 return "Reports test results as an XML document";
5138 virtual ~XmlReporter();
5142 virtual bool shouldRedirectStdout()
const {
5146 virtual void StartTesting() {
5147 m_xml = XmlWriter( m_config.stream );
5148 m_xml.startElement(
"Catch" );
5149 if( !m_config.name.empty() )
5150 m_xml.writeAttribute(
"name", m_config.name );
5153 virtual void EndTesting(
const Totals& totals ) {
5154 m_xml.scopedElement(
"OverallResults" )
5155 .writeAttribute(
"successes", totals.assertions.passed )
5156 .writeAttribute(
"failures", totals.assertions.failed );
5160 virtual void StartGroup(
const std::string& groupName ) {
5161 m_xml.startElement(
"Group" )
5162 .writeAttribute(
"name", groupName );
5165 virtual void EndGroup(
const std::string&,
const Totals& totals ) {
5166 m_xml.scopedElement(
"OverallResults" )
5167 .writeAttribute(
"successes", totals.assertions.passed )
5168 .writeAttribute(
"failures", totals.assertions.failed );
5172 virtual void StartSection(
const std::string& sectionName,
const std::string& description ) {
5173 m_xml.startElement(
"Section" )
5174 .writeAttribute(
"name", sectionName )
5175 .writeAttribute(
"description", description );
5177 virtual void NoAssertionsInSection(
const std::string& ) {}
5178 virtual void NoAssertionsInTestCase(
const std::string& ) {}
5180 virtual void EndSection(
const std::string& ,
const Counts& assertions ) {
5181 m_xml.scopedElement(
"OverallResults" )
5182 .writeAttribute(
"successes", assertions.passed )
5183 .writeAttribute(
"failures", assertions.failed );
5187 virtual void StartTestCase(
const Catch::TestCaseInfo& testInfo ) {
5188 m_xml.startElement(
"TestCase" ).writeAttribute(
"name", testInfo.getName() );
5189 m_currentTestSuccess =
true;
5192 virtual void Result(
const Catch::ResultInfo& resultInfo ) {
5193 if( !m_config.includeSuccessfulResults && resultInfo.getResultType() == ResultWas::Ok )
5196 if( resultInfo.hasExpression() ) {
5197 m_xml.startElement(
"Expression" )
5198 .writeAttribute(
"success", resultInfo.ok() )
5199 .writeAttribute(
"filename", resultInfo.getFilename() )
5200 .writeAttribute(
"line", resultInfo.getLine() );
5202 m_xml.scopedElement(
"Original" )
5203 .writeText( resultInfo.getExpression() );
5204 m_xml.scopedElement(
"Expanded" )
5205 .writeText( resultInfo.getExpandedExpression() );
5206 m_currentTestSuccess &= resultInfo.ok();
5209 switch( resultInfo.getResultType() ) {
5210 case ResultWas::ThrewException:
5211 m_xml.scopedElement(
"Exception" )
5212 .writeAttribute(
"filename", resultInfo.getFilename() )
5213 .writeAttribute(
"line", resultInfo.getLine() )
5214 .writeText( resultInfo.getMessage() );
5215 m_currentTestSuccess =
false;
5217 case ResultWas::Info:
5218 m_xml.scopedElement(
"Info" )
5219 .writeText( resultInfo.getMessage() );
5221 case ResultWas::Warning:
5222 m_xml.scopedElement(
"Warning" )
5223 .writeText( resultInfo.getMessage() );
5225 case ResultWas::ExplicitFailure:
5226 m_xml.scopedElement(
"Failure" )
5227 .writeText( resultInfo.getMessage() );
5228 m_currentTestSuccess =
false;
5230 case ResultWas::Unknown:
5232 case ResultWas::FailureBit:
5233 case ResultWas::ExpressionFailed:
5234 case ResultWas::Exception:
5235 case ResultWas::DidntThrowException:
5238 if( resultInfo.hasExpression() )
5242 virtual void Aborted() {
5246 virtual void EndTestCase(
const Catch::TestCaseInfo&,
const Totals&,
const std::string&,
const std::string& ) {
5247 m_xml.scopedElement(
"OverallResult" ).writeAttribute(
"success", m_currentTestSuccess );
5252 ReporterConfig m_config;
5253 bool m_currentTestSuccess;
5260 #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
5264 class JunitReporter :
public SharedImpl<IReporter> {
5267 std::string m_element;
5268 std::string m_resultType;
5269 std::string m_message;
5270 std::string m_content;
5273 struct TestCaseStats {
5275 TestCaseStats(
const std::string& name = std::string() ) :m_name( name ){}
5277 double m_timeInSeconds;
5278 std::string m_status;
5279 std::string m_className;
5281 std::vector<TestStats> m_testStats;
5286 Stats(
const std::string& name = std::string() )
5287 : m_testsCount( 0 ),
5288 m_failuresCount( 0 ),
5289 m_disabledCount( 0 ),
5291 m_timeInSeconds( 0 ),
5295 std::size_t m_testsCount;
5296 std::size_t m_failuresCount;
5297 std::size_t m_disabledCount;
5298 std::size_t m_errorsCount;
5299 double m_timeInSeconds;
5302 std::vector<TestCaseStats> m_testCaseStats;
5306 JunitReporter(
const ReporterConfig& config )
5307 : m_config( config ),
5308 m_testSuiteStats(
"AllTests" ),
5309 m_currentStats( &m_testSuiteStats )
5311 virtual ~JunitReporter();
5313 static std::string getDescription() {
5314 return "Reports test results in an XML format that looks like Ant's junitreport target";
5319 virtual bool shouldRedirectStdout()
const {
5323 virtual void StartTesting(){}
5325 virtual void StartGroup(
const std::string& groupName ) {
5326 m_statsForSuites.push_back( Stats( groupName ) );
5327 m_currentStats = &m_statsForSuites.back();
5330 virtual void EndGroup(
const std::string&,
const Totals& totals ) {
5331 m_currentStats->m_testsCount = totals.assertions.total();
5332 m_currentStats = &m_testSuiteStats;
5335 virtual void StartSection(
const std::string&,
const std::string& ){}
5337 virtual void NoAssertionsInSection(
const std::string& ) {}
5338 virtual void NoAssertionsInTestCase(
const std::string& ) {}
5340 virtual void EndSection(
const std::string&,
const Counts& ) {}
5342 virtual void StartTestCase(
const Catch::TestCaseInfo& testInfo ) {
5343 m_currentStats->m_testCaseStats.push_back( TestCaseStats( testInfo.getName() ) );
5346 virtual void Result(
const Catch::ResultInfo& resultInfo ) {
5347 if( resultInfo.getResultType() != ResultWas::Ok || m_config.includeSuccessfulResults ) {
5348 TestCaseStats& testCaseStats = m_currentStats->m_testCaseStats.back();
5350 std::ostringstream oss;
5351 if( !resultInfo.getMessage().empty() )
5352 oss << resultInfo.getMessage() <<
" at ";
5353 oss << SourceLineInfo( resultInfo.getFilename(), resultInfo.getLine() );
5354 stats.m_content = oss.str();
5355 stats.m_message = resultInfo.getExpandedExpression();
5356 stats.m_resultType = resultInfo.getTestMacroName();
5358 switch( resultInfo.getResultType() ) {
5359 case ResultWas::ThrewException:
5360 stats.m_element =
"error";
5361 m_currentStats->m_errorsCount++;
5363 case ResultWas::Info:
5364 stats.m_element =
"info";
5366 case ResultWas::Warning:
5367 stats.m_element =
"warning";
5369 case ResultWas::ExplicitFailure:
5370 stats.m_element =
"failure";
5371 m_currentStats->m_failuresCount++;
5373 case ResultWas::ExpressionFailed:
5374 stats.m_element =
"failure";
5375 m_currentStats->m_failuresCount++;
5378 stats.m_element =
"success";
5380 case ResultWas::Unknown:
5381 case ResultWas::FailureBit:
5382 case ResultWas::Exception:
5383 case ResultWas::DidntThrowException:
5386 testCaseStats.m_testStats.push_back( stats );
5390 virtual void EndTestCase(
const Catch::TestCaseInfo&,
const Totals&,
const std::string& stdOut,
const std::string& stdErr ) {
5391 if( !stdOut.empty() )
5392 m_stdOut << stdOut <<
"\n";
5393 if( !stdErr.empty() )
5394 m_stdErr << stdErr <<
"\n";
5397 virtual void Aborted() {
5401 virtual void EndTesting(
const Totals& ) {
5402 std::ostream& str = m_config.stream;
5404 XmlWriter xml( str );
5406 if( m_statsForSuites.size() > 0 )
5407 xml.startElement(
"testsuites" );
5409 std::vector<Stats>::const_iterator it = m_statsForSuites.begin();
5410 std::vector<Stats>::const_iterator itEnd = m_statsForSuites.end();
5412 for(; it != itEnd; ++it ) {
5413 XmlWriter::ScopedElement e = xml.scopedElement(
"testsuite" );
5414 xml.writeAttribute(
"name", it->m_name );
5415 xml.writeAttribute(
"errors", it->m_errorsCount );
5416 xml.writeAttribute(
"failures", it->m_failuresCount );
5417 xml.writeAttribute(
"tests", it->m_testsCount );
5418 xml.writeAttribute(
"hostname",
"tbd" );
5419 xml.writeAttribute(
"time",
"tbd" );
5420 xml.writeAttribute(
"timestamp",
"tbd" );
5422 OutputTestCases( xml, *it );
5425 xml.scopedElement(
"system-out" ).writeText( trim( m_stdOut.str() ) );
5426 xml.scopedElement(
"system-err" ).writeText( trim( m_stdErr.str() ) );
5430 void OutputTestCases( XmlWriter& xml,
const Stats& stats ) {
5431 std::vector<TestCaseStats>::const_iterator it = stats.m_testCaseStats.begin();
5432 std::vector<TestCaseStats>::const_iterator itEnd = stats.m_testCaseStats.end();
5433 for(; it != itEnd; ++it ) {
5434 xml.writeBlankLine();
5435 xml.writeComment(
"Test case" );
5437 XmlWriter::ScopedElement e = xml.scopedElement(
"testcase" );
5438 xml.writeAttribute(
"classname", it->m_className );
5439 xml.writeAttribute(
"name", it->m_name );
5440 xml.writeAttribute(
"time",
"tbd" );
5442 OutputTestResult( xml, *it );
5446 void OutputTestResult( XmlWriter& xml,
const TestCaseStats& stats ) {
5447 std::vector<TestStats>::const_iterator it = stats.m_testStats.begin();
5448 std::vector<TestStats>::const_iterator itEnd = stats.m_testStats.end();
5449 for(; it != itEnd; ++it ) {
5450 if( it->m_element !=
"success" ) {
5451 XmlWriter::ScopedElement e = xml.scopedElement( it->m_element );
5453 xml.writeAttribute(
"message", it->m_message );
5454 xml.writeAttribute(
"type", it->m_resultType );
5455 if( !it->m_content.empty() )
5456 xml.writeText( it->m_content );
5462 ReporterConfig m_config;
5463 bool m_currentTestSuccess;
5465 Stats m_testSuiteStats;
5466 Stats* m_currentStats;
5467 std::vector<Stats> m_statsForSuites;
5468 std::ostringstream m_stdOut;
5469 std::ostringstream m_stdErr;
5475 NonCopyable::~NonCopyable() {}
5476 IShared::~IShared() {}
5477 StreamBufBase::~StreamBufBase() {}
5478 IContext::~IContext() {}
5479 IResultCapture::~IResultCapture() {}
5480 ITestCase::~ITestCase() {}
5481 ITestCaseRegistry::~ITestCaseRegistry() {}
5482 IRegistryHub::~IRegistryHub() {}
5483 IMutableRegistryHub::~IMutableRegistryHub() {}
5484 IExceptionTranslator::~IExceptionTranslator() {}
5485 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
5486 IReporter::~IReporter() {}
5487 IReporterFactory::~IReporterFactory() {}
5488 IReporterRegistry::~IReporterRegistry() {}
5489 BasicReporter::~BasicReporter() {}
5490 IRunner::~IRunner() {}
5491 IMutableContext::~IMutableContext() {}
5492 IConfig::~IConfig() {}
5493 XmlReporter::~XmlReporter() {}
5494 JunitReporter::~JunitReporter() {}
5495 TestRegistry::~TestRegistry() {}
5496 FreeFunctionTestCase::~FreeFunctionTestCase() {}
5497 IGeneratorInfo::~IGeneratorInfo() {}
5498 IGeneratorsForTest::~IGeneratorsForTest() {}
5500 void Config::dummy() {}
5502 INTERNAL_CATCH_REGISTER_REPORTER(
"basic", BasicReporter )
5503 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
5504 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
5509 #pragma clang diagnostic pop
5513 #ifdef CATCH_CONFIG_MAIN
5515 #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
5520 int main (
int argc,
char *
const argv[]) {
5521 return Catch::Main( argc, argv );
5527 int main (
int argc,
char *
const argv[]) {
5528 #if !CATCH_ARC_ENABLED
5529 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
5532 Catch::registerTestMethods();
5533 int result = Catch::Main( argc, (
char*
const*)argv );
5535 #if !CATCH_ARC_ENABLED
5549 #ifdef CATCH_CONFIG_PREFIX_ALL
5551 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "CATCH_REQUIRE" )
5552 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "CATCH_REQUIRE_FALSE" )
5554 #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "CATCH_REQUIRE_THROWS" )
5555 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "CATCH_REQUIRE_THROWS_AS" )
5556 #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "CATCH_REQUIRE_NOTHROW" )
5558 #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CATCH_CHECK" )
5559 #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CATCH_CHECK_FALSE" )
5560 #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CATCH_CHECKED_IF" )
5561 #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CATCH_CHECKED_ELSE" )
5563 #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CATCH_CHECK_THROWS" )
5564 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CATCH_CHECK_THROWS_AS" )
5565 #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CATCH_CHECK_NOTHROW" )
5567 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CATCH_CHECK_THAT" )
5568 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "CATCH_REQUIRE_THAT" )
5570 #define CATCH_INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "CATCH_INFO" )
5571 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "CATCH_WARN" )
5572 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "CATCH_FAIL" )
5573 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, false, "CATCH_SUCCEED" )
5574 #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
5575 #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CATCH_CAPTURE" )
5577 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
5579 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
5580 #define CATCH_TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
5581 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
5582 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
5584 #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
5586 #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
5595 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, false, true, "REQUIRE" )
5596 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, true, "REQUIRE_FALSE" )
5598 #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., true, "REQUIRE_THROWS" )
5599 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, true, "REQUIRE_THROWS_AS" )
5600 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, true, "REQUIRE_NOTHROW" )
5602 #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, false, false, "CHECK" )
5603 #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, true, false, "CHECK_FALSE" )
5604 #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, false, false, "CHECKED_IF" )
5605 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, false, false, "CHECKED_ELSE" )
5607 #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., false, "CHECK_THROWS" )
5608 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, false, "CHECK_THROWS_AS" )
5609 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, false, "CHECK_NOTHROW" )
5611 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, false, "CHECK_THAT" )
5612 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, true, "REQUIRE_THAT" )
5614 #define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, false, "INFO" )
5615 #define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, false, "WARN" )
5616 #define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, true, "FAIL" )
5617 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, false, "SUCCEED" )
5618 #define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg )
5619 #define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, false, "CAPTURE" )
5621 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
5623 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
5624 #define TEST_CASE_NORETURN( name, description ) INTERNAL_CATCH_TESTCASE_NORETURN( name, description )
5625 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "Anonymous test case" )
5626 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
5628 #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
5630 #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
5634 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
5636 using Catch::Detail::Approx;
5639 #pragma clang diagnostic pop
5642 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED