11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
14 #define TWOBLUECUBES_CATCH_HPP_INCLUDED
17 #pragma clang diagnostic ignored "-Wglobal-constructors"
18 #pragma clang diagnostic ignored "-Wvariadic-macros"
19 #pragma clang diagnostic ignored "-Wc99-extensions"
20 #pragma clang diagnostic push
21 #pragma clang diagnostic ignored "-Wpadded"
25 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
28 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
30 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
31 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
32 #define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
34 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
35 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
42 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
48 #if __has_feature(cxx_nullptr)
50 #define CATCH_CONFIG_CPP11_NULLPTR
60 #if (__BORLANDC__ > 0x582 )
64 #endif // __BORLANDC__
68 #ifdef __EDG_VERSION__
70 #if (__EDG_VERSION__ > 238 )
74 #endif // __EDG_VERSION__
80 #if (__DMC__ > 0x840 )
92 #if (__GNUC_MINOR__ >= 96 )
100 #endif // __GNUC__ < 3
102 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
104 #define CATCH_CONFIG_CPP11_NULLPTR
113 #if (_MSC_VER >= 1310 ) // (VC++ 7.0+)
120 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
121 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
122 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
123 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
125 #ifndef CATCH_CONFIG_NO_VARIADIC_MACROS
126 #define CATCH_CONFIG_VARIADIC_MACROS
146 return value ? &SafeBool::trueValue : 0;
149 void trueValue()
const {}
152 template<
typename ContainerT>
154 typename ContainerT::const_iterator it = container.begin();
155 typename ContainerT::const_iterator itEnd = container.end();
156 for(; it != itEnd; ++it )
159 template<
typename AssociativeContainerT>
161 typename AssociativeContainerT::const_iterator it = container.begin();
162 typename AssociativeContainerT::const_iterator itEnd = container.end();
163 for(; it != itEnd; ++it )
167 bool startsWith( std::string
const& s, std::string
const& prefix );
168 bool endsWith( std::string
const& s, std::string
const& suffix );
169 bool contains( std::string
const& s, std::string
const& infix );
171 std::string
toLower( std::string
const& s );
172 std::string
trim( std::string
const& str );
175 pluralise( std::size_t count, std::string
const& label );
198 inline bool isTrue(
bool value ){
return value; }
200 void throwLogicError( std::string
const& message, SourceLineInfo
const& locationInfo );
208 return std::string();
217 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
218 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
231 virtual const char*
what()
const throw();
241 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
244 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
247 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
255 virtual bool moveNext() = 0;
256 virtual std::size_t getCurrentIndex()
const = 0;
262 virtual IGeneratorInfo& getGeneratorInfo( std::string
const& fileInfo, std::size_t size ) = 0;
263 virtual bool moveNext() = 0;
271 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
274 #pragma clang diagnostic push
275 #pragma clang diagnostic ignored "-Wpadded"
291 Ptr(
Ptr const& other ) : m_p( other.m_p ){
314 void swap(
Ptr& other ) { std::swap( m_p, other.m_p ); }
315 T*
get() {
return m_p; }
316 const T*
get()
const{
return m_p; }
319 bool operator !()
const {
return m_p == NULL; }
328 virtual void addRef()
const = 0;
329 virtual void release()
const = 0;
332 template<
typename T = IShared>
351 #pragma clang diagnostic pop
362 struct IResultCapture;
364 struct IGeneratorsForTest;
372 virtual IRunner& getRunner() = 0;
373 virtual size_t getGeneratorIndex( std::string
const& fileInfo,
size_t totalSize ) = 0;
374 virtual bool advanceGeneratorsForCurrentTest() = 0;
381 virtual void setResultCapture(
IResultCapture* resultCapture ) = 0;
382 virtual void setRunner(
IRunner* runner ) = 0;
394 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
397 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
403 class TestCaseFilters;
406 virtual void invoke ()
const = 0;
415 virtual std::vector<TestCase>
const& getAllTests()
const = 0;
416 virtual std::vector<TestCase> getMatchingTestCases( std::string
const& rawTestSpec )
const = 0;
436 void (C::*m_method)();
442 NameAndDesc(
const char* _name =
"",
const char* _description=
"" )
443 : name( _name ), description( _description )
458 char const* className,
467 void registerTestCase(
ITestCase* testCase,
468 char const* className,
476 void operator= (
AutoReg const& );
481 #ifdef CATCH_CONFIG_VARIADIC_MACROS
482 #define INTERNAL_CATCH_TESTCASE( ... ) \
484 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
485 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
486 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
489 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
490 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
493 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
495 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
498 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
500 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
503 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
505 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
506 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
507 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
510 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
511 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
514 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
516 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
519 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
521 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
526 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
529 #define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED
532 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
535 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED
538 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
541 #define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED
548 static const bool value =
true;
553 static const bool value =
false;
558 #ifdef CATCH_CONFIG_SFINAE
560 template<
bool>
struct NotABooleanExpression;
562 template<
bool c>
struct If : NotABooleanExpression<c> {};
563 template<>
struct If<true> : TrueType {};
564 template<>
struct If<false> : FalseType {};
566 template<
int size>
struct SizedIf;
567 template<>
struct SizedIf<sizeof(TrueType)> : TrueType {};
568 template<>
struct SizedIf<sizeof(FalseType)> : FalseType {};
570 #endif // CATCH_CONFIG_SFINAE
581 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
583 #import <Foundation/Foundation.h>
586 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
588 #define CATCH_ARC_ENABLED 0
591 void arcSafeRelease( NSObject* obj );
592 id performOptionalSelector(
id obj,
SEL sel );
594 #if !CATCH_ARC_ENABLED
595 inline void arcSafeRelease( NSObject* obj ) {
598 inline id performOptionalSelector(
id obj,
SEL sel ) {
599 if( [obj respondsToSelector: sel] )
600 return [obj performSelector: sel];
603 #define CATCH_UNSAFE_UNRETAINED
604 #define CATCH_ARC_STRONG
606 inline void arcSafeRelease( NSObject* ){}
607 inline id performOptionalSelector(
id obj,
SEL sel ) {
609 #pragma clang diagnostic push
610 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
612 if( [obj respondsToSelector: sel] )
613 return [obj performSelector: sel];
615 #pragma clang diagnostic pop
619 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
620 #define CATCH_ARC_STRONG __strong
631 #ifdef CATCH_CONFIG_SFINAE
634 class IsStreamInsertableHelper {
635 template<
int N>
struct TrueIfSizeable :
TrueType {};
637 template<
typename T2>
638 static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
642 typedef SizedIf<sizeof(dummy((T*)0))> type;
651 template<
typename T>
BorgType( T
const& );
661 static std::ostream &
s;
671 static std::string
convert( T
const& ) {
return "{?}"; }
677 static std::string
convert( T
const& _value ) {
678 std::ostringstream oss;
690 unsigned char bytes[
sizeof(T)];
695 std::ostringstream oss;
697 for(
unsigned char* cp = bytes; cp < bytes+
sizeof(T); ++cp )
698 oss << std::hex << std::setw(2) << std::setfill(
'0') << (
unsigned int)*cp;
705 std::string
toString( T
const& value );
722 template<
typename R,
typename C>
733 template<
typename InputIterator>
734 std::string
rangeToString( InputIterator first, InputIterator last );
737 template<
typename T,
typename Allocator>
739 static std::string
convert( std::vector<T,Allocator>
const& v ) {
765 inline std::string
toString( std::string
const& value ) {
766 return "\"" + value +
"\"";
769 inline std::string
toString( std::wstring
const& value ) {
770 std::ostringstream oss;
772 for(
size_t i = 0; i < value.size(); ++i )
773 oss << static_cast<char>( value[i] <= 0xff ? value[i] :
'?');
778 inline std::string
toString(
const char*
const value ) {
779 return value ?
Catch::toString( std::string( value ) ) : std::string(
"{null string}" );
787 std::ostringstream oss;
792 inline std::string
toString(
unsigned long value ) {
793 std::ostringstream oss;
795 oss <<
"0x" << std::hex << value;
801 inline std::string
toString(
unsigned int value ) {
802 return toString( static_cast<unsigned long>( value ) );
805 inline std::string
toString(
const double value ) {
806 std::ostringstream oss;
807 oss << std::setprecision( 10 )
810 std::string d = oss.str();
811 std::size_t i = d.find_last_not_of(
'0' );
812 if( i != std::string::npos && i != d.size()-1 ) {
815 d = d.substr( 0, i+1 );
821 return value ?
"true" :
"false";
826 ?
toString( static_cast<unsigned int>( value ) )
831 return toString( static_cast<char>( value ) );
834 inline std::string
toString(
unsigned char value ) {
835 return toString( static_cast<char>( value ) );
838 #ifdef CATCH_CONFIG_CPP11_NULLPTR
839 inline std::string
toString( std::nullptr_t ) {
845 inline std::string
toString( NSString
const *
const& nsstring ) {
848 return std::string(
"@\"" ) + [nsstring UTF8String] +
"\"";
850 inline std::string
toString( NSString * CATCH_ARC_STRONG
const& nsstring ) {
853 return std::string(
"@\"" ) + [nsstring UTF8String] +
"\"";
855 inline std::string
toString( NSObject*
const& nsObject ) {
856 return toString( [nsObject description] );
861 template<
typename InputIterator>
863 std::ostringstream oss;
865 if( first != last ) {
867 for( ++first ; first != last ; ++first ) {
879 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
883 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
896 ExpressionFailed = FailureBit | 1,
897 ExplicitFailure = FailureBit | 2,
899 Exception = 0x100 | FailureBit,
901 ThrewException = Exception | 1,
902 DidntThrowException = Exception | 2
925 ContinueOnFailure = 0x01,
948 std::string
const& _capturedExpression,
973 bool succeeded()
const;
975 bool hasExpression()
const;
976 bool hasMessage()
const;
977 std::string getExpression()
const;
978 std::string getExpressionInMacro()
const;
979 bool hasExpandedExpression()
const;
980 std::string getExpandedExpression()
const;
981 std::string getMessage()
const;
983 std::string getTestMacroName()
const;
993 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
996 #pragma warning(push)
997 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1001 namespace Internal {
1020 template<
typename T>
1021 inline T&
opCast(T
const& t) {
return const_cast<T&
>(t); }
1024 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1025 inline std::nullptr_t
opCast(std::nullptr_t) {
return nullptr; }
1026 #endif // CATCH_CONFIG_CPP11_NULLPTR
1030 template<
typename T1,
typename T2, Operator Op>
1033 template<
typename T1,
typename T2>
1039 template<
typename T1,
typename T2>
1045 template<
typename T1,
typename T2>
1051 template<
typename T1,
typename T2>
1057 template<
typename T1,
typename T2>
1063 template<
typename T1,
typename T2>
1070 template<Operator Op,
typename T1,
typename T2>
1079 template<Operator Op,
typename T1,
typename T2>
1085 template<Operator Op>
bool compare(
unsigned int lhs,
int rhs ) {
1086 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1088 template<Operator Op>
bool compare(
unsigned long lhs,
int rhs ) {
1089 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1091 template<Operator Op>
bool compare(
unsigned char lhs,
int rhs ) {
1092 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1096 template<Operator Op>
bool compare(
unsigned int lhs,
long rhs ) {
1097 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1099 template<Operator Op>
bool compare(
unsigned long lhs,
long rhs ) {
1100 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1102 template<Operator Op>
bool compare(
unsigned char lhs,
long rhs ) {
1103 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1107 template<Operator Op>
bool compare(
int lhs,
unsigned int rhs ) {
1108 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1110 template<Operator Op>
bool compare(
int lhs,
unsigned long rhs ) {
1111 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1113 template<Operator Op>
bool compare(
int lhs,
unsigned char rhs ) {
1114 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1118 template<Operator Op>
bool compare(
long lhs,
unsigned int rhs ) {
1119 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1121 template<Operator Op>
bool compare(
long lhs,
unsigned long rhs ) {
1122 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1124 template<Operator Op>
bool compare(
long lhs,
unsigned char rhs ) {
1125 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1129 template<Operator Op,
typename T>
bool compare(
long lhs, T* rhs ) {
1132 template<Operator Op,
typename T>
bool compare( T* lhs,
long rhs ) {
1137 template<Operator Op,
typename T>
bool compare(
int lhs, T* rhs ) {
1140 template<Operator Op,
typename T>
bool compare( T* lhs,
int rhs ) {
1144 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1146 template<Operator Op,
typename T>
bool compare( std::nullptr_t, T* rhs ) {
1147 return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
1149 template<Operator Op,
typename T>
bool compare( T* lhs, std::nullptr_t ) {
1150 return Evaluator<T*, T*, Op>::evaluate( lhs, NULL );
1152 #endif // CATCH_CONFIG_CPP11_NULLPTR
1158 #pragma warning(pop)
1163 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1182 template<
typename T>
1188 std::string reconstructExpression(
AssertionInfo const& info )
const;
1192 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT
const& );
1193 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT
const& );
1197 struct ExprComponents {
1200 std::string lhs, rhs, op;
1202 std::ostringstream m_stream;
1211 template<
typename T>
1218 template<
typename RhsT>
1220 return captureExpression<Internal::IsEqualTo>( rhs );
1223 template<
typename RhsT>
1225 return captureExpression<Internal::IsNotEqualTo>( rhs );
1228 template<
typename RhsT>
1230 return captureExpression<Internal::IsLessThan>( rhs );
1233 template<
typename RhsT>
1235 return captureExpression<Internal::IsGreaterThan>( rhs );
1238 template<
typename RhsT>
1240 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1243 template<
typename RhsT>
1245 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1249 return captureExpression<Internal::IsEqualTo>( rhs );
1253 return captureExpression<Internal::IsNotEqualTo>( rhs );
1257 bool value = m_lhs ?
true :
false;
1266 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator + ( RhsT
const& );
1267 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT
const& );
1268 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT
const& );
1269 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT
const& );
1270 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT
const& );
1271 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT
const& );
1274 template<Internal::Operator Op,
typename RhsT>
1284 ExpressionResultBuilder m_result;
1296 template<
typename T>
1309 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1333 static unsigned int globalCount;
1340 : m_info( macroName, lineInfo, type )
1343 template<
typename T>
1364 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1371 class ExpressionResultBuilder;
1372 class AssertionResult;
1373 struct AssertionInfo;
1376 class ScopedMessageBuilder;
1384 virtual bool sectionStarted(
SectionInfo const& sectionInfo,
1385 Counts& assertions ) = 0;
1386 virtual void sectionEnded(
SectionInfo const& name,
Counts const& assertions,
double _durationInSeconds ) = 0;
1387 virtual void pushScopedMessage(
MessageInfo const& message ) = 0;
1388 virtual void popScopedMessage(
MessageInfo const& message ) = 0;
1390 virtual bool shouldDebugBreak()
const = 0;
1394 virtual std::string getCurrentTestName()
const = 0;
1400 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
1403 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1405 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1406 #define CATCH_PLATFORM_MAC
1407 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1408 #define CATCH_PLATFORM_IPHONE
1409 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1410 #define CATCH_PLATFORM_WINDOWS
1421 #ifdef CATCH_PLATFORM_MAC
1426 #if defined(__ppc64__) || defined(__ppc__)
1427 #define CATCH_BREAK_INTO_DEBUGGER() \
1428 if( Catch::isDebuggerActive() ) { \
1429 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1430 : : : "memory","r0","r3","r4" ); \
1433 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1437 #elif defined(_MSC_VER)
1438 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
1439 #elif defined(__MINGW32__)
1440 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
1441 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
1444 #ifndef CATCH_BREAK_INTO_DEBUGGER
1445 #define CATCH_BREAK_INTO_DEBUGGER() Catch::isTrue( true );
1449 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
1456 struct ITestCaseRegistry;
1457 struct IExceptionTranslatorRegistry;
1458 struct IExceptionTranslator;
1459 struct IReporterRegistry;
1460 struct IReporterFactory;
1465 virtual IReporterRegistry
const& getReporterRegistry()
const = 0;
1472 virtual void registerReporter( std::string
const& name, IReporterFactory* factory ) = 0;
1473 virtual void registerTest(
TestCase const& testInfo ) = 0;
1485 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
1513 virtual bool allowThrows()
const = 0;
1514 virtual std::ostream& stream()
const = 0;
1515 virtual std::string name()
const = 0;
1516 virtual bool includeSuccessfulResults()
const = 0;
1517 virtual bool shouldDebugBreak()
const = 0;
1518 virtual bool warnAboutMissingAssertions()
const = 0;
1519 virtual int abortAfter()
const = 0;
1532 template<
typename MatcherT>
1534 std::string
const& matcherCallAsString ) {
1535 std::string matcherAsString = matcher.toString();
1536 if( matcherAsString ==
"{?}" )
1537 matcherAsString = matcherCallAsString;
1539 .
setRhs( matcherAsString )
1540 .
setOp(
"matches" );
1543 template<
typename MatcherT,
typename ArgT>
1546 std::string
const& matcherCallAsString ) {
1552 template<
typename MatcherT,
typename ArgT>
1555 std::string
const& matcherCallAsString ) {
1566 #define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo )
1569 #define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \
1570 if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \
1571 if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \
1572 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \
1573 if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \
1574 Catch::isTrue( false && originalExpr ); \
1578 #define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \
1579 Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition );
1582 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
1584 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
1586 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
1587 } catch( Catch::TestFailureException& ) { \
1590 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
1591 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \
1593 } while( Catch::isTrue( false ) )
1596 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
1597 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
1598 if( Catch::getResultCapture().getLastResult()->succeeded() )
1601 #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
1602 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
1603 if( !Catch::getResultCapture().getLastResult()->succeeded() )
1606 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
1608 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
1611 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
1614 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \
1616 } while( Catch::isTrue( false ) )
1619 #define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
1621 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \
1623 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
1626 catch( Catch::TestFailureException& ) { \
1629 catch( exceptionType ) { \
1630 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \
1634 #define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \
1636 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
1637 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
1638 } while( Catch::isTrue( false ) )
1641 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
1643 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
1644 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \
1646 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
1647 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
1649 } while( Catch::isTrue( false ) )
1652 #ifdef CATCH_CONFIG_VARIADIC_MACROS
1653 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
1655 INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \
1656 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << __VA_ARGS__ +::Catch::StreamEndStop(), resultDisposition, true ) \
1657 } while( Catch::isTrue( false ) )
1659 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
1661 INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \
1662 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \
1663 } while( Catch::isTrue( false ) )
1667 #define INTERNAL_CATCH_INFO( log, macroName ) \
1668 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
1671 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
1673 INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \
1675 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
1676 } catch( Catch::TestFailureException& ) { \
1679 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \
1680 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \
1682 } while( Catch::isTrue( false ) )
1685 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
1688 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
1694 std::string
const& _description,
1697 description( _description ),
1698 lineInfo( _lineInfo )
1709 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1731 return passed + failed;
1748 Totals diff = *
this - prevTotals;
1768 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
1770 #ifdef CATCH_PLATFORM_WINDOWS
1771 typedef unsigned long long uint64_t;
1782 unsigned int getElapsedNanoseconds()
const;
1783 unsigned int getElapsedMilliseconds()
const;
1784 double getElapsedSeconds()
const;
1799 std::string
const& name,
1800 std::string
const& description =
"" );
1812 bool m_sectionIncluded;
1818 #ifdef CATCH_CONFIG_VARIADIC_MACROS
1819 #define INTERNAL_CATCH_SECTION( ... ) \
1820 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
1822 #define INTERNAL_CATCH_SECTION( name, desc ) \
1823 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) )
1827 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
1836 template<
typename T>
1839 virtual T getValue( std::size_t index )
const = 0;
1840 virtual std::size_t size ()
const = 0;
1843 template<
typename T>
1849 return m_from+
static_cast<int>( index );
1853 return static_cast<std::size_t
>( 1+m_to-m_from );
1862 template<
typename T>
1868 m_values.push_back( value );
1872 return m_values[index];
1876 return m_values.size();
1880 std::vector<T> m_values;
1883 template<
typename T>
1890 : m_fileInfo( other.m_fileInfo ),
1897 m_fileInfo = fileInfo;
1905 operator T ()
const {
1908 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
1909 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
1910 for(
size_t index = 0; it != itEnd; ++it )
1913 if( overallIndex >= index && overallIndex < index + generator->size() )
1915 return generator->
getValue( overallIndex-index );
1917 index += generator->
size();
1924 m_totalSize += generator->
size();
1925 m_composed.push_back( generator );
1935 valuesGen->
add( value );
1943 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
1944 m_totalSize += other.m_totalSize;
1945 other.m_composed.clear();
1948 std::vector<const IGenerator<T>*> m_composed;
1949 std::string m_fileInfo;
1953 namespace Generators
1955 template<
typename T>
1962 template<
typename T>
1966 valuesGen->
add( val1 );
1967 valuesGen->
add( val2 );
1968 generators.
add( valuesGen );
1972 template<
typename T>
1976 valuesGen->
add( val1 );
1977 valuesGen->
add( val2 );
1978 valuesGen->
add( val3 );
1979 generators.
add( valuesGen );
1983 template<
typename T>
1987 valuesGen->
add( val1 );
1988 valuesGen->
add( val2 );
1989 valuesGen->
add( val3 );
1990 valuesGen->
add( val4 );
1991 generators.
add( valuesGen );
1997 using namespace Generators;
2001 #define INTERNAL_CATCH_LINESTR2( line ) #line
2002 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2004 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2007 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2017 virtual std::string translate()
const = 0;
2027 template<
typename T>
2031 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2032 : m_translateFunction( translateFunction )
2035 virtual std::string translate()
const {
2040 return m_translateFunction( ex );
2045 std::string(*m_translateFunction)( T& );
2049 template<
typename T>
2052 (
new ExceptionTranslator<T>( translateFunction ) );
2058 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2059 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2060 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2061 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2064 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2075 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2081 : m_epsilon( other.m_epsilon ),
2082 m_scale( other.m_scale ),
2083 m_value( other.m_value )
2093 approx.
scale( m_scale );
2097 friend bool operator == (
double lhs,
Approx const& rhs ) {
2099 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2102 friend bool operator == (
Approx const& lhs,
double rhs ) {
2103 return operator==( rhs, lhs );
2106 friend bool operator != (
double lhs,
Approx const& rhs ) {
2107 return !operator==( lhs, rhs );
2110 friend bool operator != (
Approx const& lhs,
double rhs ) {
2111 return !operator==( rhs, lhs );
2115 m_epsilon = newEpsilon;
2125 std::ostringstream oss;
2139 return value.toString();
2145 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
2148 namespace Matchers {
2151 template<
typename ExpressionT>
2158 virtual bool match( ExpressionT
const& expr )
const = 0;
2159 virtual std::string
toString()
const = 0;
2162 template<
typename DerivedT,
typename ExpressionT>
2172 template<
typename ExpressionT>
2180 m_matchers.push_back( matcher.
clone() );
2183 virtual bool match( ExpressionT
const& expr )
const
2185 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2186 if( !m_matchers[i]->match( expr ) )
2191 std::ostringstream oss;
2193 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2196 oss << m_matchers[i]->toString();
2203 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
2206 template<
typename ExpressionT>
2214 m_matchers.push_back( matcher.
clone() );
2217 virtual bool match( ExpressionT
const& expr )
const
2219 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2220 if( m_matchers[i]->match( expr ) )
2225 std::ostringstream oss;
2227 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2230 oss << m_matchers[i]->toString();
2237 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
2242 namespace StdString {
2244 inline std::string
makeString( std::string
const& str ) {
return str; }
2245 inline std::string
makeString(
const char* str ) {
return str ? std::string( str ) : std::string(); }
2248 Equals( std::string
const& str ) : m_str( str ){}
2253 virtual bool match( std::string
const& expr )
const {
2254 return m_str == expr;
2257 return "equals: \"" + m_str +
"\"";
2264 Contains( std::string
const& substr ) : m_substr( substr ){}
2269 virtual bool match( std::string
const& expr )
const {
2270 return expr.find( m_substr ) != std::string::npos;
2273 return "contains: \"" + m_substr +
"\"";
2285 virtual bool match( std::string
const& expr )
const {
2286 return expr.find( m_substr ) == 0;
2289 return "starts with: \"" + m_substr +
"\"";
2296 EndsWith( std::string
const& substr ) : m_substr( substr ){}
2301 virtual bool match( std::string
const& expr )
const {
2302 return expr.find( m_substr ) == expr.size() - m_substr.size();
2305 return "ends with: \"" + m_substr +
"\"";
2315 template<
typename ExpressionT>
2320 template<
typename ExpressionT>
2326 template<
typename ExpressionT>
2331 template<
typename ExpressionT>
2365 using namespace Matchers;
2372 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2378 #pragma clang diagnostic push
2379 #pragma clang diagnostic ignored "-Wpadded"
2388 std::string
const& _className,
2389 std::string
const& _description,
2390 std::set<std::string>
const& _tags,
2411 TestCase withName( std::string
const& _newName )
const;
2413 void invoke()
const;
2417 bool isHidden()
const;
2418 bool hasTag( std::string
const& tag )
const;
2419 bool matchesTags( std::string
const& tagPattern )
const;
2420 std::set<std::string>
const& getTags()
const;
2423 bool operator == (
TestCase const& other )
const;
2424 bool operator < (
TestCase const& other )
const;
2432 std::string
const& className,
2433 std::string
const& name,
2434 std::string
const& description,
2439 #pragma clang diagnostic pop
2443 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2456 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2458 #import <objc/runtime.h>
2480 class OcMethod :
public SharedImpl<ITestCase> {
2483 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2485 virtual void invoke()
const {
2486 id obj = [[m_cls alloc] init];
2488 performOptionalSelector( obj,
@selector(setUp) );
2489 performOptionalSelector( obj, m_sel );
2490 performOptionalSelector( obj,
@selector(tearDown) );
2492 arcSafeRelease( obj );
2495 virtual ~OcMethod() {}
2503 inline std::string getAnnotation( Class cls,
2504 std::string
const& annotationName,
2505 std::string
const& testCaseName ) {
2506 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2507 SEL sel = NSSelectorFromString( selStr );
2508 arcSafeRelease( selStr );
2509 id value = performOptionalSelector( cls, sel );
2511 return [(NSString*)value UTF8String];
2516 inline size_t registerTestMethods() {
2517 size_t noTestMethods = 0;
2518 int noClasses = objc_getClassList( NULL, 0 );
2520 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc(
sizeof(Class) * noClasses);
2521 objc_getClassList( classes, noClasses );
2523 for(
int c = 0; c < noClasses; c++ ) {
2524 Class cls = classes[c];
2527 Method* methods = class_copyMethodList( cls, &count );
2528 for( u_int m = 0; m < count ; m++ ) {
2529 SEL selector = method_getName(methods[m]);
2530 std::string methodName = sel_getName(selector);
2531 if(
startsWith( methodName,
"Catch_TestCase_" ) ) {
2532 std::string testCaseName = methodName.substr( 15 );
2533 std::string name = Detail::getAnnotation( cls,
"Name", testCaseName );
2534 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
2535 const char* className = class_getName( cls );
2544 return noTestMethods;
2547 namespace Matchers {
2549 namespace NSStringMatchers {
2551 template<
typename MatcherT>
2552 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
2553 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2554 StringHolder( StringHolder
const& other ) : m_substr( [other.m_substr copy] ){}
2556 arcSafeRelease( m_substr );
2563 Equals( NSString* substr ) : StringHolder( substr ){}
2565 virtual bool match( ExpressionType
const& str )
const {
2566 return (str != nil || m_substr == nil ) &&
2567 [str isEqualToString:m_substr];
2570 virtual std::string
toString()
const {
2571 return "equals string: \"" + Catch::toString( m_substr ) + "\"";
2576 Contains( NSString* substr ) : StringHolder( substr ){}
2578 virtual bool match( ExpressionType
const& str )
const {
2579 return (str != nil || m_substr == nil ) &&
2580 [str rangeOfString:m_substr].location != NSNotFound;
2583 virtual std::string
toString()
const {
2584 return "contains string: \"" + Catch::toString( m_substr ) + "\"";
2589 StartsWith( NSString* substr ) : StringHolder( substr ){}
2591 virtual bool match( ExpressionType
const& str )
const {
2592 return (str != nil || m_substr == nil ) &&
2593 [str rangeOfString:m_substr].location == 0;
2596 virtual std::string
toString()
const {
2597 return "starts with: \"" + Catch::toString( m_substr ) + "\"";
2601 EndsWith( NSString* substr ) : StringHolder( substr ){}
2603 virtual bool match( ExpressionType
const& str )
const {
2604 return (str != nil || m_substr == nil ) &&
2605 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2608 virtual std::string
toString()
const {
2609 return "ends with: \"" + Catch::toString( m_substr ) + "\"";
2630 using namespace Matchers;
2635 #define OC_TEST_CASE( name, desc )\
2636 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
2640 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
2644 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2648 #if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER )
2650 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
2656 #pragma clang diagnostic push
2657 #pragma clang diagnostic ignored "-Wweak-vtables"
2661 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
2664 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2667 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
2670 #define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED
2673 #define TWOBLUECUBES_CATCH_TAGS_H_INCLUDED
2681 #pragma clang diagnostic ignored "-Wpadded"
2687 virtual ~TagParser();
2689 void parse( std::string
const& str );
2692 virtual void acceptTag( std::string
const& tag ) = 0;
2693 virtual void acceptChar(
char c ) = 0;
2694 virtual void endParse() {}
2699 class TagExtracter :
public TagParser {
2702 TagExtracter( std::set<std::string>& tags );
2703 virtual ~TagExtracter();
2705 void parse( std::string& description );
2708 virtual void acceptTag( std::string
const& tag );
2709 virtual void acceptChar(
char c );
2711 TagExtracter& operator=(TagExtracter
const&);
2713 std::set<std::string>& m_tags;
2714 std::string m_remainder;
2720 Tag( std::string
const& name,
bool isNegated );
2721 std::string getName()
const;
2722 bool isNegated()
const;
2723 bool operator ! ()
const;
2731 typedef std::map<std::string, Tag> TagMap;
2733 void add( Tag
const& tag );
2735 bool matches( std::set<std::string>
const& tags )
const;
2741 class TagExpression {
2743 bool matches( std::set<std::string>
const& tags )
const;
2746 friend class TagExpressionParser;
2748 std::vector<TagSet> m_tagSets;
2751 class TagExpressionParser :
public TagParser {
2753 TagExpressionParser( TagExpression& exp );
2754 ~TagExpressionParser();
2757 virtual void acceptTag( std::string
const& tag );
2758 virtual void acceptChar(
char c );
2759 virtual void endParse();
2761 TagExpressionParser& operator=(TagExpressionParser
const&);
2764 TagSet m_currentTagSet;
2765 TagExpression& m_exp;
2777 struct IfFilterMatches{
enum DoWhat {
2778 AutoDetectBehaviour,
2783 class TestCaseFilter {
2784 enum WildcardPosition {
2786 WildcardAtStart = 1,
2788 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
2792 TestCaseFilter( std::string
const& testSpec, IfFilterMatches::DoWhat matchBehaviour = IfFilterMatches::AutoDetectBehaviour );
2794 IfFilterMatches::DoWhat getFilterType()
const;
2795 bool shouldInclude( TestCase
const& testCase )
const;
2798 bool isMatch( TestCase
const& testCase )
const;
2800 std::string m_stringToMatch;
2801 IfFilterMatches::DoWhat m_filterType;
2802 WildcardPosition m_wildcardPosition;
2805 class TestCaseFilters {
2807 TestCaseFilters( std::string
const& name );
2808 std::string getName()
const;
2809 void addFilter( TestCaseFilter
const& filter );
2810 void addTags( std::string
const& tagPattern );
2811 bool shouldInclude( TestCase
const& testCase )
const;
2814 std::vector<TagExpression> m_tagExpressions;
2815 std::vector<TestCaseFilter> m_inclusionFilters;
2816 std::vector<TestCaseFilter> m_exclusionFilters;
2823 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
2825 #include <streambuf>
2828 #pragma clang diagnostic ignored "-Wpadded"
2836 Stream( std::streambuf* _streamBuf,
bool _isOwned );
2839 std::streambuf* streamBuf;
2851 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
2852 #define CATCH_CONFIG_CONSOLE_WIDTH 80
2860 : listTests( false ),
2862 listReporters( false ),
2863 listTestNamesOnly( false ),
2864 showSuccessfulTests( false ),
2865 shouldDebugBreak( false ),
2869 verbosity( Verbosity::Normal ),
2870 warnings( WarnAbout::Nothing ),
2871 showDurations( ShowDurations::DefaultForReporter )
2877 bool listTestNamesOnly;
2879 bool showSuccessfulTests;
2880 bool shouldDebugBreak;
2890 std::string reporterName;
2891 std::string outputFilename;
2893 std::string processName;
2895 std::vector<std::string> testsOrTags;
2898 class Config :
public SharedImpl<IConfig> {
2900 Config( Config
const& other );
2901 Config& operator = ( Config
const& other );
2902 virtual void dummy();
2906 : m_os( std::cout.rdbuf() )
2909 Config( ConfigData
const& data )
2911 m_os( std::cout.rdbuf() )
2913 if( !data.testsOrTags.empty() ) {
2914 std::string groupName;
2915 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
2918 groupName += data.testsOrTags[i];
2920 TestCaseFilters filters( groupName );
2921 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) {
2922 std::string filter = data.testsOrTags[i];
2924 filters.addTags( filter );
2926 filters.addFilter( TestCaseFilter( filter ) );
2928 m_filterSets.push_back( filters );
2933 m_os.rdbuf( std::cout.rdbuf() );
2937 void setFilename( std::string
const& filename ) {
2938 m_data.outputFilename = filename;
2941 std::string
const& getFilename()
const {
2942 return m_data.outputFilename ;
2945 bool listTests()
const {
return m_data.listTests; }
2946 bool listTestNamesOnly()
const {
return m_data.listTestNamesOnly; }
2947 bool listTags()
const {
return m_data.listTags; }
2948 bool listReporters()
const {
return m_data.listReporters; }
2950 std::string getProcessName()
const {
2951 return m_data.processName;
2954 bool shouldDebugBreak()
const {
2955 return m_data.shouldDebugBreak;
2958 void setStreamBuf( std::streambuf* buf ) {
2959 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
2962 void useStream( std::string
const& streamName ) {
2964 setStreamBuf( stream.streamBuf );
2969 std::string getReporterName()
const {
return m_data.reporterName; }
2971 void addTestSpec( std::string
const& testSpec ) {
2972 TestCaseFilters filters( testSpec );
2973 filters.addFilter( TestCaseFilter( testSpec ) );
2974 m_filterSets.push_back( filters );
2977 int abortAfter()
const {
2978 return m_data.abortAfter;
2981 std::vector<TestCaseFilters>
const& filters()
const {
2982 return m_filterSets;
2985 bool showHelp()
const {
return m_data.showHelp; }
2988 virtual bool allowThrows()
const {
return !m_data.noThrow; }
2989 virtual std::ostream& stream()
const {
return m_os; }
2990 virtual std::string name()
const {
return m_data.name.empty() ? m_data.processName : m_data.name; }
2991 virtual bool includeSuccessfulResults()
const {
return m_data.showSuccessfulTests; }
2999 mutable std::ostream m_os;
3000 std::vector<TestCaseFilters> m_filterSets;
3006 #define TWOBLUECUBES_CLARA_H_INCLUDED
3009 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
3016 struct TextAttributes {
3018 : initialIndent( std::string::npos ),
3020 width( CATCH_CONFIG_CONSOLE_WIDTH-1 ),
3024 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value;
return *
this; }
3025 TextAttributes& setIndent( std::size_t _value ) { indent = _value;
return *
this; }
3026 TextAttributes& setWidth( std::size_t _value ) { width = _value;
return *
this; }
3027 TextAttributes& setTabChar(
char _value ) { tabChar = _value;
return *
this; }
3029 std::size_t initialIndent;
3037 Text( std::string
const& _str, TextAttributes
const& _attr = TextAttributes() );
3038 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos );
3040 typedef std::vector<std::string>::const_iterator const_iterator;
3042 const_iterator begin()
const {
return lines.begin(); }
3043 const_iterator end()
const {
return lines.end(); }
3044 std::string
const& last()
const {
return lines.back(); }
3045 std::size_t size()
const {
return lines.size(); }
3046 std::string
const& operator[]( std::size_t _index )
const {
return lines[_index]; }
3049 friend std::ostream&
operator << ( std::ostream& _stream, Text
const& _text );
3053 TextAttributes attr;
3054 std::vector<std::string> lines;
3061 template<
typename T>
struct RemoveConstRef{
typedef T type; };
3062 template<
typename T>
struct RemoveConstRef<T&>{
typedef T type; };
3063 template<
typename T>
struct RemoveConstRef<T const&>{
typedef T type; };
3064 template<
typename T>
struct RemoveConstRef<T const>{
typedef T type; };
3066 template<
typename T>
struct IsBool {
static const bool value =
false; };
3067 template<>
struct IsBool<bool> {
static const bool value =
true; };
3069 template<
typename T>
3070 void convertInto( std::string
const& _source, T& _dest ) {
3071 std::stringstream ss;
3075 throw std::runtime_error(
"Unable to convert " + _source +
" to destination type" );
3077 inline void convertInto( std::string
const& _source, std::string& _dest ) {
3080 inline void convertInto( std::string
const& _source,
bool& _dest ) {
3081 std::string sourceLC = _source;
3082 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
3083 if( sourceLC ==
"y" || sourceLC ==
"1" || sourceLC ==
"true" || sourceLC ==
"yes" || sourceLC ==
"on" )
3085 else if( sourceLC ==
"n" || sourceLC ==
"0" || sourceLC ==
"false" || sourceLC ==
"no" || sourceLC ==
"off" )
3088 throw std::runtime_error(
"Expected a boolean value but did not recognise:\n '" + _source +
"'" );
3090 inline void convertInto(
bool _source,
bool& _dest ) {
3093 template<
typename T>
3094 inline void convertInto(
bool, T& ) {
3095 throw std::runtime_error(
"Invalid conversion" );
3098 template<
typename ConfigT>
3099 struct IArgFunction {
3100 virtual ~IArgFunction() {}
3101 virtual void set( ConfigT& config, std::string
const& value )
const = 0;
3102 virtual void setFlag( ConfigT& config )
const = 0;
3103 virtual bool takesArg()
const = 0;
3104 virtual IArgFunction* clone()
const = 0;
3107 template<
typename ConfigT>
3108 class BoundArgFunction {
3110 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
3111 BoundArgFunction( BoundArgFunction
const& other ) : functionObj( other.functionObj->clone() ) {}
3112 BoundArgFunction& operator = ( BoundArgFunction
const& other ) {
3113 IArgFunction<ConfigT>* newFunctionObj = other.functionObj->clone();
3115 functionObj = newFunctionObj;
3118 ~BoundArgFunction() {
delete functionObj; }
3120 void set( ConfigT& config, std::string
const& value )
const {
3121 functionObj->set( config, value );
3123 void setFlag( ConfigT& config )
const {
3124 functionObj->setFlag( config );
3126 bool takesArg()
const {
return functionObj->takesArg(); }
3128 IArgFunction<ConfigT>* functionObj;
3131 template<
typename C>
3132 struct NullBinder : IArgFunction<C>{
3133 virtual void set( C&, std::string
const& )
const {}
3134 virtual void setFlag( C& )
const {}
3135 virtual bool takesArg()
const {
return true; }
3136 virtual IArgFunction<C>* clone()
const {
return new NullBinder( *
this ); }
3139 template<
typename C,
typename M>
3140 struct BoundDataMember : IArgFunction<C>{
3141 BoundDataMember( M C::* _member ) : member( _member ) {}
3142 virtual void set( C& p, std::string
const& stringValue )
const {
3143 convertInto( stringValue, p.*member );
3145 virtual void setFlag( C& p )
const {
3146 convertInto(
true, p.*member );
3148 virtual bool takesArg()
const {
return !IsBool<M>::value; }
3149 virtual IArgFunction<C>* clone()
const {
return new BoundDataMember( *
this ); }
3152 template<
typename C,
typename M>
3153 struct BoundUnaryMethod : IArgFunction<C>{
3154 BoundUnaryMethod(
void (C::*_member)( M ) ) : member( _member ) {}
3155 virtual void set( C& p, std::string
const& stringValue )
const {
3156 typename RemoveConstRef<M>::type value;
3157 convertInto( stringValue, value );
3158 (p.*member)( value );
3160 virtual void setFlag( C& p )
const {
3161 typename RemoveConstRef<M>::type value;
3162 convertInto(
true, value );
3163 (p.*member)( value );
3165 virtual bool takesArg()
const {
return !IsBool<M>::value; }
3166 virtual IArgFunction<C>* clone()
const {
return new BoundUnaryMethod( *
this ); }
3167 void (C::*member)( M );
3169 template<
typename C>
3170 struct BoundNullaryMethod : IArgFunction<C>{
3171 BoundNullaryMethod(
void (C::*_member)() ) : member( _member ) {}
3172 virtual void set( C& p, std::string
const& stringValue )
const {
3174 convertInto( stringValue, value );
3178 virtual void setFlag( C& p )
const {
3181 virtual bool takesArg()
const {
return false; }
3182 virtual IArgFunction<C>* clone()
const {
return new BoundNullaryMethod( *
this ); }
3183 void (C::*member)();
3186 template<
typename C>
3187 struct BoundUnaryFunction : IArgFunction<C>{
3188 BoundUnaryFunction(
void (*_function)( C& ) ) : function( _function ) {}
3189 virtual void set( C& obj, std::string
const& stringValue )
const {
3191 convertInto( stringValue, value );
3195 virtual void setFlag( C& p )
const {
3198 virtual bool takesArg()
const {
return false; }
3199 virtual IArgFunction<C>* clone()
const {
return new BoundUnaryFunction( *
this ); }
3200 void (*
function)( C& );
3203 template<
typename C,
typename T>
3204 struct BoundBinaryFunction : IArgFunction<C>{
3205 BoundBinaryFunction(
void (*_function)( C&, T ) ) : function( _function ) {}
3206 virtual void set( C& obj, std::string
const& stringValue )
const {
3207 typename RemoveConstRef<T>::type value;
3208 convertInto( stringValue, value );
3209 function( obj, value );
3211 virtual void setFlag( C& obj )
const {
3212 typename RemoveConstRef<T>::type value;
3213 convertInto(
true, value );
3214 function( obj, value );
3216 virtual bool takesArg()
const {
return !IsBool<T>::value; }
3217 virtual IArgFunction<C>* clone()
const {
return new BoundBinaryFunction( *
this ); }
3218 void (*
function)( C&, T );
3221 template<
typename C,
typename M>
3222 BoundArgFunction<C> makeBoundField( M C::* _member ) {
3223 return BoundArgFunction<C>(
new BoundDataMember<C,M>( _member ) );
3225 template<
typename C,
typename M>
3226 BoundArgFunction<C> makeBoundField(
void (C::*_member)( M ) ) {
3227 return BoundArgFunction<C>(
new BoundUnaryMethod<C,M>( _member ) );
3229 template<
typename C>
3230 BoundArgFunction<C> makeBoundField(
void (C::*_member)() ) {
3231 return BoundArgFunction<C>(
new BoundNullaryMethod<C>( _member ) );
3233 template<
typename C>
3234 BoundArgFunction<C> makeBoundField(
void (*_function)( C& ) ) {
3235 return BoundArgFunction<C>(
new BoundUnaryFunction<C>( _function ) );
3237 template<
typename C,
typename T>
3238 BoundArgFunction<C> makeBoundField(
void (*_function)( C&, T ) ) {
3239 return BoundArgFunction<C>(
new BoundBinaryFunction<C, T>( _function ) );
3244 Parser() : separators(
" \t=:" ) {}
3247 enum Type { Positional, ShortOpt, LongOpt };
3248 Token(
Type _type, std::string
const& _data ) : type( _type ), data( _data ) {}
3253 void parseIntoTokens(
int argc,
char const *
const * argv, std::vector<Parser::Token>& tokens )
const {
3254 const std::string doubleDash =
"--";
3255 for(
int i = 1; i < argc && argv[i] != doubleDash; ++i )
3256 parseIntoTokens( argv[i] , tokens);
3258 void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens )
const {
3259 while( !arg.empty() ) {
3260 Parser::Token token( Parser::Token::Positional, arg );
3262 if( token.data[0] ==
'-' ) {
3263 if( token.data.size() > 1 && token.data[1] ==
'-' ) {
3264 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
3267 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
3268 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
3269 arg =
"-" + token.data.substr( 1 );
3270 token.data = token.data.substr( 0, 1 );
3274 if( token.type != Parser::Token::Positional ) {
3275 std::size_t pos = token.data.find_first_of( separators );
3276 if( pos != std::string::npos ) {
3277 arg = token.data.substr( pos+1 );
3278 token.data = token.data.substr( 0, pos );
3281 tokens.push_back( token );
3284 std::string separators;
3287 template<
typename ConfigT>
3291 Arg( Detail::BoundArgFunction<ConfigT>
const& _boundField ) : boundField( _boundField ), position( -1 ) {}
3293 bool hasShortName( std::string
const& shortName )
const {
3294 for( std::vector<std::string>::const_iterator
3295 it = shortNames.begin(), itEnd = shortNames.end();
3298 if( *it == shortName )
3302 bool hasLongName( std::string
const& _longName )
const {
3303 return _longName == longName;
3305 bool takesArg()
const {
3306 return !hint.empty();
3308 bool isFixedPositional()
const {
3309 return position != -1;
3311 bool isAnyPositional()
const {
3312 return position == -1 && shortNames.empty() && longName.empty();
3314 std::string dbgName()
const {
3315 if( !longName.empty() )
3316 return "--" + longName;
3317 if( !shortNames.empty() )
3318 return "-" + shortNames[0];
3319 return "positional args";
3321 void validate()
const {
3322 if( boundField.takesArg() && !takesArg() )
3323 throw std::logic_error( dbgName() + " must specify an arg name" );
3325 std::string commands()
const {
3326 std::ostringstream oss;
3328 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
3329 for(; it != itEnd; ++it ) {
3336 if( !longName.empty() ) {
3339 oss <<
"--" << longName;
3342 oss <<
" <" << hint <<
">";
3346 Detail::BoundArgFunction<ConfigT> boundField;
3347 std::vector<std::string> shortNames;
3348 std::string longName;
3349 std::string description;
3355 #if defined(__cplusplus) && __cplusplus > 199711L
3356 typedef std::unique_ptr<Arg> ArgAutoPtr;
3358 typedef std::auto_ptr<Arg> ArgAutoPtr;
3363 template<
typename F>
3364 ArgBinder( CommandLine* cl, F f )
3366 m_arg( Detail::makeBoundField( f ) )
3368 ArgBinder( ArgBinder& other )
3369 : m_cl( other.m_cl ),
3370 m_arg( other.m_arg )
3377 if( m_arg.isFixedPositional() ) {
3378 m_cl->m_positionalArgs.insert( std::make_pair( m_arg.position, m_arg ) );
3379 if( m_arg.position > m_cl->m_highestSpecifiedArgPosition )
3380 m_cl->m_highestSpecifiedArgPosition = m_arg.position;
3382 else if( m_arg.isAnyPositional() ) {
3383 if( m_cl->m_arg.get() )
3384 throw std::logic_error(
"Only one unpositional argument can be added" );
3385 m_cl->m_arg = ArgAutoPtr(
new Arg( m_arg ) );
3388 m_cl->m_options.push_back( m_arg );
3391 ArgBinder& shortOpt( std::string
const& name ) {
3392 m_arg.shortNames.push_back( name );
3395 ArgBinder& longOpt( std::string
const& name ) {
3396 m_arg.longName = name;
3399 ArgBinder& describe( std::string
const& description ) {
3400 m_arg.description = description;
3403 ArgBinder& hint( std::string
const& hint ) {
3407 ArgBinder& position(
int position ) {
3408 m_arg.position = position;
3419 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
3420 m_highestSpecifiedArgPosition( 0 ),
3421 m_throwOnUnrecognisedTokens( false )
3423 CommandLine( CommandLine
const& other )
3424 : m_boundProcessName( other.m_boundProcessName ),
3425 m_options ( other.m_options ),
3426 m_positionalArgs( other.m_positionalArgs ),
3427 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
3428 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
3430 if( other.m_arg.get() )
3431 m_arg = ArgAutoPtr(
new Arg( *other.m_arg ) );
3434 CommandLine& setThrowOnUnrecognisedTokens(
bool shouldThrow =
true ) {
3435 m_throwOnUnrecognisedTokens = shouldThrow;
3439 template<
typename F>
3440 ArgBinder bind( F f ) {
3441 ArgBinder binder(
this, f );
3444 template<
typename F>
3445 void bindProcessName( F f ) {
3446 m_boundProcessName = Detail::makeBoundField( f );
3449 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = CATCH_CONFIG_CONSOLE_WIDTH )
const {
3450 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
3451 std::size_t maxWidth = 0;
3452 for( it = itBegin; it != itEnd; ++it )
3453 maxWidth = (std::max)( maxWidth, it->commands().size() );
3455 for( it = itBegin; it != itEnd; ++it ) {
3456 Catch::Text usage( it->commands(), Catch::TextAttributes()
3457 .setWidth( maxWidth+indent )
3458 .setIndent( indent ) );
3460 Catch::Text desc( it->description, Catch::TextAttributes()
3461 .setWidth( width - maxWidth -3 ) );
3463 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
3464 std::string usageCol = i < usage.size() ? usage[i] :
"";
3467 if( i < desc.size() && !desc[i].empty() )
3468 os << std::string( indent + 2 + maxWidth - usageCol.size(),
' ' )
3474 std::string optUsage()
const {
3475 std::ostringstream oss;
3480 void argSynopsis( std::ostream& os )
const {
3481 for(
int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
3484 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
3485 if( it != m_positionalArgs.end() )
3486 os <<
"<" << it->second.hint <<
">";
3487 else if( m_arg.get() )
3488 os <<
"<" << m_arg->hint <<
">";
3490 throw std::logic_error(
"non consecutive positional arguments with no floating args" );
3494 if( m_highestSpecifiedArgPosition > 1 )
3496 os <<
"[<" << m_arg->hint <<
"> ...]";
3499 std::string argSynopsis()
const {
3500 std::ostringstream oss;
3505 void usage( std::ostream& os, std::string
const& procName )
const {
3506 os <<
"usage:\n " << procName <<
" ";
3508 if( !m_options.empty() ) {
3509 os <<
" [options]\n\nwhere options are: \n";
3514 std::string usage( std::string
const& procName )
const {
3515 std::ostringstream oss;
3516 usage( oss, procName );
3520 std::vector<Parser::Token> parseInto(
int argc,
char const *
const * argv, ConfigT& config )
const {
3521 std::string processName = argv[0];
3522 std::size_t lastSlash = processName.find_last_of(
"/\\" );
3523 if( lastSlash != std::string::npos )
3524 processName = processName.substr( lastSlash+1 );
3525 m_boundProcessName.set( config, processName );
3526 std::vector<Parser::Token> tokens;
3528 parser.parseIntoTokens( argc, argv, tokens );
3529 return populate( tokens, config );
3532 std::vector<Parser::Token> populate( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
3533 if( m_options.empty() && m_positionalArgs.empty() )
3534 throw std::logic_error(
"No options or arguments specified" );
3536 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
3537 unusedTokens = populateFixedArgs( unusedTokens, config );
3538 unusedTokens = populateFloatingArgs( unusedTokens, config );
3539 return unusedTokens;
3542 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
3543 std::vector<Parser::Token> unusedTokens;
3544 std::vector<std::string> errors;
3545 for( std::size_t i = 0; i < tokens.size(); ++i ) {
3546 Parser::Token
const& token = tokens[i];
3547 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
3548 for(; it != itEnd; ++it ) {
3549 Arg
const& arg = *it;
3552 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
3553 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
3554 if( arg.takesArg() ) {
3555 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
3556 errors.push_back( "Expected argument to option: " + token.data );
3558 arg.boundField.set( config, tokens[++i].data );
3561 arg.boundField.setFlag( config );
3566 catch( std::exception& ex ) {
3567 errors.push_back( std::string( ex.what() ) +
"\n- while parsing: (" + arg.commands() + ")" );
3571 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
3572 unusedTokens.push_back( token );
3573 else if( m_throwOnUnrecognisedTokens )
3574 errors.push_back(
"unrecognised option: " + token.data );
3577 if( !errors.empty() ) {
3578 std::ostringstream oss;
3579 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
3582 if( it != errors.begin() )
3586 throw std::runtime_error( oss.str() );
3588 return unusedTokens;
3590 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
3591 std::vector<Parser::Token> unusedTokens;
3593 for( std::size_t i = 0; i < tokens.size(); ++i ) {
3594 Parser::Token
const& token = tokens[i];
3595 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
3596 if( it != m_positionalArgs.end() )
3597 it->second.boundField.set( config, token.data );
3599 unusedTokens.push_back( token );
3600 if( token.type == Parser::Token::Positional )
3603 return unusedTokens;
3605 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
3608 std::vector<Parser::Token> unusedTokens;
3609 for( std::size_t i = 0; i < tokens.size(); ++i ) {
3610 Parser::Token
const& token = tokens[i];
3611 if( token.type == Parser::Token::Positional )
3612 m_arg->boundField.set( config, token.data );
3614 unusedTokens.push_back( token );
3616 return unusedTokens;
3620 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
3621 std::vector<Arg> m_options;
3622 std::map<int, Arg> m_positionalArgs;
3624 int m_highestSpecifiedArgPosition;
3625 bool m_throwOnUnrecognisedTokens;
3634 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
3635 inline void abortAfterX( ConfigData& config,
int x ) {
3637 throw std::runtime_error(
"Value after -x or --abortAfter must be greater than zero" );
3638 config.abortAfter =
x;
3640 inline void addTestOrTags( ConfigData& config, std::string
const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
3642 inline void addWarning( ConfigData& config, std::string
const& _warning ) {
3643 if( _warning ==
"NoAssertions" )
3646 throw std::runtime_error(
"Unrecognised warning: '" + _warning +
"'" );
3649 inline void setVerbosity( ConfigData& config,
int level ) {
3653 inline void setShowDurations( ConfigData& config,
bool _showDurations ) {
3654 config.showDurations = _showDurations
3658 inline void loadTestNamesFromFile( ConfigData& config, std::string
const& _filename ) {
3659 std::ifstream f( _filename.c_str() );
3661 throw std::domain_error(
"Unable to load input file: " + _filename );
3664 while( std::getline( f, line ) ) {
3666 if( !line.empty() && !
startsWith( line,
"#" ) )
3667 addTestOrTags( config, line );
3671 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
3673 Clara::CommandLine<ConfigData> cli;
3675 cli.bindProcessName( &ConfigData::processName );
3677 cli.bind( &ConfigData::showHelp )
3678 .describe(
"display usage information" )
3683 cli.bind( &ConfigData::listTests )
3684 .describe(
"list all/matching test cases" )
3686 .longOpt(
"list-tests" );
3688 cli.bind( &ConfigData::listTags )
3689 .describe(
"list all/matching tags" )
3691 .longOpt(
"list-tags" );
3693 cli.bind( &ConfigData::showSuccessfulTests )
3694 .describe(
"include successful tests in output" )
3696 .longOpt(
"success" );
3698 cli.bind( &ConfigData::shouldDebugBreak )
3699 .describe(
"break into debugger on failure" )
3701 .longOpt(
"break" );
3703 cli.bind( &ConfigData::noThrow )
3704 .describe(
"skip exception tests" )
3706 .longOpt(
"nothrow" );
3708 cli.bind( &ConfigData::outputFilename )
3709 .describe(
"output filename" )
3712 .hint(
"filename" );
3714 cli.bind( &ConfigData::reporterName )
3715 .describe(
"reporter to use (defaults to console)" )
3717 .longOpt(
"reporter" )
3721 cli.bind( &ConfigData::name )
3722 .describe(
"suite name" )
3727 cli.bind( &abortAfterFirst )
3728 .describe(
"abort at first failure" )
3730 .longOpt(
"abort" );
3732 cli.bind( &abortAfterX )
3733 .describe(
"abort after x failures" )
3735 .longOpt(
"abortx" )
3736 .hint(
"number of failures" );
3738 cli.bind( &addWarning )
3739 .describe(
"enable warnings" )
3742 .hint(
"warning name" );
3750 cli.bind( &addTestOrTags )
3751 .describe(
"which test or tests to use" )
3752 .hint(
"test name, pattern or tags" );
3754 cli.bind( &setShowDurations )
3755 .describe(
"show test durations" )
3757 .longOpt(
"durations" )
3760 cli.bind( &loadTestNamesFromFile )
3761 .describe(
"load test names to run from a file" )
3763 .longOpt(
"input-file" )
3764 .hint(
"filename" );
3767 cli.bind( &ConfigData::listTestNamesOnly )
3768 .describe(
"list all/matching test cases names only" )
3769 .longOpt(
"list-test-names-only" );
3771 cli.bind( &ConfigData::listReporters )
3772 .describe(
"list all reporters" )
3773 .longOpt(
"list-reporters" );
3781 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
3784 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
3806 BrightRed = Bright | Red,
3807 BrightGreen = Bright | Green,
3808 LightGrey = Bright | Grey,
3809 BrightWhite = Bright | White,
3812 FileName = LightGrey,
3813 ResultError = BrightRed,
3814 ResultSuccess = BrightGreen,
3819 OriginalExpression = Cyan,
3820 ReconstructedExpression = Yellow,
3822 SecondaryText = LightGrey,
3827 Colour( Code _colourCode );
3831 static void use( Code _colourCode );
3834 static Detail::IColourImpl* impl;
3840 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
3843 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
3848 template<
typename T>
3851 Option() : nullableValue( NULL ) {}
3852 Option( T
const& _value )
3853 : nullableValue( new( storage ) T( _value ) )
3855 Option( Option
const& _other )
3856 : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
3863 Option& operator= ( Option
const& _other ) {
3866 nullableValue =
new( storage ) T( *_other );
3869 Option& operator = ( T
const& _value ) {
3871 nullableValue =
new( storage ) T( _value );
3877 nullableValue->~T();
3878 nullableValue = NULL;
3881 T& operator*() {
return *nullableValue; }
3882 T
const& operator*()
const {
return *nullableValue; }
3883 T* operator->() {
return nullableValue; }
3884 const T* operator->()
const {
return nullableValue; }
3886 T valueOr( T
const& defaultValue )
const {
3887 return nullableValue ? *nullableValue : defaultValue;
3890 bool some()
const {
return nullableValue != NULL; }
3891 bool none()
const {
return nullableValue == NULL; }
3893 bool operator !()
const {
return nullableValue == NULL; }
3900 char storage[sizeof(T)];
3912 struct ReporterConfig {
3913 explicit ReporterConfig( Ptr<IConfig>
const& _fullConfig )
3914 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
3916 ReporterConfig( Ptr<IConfig>
const& _fullConfig, std::ostream& _stream )
3917 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
3919 std::ostream& stream()
const {
return *m_stream; }
3920 Ptr<IConfig> fullConfig()
const {
return m_fullConfig; }
3923 std::ostream* m_stream;
3924 Ptr<IConfig> m_fullConfig;
3927 struct ReporterPreferences {
3928 ReporterPreferences()
3929 : shouldRedirectStdOut( false )
3932 bool shouldRedirectStdOut;
3935 template<
typename T>
3936 struct LazyStat : Option<T> {
3937 LazyStat() : used( false ) {}
3938 LazyStat& operator=( T
const& _value ) {
3939 Option<T>::operator=( _value );
3950 struct TestRunInfo {
3951 TestRunInfo( std::string
const& _name ) : name( _name ) {}
3955 GroupInfo( std::string
const& _name,
3956 std::size_t _groupIndex,
3957 std::size_t _groupsCount )
3959 groupIndex( _groupIndex ),
3960 groupsCounts( _groupsCount )
3964 std::size_t groupIndex;
3965 std::size_t groupsCounts;
3968 struct AssertionStats {
3969 AssertionStats( AssertionResult
const& _assertionResult,
3970 std::vector<MessageInfo>
const& _infoMessages,
3971 Totals
const& _totals )
3972 : assertionResult( _assertionResult ),
3973 infoMessages( _infoMessages ),
3976 if( assertionResult.hasMessage() ) {
3979 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
3980 builder << assertionResult.getMessage();
3981 builder.m_info.message = builder.m_stream.str();
3983 infoMessages.push_back( builder.m_info );
3986 virtual ~AssertionStats();
3988 AssertionResult assertionResult;
3989 std::vector<MessageInfo> infoMessages;
3993 struct SectionStats {
3994 SectionStats( SectionInfo
const& _sectionInfo,
3995 Counts
const& _assertions,
3996 double _durationInSeconds,
3997 bool _missingAssertions )
3998 : sectionInfo( _sectionInfo ),
3999 assertions( _assertions ),
4000 durationInSeconds( _durationInSeconds ),
4001 missingAssertions( _missingAssertions )
4003 virtual ~SectionStats();
4005 SectionInfo sectionInfo;
4007 double durationInSeconds;
4008 bool missingAssertions;
4011 struct TestCaseStats {
4012 TestCaseStats( TestCaseInfo
const& _testInfo,
4013 Totals
const& _totals,
4014 std::string
const& _stdOut,
4015 std::string
const& _stdErr,
4017 : testInfo( _testInfo ),
4021 aborting( _aborting )
4023 virtual ~TestCaseStats();
4025 TestCaseInfo testInfo;
4032 struct TestGroupStats {
4033 TestGroupStats( GroupInfo
const& _groupInfo,
4034 Totals
const& _totals,
4036 : groupInfo( _groupInfo ),
4038 aborting( _aborting )
4040 TestGroupStats( GroupInfo
const& _groupInfo )
4041 : groupInfo( _groupInfo ),
4044 virtual ~TestGroupStats();
4046 GroupInfo groupInfo;
4051 struct TestRunStats {
4052 TestRunStats( TestRunInfo
const& _runInfo,
4053 Totals
const& _totals,
4055 : runInfo( _runInfo ),
4057 aborting( _aborting )
4059 TestRunStats( TestRunStats
const& _other )
4060 : runInfo( _other.runInfo ),
4061 totals( _other.totals ),
4062 aborting( _other.aborting )
4064 virtual ~TestRunStats();
4066 TestRunInfo runInfo;
4071 struct IStreamingReporter : IShared {
4072 virtual ~IStreamingReporter();
4077 virtual ReporterPreferences getPreferences()
const = 0;
4079 virtual void noMatchingTestCases( std::string
const& spec ) = 0;
4081 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
4082 virtual void testGroupStarting( GroupInfo
const& groupInfo ) = 0;
4084 virtual void testCaseStarting( TestCaseInfo
const& testInfo ) = 0;
4085 virtual void sectionStarting( SectionInfo
const& sectionInfo ) = 0;
4087 virtual void assertionStarting( AssertionInfo
const& assertionInfo ) = 0;
4089 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
4090 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
4091 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
4092 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
4093 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
4096 struct IReporterFactory {
4097 virtual ~IReporterFactory();
4098 virtual IStreamingReporter* create( ReporterConfig
const& config )
const = 0;
4099 virtual std::string getDescription()
const = 0;
4102 struct IReporterRegistry {
4103 typedef std::map<std::string, IReporterFactory*> FactoryMap;
4105 virtual ~IReporterRegistry();
4106 virtual IStreamingReporter* create( std::string
const& name, Ptr<IConfig>
const& config )
const = 0;
4107 virtual FactoryMap
const& getFactories()
const = 0;
4113 #include <algorithm>
4116 inline bool matchesFilters( std::vector<TestCaseFilters>
const& filters, TestCase
const& testCase ) {
4117 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
4118 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
4119 for(; it != itEnd; ++it )
4120 if( !it->shouldInclude( testCase ) )
4125 inline std::size_t listTests( Config
const& config ) {
4126 if( config.filters().empty() )
4127 std::cout <<
"All available test cases:\n";
4129 std::cout <<
"Matching test cases:\n";
4131 std::size_t matchedTests = 0;
4132 TextAttributes nameAttr, tagsAttr;
4133 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
4134 tagsAttr.setIndent( 6 );
4137 for( std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
4140 if( matchesFilters( config.filters(), *it ) ) {
4142 TestCaseInfo
const& testCaseInfo = it->getTestCaseInfo();
4143 Colour::Code colour = testCaseInfo.isHidden
4144 ? Colour::SecondaryText
4146 Colour colourGuard( colour );
4148 std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl;
4149 if( !testCaseInfo.tags.empty() )
4150 std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
4153 if( config.filters().empty() )
4154 std::cout << pluralise( matchedTests,
"test case" ) <<
"\n" << std::endl;
4156 std::cout << pluralise( matchedTests,
"matching test case" ) <<
"\n" << std::endl;
4157 return matchedTests;
4160 inline std::size_t listTestsNamesOnly( Config
const& config ) {
4161 std::size_t matchedTests = 0;
4163 for( std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
4166 if( matchesFilters( config.filters(), *it ) ) {
4168 TestCaseInfo
const& testCaseInfo = it->getTestCaseInfo();
4169 std::cout << testCaseInfo.name << std::endl;
4171 return matchedTests;
4174 inline std::size_t listTags( Config
const& config ) {
4175 if( config.filters().empty() )
4176 std::cout <<
"All available tags:\n";
4178 std::cout <<
"Matching tags:\n";
4180 std::map<std::string, int> tagCounts;
4183 for( std::vector<TestCase>::const_iterator it = allTests.begin(),
4184 itEnd = allTests.end();
4187 if( matchesFilters( config.filters(), *it ) ) {
4188 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
4189 tagItEnd = it->getTestCaseInfo().tags.end();
4192 std::string tagName = *tagIt;
4193 std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
4194 if( countIt == tagCounts.end() )
4195 tagCounts.insert( std::make_pair( tagName, 1 ) );
4202 for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(),
4203 countItEnd = tagCounts.end();
4204 countIt != countItEnd;
4206 std::ostringstream oss;
4207 oss <<
" " << countIt->second <<
" ";
4208 Text wrapper(
"[" + countIt->first +
"]", TextAttributes()
4209 .setInitialIndent( 0 )
4210 .setIndent( oss.str().size() )
4211 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
4212 std::cout << oss.str() << wrapper <<
"\n";
4214 std::cout << pluralise( tagCounts.size(),
"tag" ) <<
"\n" << std::endl;
4215 return tagCounts.size();
4218 inline std::size_t listReporters( Config
const& ) {
4219 std::cout <<
"Available reports:\n";
4221 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
4222 std::size_t maxNameLen = 0;
4223 for(it = itBegin; it != itEnd; ++it )
4224 maxNameLen = (std::max)( maxNameLen, it->first.size() );
4226 for(it = itBegin; it != itEnd; ++it ) {
4227 Text wrapper( it->second->getDescription(), TextAttributes()
4228 .setInitialIndent( 0 )
4229 .setIndent( 7+maxNameLen )
4230 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
4234 << std::string( maxNameLen - it->first.size() + 2, ' ' )
4237 std::cout << std::endl;
4238 return factories.size();
4241 inline Option<std::size_t> list( Config
const& config ) {
4242 Option<std::size_t> listedCount;
4243 if( config.listTests() )
4244 listedCount = listedCount.valueOr(0) + listTests( config );
4245 if( config.listTestNamesOnly() )
4246 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
4247 if( config.listTags() )
4248 listedCount = listedCount.valueOr(0) + listTags( config );
4249 if( config.listReporters() )
4250 listedCount = listedCount.valueOr(0) + listReporters( config );
4257 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
4260 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
4267 namespace SectionTracking {
4269 class TrackedSection {
4271 typedef std::map<std::string, TrackedSection> TrackedSections;
4281 TrackedSection( std::string
const& name, TrackedSection* parent )
4282 : m_name( name ), m_runState( NotStarted ), m_parent( parent )
4285 RunState runState()
const {
return m_runState; }
4287 void addChild( std::string
const& childName ) {
4288 m_children.insert( std::make_pair( childName, TrackedSection( childName,
this ) ) );
4290 TrackedSection* getChild( std::string
const& childName ) {
4291 return &m_children.find( childName )->second;
4295 if( m_runState == NotStarted )
4296 m_runState = Executing;
4299 for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
4302 if( it->second.runState() != Completed ) {
4303 m_runState = ExecutingChildren;
4306 m_runState = Completed;
4308 TrackedSection* getParent() {
4311 bool hasChildren()
const {
4312 return !m_children.empty();
4317 RunState m_runState;
4318 TrackedSections m_children;
4319 TrackedSection* m_parent;
4323 class TestCaseTracker {
4325 TestCaseTracker( std::string
const& testCaseName )
4326 : m_testCase( testCaseName, NULL ),
4327 m_currentSection( &m_testCase ),
4328 m_completedASectionThisRun( false )
4331 bool enterSection( std::string
const& name ) {
4332 if( m_completedASectionThisRun )
4334 if( m_currentSection->runState() == TrackedSection::Executing ) {
4335 m_currentSection->addChild( name );
4339 TrackedSection* child = m_currentSection->getChild( name );
4340 if( child->runState() != TrackedSection::Completed ) {
4341 m_currentSection = child;
4342 m_currentSection->enter();
4348 void leaveSection() {
4349 m_currentSection->leave();
4350 m_currentSection = m_currentSection->getParent();
4351 assert( m_currentSection != NULL );
4352 m_completedASectionThisRun =
true;
4355 bool currentSectionHasChildren()
const {
4356 return m_currentSection->hasChildren();
4358 bool isCompleted()
const {
4359 return m_testCase.runState() == TrackedSection::Completed;
4364 Guard( TestCaseTracker& tracker )
4365 : m_tracker( tracker )
4367 m_tracker.enterTestCase();
4370 m_tracker.leaveTestCase();
4373 Guard( Guard
const& );
4374 void operator = ( Guard
const& );
4375 TestCaseTracker& m_tracker;
4379 void enterTestCase() {
4380 m_currentSection = &m_testCase;
4381 m_completedASectionThisRun =
false;
4384 void leaveTestCase() {
4388 TrackedSection m_testCase;
4389 TrackedSection* m_currentSection;
4390 bool m_completedASectionThisRun;
4395 using SectionTracking::TestCaseTracker;
4404 class StreamRedirect {
4407 StreamRedirect( std::ostream& stream, std::string& targetString )
4408 : m_stream( stream ),
4409 m_prevBuf( stream.rdbuf() ),
4410 m_targetString( targetString )
4412 stream.rdbuf( m_oss.rdbuf() );
4416 m_targetString += m_oss.str();
4417 m_stream.rdbuf( m_prevBuf );
4421 std::ostream& m_stream;
4422 std::streambuf* m_prevBuf;
4423 std::ostringstream m_oss;
4424 std::string& m_targetString;
4429 class RunContext :
public IResultCapture,
public IRunner {
4431 RunContext( RunContext
const& );
4432 void operator =( RunContext
const& );
4436 explicit RunContext( Ptr<IConfig const>
const& config, Ptr<IStreamingReporter>
const& reporter )
4437 : m_runInfo( config->name() ),
4439 m_activeTestCase( NULL ),
4441 m_reporter( reporter ),
4442 m_prevRunner( &m_context.getRunner() ),
4444 m_prevConfig( m_context.getConfig() )
4446 m_context.setRunner(
this );
4447 m_context.setConfig( m_config );
4448 m_context.setResultCapture(
this );
4449 m_reporter->testRunStarting( m_runInfo );
4452 virtual ~RunContext() {
4453 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
4454 m_context.setRunner( m_prevRunner );
4455 m_context.setConfig( NULL );
4456 m_context.setResultCapture( m_prevResultCapture );
4457 m_context.setConfig( m_prevConfig );
4460 void testGroupStarting( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
4461 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
4463 void testGroupEnded( std::string
const& testSpec, Totals
const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
4464 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
4467 Totals runMatching( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
4473 testGroupStarting( testSpec, groupIndex, groupsCount );
4475 std::vector<TestCase>::const_iterator it = matchingTests.begin();
4476 std::vector<TestCase>::const_iterator itEnd = matchingTests.end();
4477 for(; it != itEnd; ++it )
4478 totals += runTest( *it );
4480 testGroupEnded( testSpec, totals, groupIndex, groupsCount );
4484 Totals runTest( TestCase
const& testCase ) {
4485 Totals prevTotals = m_totals;
4487 std::string redirectedCout;
4488 std::string redirectedCerr;
4490 TestCaseInfo testInfo = testCase.getTestCaseInfo();
4492 m_reporter->testCaseStarting( testInfo );
4494 m_activeTestCase = &testCase;
4495 m_testCaseTracker = TestCaseTracker( testInfo.name );
4499 runCurrentTest( redirectedCout, redirectedCerr );
4501 while( !m_testCaseTracker->isCompleted() && !aborting() );
4505 Totals deltaTotals = m_totals.delta( prevTotals );
4506 m_totals.testCases += deltaTotals.testCases;
4507 m_reporter->testCaseEnded( TestCaseStats( testInfo,
4513 m_activeTestCase = NULL;
4514 m_testCaseTracker.reset();
4519 Ptr<IConfig const> config()
const {
4525 virtual ResultAction::Value acceptExpression( ExpressionResultBuilder
const& assertionResult, AssertionInfo
const& assertionInfo ) {
4526 m_lastAssertionInfo = assertionInfo;
4527 return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) );
4530 virtual void assertionEnded( AssertionResult
const& result ) {
4532 m_totals.assertions.passed++;
4534 else if( !result.isOk() ) {
4535 m_totals.assertions.failed++;
4538 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
4542 m_lastAssertionInfo = AssertionInfo(
"", m_lastAssertionInfo.lineInfo,
"{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
4545 virtual bool sectionStarted (
4546 SectionInfo
const& sectionInfo,
4550 std::ostringstream oss;
4551 oss << sectionInfo.name <<
"@" << sectionInfo.lineInfo;
4553 if( !m_testCaseTracker->enterSection( oss.str() ) )
4556 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
4558 m_reporter->sectionStarting( sectionInfo );
4560 assertions = m_totals.assertions;
4564 bool testForMissingAssertions( Counts& assertions ) {
4565 if( assertions.total() != 0 ||
4566 !m_config->warnAboutMissingAssertions() ||
4567 m_testCaseTracker->currentSectionHasChildren() )
4569 m_totals.assertions.failed++;
4570 assertions.failed++;
4574 virtual void sectionEnded( SectionInfo
const& info, Counts
const& prevAssertions,
double _durationInSeconds ) {
4575 if( std::uncaught_exception() ) {
4576 m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
4580 Counts assertions = m_totals.assertions - prevAssertions;
4581 bool missingAssertions = testForMissingAssertions( assertions );
4583 m_testCaseTracker->leaveSection();
4585 m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
4589 virtual void pushScopedMessage( MessageInfo
const& message ) {
4590 m_messages.push_back( message );
4593 virtual void popScopedMessage( MessageInfo
const& message ) {
4594 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
4597 virtual bool shouldDebugBreak()
const {
4598 return m_config->shouldDebugBreak();
4601 virtual std::string getCurrentTestName()
const {
4602 return m_activeTestCase
4603 ? m_activeTestCase->getTestCaseInfo().name
4607 virtual const AssertionResult* getLastResult()
const {
4608 return &m_lastResult;
4613 bool aborting()
const {
4614 return m_totals.assertions.failed ==
static_cast<std::size_t
>( m_config->abortAfter() );
4620 m_lastResult = result;
4621 assertionEnded( m_lastResult );
4625 if( !m_lastResult.isOk() ) {
4627 if( shouldDebugBreak() )
4635 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
4636 TestCaseInfo
const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
4637 SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
4638 m_reporter->sectionStarting( testCaseSection );
4639 Counts prevAssertions = m_totals.assertions;
4640 double duration = 0;
4643 TestCaseTracker::Guard guard( *m_testCaseTracker );
4647 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
4648 StreamRedirect coutRedir( std::cout, redirectedCout );
4649 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
4650 m_activeTestCase->invoke();
4653 m_activeTestCase->invoke();
4655 duration = timer.getElapsedSeconds();
4657 catch( TestFailureException& ) {
4663 actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) );
4667 for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
4668 itEnd = m_unfinishedSections.end();
4671 sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
4672 m_unfinishedSections.clear();
4675 Counts assertions = m_totals.assertions - prevAssertions;
4676 bool missingAssertions = testForMissingAssertions( assertions );
4678 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
4679 m_reporter->sectionEnded( testCaseSectionStats );
4683 struct UnfinishedSections {
4684 UnfinishedSections( SectionInfo
const& _info, Counts
const& _prevAssertions,
double _durationInSeconds )
4685 : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
4689 Counts prevAssertions;
4690 double durationInSeconds;
4693 TestRunInfo m_runInfo;
4694 IMutableContext& m_context;
4695 TestCase
const* m_activeTestCase;
4696 Option<TestCaseTracker> m_testCaseTracker;
4697 AssertionResult m_lastResult;
4699 Ptr<IConfig const> m_config;
4701 Ptr<IStreamingReporter> m_reporter;
4702 std::vector<MessageInfo> m_messages;
4703 IRunner* m_prevRunner;
4704 IResultCapture* m_prevResultCapture;
4705 Ptr<IConfig const> m_prevConfig;
4706 AssertionInfo m_lastAssertionInfo;
4707 std::vector<UnfinishedSections> m_unfinishedSections;
4713 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
4719 Version(
unsigned int _majorVersion,
4720 unsigned int _minorVersion,
4721 unsigned int _buildNumber,
4722 std::string
const& _branchName )
4723 : majorVersion( _majorVersion ),
4724 minorVersion( _minorVersion ),
4725 buildNumber( _buildNumber ),
4726 branchName( _branchName )
4729 const unsigned int majorVersion;
4730 const unsigned int minorVersion;
4731 const unsigned int buildNumber;
4732 const std::string branchName;
4735 void operator=( Version
const& );
4738 extern Version libraryVersion;
4750 Runner( Ptr<Config>
const& config )
4751 : m_config( config )
4759 std::vector<TestCaseFilters> filterGroups = m_config->filters();
4760 if( filterGroups.empty() ) {
4761 TestCaseFilters filterGroup(
"" );
4762 filterGroups.push_back( filterGroup );
4765 RunContext context( m_config.get(), m_reporter );
4769 for( std::size_t i=0; i < filterGroups.size() && !context.aborting(); ++i ) {
4770 context.testGroupStarting( filterGroups[i].getName(), i, filterGroups.size() );
4771 totals += runTestsForGroup( context, filterGroups[i] );
4772 context.testGroupEnded( filterGroups[i].getName(), totals, i, filterGroups.size() );
4777 Totals runTestsForGroup( RunContext& context,
const TestCaseFilters& filterGroup ) {
4781 int testsRunForGroup = 0;
4782 for(; it != itEnd; ++it ) {
4783 if( filterGroup.shouldInclude( *it ) ) {
4785 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
4787 if( context.aborting() )
4790 totals += context.runTest( *it );
4791 m_testsAlreadyRun.insert( *it );
4795 if( testsRunForGroup == 0 && !filterGroup.getName().empty() )
4796 m_reporter->noMatchingTestCases( filterGroup.getName() );
4804 if( !m_config->getFilename().empty() ) {
4805 m_ofs.open( m_config->getFilename().c_str() );
4806 if( m_ofs.fail() ) {
4807 std::ostringstream oss;
4808 oss <<
"Unable to open file: '" << m_config->getFilename() <<
"'";
4809 throw std::domain_error( oss.str() );
4811 m_config->setStreamBuf( m_ofs.rdbuf() );
4814 void makeReporter() {
4815 std::string reporterName = m_config->getReporterName().empty()
4817 : m_config->getReporterName();
4821 std::ostringstream oss;
4822 oss <<
"No reporter registered with name: '" << reporterName <<
"'";
4823 throw std::domain_error( oss.str() );
4828 Ptr<Config> m_config;
4829 std::ofstream m_ofs;
4830 Ptr<IStreamingReporter> m_reporter;
4831 std::set<TestCase> m_testsAlreadyRun;
4835 static bool alreadyInstantiated;
4839 struct OnUnusedOptions {
enum DoWhat { Ignore, Fail }; };
4842 : m_cli( makeCommandLineParser() ) {
4843 if( alreadyInstantiated ) {
4844 std::string msg =
"Only one instance of Catch::Session can ever be used";
4845 std::cerr << msg << std::endl;
4846 throw std::logic_error( msg );
4848 alreadyInstantiated =
true;
4854 void showHelp( std::string
const& processName ) {
4855 std::cout <<
"\nCatch v" << libraryVersion.majorVersion <<
"."
4856 << libraryVersion.minorVersion <<
" build "
4857 << libraryVersion.buildNumber;
4858 if( libraryVersion.branchName !=
"master" )
4859 std::cout <<
" (" << libraryVersion.branchName <<
" branch)";
4862 m_cli.usage( std::cout, processName );
4863 std::cout <<
"For more detail usage please see the project docs\n" << std::endl;
4866 int applyCommandLine(
int argc,
char*
const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
4868 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
4869 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
4870 if( m_configData.showHelp )
4871 showHelp( m_configData.processName );
4874 catch( std::exception& ex ) {
4876 Colour colourGuard( Colour::Red );
4877 std::cerr <<
"\nError(s) in input:\n"
4878 << Text( ex.what(), TextAttributes().setIndent(2) )
4881 m_cli.usage( std::cout, m_configData.processName );
4882 return (std::numeric_limits<int>::max)();
4887 void useConfigData( ConfigData
const& _configData ) {
4888 m_configData = _configData;
4892 int run(
int argc,
char*
const argv[] ) {
4894 int returnCode = applyCommandLine( argc, argv );
4895 if( returnCode == 0 )
4901 if( m_configData.showHelp )
4907 Runner runner( m_config );
4910 if( Option<std::size_t> listed = list( config() ) )
4911 return static_cast<int>( *listed );
4913 return static_cast<int>( runner.runTests().assertions.failed );
4915 catch( std::exception& ex ) {
4916 std::cerr << ex.what() << std::endl;
4917 return (std::numeric_limits<int>::max)();
4921 Clara::CommandLine<ConfigData>
const& cli()
const {
4924 std::vector<Clara::Parser::Token>
const& unusedTokens()
const {
4925 return m_unusedTokens;
4927 ConfigData& configData() {
4928 return m_configData;
4932 m_config =
new Config( m_configData );
4937 Clara::CommandLine<ConfigData> m_cli;
4938 std::vector<Clara::Parser::Token> m_unusedTokens;
4939 ConfigData m_configData;
4940 Ptr<Config> m_config;
4943 bool Session::alreadyInstantiated =
false;
4948 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
4951 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
4960 class TestRegistry :
public ITestCaseRegistry {
4962 TestRegistry() : m_unnamedCount( 0 ) {}
4963 virtual ~TestRegistry();
4965 virtual void registerTest( TestCase
const& testCase ) {
4966 std::string name = testCase.getTestCaseInfo().name;
4968 std::ostringstream oss;
4969 oss <<
"Anonymous test case " << ++m_unnamedCount;
4970 return registerTest( testCase.withName( oss.str() ) );
4973 if( m_functions.find( testCase ) == m_functions.end() ) {
4974 m_functions.insert( testCase );
4975 m_functionsInOrder.push_back( testCase );
4976 if( !testCase.isHidden() )
4977 m_nonHiddenFunctions.push_back( testCase );
4980 TestCase
const& prev = *m_functions.find( testCase );
4981 std::cerr <<
"error: TEST_CASE( \"" << name <<
"\" ) already defined.\n"
4982 <<
"\tFirst seen at " << prev.getTestCaseInfo().lineInfo <<
"\n"
4983 <<
"\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
4988 virtual std::vector<TestCase>
const& getAllTests()
const {
4989 return m_functionsInOrder;
4992 virtual std::vector<TestCase>
const& getAllNonHiddenTests()
const {
4993 return m_nonHiddenFunctions;
4997 virtual std::vector<TestCase> getMatchingTestCases( std::string
const& rawTestSpec )
const {
4998 std::vector<TestCase> matchingTests;
4999 getMatchingTestCases( rawTestSpec, matchingTests );
5000 return matchingTests;
5004 virtual void getMatchingTestCases( std::string
const& rawTestSpec, std::vector<TestCase>& matchingTestsOut )
const {
5005 TestCaseFilter filter( rawTestSpec );
5007 std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
5008 std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
5009 for(; it != itEnd; ++it ) {
5010 if( filter.shouldInclude( *it ) ) {
5011 matchingTestsOut.push_back( *it );
5015 virtual void getMatchingTestCases( TestCaseFilters
const& filters, std::vector<TestCase>& matchingTestsOut )
const {
5016 std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
5017 std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
5019 for(; it != itEnd; ++it )
5020 if( filters.shouldInclude( *it ) )
5021 matchingTestsOut.push_back( *it );
5026 std::set<TestCase> m_functions;
5027 std::vector<TestCase> m_functionsInOrder;
5028 std::vector<TestCase> m_nonHiddenFunctions;
5029 size_t m_unnamedCount;
5034 class FreeFunctionTestCase :
public SharedImpl<ITestCase> {
5037 FreeFunctionTestCase(
TestFunction fun ) : m_fun( fun ) {}
5039 virtual void invoke()
const {
5044 virtual ~FreeFunctionTestCase();
5049 inline std::string extractClassName( std::string
const& classOrQualifiedMethodName ) {
5050 std::string className = classOrQualifiedMethodName;
5053 std::size_t lastColons = className.rfind(
"::" );
5054 std::size_t penultimateColons = className.rfind(
"::", lastColons-1 );
5055 if( penultimateColons == std::string::npos )
5056 penultimateColons = 1;
5057 className = className.substr( penultimateColons, lastColons-penultimateColons );
5065 SourceLineInfo
const& lineInfo,
5066 NameAndDesc
const& nameAndDesc ) {
5067 registerTestCase(
new FreeFunctionTestCase(
function ),
"", nameAndDesc, lineInfo );
5070 AutoReg::~AutoReg() {}
5072 void AutoReg::registerTestCase( ITestCase* testCase,
5073 char const* classOrQualifiedMethodName,
5074 NameAndDesc
const& nameAndDesc,
5075 SourceLineInfo
const& lineInfo ) {
5079 extractClassName( classOrQualifiedMethodName ),
5081 nameAndDesc.description,
5088 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
5094 class ReporterRegistry :
public IReporterRegistry {
5098 virtual ~ReporterRegistry() {
5102 virtual IStreamingReporter* create( std::string
const& name, Ptr<IConfig>
const& config )
const {
5103 FactoryMap::const_iterator it = m_factories.find( name );
5104 if( it == m_factories.end() )
5106 return it->second->create( ReporterConfig( config ) );
5109 void registerReporter( std::string
const& name, IReporterFactory* factory ) {
5110 m_factories.insert( std::make_pair( name, factory ) );
5113 FactoryMap
const& getFactories()
const {
5118 FactoryMap m_factories;
5123 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
5126 #import "Foundation/Foundation.h"
5131 class ExceptionTranslatorRegistry :
public IExceptionTranslatorRegistry {
5133 ~ExceptionTranslatorRegistry() {
5137 virtual void registerTranslator(
const IExceptionTranslator* translator ) {
5138 m_translators.push_back( translator );
5148 @catch (NSException *exception) {
5149 return toString( [exception description] );
5155 catch( std::exception& ex ) {
5158 catch( std::string& msg ) {
5161 catch(
const char* msg ) {
5165 return tryTranslators( m_translators.begin() );
5169 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it )
const {
5170 if( it == m_translators.end() )
5171 return "Unknown exception";
5174 return (*it)->translate();
5177 return tryTranslators( it+1 );
5182 std::vector<const IExceptionTranslator*> m_translators;
5190 class RegistryHub :
public IRegistryHub,
public IMutableRegistryHub {
5192 RegistryHub( RegistryHub
const& );
5193 void operator=( RegistryHub
const& );
5198 virtual IReporterRegistry
const& getReporterRegistry()
const {
5199 return m_reporterRegistry;
5201 virtual ITestCaseRegistry
const& getTestCaseRegistry()
const {
5202 return m_testCaseRegistry;
5204 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
5205 return m_exceptionTranslatorRegistry;
5209 virtual void registerReporter( std::string
const& name, IReporterFactory* factory ) {
5210 m_reporterRegistry.registerReporter( name, factory );
5212 virtual void registerTest( TestCase
const& testInfo ) {
5213 m_testCaseRegistry.registerTest( testInfo );
5215 virtual void registerTranslator(
const IExceptionTranslator* translator ) {
5216 m_exceptionTranslatorRegistry.registerTranslator( translator );
5220 TestRegistry m_testCaseRegistry;
5221 ReporterRegistry m_reporterRegistry;
5222 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
5226 inline RegistryHub*& getTheRegistryHub() {
5227 static RegistryHub* theRegistryHub = NULL;
5228 if( !theRegistryHub )
5229 theRegistryHub =
new RegistryHub();
5230 return theRegistryHub;
5235 return *getTheRegistryHub();
5238 return *getTheRegistryHub();
5241 delete getTheRegistryHub();
5242 getTheRegistryHub() = NULL;
5252 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
5259 : m_lineInfo( lineInfo ) {
5260 std::ostringstream oss;
5261 oss << lineInfo <<
": function ";
5262 oss <<
"not implemented";
5267 return m_what.c_str();
5273 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
5276 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
5279 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
5281 #include <streambuf>
5285 class StreamBufBase :
public std::streambuf {
5287 virtual ~StreamBufBase() throw();
5291 #include <stdexcept>
5296 template<
typename WriterF,
size_t bufferSize=256>
5297 class StreamBufImpl :
public StreamBufBase {
5298 char data[bufferSize];
5303 setp( data, data +
sizeof(data) );
5306 ~StreamBufImpl() throw() {
5311 int overflow(
int c ) {
5315 if( pbase() == epptr() )
5316 m_writer( std::string( 1, static_cast<char>( c ) ) );
5318 sputc( static_cast<char>( c ) );
5324 if( pbase() != pptr() ) {
5325 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
5326 setp( pbase(), epptr() );
5334 struct OutputDebugWriter {
5336 void operator()( std::string
const&str ) {
5342 : streamBuf( NULL ), isOwned( false )
5345 Stream::Stream( std::streambuf* _streamBuf,
bool _isOwned )
5346 : streamBuf( _streamBuf ), isOwned( _isOwned )
5349 void Stream::release() {
5360 class Context :
public IMutableContext {
5362 Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
5363 Context( Context
const& );
5364 void operator=( Context
const& );
5368 return *m_resultCapture;
5370 virtual IRunner& getRunner() {
5373 virtual size_t getGeneratorIndex( std::string
const& fileInfo,
size_t totalSize ) {
5374 return getGeneratorsForCurrentTest()
5375 .getGeneratorInfo( fileInfo, totalSize )
5378 virtual bool advanceGeneratorsForCurrentTest() {
5379 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
5380 return generators && generators->moveNext();
5383 virtual Ptr<IConfig const> getConfig()
const {
5388 virtual void setResultCapture( IResultCapture* resultCapture ) {
5389 m_resultCapture = resultCapture;
5391 virtual void setRunner( IRunner* runner ) {
5394 virtual void setConfig( Ptr<IConfig const>
const& config ) {
5401 IGeneratorsForTest* findGeneratorsForCurrentTest() {
5404 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
5405 m_generatorsByTestName.find( testName );
5406 return it != m_generatorsByTestName.end()
5411 IGeneratorsForTest& getGeneratorsForCurrentTest() {
5412 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
5416 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
5422 Ptr<IConfig const> m_config;
5424 IResultCapture* m_resultCapture;
5425 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
5429 Context* currentContext = NULL;
5432 if( !currentContext )
5433 currentContext =
new Context();
5434 return *currentContext;
5441 if( streamName ==
"stdout" )
return Stream( std::cout.rdbuf(),
false );
5442 if( streamName ==
"stderr" )
return Stream( std::cerr.rdbuf(),
false );
5443 if( streamName ==
"debug" )
return Stream(
new StreamBufImpl<OutputDebugWriter>,
true );
5445 throw std::domain_error(
"Unknown stream: " + streamName );
5449 delete currentContext;
5450 currentContext = NULL;
5455 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
5457 namespace Catch {
namespace Detail {
5458 struct IColourImpl {
5459 virtual ~IColourImpl() {}
5460 virtual void use( Colour::Code _colourCode ) = 0;
5464 #if defined ( CATCH_PLATFORM_WINDOWS )
5473 #include <windows.h>
5479 class Win32ColourImpl :
public Detail::IColourImpl {
5481 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
5483 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
5484 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
5485 originalAttributes = csbiInfo.wAttributes;
5488 virtual void use( Colour::Code _colourCode ) {
5489 switch( _colourCode ) {
5490 case Colour::None:
return setTextAttribute( originalAttributes );
5491 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
5492 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
5493 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
5494 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
5495 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
5496 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
5497 case Colour::Grey:
return setTextAttribute( 0 );
5499 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
5500 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
5501 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
5502 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
5504 case Colour::Bright:
throw std::logic_error(
"not a colour" );
5509 void setTextAttribute( WORD _textAttribute ) {
5510 SetConsoleTextAttribute( stdoutHandle, _textAttribute );
5512 HANDLE stdoutHandle;
5513 WORD originalAttributes;
5516 inline bool shouldUseColourForPlatform() {
5520 Win32ColourImpl platformColourImpl;
5525 #else // Not Windows - assumed to be POSIX compatible
5536 class PosixColourImpl :
public Detail::IColourImpl {
5538 virtual void use( Colour::Code _colourCode ) {
5539 switch( _colourCode ) {
5541 case Colour::White:
return setColour(
"[0m" );
5542 case Colour::Red:
return setColour(
"[0;31m" );
5543 case Colour::Green:
return setColour(
"[0;32m" );
5544 case Colour::Blue:
return setColour(
"[0:34m" );
5545 case Colour::Cyan:
return setColour(
"[0;36m" );
5546 case Colour::Yellow:
return setColour(
"[0;33m" );
5547 case Colour::Grey:
return setColour(
"[1;30m" );
5549 case Colour::LightGrey:
return setColour(
"[0;37m" );
5550 case Colour::BrightRed:
return setColour(
"[1;31m" );
5551 case Colour::BrightGreen:
return setColour(
"[1;32m" );
5552 case Colour::BrightWhite:
return setColour(
"[1;37m" );
5554 case Colour::Bright:
throw std::logic_error(
"not a colour" );
5558 void setColour(
const char* _escapeCode ) {
5559 std::cout <<
'\033' << _escapeCode;
5563 inline bool shouldUseColourForPlatform() {
5564 return isatty(STDOUT_FILENO);
5567 PosixColourImpl platformColourImpl;
5572 #endif // not Windows
5577 struct NoColourImpl : Detail::IColourImpl {
5578 void use( Colour::Code ) {}
5580 NoColourImpl noColourImpl;
5581 static const bool shouldUseColour = shouldUseColourForPlatform() &&
5585 Colour::Colour( Code _colourCode ){ use( _colourCode ); }
5586 Colour::~Colour(){ use( None ); }
5587 void Colour::use( Code _colourCode ) {
5588 impl->use( _colourCode );
5591 Detail::IColourImpl* Colour::impl = shouldUseColour
5592 ?
static_cast<Detail::IColourImpl*
>( &platformColourImpl )
5593 : static_cast<Detail::IColourImpl*>( &noColourImpl );
5598 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
5606 struct GeneratorInfo : IGeneratorInfo {
5608 GeneratorInfo( std::size_t size )
5614 if( ++m_currentIndex == m_size ) {
5621 std::size_t getCurrentIndex()
const {
5622 return m_currentIndex;
5626 std::size_t m_currentIndex;
5631 class GeneratorsForTest :
public IGeneratorsForTest {
5634 ~GeneratorsForTest() {
5638 IGeneratorInfo& getGeneratorInfo( std::string
const& fileInfo, std::size_t size ) {
5639 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
5640 if( it == m_generatorsByName.end() ) {
5641 IGeneratorInfo* info =
new GeneratorInfo( size );
5642 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
5643 m_generatorsInOrder.push_back( info );
5650 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
5651 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
5652 for(; it != itEnd; ++it ) {
5653 if( (*it)->moveNext() )
5660 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
5661 std::vector<IGeneratorInfo*> m_generatorsInOrder;
5666 return new GeneratorsForTest();
5672 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
5677 SourceLineInfo
const& _lineInfo,
5678 std::string
const& _capturedExpression,
5680 : macroName( _macroName ),
5681 lineInfo( _lineInfo ),
5682 capturedExpression( _capturedExpression ),
5683 resultDisposition( _resultDisposition )
5690 m_resultData( data )
5719 return "!" +
m_info.capturedExpression;
5752 #define TWOBLUECUBES_CATCH_EXPRESSIONRESULT_BUILDER_HPP_INCLUDED
5762 : m_data( other.m_data ),
5763 m_exprComponents( other.m_exprComponents )
5765 m_stream << other.m_stream.str();
5768 m_data = other.m_data;
5769 m_exprComponents = other.m_exprComponents;
5771 m_stream << other.m_stream.str();
5783 m_exprComponents.shouldNegate =
shouldNegate( resultDisposition );
5787 m_exprComponents.lhs = lhs;
5791 m_exprComponents.rhs = rhs;
5795 m_exprComponents.op = op;
5802 AssertionResultData data = m_data;
5805 if( m_exprComponents.shouldNegate && data.resultType ==
ResultWas::Ok )
5810 data.message = m_stream.str();
5812 if( m_exprComponents.shouldNegate ) {
5813 if( m_exprComponents.op ==
"" )
5814 data.reconstructedExpression =
"!" + data.reconstructedExpression;
5816 data.reconstructedExpression =
"!(" + data.reconstructedExpression + ")";
5818 return AssertionResult( info, data );
5821 if( m_exprComponents.op ==
"" )
5822 return m_exprComponents.lhs.empty() ? info.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
5823 else if( m_exprComponents.op ==
"matches" )
5824 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
5825 else if( m_exprComponents.op !=
"!" ) {
5826 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
5827 m_exprComponents.lhs.find("\n") == std::string::npos &&
5828 m_exprComponents.rhs.find("\n") == std::string::npos )
5829 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
5831 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
5834 return "{can't expand - use " + info.macroName + "_FALSE( " + info.capturedExpression.substr(1) + " ) instead of " + info.macroName + "( " + info.capturedExpression + " ) for better diagnostics}";
5840 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
5845 std::string
const& _className,
5846 std::string
const& _name,
5847 std::string
const& _descOrTags,
5848 SourceLineInfo
const& _lineInfo )
5850 std::string desc = _descOrTags;
5852 std::set<std::string> tags;
5853 TagExtracter( tags ).parse( desc );
5854 if( tags.find(
"hide" ) != tags.end() || tags.find(
"." ) != tags.end() )
5858 tags.insert(
"hide" );
5861 TestCaseInfo info( _name, _className, desc, tags, isHidden, _lineInfo );
5862 return TestCase( _testCase, info );
5866 std::string
const& _className,
5867 std::string
const& _description,
5868 std::set<std::string>
const& _tags,
5870 SourceLineInfo
const& _lineInfo )
5872 className( _className ),
5873 description( _description ),
5875 lineInfo( _lineInfo ),
5876 isHidden( _isHidden )
5878 std::ostringstream oss;
5879 for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it )
5880 oss << "[" << *it << "]";
5881 tagsAsString = oss.str();
5885 : name( other.name ),
5886 className( other.className ),
5887 description( other.description ),
5889 tagsAsString( other.tagsAsString ),
5890 lineInfo( other.lineInfo ),
5891 isHidden( other.isHidden )
5894 TestCase::TestCase( ITestCase* testCase, TestCaseInfo
const& info ) : TestCaseInfo( info ), test( testCase ) {}
5897 : TestCaseInfo( other ),
5903 other.name = _newName;
5916 return tags.find(
toLower( tag ) ) != tags.end();
5920 TagExpressionParser( exp ).parse( tagPattern );
5921 return exp.matches( tags );
5928 test.swap( other.test );
5929 className.swap( other.className );
5930 name.swap( other.name );
5932 std::swap( lineInfo, other.lineInfo );
5936 return test.get() == other.test.get() &&
5937 name == other.name &&
5938 className == other.className;
5942 return name < other.name;
5958 #define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED
5961 TagParser::~TagParser() {}
5963 void TagParser::parse( std::string
const& str ) {
5964 std::size_t pos = 0;
5965 while( pos < str.size() ) {
5968 std::size_t end = str.find_first_of(
']', pos );
5969 if( end != std::string::npos ) {
5970 acceptTag( str.substr( pos+1, end-pos-1 ) );
5986 TagExtracter::TagExtracter( std::set<std::string>& tags )
5990 TagExtracter::~TagExtracter() {}
5992 void TagExtracter::parse( std::string& description ) {
5993 TagParser::parse( description );
5994 description = m_remainder;
5997 void TagExtracter::acceptTag( std::string
const& tag ) {
5998 m_tags.insert(
toLower( tag ) );
6000 void TagExtracter::acceptChar(
char c ) {
6004 Tag::Tag() : m_isNegated( false ) {}
6005 Tag::Tag( std::string
const& name,
bool isNegated )
6007 m_isNegated( isNegated )
6010 std::string Tag::getName()
const {
6013 bool Tag::isNegated()
const {
6017 bool Tag::operator ! ()
const {
6018 return m_name.empty();
6021 void TagSet::add( Tag
const& tag ) {
6022 m_tags.insert( std::make_pair(
toLower( tag.getName() ), tag ) );
6025 bool TagSet::empty()
const {
6026 return m_tags.empty();
6029 bool TagSet::matches( std::set<std::string>
const& tags )
const {
6030 for( TagMap::const_iterator
6031 it = m_tags.begin(), itEnd = m_tags.end();
6034 bool found = tags.find( it->first ) != tags.end();
6035 if( found == it->second.isNegated() )
6041 bool TagExpression::matches( std::set<std::string>
const& tags )
const {
6042 for( std::vector<TagSet>::const_iterator
6043 it = m_tagSets.begin(), itEnd = m_tagSets.end();
6046 if( it->matches( tags ) )
6051 TagExpressionParser::TagExpressionParser( TagExpression& exp )
6052 : m_isNegated( false ),
6056 TagExpressionParser::~TagExpressionParser() {}
6058 void TagExpressionParser::acceptTag( std::string
const& tag ) {
6059 m_currentTagSet.add( Tag( tag, m_isNegated ) );
6060 m_isNegated =
false;
6063 void TagExpressionParser::acceptChar(
char c ) {
6069 m_exp.m_tagSets.push_back( m_currentTagSet );
6070 m_currentTagSet = TagSet();
6075 void TagExpressionParser::endParse() {
6076 if( !m_currentTagSet.empty() )
6077 m_exp.m_tagSets.push_back( m_currentTagSet );
6083 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
6087 TestCaseFilter::TestCaseFilter( std::string
const& testSpec, IfFilterMatches::DoWhat matchBehaviour )
6088 : m_stringToMatch(
toLower( testSpec ) ),
6089 m_filterType( matchBehaviour ),
6090 m_wildcardPosition( NoWildcard )
6092 if( m_filterType == IfFilterMatches::AutoDetectBehaviour ) {
6093 if(
startsWith( m_stringToMatch,
"exclude:" ) ) {
6094 m_stringToMatch = m_stringToMatch.substr( 8 );
6095 m_filterType = IfFilterMatches::ExcludeTests;
6097 else if(
startsWith( m_stringToMatch,
"~" ) ) {
6098 m_stringToMatch = m_stringToMatch.substr( 1 );
6099 m_filterType = IfFilterMatches::ExcludeTests;
6102 m_filterType = IfFilterMatches::IncludeTests;
6107 m_stringToMatch = m_stringToMatch.substr( 1 );
6108 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
6110 if(
endsWith( m_stringToMatch,
"*" ) ) {
6111 m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
6112 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
6116 IfFilterMatches::DoWhat TestCaseFilter::getFilterType()
const {
6117 return m_filterType;
6120 bool TestCaseFilter::shouldInclude( TestCase
const& testCase )
const {
6121 return isMatch( testCase ) == (m_filterType == IfFilterMatches::IncludeTests);
6125 #pragma clang diagnostic push
6126 #pragma clang diagnostic ignored "-Wunreachable-code"
6129 bool TestCaseFilter::isMatch( TestCase
const& testCase )
const {
6130 std::string name = testCase.getTestCaseInfo().name;
6133 switch( m_wildcardPosition ) {
6135 return m_stringToMatch == name;
6136 case WildcardAtStart:
6137 return endsWith( name, m_stringToMatch );
6140 case WildcardAtBothEnds:
6141 return contains( name, m_stringToMatch );
6143 throw std::logic_error(
"Unhandled wildcard type" );
6147 #pragma clang diagnostic pop
6150 TestCaseFilters::TestCaseFilters( std::string
const& name ) : m_name( name ) {}
6152 std::string TestCaseFilters::getName()
const {
6156 void TestCaseFilters::addFilter( TestCaseFilter
const& filter ) {
6157 if( filter.getFilterType() == IfFilterMatches::ExcludeTests )
6158 m_exclusionFilters.push_back( filter );
6160 m_inclusionFilters.push_back( filter );
6163 void TestCaseFilters::addTags( std::string
const& tagPattern ) {
6165 TagExpressionParser( exp ).parse( tagPattern );
6167 m_tagExpressions.push_back( exp );
6170 bool TestCaseFilters::shouldInclude( TestCase
const& testCase )
const {
6171 if( !m_tagExpressions.empty() ) {
6172 std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
6173 std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
6174 for(; it != itEnd; ++it )
6175 if( it->matches( testCase.getTags() ) )
6181 if( !m_inclusionFilters.empty() ) {
6182 std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
6183 std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
6184 for(; it != itEnd; ++it )
6185 if( it->shouldInclude( testCase ) )
6190 else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
6191 return !testCase.isHidden();
6194 std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
6195 std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
6196 for(; it != itEnd; ++it )
6197 if( !it->shouldInclude( testCase ) )
6204 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
6209 Version libraryVersion( 1, 0, 25,
"master" );
6213 #define TWOBLUECUBES_CATCH_TEXT_HPP_INCLUDED
6220 Text::Text( std::string
const& _str, TextAttributes
const& _attr )
6223 std::string wrappableChars =
" [({.,/|\\-";
6224 std::size_t indent = _attr.initialIndent != std::string::npos
6225 ? _attr.initialIndent
6227 std::string remainder = _str;
6229 while( !remainder.empty() ) {
6230 if( lines.size() >= 1000 ) {
6231 lines.push_back(
"... message truncated due to excessive size" );
6234 std::size_t tabPos = std::string::npos;
6235 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
6236 std::size_t pos = remainder.find_first_of(
'\n' );
6237 if( pos <= width ) {
6240 pos = remainder.find_last_of( _attr.tabChar, width );
6241 if( pos != std::string::npos ) {
6243 if( remainder[width] ==
'\n' )
6245 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
6248 if( width == remainder.size() ) {
6249 spliceLine( indent, remainder, width );
6251 else if( remainder[width] ==
'\n' ) {
6252 spliceLine( indent, remainder, width );
6253 if( width <= 1 || remainder.size() != 1 )
6254 remainder = remainder.substr( 1 );
6255 indent = _attr.indent;
6258 pos = remainder.find_last_of( wrappableChars, width );
6259 if( pos != std::string::npos && pos > 0 ) {
6260 spliceLine( indent, remainder, pos );
6261 if( remainder[0] ==
' ' )
6262 remainder = remainder.substr( 1 );
6265 spliceLine( indent, remainder, width-1 );
6266 lines.back() += "-";
6268 if( lines.size() == 1 )
6269 indent = _attr.indent;
6270 if( tabPos != std::string::npos )
6276 void Text::spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
6277 lines.push_back( std::string( _indent,
' ' ) + _remainder.substr( 0, _pos ) );
6278 _remainder = _remainder.substr( _pos );
6282 std::ostringstream oss;
6287 std::ostream&
operator << ( std::ostream& _stream, Text
const& _text ) {
6288 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
6289 it != itEnd; ++it ) {
6290 if( it != _text.begin() )
6300 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
6305 SourceLineInfo
const& _lineInfo,
6307 : macroName( _macroName ),
6308 lineInfo( _lineInfo ),
6310 sequence( ++globalCount )
6314 unsigned int MessageInfo::globalCount = 0;
6319 : m_info( builder.m_info )
6321 m_info.message = builder.m_stream.str();
6331 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
6334 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
6339 struct IReporter : IShared {
6340 virtual ~IReporter();
6342 virtual bool shouldRedirectStdout()
const = 0;
6344 virtual void StartTesting() = 0;
6345 virtual void EndTesting( Totals
const& totals ) = 0;
6346 virtual void StartGroup( std::string
const& groupName ) = 0;
6347 virtual void EndGroup( std::string
const& groupName, Totals
const& totals ) = 0;
6348 virtual void StartTestCase( TestCaseInfo
const& testInfo ) = 0;
6349 virtual void EndTestCase( TestCaseInfo
const& testInfo, Totals
const& totals, std::string
const& stdOut, std::string
const& stdErr ) = 0;
6350 virtual void StartSection( std::string
const& sectionName, std::string
const& description ) = 0;
6351 virtual void EndSection( std::string
const& sectionName, Counts
const& assertions ) = 0;
6352 virtual void NoAssertionsInSection( std::string
const& sectionName ) = 0;
6353 virtual void NoAssertionsInTestCase( std::string
const& testName ) = 0;
6354 virtual void Aborted() = 0;
6355 virtual void Result( AssertionResult
const& result ) = 0;
6358 class LegacyReporterAdapter :
public SharedImpl<IStreamingReporter>
6361 LegacyReporterAdapter( Ptr<IReporter>
const& legacyReporter );
6362 virtual ~LegacyReporterAdapter();
6364 virtual ReporterPreferences getPreferences()
const;
6365 virtual void noMatchingTestCases( std::string
const& );
6366 virtual void testRunStarting( TestRunInfo
const& );
6367 virtual void testGroupStarting( GroupInfo
const& groupInfo );
6368 virtual void testCaseStarting( TestCaseInfo
const& testInfo );
6369 virtual void sectionStarting( SectionInfo
const& sectionInfo );
6370 virtual void assertionStarting( AssertionInfo
const& );
6371 virtual bool assertionEnded( AssertionStats
const& assertionStats );
6372 virtual void sectionEnded( SectionStats
const& sectionStats );
6373 virtual void testCaseEnded( TestCaseStats
const& testCaseStats );
6374 virtual void testGroupEnded( TestGroupStats
const& testGroupStats );
6375 virtual void testRunEnded( TestRunStats
const& testRunStats );
6378 Ptr<IReporter> m_legacyReporter;
6384 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter>
const& legacyReporter )
6385 : m_legacyReporter( legacyReporter )
6387 LegacyReporterAdapter::~LegacyReporterAdapter() {}
6389 ReporterPreferences LegacyReporterAdapter::getPreferences()
const {
6390 ReporterPreferences prefs;
6391 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
6395 void LegacyReporterAdapter::noMatchingTestCases( std::string
const& ) {}
6396 void LegacyReporterAdapter::testRunStarting( TestRunInfo
const& ) {
6397 m_legacyReporter->StartTesting();
6399 void LegacyReporterAdapter::testGroupStarting( GroupInfo
const& groupInfo ) {
6400 m_legacyReporter->StartGroup( groupInfo.name );
6402 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo
const& testInfo ) {
6403 m_legacyReporter->StartTestCase( testInfo );
6405 void LegacyReporterAdapter::sectionStarting( SectionInfo
const& sectionInfo ) {
6406 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
6408 void LegacyReporterAdapter::assertionStarting( AssertionInfo
const& ) {
6412 bool LegacyReporterAdapter::assertionEnded( AssertionStats
const& assertionStats ) {
6413 if( assertionStats.assertionResult.getResultType() !=
ResultWas::Ok ) {
6414 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
6418 ExpressionResultBuilder expressionBuilder( it->type );
6419 expressionBuilder << it->message;
6421 AssertionResult result = expressionBuilder.buildResult( info );
6422 m_legacyReporter->Result( result );
6426 m_legacyReporter->Result( assertionStats.assertionResult );
6429 void LegacyReporterAdapter::sectionEnded( SectionStats
const& sectionStats ) {
6430 if( sectionStats.missingAssertions )
6431 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
6432 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
6434 void LegacyReporterAdapter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
6435 m_legacyReporter->EndTestCase
6436 ( testCaseStats.testInfo,
6437 testCaseStats.totals,
6438 testCaseStats.stdOut,
6439 testCaseStats.stdErr );
6441 void LegacyReporterAdapter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
6442 if( testGroupStats.aborting )
6443 m_legacyReporter->Aborted();
6444 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
6446 void LegacyReporterAdapter::testRunEnded( TestRunStats
const& testRunStats ) {
6447 m_legacyReporter->EndTesting( testRunStats.totals );
6454 #pragma clang diagnostic push
6455 #pragma clang diagnostic ignored "-Wc++11-long-long"
6458 #ifdef CATCH_PLATFORM_WINDOWS
6459 #include <windows.h>
6461 #include <sys/time.h>
6467 #ifdef CATCH_PLATFORM_WINDOWS
6468 uint64_t getCurrentTicks() {
6469 static uint64_t hz=0, hzo=0;
6471 QueryPerformanceFrequency((LARGE_INTEGER*)&hz);
6472 QueryPerformanceCounter((LARGE_INTEGER*)&hzo);
6475 QueryPerformanceCounter((LARGE_INTEGER*)&t);
6476 return ((t-hzo)*1000000)/hz;
6479 uint64_t getCurrentTicks() {
6481 gettimeofday(&t,NULL);
6482 return (uint64_t)t.tv_sec * 1000000ull + (uint64_t)t.tv_usec;
6488 m_ticks = getCurrentTicks();
6491 return (
unsigned int)(getCurrentTicks() - m_ticks);
6494 return (
unsigned int)((getCurrentTicks() - m_ticks)/1000);
6497 return (getCurrentTicks() - m_ticks)/1000000.0;
6503 #pragma clang diagnostic pop
6506 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
6510 bool startsWith( std::string
const& s, std::string
const& prefix ) {
6511 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
6513 bool endsWith( std::string
const& s, std::string
const& suffix ) {
6514 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
6516 bool contains( std::string
const& s, std::string
const& infix ) {
6517 return s.find( infix ) != std::string::npos;
6520 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
6522 std::string
toLower( std::string
const& s ) {
6527 std::string
trim( std::string
const& str ) {
6528 static char const* whitespaceChars =
"\n\r\t ";
6529 std::string::size_type start = str.find_first_not_of( whitespaceChars );
6530 std::string::size_type end = str.find_last_not_of( whitespaceChars );
6532 return start != std::string::npos ? str.substr( start, 1+end-start ) :
"";
6540 std::ostream&
operator << ( std::ostream& os, pluralise
const& pluraliser ) {
6541 os << pluraliser.m_count <<
" " << pluraliser.m_label;
6542 if( pluraliser.m_count != 1 )
6553 : file( other.file ),
6557 return file.empty();
6560 return line == other.line &&
file == other.file;
6563 std::ostream&
operator << ( std::ostream& os, SourceLineInfo
const& info ) {
6565 os << info.file <<
"(" << info.line <<
")";
6567 os << info.file <<
":" << info.line;
6572 void throwLogicError( std::string
const& message, SourceLineInfo
const& locationInfo ) {
6573 std::ostringstream oss;
6574 oss << locationInfo <<
": Internal Catch error: '" << message <<
"'";
6576 throw std::logic_error( oss.str() );
6581 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
6586 std::string
const& name,
6587 std::string
const& description )
6588 : m_info( name, description, lineInfo ),
6595 if( m_sectionIncluded )
6600 Section::operator bool() {
6601 return m_sectionIncluded;
6607 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
6611 #ifdef CATCH_PLATFORM_MAC
6614 #include <stdbool.h>
6615 #include <sys/types.h>
6617 #include <sys/sysctl.h>
6629 struct kinfo_proc info;
6635 info.kp_proc.p_flag = 0;
6642 mib[2] = KERN_PROC_PID;
6647 size =
sizeof(info);
6648 if( sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size, NULL, 0) != 0 ) {
6649 std::cerr <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
6655 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
6659 #elif defined(_MSC_VER)
6660 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
6663 return IsDebuggerPresent() != 0;
6666 #elif defined(__MINGW32__)
6667 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
6670 return IsDebuggerPresent() != 0;
6679 #ifdef CATCH_PLATFORM_WINDOWS
6680 extern "C" __declspec(dllimport)
void __stdcall OutputDebugStringA( const
char* );
6683 ::OutputDebugStringA( text.c_str() );
6696 #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
6699 #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
6703 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
6705 StreamingReporterBase( ReporterConfig
const& _config )
6706 : m_config( _config.fullConfig() ),
6707 stream( _config.stream() )
6710 virtual ~StreamingReporterBase();
6712 virtual void noMatchingTestCases( std::string
const& ) {}
6714 virtual void testRunStarting( TestRunInfo
const& _testRunInfo ) {
6715 currentTestRunInfo = _testRunInfo;
6717 virtual void testGroupStarting( GroupInfo
const& _groupInfo ) {
6718 currentGroupInfo = _groupInfo;
6721 virtual void testCaseStarting( TestCaseInfo
const& _testInfo ) {
6722 currentTestCaseInfo = _testInfo;
6724 virtual void sectionStarting( SectionInfo
const& _sectionInfo ) {
6725 m_sectionStack.push_back( _sectionInfo );
6728 virtual void sectionEnded( SectionStats
const& ) {
6729 m_sectionStack.pop_back();
6731 virtual void testCaseEnded( TestCaseStats
const& ) {
6732 currentTestCaseInfo.reset();
6733 assert( m_sectionStack.empty() );
6735 virtual void testGroupEnded( TestGroupStats
const& ) {
6736 currentGroupInfo.reset();
6738 virtual void testRunEnded( TestRunStats
const& ) {
6739 currentTestCaseInfo.reset();
6740 currentGroupInfo.reset();
6741 currentTestRunInfo.reset();
6744 Ptr<IConfig> m_config;
6745 std::ostream& stream;
6747 LazyStat<TestRunInfo> currentTestRunInfo;
6748 LazyStat<GroupInfo> currentGroupInfo;
6749 LazyStat<TestCaseInfo> currentTestCaseInfo;
6751 std::vector<SectionInfo> m_sectionStack;
6754 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
6755 template<
typename T,
typename ChildNodeT>
6756 struct Node : SharedImpl<> {
6757 explicit Node( T
const& _value ) : value( _value ) {}
6760 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
6762 ChildNodes children;
6764 struct SectionNode : SharedImpl<> {
6765 explicit SectionNode( SectionStats
const& _stats ) : stats( _stats ) {}
6766 virtual ~SectionNode();
6768 bool operator == ( SectionNode
const& other )
const {
6769 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
6771 bool operator == ( Ptr<SectionNode>
const& other )
const {
6772 return operator==( *other );
6776 typedef std::vector<Ptr<SectionNode> > ChildSections;
6777 typedef std::vector<AssertionStats> Assertions;
6778 ChildSections childSections;
6779 Assertions assertions;
6784 struct BySectionInfo {
6785 BySectionInfo( SectionInfo
const& other ) : m_other( other ) {}
6786 bool operator() ( Ptr<SectionNode>
const& node )
const {
6787 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
6790 SectionInfo
const& m_other;
6793 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
6794 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
6795 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
6797 CumulativeReporterBase( ReporterConfig
const& _config )
6798 : m_config( _config.fullConfig() ),
6799 stream( _config.stream() )
6801 ~CumulativeReporterBase();
6803 virtual void testRunStarting( TestRunInfo
const& ) {}
6804 virtual void testGroupStarting( GroupInfo
const& ) {}
6806 virtual void testCaseStarting( TestCaseInfo
const& ) {}
6808 virtual void sectionStarting( SectionInfo
const& sectionInfo ) {
6809 SectionStats incompleteStats( sectionInfo, Counts(), 0,
false );
6810 Ptr<SectionNode> node;
6811 if( m_sectionStack.empty() ) {
6812 if( !m_rootSection )
6813 m_rootSection =
new SectionNode( incompleteStats );
6814 node = m_rootSection;
6817 SectionNode& parentNode = *m_sectionStack.back();
6818 SectionNode::ChildSections::const_iterator it =
6819 std::find_if( parentNode.childSections.begin(),
6820 parentNode.childSections.end(),
6821 BySectionInfo( sectionInfo ) );
6822 if( it == parentNode.childSections.end() ) {
6823 node =
new SectionNode( incompleteStats );
6824 parentNode.childSections.push_back( node );
6829 m_sectionStack.push_back( node );
6830 m_deepestSection = node;
6833 virtual void assertionStarting( AssertionInfo
const& ) {}
6835 virtual bool assertionEnded( AssertionStats
const& assertionStats ) {
6836 assert( !m_sectionStack.empty() );
6837 SectionNode& sectionNode = *m_sectionStack.back();
6838 sectionNode.assertions.push_back( assertionStats );
6841 virtual void sectionEnded( SectionStats
const& sectionStats ) {
6842 assert( !m_sectionStack.empty() );
6843 SectionNode& node = *m_sectionStack.back();
6844 node.stats = sectionStats;
6845 m_sectionStack.pop_back();
6847 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) {
6848 Ptr<TestCaseNode> node =
new TestCaseNode( testCaseStats );
6849 assert( m_sectionStack.size() == 0 );
6850 node->children.push_back( m_rootSection );
6851 m_testCases.push_back( node );
6852 m_rootSection.reset();
6854 assert( m_deepestSection );
6855 m_deepestSection->stdOut = testCaseStats.stdOut;
6856 m_deepestSection->stdErr = testCaseStats.stdErr;
6858 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) {
6859 Ptr<TestGroupNode> node =
new TestGroupNode( testGroupStats );
6860 node->children.swap( m_testCases );
6861 m_testGroups.push_back( node );
6863 virtual void testRunEnded( TestRunStats
const& testRunStats ) {
6864 Ptr<TestRunNode> node =
new TestRunNode( testRunStats );
6865 node->children.swap( m_testGroups );
6866 m_testRuns.push_back( node );
6867 testRunEndedCumulative();
6869 virtual void testRunEndedCumulative() = 0;
6871 Ptr<IConfig> m_config;
6872 std::ostream& stream;
6873 std::vector<AssertionStats> m_assertions;
6874 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
6875 std::vector<Ptr<TestCaseNode> > m_testCases;
6876 std::vector<Ptr<TestGroupNode> > m_testGroups;
6878 std::vector<Ptr<TestRunNode> > m_testRuns;
6880 Ptr<SectionNode> m_rootSection;
6881 Ptr<SectionNode> m_deepestSection;
6882 std::vector<Ptr<SectionNode> > m_sectionStack;
6889 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
6893 template<
typename T>
6894 class LegacyReporterRegistrar {
6896 class ReporterFactory :
public IReporterFactory {
6897 virtual IStreamingReporter* create( ReporterConfig
const& config )
const {
6898 return new LegacyReporterAdapter(
new T( config ) );
6901 virtual std::string getDescription()
const {
6902 return T::getDescription();
6908 LegacyReporterRegistrar( std::string
const& name ) {
6913 template<
typename T>
6914 class ReporterRegistrar {
6916 class ReporterFactory :
public IReporterFactory {
6929 virtual IStreamingReporter* create( ReporterConfig
const& config )
const {
6930 return new T( config );
6933 virtual std::string getDescription()
const {
6934 return T::getDescription();
6940 ReporterRegistrar( std::string
const& name ) {
6946 #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
6947 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
6948 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
6949 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
6952 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
6964 class ScopedElement {
6966 ScopedElement( XmlWriter* writer )
6967 : m_writer( writer )
6970 ScopedElement( ScopedElement
const& other )
6971 : m_writer( other.m_writer ){
6972 other.m_writer = NULL;
6977 m_writer->endElement();
6980 ScopedElement& writeText( std::string
const& text,
bool indent =
true ) {
6981 m_writer->writeText( text, indent );
6985 template<
typename T>
6986 ScopedElement& writeAttribute( std::string
const& name, T
const& attribute ) {
6987 m_writer->writeAttribute( name, attribute );
6992 mutable XmlWriter* m_writer;
6996 : m_tagIsOpen( false ),
6997 m_needsNewline( false ),
7001 XmlWriter( std::ostream& os )
7002 : m_tagIsOpen( false ),
7003 m_needsNewline( false ),
7008 while( !m_tags.empty() )
7012 XmlWriter& operator = ( XmlWriter
const& other ) {
7013 XmlWriter temp( other );
7018 void swap( XmlWriter& other ) {
7019 std::swap( m_tagIsOpen, other.m_tagIsOpen );
7020 std::swap( m_needsNewline, other.m_needsNewline );
7021 std::swap( m_tags, other.m_tags );
7022 std::swap( m_indent, other.m_indent );
7023 std::swap( m_os, other.m_os );
7026 XmlWriter& startElement( std::string
const& name ) {
7028 newlineIfNecessary();
7029 stream() << m_indent <<
"<" << name;
7030 m_tags.push_back( name );
7036 ScopedElement scopedElement( std::string
const& name ) {
7037 ScopedElement scoped(
this );
7038 startElement( name );
7042 XmlWriter& endElement() {
7043 newlineIfNecessary();
7044 m_indent = m_indent.substr( 0, m_indent.size()-2 );
7047 m_tagIsOpen =
false;
7050 stream() << m_indent <<
"</" << m_tags.back() <<
">\n";
7056 XmlWriter& writeAttribute( std::string
const& name, std::string
const& attribute ) {
7057 if( !name.empty() && !attribute.empty() ) {
7058 stream() <<
" " << name <<
"=\"";
7059 writeEncodedText( attribute );
7065 XmlWriter& writeAttribute( std::string
const& name,
bool attribute ) {
7066 stream() <<
" " << name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
"\"";
7070 template<
typename T>
7071 XmlWriter& writeAttribute( std::string
const& name, T
const& attribute ) {
7073 stream() <<
" " << name <<
"=\"" << attribute <<
"\"";
7077 XmlWriter& writeText( std::string
const& text,
bool indent =
true ) {
7078 if( !text.empty() ){
7079 bool tagWasOpen = m_tagIsOpen;
7081 if( tagWasOpen && indent )
7082 stream() << m_indent;
7083 writeEncodedText( text );
7084 m_needsNewline =
true;
7089 XmlWriter& writeComment( std::string
const& text ) {
7091 stream() << m_indent <<
"<!--" << text <<
"-->";
7092 m_needsNewline =
true;
7096 XmlWriter& writeBlankLine() {
7104 std::ostream& stream() {
7108 void ensureTagClosed() {
7111 m_tagIsOpen =
false;
7115 void newlineIfNecessary() {
7116 if( m_needsNewline ) {
7118 m_needsNewline =
false;
7122 void writeEncodedText( std::string
const& text ) {
7123 static const char* charsToEncode =
"<&\"";
7124 std::string mtext = text;
7125 std::string::size_type pos = mtext.find_first_of( charsToEncode );
7126 while( pos != std::string::npos ) {
7127 stream() << mtext.substr( 0, pos );
7129 switch( mtext[pos] ) {
7134 stream() <<
"&";
7137 stream() <<
""";
7140 mtext = mtext.substr( pos+1 );
7141 pos = mtext.find_first_of( charsToEncode );
7147 bool m_needsNewline;
7148 std::vector<std::string> m_tags;
7149 std::string m_indent;
7155 class XmlReporter :
public SharedImpl<IReporter> {
7157 XmlReporter( ReporterConfig
const& config ) : m_config( config ), m_sectionDepth( 0 ) {}
7159 static std::string getDescription() {
7160 return "Reports test results as an XML document";
7162 virtual ~XmlReporter();
7166 virtual bool shouldRedirectStdout()
const {
7170 virtual void StartTesting() {
7171 m_xml = XmlWriter( m_config.stream() );
7172 m_xml.startElement(
"Catch" );
7173 if( !m_config.fullConfig()->name().empty() )
7174 m_xml.writeAttribute(
"name", m_config.fullConfig()->name() );
7177 virtual void EndTesting(
const Totals& totals ) {
7178 m_xml.scopedElement(
"OverallResults" )
7179 .writeAttribute(
"successes", totals.assertions.passed )
7180 .writeAttribute(
"failures", totals.assertions.failed );
7184 virtual void StartGroup(
const std::string& groupName ) {
7185 m_xml.startElement(
"Group" )
7186 .writeAttribute(
"name", groupName );
7189 virtual void EndGroup(
const std::string&,
const Totals& totals ) {
7190 m_xml.scopedElement(
"OverallResults" )
7191 .writeAttribute(
"successes", totals.assertions.passed )
7192 .writeAttribute(
"failures", totals.assertions.failed );
7196 virtual void StartSection(
const std::string& sectionName,
const std::string& description ) {
7197 if( m_sectionDepth++ > 0 ) {
7198 m_xml.startElement(
"Section" )
7199 .writeAttribute(
"name",
trim( sectionName ) )
7200 .writeAttribute(
"description", description );
7203 virtual void NoAssertionsInSection(
const std::string& ) {}
7204 virtual void NoAssertionsInTestCase(
const std::string& ) {}
7206 virtual void EndSection(
const std::string& ,
const Counts& assertions ) {
7207 if( --m_sectionDepth > 0 ) {
7208 m_xml.scopedElement(
"OverallResults" )
7209 .writeAttribute(
"successes", assertions.passed )
7210 .writeAttribute(
"failures", assertions.failed );
7216 m_xml.startElement(
"TestCase" ).writeAttribute(
"name",
trim( testInfo.
name ) );
7217 m_currentTestSuccess =
true;
7225 m_xml.startElement(
"Expression" )
7226 .writeAttribute(
"success", assertionResult.
succeeded() )
7230 m_xml.scopedElement(
"Original" )
7232 m_xml.scopedElement(
"Expanded" )
7234 m_currentTestSuccess &= assertionResult.
succeeded();
7239 m_xml.scopedElement(
"Exception" )
7243 m_currentTestSuccess =
false;
7246 m_xml.scopedElement(
"Info" )
7250 m_xml.scopedElement(
"Warning" )
7254 m_xml.scopedElement(
"Failure" )
7256 m_currentTestSuccess =
false;
7270 virtual void Aborted() {
7274 virtual void EndTestCase(
const Catch::TestCaseInfo&,
const Totals&,
const std::string&,
const std::string& ) {
7275 m_xml.scopedElement(
"OverallResult" ).writeAttribute(
"success", m_currentTestSuccess );
7280 ReporterConfig m_config;
7281 bool m_currentTestSuccess;
7289 #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
7295 class JunitReporter :
public CumulativeReporterBase {
7297 JunitReporter( ReporterConfig
const& _config )
7298 : CumulativeReporterBase( _config ),
7299 xml( _config.stream() )
7304 static std::string getDescription() {
7305 return "Reports test results in an XML format that looks like Ant's junitreport target";
7308 virtual void noMatchingTestCases( std::string
const& ) {}
7310 virtual ReporterPreferences getPreferences()
const {
7311 ReporterPreferences prefs;
7312 prefs.shouldRedirectStdOut =
true;
7316 virtual void testRunStarting( TestRunInfo
const& runInfo ) {
7317 CumulativeReporterBase::testRunStarting( runInfo );
7318 xml.startElement(
"testsuites" );
7321 virtual void testGroupStarting( GroupInfo
const& groupInfo ) {
7323 stdOutForSuite.str(
"");
7324 stdErrForSuite.str(
"");
7325 unexpectedExceptions = 0;
7326 CumulativeReporterBase::testGroupStarting( groupInfo );
7329 virtual bool assertionEnded( AssertionStats
const& assertionStats ) {
7331 unexpectedExceptions++;
7332 return CumulativeReporterBase::assertionEnded( assertionStats );
7335 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) {
7336 stdOutForSuite << testCaseStats.stdOut;
7337 stdErrForSuite << testCaseStats.stdErr;
7338 CumulativeReporterBase::testCaseEnded( testCaseStats );
7341 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) {
7342 double suiteTime = suiteTimer.getElapsedSeconds();
7343 CumulativeReporterBase::testGroupEnded( testGroupStats );
7344 writeGroup( *m_testGroups.back(), suiteTime );
7347 virtual void testRunEndedCumulative() {
7351 void writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
7352 XmlWriter::ScopedElement e = xml.scopedElement(
"testsuite" );
7353 TestGroupStats
const& stats = groupNode.value;
7354 xml.writeAttribute(
"name", stats.groupInfo.name );
7355 xml.writeAttribute(
"errors", unexpectedExceptions );
7356 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
7357 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
7358 xml.writeAttribute(
"hostname",
"tbd" );
7360 xml.writeAttribute(
"time",
"" );
7362 xml.writeAttribute(
"time", suiteTime );
7363 xml.writeAttribute(
"timestamp",
"tbd" );
7366 for( TestGroupNode::ChildNodes::const_iterator
7367 it = groupNode.children.begin(), itEnd = groupNode.children.end();
7370 writeTestCase( **it );
7372 xml.scopedElement(
"system-out" ).writeText(
trim( stdOutForSuite.str() ),
false );
7373 xml.scopedElement(
"system-err" ).writeText(
trim( stdErrForSuite.str() ),
false );
7376 void writeTestCase( TestCaseNode
const& testCaseNode ) {
7377 TestCaseStats
const& stats = testCaseNode.value;
7381 assert( testCaseNode.children.size() == 1 );
7382 SectionNode
const& rootSection = *testCaseNode.children.front();
7384 std::string className = stats.testInfo.className;
7386 if( className.empty() ) {
7387 if( rootSection.childSections.empty() )
7388 className =
"global";
7390 writeSection( className,
"", rootSection );
7393 void writeSection( std::string
const& className,
7394 std::string
const& rootName,
7395 SectionNode
const& sectionNode ) {
7396 std::string name =
trim( sectionNode.stats.sectionInfo.name );
7397 if( !rootName.empty() )
7398 name = rootName +
"/" + name;
7400 if( !sectionNode.assertions.empty() ||
7401 !sectionNode.stdOut.empty() ||
7402 !sectionNode.stdErr.empty() ) {
7403 XmlWriter::ScopedElement e = xml.scopedElement(
"testcase" );
7404 if( className.empty() ) {
7405 xml.writeAttribute(
"classname", name );
7406 xml.writeAttribute(
"name",
"root" );
7409 xml.writeAttribute(
"classname", className );
7410 xml.writeAttribute(
"name", name );
7412 xml.writeAttribute(
"time",
toString( sectionNode.stats.durationInSeconds ) );
7414 writeAssertions( sectionNode );
7416 if( !sectionNode.stdOut.empty() )
7417 xml.scopedElement(
"system-out" ).writeText(
trim( sectionNode.stdOut ),
false );
7418 if( !sectionNode.stdErr.empty() )
7419 xml.scopedElement(
"system-err" ).writeText(
trim( sectionNode.stdErr ),
false );
7421 for( SectionNode::ChildSections::const_iterator
7422 it = sectionNode.childSections.begin(),
7423 itEnd = sectionNode.childSections.end();
7426 if( className.empty() )
7427 writeSection( name, "", **it );
7429 writeSection( className, name, **it );
7432 void writeAssertions( SectionNode
const& sectionNode ) {
7433 for( SectionNode::Assertions::const_iterator
7434 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
7437 writeAssertion( *it );
7439 void writeAssertion( AssertionStats
const& stats ) {
7440 AssertionResult
const& result = stats.assertionResult;
7441 if( !result.isOk() ) {
7442 std::string elementName;
7443 switch( result.getResultType() ) {
7445 elementName =
"error";
7448 elementName =
"failure";
7451 elementName =
"failure";
7454 elementName =
"failure";
7464 elementName =
"internalError";
7468 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
7470 xml.writeAttribute(
"message", result.getExpandedExpression() );
7471 xml.writeAttribute(
"type", result.getTestMacroName() );
7473 std::ostringstream oss;
7474 if( !result.getMessage().empty() )
7475 oss << result.getMessage() <<
"\n";
7476 for( std::vector<MessageInfo>::const_iterator
7477 it = stats.infoMessages.begin(),
7478 itEnd = stats.infoMessages.end();
7481 if( it->type == ResultWas::Info )
7482 oss << it->message << "\n";
7484 oss <<
"at " << result.getSourceInfo();
7485 xml.writeText( oss.str(), false );
7491 std::ostringstream stdOutForSuite;
7492 std::ostringstream stdErrForSuite;
7493 unsigned int unexpectedExceptions;
7496 INTERNAL_CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
7501 #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
7505 struct ConsoleReporter : StreamingReporterBase {
7506 ConsoleReporter( ReporterConfig
const& _config )
7507 : StreamingReporterBase( _config ),
7508 m_headerPrinted( false ),
7509 m_atLeastOneTestCasePrinted( false )
7512 virtual ~ConsoleReporter();
7513 static std::string getDescription() {
7514 return "Reports test results as plain lines of text";
7516 virtual ReporterPreferences getPreferences()
const {
7517 ReporterPreferences prefs;
7518 prefs.shouldRedirectStdOut =
false;
7522 virtual void noMatchingTestCases( std::string
const& spec ) {
7523 stream <<
"No test cases matched '" << spec <<
"'" << std::endl;
7526 virtual void assertionStarting( AssertionInfo
const& ) {
7529 virtual bool assertionEnded( AssertionStats
const& _assertionStats ) {
7530 AssertionResult
const& result = _assertionStats.assertionResult;
7532 bool printInfoMessages =
true;
7535 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
7538 printInfoMessages =
false;
7543 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
7545 stream << std::endl;
7549 virtual void sectionStarting( SectionInfo
const& _sectionInfo ) {
7550 m_headerPrinted =
false;
7551 StreamingReporterBase::sectionStarting( _sectionInfo );
7553 virtual void sectionEnded( SectionStats
const& _sectionStats ) {
7554 if( _sectionStats.missingAssertions ) {
7556 Colour colour( Colour::ResultError );
7557 if( m_sectionStack.size() > 1 )
7558 stream <<
"\nNo assertions in section";
7560 stream <<
"\nNo assertions in test case";
7561 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" << std::endl;
7563 if( m_headerPrinted ) {
7565 stream <<
"Completed in " << _sectionStats.durationInSeconds <<
"s" << std::endl;
7566 m_headerPrinted =
false;
7570 stream << _sectionStats.sectionInfo.name <<
" completed in " << _sectionStats.durationInSeconds <<
"s" << std::endl;
7572 StreamingReporterBase::sectionEnded( _sectionStats );
7575 virtual void testCaseEnded( TestCaseStats
const& _testCaseStats ) {
7576 StreamingReporterBase::testCaseEnded( _testCaseStats );
7577 m_headerPrinted =
false;
7579 virtual void testGroupEnded( TestGroupStats
const& _testGroupStats ) {
7580 if( currentGroupInfo.used ) {
7581 printSummaryDivider();
7582 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
7583 printTotals( _testGroupStats.totals );
7584 stream <<
"\n" << std::endl;
7586 StreamingReporterBase::testGroupEnded( _testGroupStats );
7588 virtual void testRunEnded( TestRunStats
const& _testRunStats ) {
7589 if( m_atLeastOneTestCasePrinted )
7590 printTotalsDivider();
7591 printTotals( _testRunStats.totals );
7592 stream <<
"\n" << std::endl;
7593 StreamingReporterBase::testRunEnded( _testRunStats );
7598 class AssertionPrinter {
7599 void operator= ( AssertionPrinter
const& );
7601 AssertionPrinter( std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages )
7602 : stream( _stream ),
7604 result( _stats.assertionResult ),
7605 colour( Colour::None ),
7606 message( result.getMessage() ),
7607 messages( _stats.infoMessages ),
7608 printInfoMessages( _printInfoMessages )
7610 switch( result.getResultType() ) {
7612 colour = Colour::Success;
7613 passOrFail =
"PASSED";
7615 if( _stats.infoMessages.size() == 1 )
7616 messageLabel =
"with message";
7617 if( _stats.infoMessages.size() > 1 )
7618 messageLabel =
"with messages";
7621 if( result.isOk() ) {
7622 colour = Colour::Success;
7623 passOrFail =
"FAILED - but was ok";
7626 colour = Colour::Error;
7627 passOrFail =
"FAILED";
7629 if( _stats.infoMessages.size() == 1 )
7630 messageLabel =
"with message";
7631 if( _stats.infoMessages.size() > 1 )
7632 messageLabel =
"with messages";
7635 colour = Colour::Error;
7636 passOrFail =
"FAILED";
7637 messageLabel =
"due to unexpected exception with message";
7640 colour = Colour::Error;
7641 passOrFail =
"FAILED";
7642 messageLabel =
"because no exception was thrown where one was expected";
7645 messageLabel =
"info";
7648 messageLabel =
"warning";
7651 passOrFail =
"FAILED";
7652 colour = Colour::Error;
7653 if( _stats.infoMessages.size() == 1 )
7654 messageLabel =
"explicitly with message";
7655 if( _stats.infoMessages.size() > 1 )
7656 messageLabel =
"explicitly with messages";
7662 passOrFail =
"** internal error **";
7663 colour = Colour::Error;
7668 void print()
const {
7670 if( stats.totals.assertions.total() > 0 ) {
7674 printOriginalExpression();
7675 printReconstructedExpression();
7684 void printResultType()
const {
7685 if( !passOrFail.empty() ) {
7686 Colour colourGuard( colour );
7687 stream << passOrFail <<
":\n";
7690 void printOriginalExpression()
const {
7691 if( result.hasExpression() ) {
7692 Colour colourGuard( Colour::OriginalExpression );
7694 stream << result.getExpressionInMacro();
7698 void printReconstructedExpression()
const {
7699 if( result.hasExpandedExpression() ) {
7700 stream <<
"with expansion:\n";
7701 Colour colourGuard( Colour::ReconstructedExpression );
7702 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) <<
"\n";
7705 void printMessage()
const {
7706 if( !messageLabel.empty() )
7707 stream << messageLabel <<
":" <<
"\n";
7708 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
7713 stream << Text( it->message, TextAttributes().setIndent(2) ) <<
"\n";
7716 void printSourceInfo()
const {
7717 Colour colourGuard( Colour::FileName );
7718 stream << result.getSourceInfo() <<
": ";
7721 std::ostream& stream;
7722 AssertionStats
const& stats;
7723 AssertionResult
const& result;
7724 Colour::Code colour;
7725 std::string passOrFail;
7726 std::string messageLabel;
7727 std::string message;
7728 std::vector<MessageInfo> messages;
7729 bool printInfoMessages;
7734 if( !currentTestRunInfo.used )
7736 if( !currentGroupInfo.used )
7737 lazyPrintGroupInfo();
7739 if( !m_headerPrinted ) {
7740 printTestCaseAndSectionHeader();
7741 m_headerPrinted =
true;
7743 m_atLeastOneTestCasePrinted =
true;
7745 void lazyPrintRunInfo() {
7746 stream <<
"\n" << getTildes() <<
"\n";
7747 Colour colour( Colour::SecondaryText );
7748 stream << currentTestRunInfo->name
7749 <<
" is a Catch v" << libraryVersion.majorVersion <<
"."
7750 << libraryVersion.minorVersion <<
" b"
7751 << libraryVersion.buildNumber;
7752 if( libraryVersion.branchName !=
"master" )
7753 stream <<
" (" << libraryVersion.branchName <<
")";
7754 stream <<
" host application.\n"
7755 <<
"Run with -? for options\n\n";
7757 currentTestRunInfo.used =
true;
7759 void lazyPrintGroupInfo() {
7760 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
7761 printClosedHeader(
"Group: " + currentGroupInfo->name );
7762 currentGroupInfo.used =
true;
7765 void printTestCaseAndSectionHeader() {
7766 assert( !m_sectionStack.empty() );
7767 printOpenHeader( currentTestCaseInfo->name );
7769 if( m_sectionStack.size() > 1 ) {
7770 Colour colourGuard( Colour::Headers );
7772 std::vector<SectionInfo>::const_iterator
7773 it = m_sectionStack.begin()+1,
7774 itEnd = m_sectionStack.end();
7775 for( ; it != itEnd; ++it )
7776 printHeaderString( it->name, 2 );
7779 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
7781 if( !lineInfo.empty() ){
7782 stream << getDashes() <<
"\n";
7783 Colour colourGuard( Colour::FileName );
7784 stream << lineInfo <<
"\n";
7786 stream << getDots() <<
"\n" << std::endl;
7789 void printClosedHeader( std::string
const& _name ) {
7790 printOpenHeader( _name );
7791 stream << getDots() <<
"\n";
7793 void printOpenHeader( std::string
const& _name ) {
7794 stream << getDashes() <<
"\n";
7796 Colour colourGuard( Colour::Headers );
7797 printHeaderString( _name );
7803 void printHeaderString( std::string
const& _string, std::size_t indent = 0 ) {
7804 std::size_t i = _string.find(
": " );
7805 if( i != std::string::npos )
7809 stream << Text( _string, TextAttributes()
7810 .setIndent( indent+i)
7811 .setInitialIndent( indent ) ) <<
"\n";
7814 void printTotals(
const Totals& totals ) {
7815 if( totals.testCases.total() == 0 ) {
7816 stream <<
"No tests ran";
7818 else if( totals.assertions.total() == 0 ) {
7819 Colour colour( Colour::Yellow );
7820 printCounts(
"test case", totals.testCases );
7821 stream <<
" (no assertions)";
7823 else if( totals.assertions.failed ) {
7824 Colour colour( Colour::ResultError );
7825 printCounts(
"test case", totals.testCases );
7826 if( totals.testCases.failed > 0 ) {
7828 printCounts(
"assertion", totals.assertions );
7833 Colour colour( Colour::ResultSuccess );
7834 stream <<
"All tests passed ("
7835 << pluralise( totals.assertions.passed,
"assertion" ) <<
" in "
7836 << pluralise( totals.testCases.passed,
"test case" ) <<
")";
7839 void printCounts( std::string
const& label, Counts
const& counts ) {
7840 if( counts.total() == 1 ) {
7841 stream <<
"1 " << label <<
" - ";
7848 stream << counts.total() <<
" " << label <<
"s ";
7849 if( counts.passed ) {
7851 stream <<
"- " << counts.failed <<
" failed";
7852 else if( counts.passed == 2 )
7853 stream <<
"- both passed";
7855 stream <<
"- all passed";
7858 if( counts.failed == 2 )
7859 stream <<
"- both failed";
7861 stream <<
"- all failed";
7866 void printTotalsDivider() {
7867 stream << getDoubleDashes() <<
"\n";
7869 void printSummaryDivider() {
7870 stream << getDashes() <<
"\n";
7872 static std::string
const& getDashes() {
7873 static const std::string dashes( CATCH_CONFIG_CONSOLE_WIDTH-1,
'-' );
7876 static std::string
const& getDots() {
7877 static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1,
'.' );
7880 static std::string
const& getDoubleDashes() {
7881 static const std::string doubleDashes( CATCH_CONFIG_CONSOLE_WIDTH-1,
'=' );
7882 return doubleDashes;
7884 static std::string
const& getTildes() {
7885 static const std::string dots( CATCH_CONFIG_CONSOLE_WIDTH-1,
'~' );
7890 bool m_headerPrinted;
7891 bool m_atLeastOneTestCasePrinted;
7894 INTERNAL_CATCH_REGISTER_REPORTER(
"console", ConsoleReporter )
7901 StreamBufBase::~StreamBufBase() throw() {}
7910 IReporter::~IReporter() {}
7911 IReporterFactory::~IReporterFactory() {}
7912 IReporterRegistry::~IReporterRegistry() {}
7913 IStreamingReporter::~IStreamingReporter() {}
7914 AssertionStats::~AssertionStats() {}
7915 SectionStats::~SectionStats() {}
7916 TestCaseStats::~TestCaseStats() {}
7917 TestGroupStats::~TestGroupStats() {}
7918 TestRunStats::~TestRunStats() {}
7919 CumulativeReporterBase::SectionNode::~SectionNode() {}
7920 CumulativeReporterBase::~CumulativeReporterBase() {}
7922 StreamingReporterBase::~StreamingReporterBase() {}
7923 ConsoleReporter::~ConsoleReporter() {}
7927 XmlReporter::~XmlReporter() {}
7928 JunitReporter::~JunitReporter() {}
7929 TestRegistry::~TestRegistry() {}
7930 FreeFunctionTestCase::~FreeFunctionTestCase() {}
7939 void Config::dummy() {}
7941 INTERNAL_CATCH_REGISTER_LEGACY_REPORTER(
"xml", XmlReporter )
7945 #pragma clang diagnostic pop
7948 #endif // CATCH_CONFIG_MAIN || CATCH_CONFIG_RUNNER
7950 #ifdef CATCH_CONFIG_MAIN
7952 #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
7957 int main (
int argc,
char *
const argv[]) {
7958 return Catch::Session().run( argc, argv );
7964 int main (
int argc,
char *
const argv[]) {
7965 #if !CATCH_ARC_ENABLED
7966 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
7969 Catch::registerTestMethods();
7970 int result = Catch::Session().run( argc, (
char*
const*)argv );
7972 #if !CATCH_ARC_ENABLED
7981 #endif // CATCH_CONFIG_MAIN
7986 #ifdef CATCH_CONFIG_PREFIX_ALL
7988 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
7989 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "CATCH_REQUIRE_FALSE" )
7991 #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
7992 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
7993 #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
7995 #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
7996 #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CATCH_CHECK_FALSE" )
7997 #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
7998 #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
7999 #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
8001 #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
8002 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
8003 #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
8005 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
8006 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
8008 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
8009 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
8010 #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
8011 #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
8012 #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
8014 #ifdef CATCH_CONFIG_VARIADIC_MACROS
8015 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
8016 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
8017 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
8018 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
8019 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
8020 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
8022 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
8023 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
8024 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
8025 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
8026 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
8027 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
8029 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
8031 #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
8032 #define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
8034 #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
8037 #ifdef CATCH_CONFIG_VARIADIC_MACROS
8038 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
8040 #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
8042 #define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" )
8043 #define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" )
8044 #define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" )
8045 #define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" )
8046 #define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" )
8051 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
8052 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::NegateResult, "REQUIRE_FALSE" )
8054 #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
8055 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
8056 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
8058 #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
8059 #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::NegateResult, "CHECK_FALSE" )
8060 #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
8061 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
8062 #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
8064 #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, ..., Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
8065 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
8066 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
8068 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
8069 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
8071 #define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
8072 #define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
8073 #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
8074 #define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
8075 #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
8077 #ifdef CATCH_CONFIG_VARIADIC_MACROS
8078 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
8079 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
8080 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
8081 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
8082 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
8083 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
8085 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
8086 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
8087 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
8088 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
8089 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
8090 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
8092 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
8094 #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
8095 #define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
8097 #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
8101 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
8104 #ifdef CATCH_CONFIG_VARIADIC_MACROS
8105 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
8107 #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
8109 #define GIVEN( desc ) SECTION( " Given: " desc, "" )
8110 #define WHEN( desc ) SECTION( " When: " desc, "" )
8111 #define AND_WHEN( desc ) SECTION( "And when: " desc, "" )
8112 #define THEN( desc ) SECTION( " Then: " desc, "" )
8113 #define AND_THEN( desc ) SECTION( " And: " desc, "" )
8118 #pragma clang diagnostic pop
8121 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
std::string getExpandedExpression() const
CompositeGenerator< T > between(T from, T to)
Approx operator()(double value)
friend std::ostream & operator<<(std::ostream &os, pluralise const &pluraliser)
StartsWith(std::string const &substr)
EndsWith(std::string const &substr)
virtual bool match(ExpressionT const &expr) const
virtual std::size_t size() const
ExpressionResultBuilder & setRhs(std::string const &rhs)
ExpressionResultBuilder & setResultType(ResultWas::OfType result)
SourceLineInfo getSourceInfo() const
static bool evaluate(T1 const &lhs, T2 const &rhs)
virtual bool match(ExpressionT const &expr) const
bool hasExpandedExpression() const
void throwLogicError(std::string const &message, SourceLineInfo const &locationInfo)
CompositeGenerator & then(CompositeGenerator &other)
MethodTestCase(void(C::*method)())
static std::string convert(T const &_value)
void(SafeBool::* type)() const
ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
ExpressionResultBuilder & endExpression(ResultDisposition::Flags resultDisposition)
Equals(std::string const &str)
virtual T getValue(std::size_t index) const
virtual ~IExceptionTranslatorRegistry()
Section(SourceLineInfo const &lineInfo, std::string const &name, std::string const &description="")
CompositeGenerator< T > values(T val1, T val2, T val3, T val4)
std::string getExpression() const
MessageBuilder(std::string const ¯oName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
std::string toString(T const &value)
converts any type to a string
bool shouldNegate(int flags)
virtual IResultCapture & getResultCapture()=0
static std::string convert(U *p)
std::string toString(unsigned char value)
AssertionResult buildResult(AssertionInfo const &info) const
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
std::string capturedExpression
std::string toString() const
std::string trim(std::string const &str)
ExpressionResultBuilder expressionResultBuilderFromMatcher(MatcherT const &matcher, std::string const &matcherCallAsString)
virtual std::string toString() const
SectionInfo(std::string const &_name, std::string const &_description, SourceLineInfo const &_lineInfo)
bool hasExpression() const
std::string reconstructedExpression
TestCaseInfo const & getTestCaseInfo() const
virtual ~IResultCapture()
void deleteAllValues(AssociativeContainerT &container)
Totals delta(Totals const &prevTotals) const
void swap(TestCase &other)
IContext & getCurrentContext()
Contains(std::string const &substr)
virtual T getValue(std::size_t index) const
std::set< std::string > tags
std::string getTestMacroName() const
static const char * getName()
IGeneratorsForTest * createGeneratorsForTest()
virtual Ptr< Matcher< ExpressionT > > clone() const
NotImplementedException(SourceLineInfo const &lineInfo)
bool hasTag(std::string const &tag) const
static const char * getName()
virtual ~IExceptionTranslator()
ResultDisposition::Flags resultDisposition
#define CATCH_INTERNAL_ERROR(msg)
virtual void popScopedMessage(MessageInfo const &message)=0
static const char * getName()
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry()=0
void writeToDebugConsole(std::string const &text)
virtual void registerTest(TestCase const &testInfo)=0
AllOf & add(Matcher< ExpressionT > const &matcher)
TestCaseInfo(std::string const &_name, std::string const &_className, std::string const &_description, std::set< std::string > const &_tags, bool _isHidden, SourceLineInfo const &_lineInfo)
virtual ~IMutableContext()
virtual void invoke() const
AnyOf & add(Matcher< ExpressionT > const &matcher)
pluralise(std::size_t count, std::string const &label)
std::size_t total() const
bool applyEvaluator(T1 const &lhs, T2 const &rhs)
bool isJustInfo(int flags)
static const char * getName()
ScopedMessage(MessageBuilder const &builder)
std::string getExpressionInMacro() const
Stream createStream(std::string const &streamName)
Approx & scale(double newScale)
std::string(* exceptionTranslateFunction)()
virtual void registerTranslator(const IExceptionTranslator *translator)=0
NameAndDesc(const char *_name="", const char *_description="")
bool operator==(TestCase const &other) const
virtual std::string toString() const
static bool evaluate(T1 const &lhs, T2 const &rhs)
static const char * getName()
IRegistryHub & getRegistryHub()
MessageInfo(std::string const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
bool operator==(SourceLineInfo const &other) const
static std::string convert(R C::*p)
virtual T getValue(std::size_t index) const =0
bool compare(T *lhs, int rhs)
void add(const IGenerator< T > *generator)
Approx(Approx const &other)
IMutableRegistryHub & getMutableRegistryHub()
std::vector< double > x(ncmax, 0)
virtual bool match(std::string const &expr) const
ExpressionResultBuilder & setOp(std::string const &op)
FalseType testStreamable(FalseType)
CompositeGenerator(CompositeGenerator &other)
virtual std::string toString() const
virtual std::string getCurrentTestName() const =0
bool shouldContinueOnFailure(int flags)
static std::string convert(T const &)
std::string reconstructExpression(AssertionInfo const &info) const
TestCase withName(std::string const &_newName) const
static bool evaluate(T1 const &lhs, T2 const &rhs)
ExpressionResultBuilder & endExpression(ResultDisposition::Flags resultDisposition)
virtual Ptr< Matcher > clone() const =0
virtual std::string toString() const
std::string rangeToString(InputIterator first, InputIterator last)
virtual std::string toString() const
std::string makeString(const char *str)
virtual ITestCaseRegistry const & getTestCaseRegistry() const =0
ResultWas::OfType getResultType() const
virtual bool match(std::string const &expr) const
void toLowerInPlace(std::string &s)
ExpressionT ExpressionType
virtual IReporterRegistry const & getReporterRegistry() const =0
AnyOf(AnyOf const &other)
#define INTERNAL_CATCH_STRINGIFY(expr)
virtual bool match(std::string const &expr) const
double getElapsedSeconds() const
IResultCapture & getResultCapture()
virtual ~IMutableRegistryHub()
std::string toLower(std::string const &s)
Impl::StdString::StartsWith StartsWith(const char *substr)
Impl::StdString::EndsWith EndsWith(const char *substr)
std::string getMessage() const
virtual std::string toString() const
Equals(Equals const &other)
virtual const char * what() const
bool operator<(TestCase const &other) const
ResultWas::OfType resultType
virtual ~ITestCaseRegistry()
unsigned int getElapsedNanoseconds() const
Impl::StdString::Equals Equals(const char *str)
virtual void addRef() const
bool startsWith(std::string const &s, std::string const &prefix)
double double double *typedef void(CALLCONV AGdll_TYPE)(double *
virtual std::vector< TestCase > getMatchingTestCases(std::string const &rawTestSpec) const =0
static bool evaluate(T1 const &lhs, T2 const &rhs)
virtual size_t getGeneratorIndex(std::string const &fileInfo, size_t totalSize)=0
std::set< std::string > const & getTags() const
static const char * getName()
virtual void release() const
BetweenGenerator(T from, T to)
Contains(Contains const &other)
bool matchesTags(std::string const &tagPattern) const
CompositeGenerator & then(T value)
CompositeGenerator & setFileInfo(const char *fileInfo)
virtual ~IGeneratorsForTest()
virtual std::vector< TestCase > const & getAllTests() const =0
TestCase makeTestCase(ITestCase *testCase, std::string const &className, std::string const &name, std::string const &description, SourceLineInfo const &lineInfo)
static std::string convert(std::vector< T, Allocator > const &v)
std::string makeString(T const &value)
static bool evaluate(T1 const &lhs, T2 const &rhs)
AllOf(AllOf const &other)
IMutableContext & getCurrentMutableContext()
Impl::StdString::Contains Contains(const char *substr)
virtual bool match(std::string const &expr) const
bool endsWith(std::string const &s, std::string const &suffix)
bool contains(std::string const &s, std::string const &infix)
TestCase(ITestCase *testCase, TestCaseInfo const &info)
ExpressionResultBuilder & setLhs(std::string const &lhs)
virtual ~IGeneratorInfo()
ExpressionResultBuilder & operator=(ExpressionResultBuilder const &other)
unsigned int getElapsedMilliseconds() const
T const & operator+(T const &value, StreamEndStop)
Impl::Generic::AnyOf< ExpressionT > AnyOf(Impl::Matcher< ExpressionT > const &m1, Impl::Matcher< ExpressionT > const &m2, Impl::Matcher< ExpressionT > const &m3)
ExpressionResultBuilder(ResultWas::OfType resultType=ResultWas::Unknown)
std::string translateActiveException()
static bool evaluate(T1 const &lhs, T2 const &rhs)
StartsWith(StartsWith const &other)
AssertionResultData m_resultData
Approx & epsilon(double newEpsilon)
std::string rawMemoryToString(T value)
virtual std::size_t size() const =0
bool shouldSuppressFailure(int flags)
virtual void sectionEnded(SectionInfo const &name, Counts const &assertions, double _durationInSeconds)=0
virtual bool advanceGeneratorsForCurrentTest()=0
Impl::Generic::AllOf< ExpressionT > AllOf(Impl::Matcher< ExpressionT > const &m1, Impl::Matcher< ExpressionT > const &m2, Impl::Matcher< ExpressionT > const &m3)
TestCase & operator=(TestCase const &other)
std::ostringstream m_stream
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
static const char * getName()
virtual void pushScopedMessage(MessageInfo const &message)=0
static type makeSafe(bool value)
AutoReg(void(C::*method)(), char const *className, NameAndDesc const &nameAndDesc, SourceLineInfo const &lineInfo)
virtual std::size_t size() const
void deleteAll(ContainerT &container)
bool isOk(ResultWas::OfType resultType)
virtual ~NotImplementedException()
virtual std::string translateActiveException() const =0
EndsWith(EndsWith const &other)
virtual void registerReporter(std::string const &name, IReporterFactory *factory)=0