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" 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 50 #if (__BORLANDC__ > 0x582 ) 54 #endif // __BORLANDC__ 58 #ifdef __EDG_VERSION__ 60 #if (__EDG_VERSION__ > 238 ) 64 #endif // __EDG_VERSION__ 70 #if (__DMC__ > 0x840 ) 82 #if (__GNUC_MINOR__ >= 96 ) 90 #endif // __GNUC__ < 3 98 #if (_MSC_VER >= 1310 ) // (VC++ 7.0+) 105 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ 106 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ 107 ( defined __GNUC__ && __GNUC__ >= 3 ) || \ 108 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) 110 #ifndef CATCH_CONFIG_NO_VARIADIC_MACROS 111 #define CATCH_CONFIG_VARIADIC_MACROS 131 return value ? &SafeBool::trueValue : 0;
134 void trueValue()
const {}
137 template<
typename ContainerT>
139 typename ContainerT::const_iterator it = container.begin();
140 typename ContainerT::const_iterator itEnd = container.end();
141 for(; it != itEnd; ++it )
144 template<
typename AssociativeContainerT>
146 typename AssociativeContainerT::const_iterator it = container.begin();
147 typename AssociativeContainerT::const_iterator itEnd = container.end();
148 for(; it != itEnd; ++it )
152 template<
typename ContainerT,
typename Function>
153 inline void forEach( ContainerT& container, Function
function ) {
154 std::for_each( container.begin(), container.end(), function );
157 template<
typename ContainerT,
typename Function>
158 inline void forEach( ContainerT
const& container, Function
function ) {
159 std::for_each( container.begin(), container.end(), function );
162 inline bool startsWith( std::string
const& s, std::string
const& prefix ) {
163 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
165 inline bool endsWith( std::string
const& s, std::string
const& suffix ) {
166 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
168 inline bool contains( std::string
const& s, std::string
const& infix ) {
169 return s.find( infix ) != std::string::npos;
174 inline std::string
toLower( std::string
const& s ) {
181 pluralise( std::size_t count, std::string
const& label )
205 : file( other.file ),
212 return line == other.
line && file == other.
file;
220 os << info.
file <<
"(" << info.
line <<
")";
222 os << info.
file <<
":" << info.
line;
228 inline bool isTrue(
bool value ){
return value; }
231 std::ostringstream oss;
232 oss << locationInfo <<
": Internal Catch error: '" << message <<
"'";
234 throw std::logic_error( oss.str() );
238 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 239 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); 252 virtual const char* what()
const throw();
262 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) 265 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED 268 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED 276 virtual bool moveNext() = 0;
277 virtual std::size_t getCurrentIndex()
const = 0;
283 virtual IGeneratorInfo& getGeneratorInfo( std::string
const& fileInfo, std::size_t size ) = 0;
284 virtual bool moveNext() = 0;
292 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED 295 #pragma clang diagnostic push 296 #pragma clang diagnostic ignored "-Wpadded" 312 Ptr(
Ptr const& other ) : m_p( other.m_p ){
335 void swap(
Ptr& other ) { std::swap( m_p, other.m_p ); }
336 T*
get() {
return m_p; }
337 const T*
get()
const{
return m_p; }
340 bool operator !()
const {
return m_p == NULL; }
349 virtual void addRef()
const = 0;
350 virtual void release()
const = 0;
353 template<
typename T = IShared>
372 #pragma clang diagnostic pop 393 virtual IRunner& getRunner() = 0;
394 virtual size_t getGeneratorIndex( std::string
const& fileInfo,
size_t totalSize ) = 0;
395 virtual bool advanceGeneratorsForCurrentTest() = 0;
402 virtual void setResultCapture(
IResultCapture* resultCapture ) = 0;
403 virtual void setRunner(
IRunner* runner ) = 0;
415 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED 418 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED 424 class TestCaseFilters;
427 virtual void invoke ()
const = 0;
436 virtual std::vector<TestCase>
const& getAllTests()
const = 0;
437 virtual std::vector<TestCase> getMatchingTestCases( std::string
const& rawTestSpec )
const = 0;
457 void (C::*m_method)();
463 NameAndDesc(
const char* _name =
"",
const char* _description=
"" )
464 : name( _name ), description( _description )
479 char const* className,
488 void registerTestCase(
ITestCase* testCase,
489 char const* className,
497 void operator= (
AutoReg const& );
502 #ifdef CATCH_CONFIG_VARIADIC_MACROS 503 #define INTERNAL_CATCH_TESTCASE( ... ) \ 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( __VA_ARGS__ ) ); }\ 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, ... ) \ 511 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } 514 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\ 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( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ 521 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() 524 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ 526 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \ 527 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 ) ); }\ 528 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )() 531 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ 532 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } 535 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ 537 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \ 540 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 ); \ 542 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() 547 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED 550 #define TWOBLUECUBES_CATCH_EXPRESSION_DECOMPOSER_HPP_INCLUDED 553 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED 556 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_BUILDER_H_INCLUDED 559 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED 562 #define TWOBLUECUBES_CATCH_SFINAE_HPP_INCLUDED 569 static const bool value =
true;
574 static const bool value =
false;
579 #ifdef CATCH_CONFIG_SFINAE 581 template<
bool>
struct NotABooleanExpression;
583 template<
bool c>
struct If : NotABooleanExpression<c> {};
584 template<>
struct If<true> :
TrueType {};
585 template<>
struct If<false> :
FalseType {};
587 template<
int size>
struct SizedIf;
591 #endif // CATCH_CONFIG_SFINAE 601 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED 603 #import <Foundation/Foundation.h> 606 #define CATCH_ARC_ENABLED __has_feature(objc_arc) 608 #define CATCH_ARC_ENABLED 0 611 void arcSafeRelease( NSObject* obj );
612 id performOptionalSelector(
id obj,
SEL sel );
614 #if !CATCH_ARC_ENABLED 615 inline void arcSafeRelease( NSObject* obj ) {
618 inline id performOptionalSelector(
id obj,
SEL sel ) {
619 if( [obj respondsToSelector: sel] )
620 return [obj performSelector: sel];
623 #define CATCH_UNSAFE_UNRETAINED 624 #define CATCH_ARC_STRONG 626 inline void arcSafeRelease( NSObject* ){}
627 inline id performOptionalSelector(
id obj,
SEL sel ) {
629 #pragma clang diagnostic push 630 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 632 if( [obj respondsToSelector: sel] )
633 return [obj performSelector: sel];
635 #pragma clang diagnostic pop 639 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 640 #define CATCH_ARC_STRONG __strong 651 #ifdef CATCH_CONFIG_SFINAE 654 class IsStreamInsertableHelper {
655 template<
int N>
struct TrueIfSizeable :
TrueType {};
657 template<
typename T2>
658 static TrueIfSizeable<sizeof((*(std::ostream*)0) << *((T2 const*)0))> dummy(T2*);
662 typedef SizedIf<sizeof(dummy((T*)0))> type;
671 template<
typename T>
BorgType( T
const& );
681 static std::ostream &
s;
691 static std::string
convert( T
const& ) {
return "{?}"; }
697 static std::string
convert( T
const& _value ) {
698 std::ostringstream oss;
707 std::string
toString( T
const& value );
719 std::ostringstream oss;
727 static std::string
convert( std::vector<T>
const& v ) {
728 std::ostringstream oss;
730 for( std::size_t i = 0; i < v.size(); ++ i ) {
732 if( i < v.size() - 1 )
761 inline std::string
toString( std::string
const& value ) {
762 return "\"" + value +
"\"";
765 inline std::string
toString( std::wstring
const& value ) {
766 std::ostringstream oss;
768 for(
size_t i = 0; i < value.size(); ++i )
769 oss << static_cast<char>( value[i] <= 0xff ? value[i] :
'?');
774 inline std::string
toString(
const char*
const value ) {
775 return value ?
Catch::toString( std::string( value ) ) : std::string(
"{null string}" );
783 std::ostringstream oss;
788 inline std::string
toString(
unsigned long value ) {
789 std::ostringstream oss;
791 oss <<
"0x" << std::hex << value;
797 inline std::string
toString(
unsigned int value ) {
798 return toString( static_cast<unsigned long>( value ) );
801 inline std::string
toString(
const double value ) {
802 std::ostringstream oss;
803 oss << std::setprecision( 10 )
806 std::string d = oss.str();
807 std::size_t i = d.find_last_not_of(
'0' );
808 if( i != std::string::npos && i != d.size()-1 ) {
811 d = d.substr( 0, i+1 );
817 return value ?
"true" :
"false";
822 ?
toString( static_cast<unsigned int>( value ) )
827 return toString( static_cast<char>( value ) );
830 inline std::string
toString(
unsigned char value ) {
831 return toString( static_cast<char>( value ) );
834 #ifdef CATCH_CONFIG_CPP11_NULLPTR 835 inline std::string
toString( std::nullptr_t ) {
841 inline std::string
toString( NSString
const *
const& nsstring ) {
844 return std::string(
"@\"" ) + [nsstring UTF8String] +
"\"";
846 inline std::string
toString( NSString * CATCH_ARC_STRONG
const& nsstring ) {
849 return std::string(
"@\"" ) + [nsstring UTF8String] +
"\"";
851 inline std::string
toString( NSObject*
const& nsObject ) {
852 return toString( [nsObject description] );
859 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED 863 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED 876 ExpressionFailed = FailureBit | 1,
877 ExplicitFailure = FailureBit | 2,
879 Exception = 0x100 | FailureBit,
881 ThrewException = Exception | 1,
882 DidntThrowException = Exception | 2
905 ContinueOnFailure = 0x01,
928 std::string
const& _capturedExpression,
953 bool succeeded()
const;
955 bool hasExpression()
const;
956 bool hasMessage()
const;
957 std::string getExpression()
const;
958 std::string getExpressionInMacro()
const;
959 bool hasExpandedExpression()
const;
960 std::string getExpandedExpression()
const;
961 std::string getMessage()
const;
963 std::string getTestMacroName()
const;
973 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED 976 #pragma warning(push) 977 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch 1000 template<
typename T>
1001 inline T&
opCast(T
const& t) {
return const_cast<T&
>(t); }
1004 #ifdef CATCH_CONFIG_CPP11_NULLPTR 1005 inline std::nullptr_t
opCast(std::nullptr_t) {
return nullptr; }
1006 #endif // CATCH_CONFIG_CPP11_NULLPTR 1010 template<
typename T1,
typename T2, Operator Op>
1013 template<
typename T1,
typename T2>
1019 template<
typename T1,
typename T2>
1025 template<
typename T1,
typename T2>
1031 template<
typename T1,
typename T2>
1037 template<
typename T1,
typename T2>
1043 template<
typename T1,
typename T2>
1050 template<Operator Op,
typename T1,
typename T2>
1059 template<Operator Op,
typename T1,
typename T2>
1065 template<Operator Op>
bool compare(
unsigned int lhs,
int rhs ) {
1066 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1068 template<Operator Op>
bool compare(
unsigned long lhs,
int rhs ) {
1069 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1071 template<Operator Op>
bool compare(
unsigned char lhs,
int rhs ) {
1072 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1076 template<Operator Op>
bool compare(
unsigned int lhs,
long rhs ) {
1077 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1079 template<Operator Op>
bool compare(
unsigned long lhs,
long rhs ) {
1080 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1082 template<Operator Op>
bool compare(
unsigned char lhs,
long rhs ) {
1083 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1087 template<Operator Op>
bool compare(
int lhs,
unsigned int rhs ) {
1088 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1090 template<Operator Op>
bool compare(
int lhs,
unsigned long rhs ) {
1091 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1093 template<Operator Op>
bool compare(
int lhs,
unsigned char rhs ) {
1094 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1098 template<Operator Op>
bool compare(
long lhs,
unsigned int rhs ) {
1099 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1101 template<Operator Op>
bool compare(
long lhs,
unsigned long rhs ) {
1102 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1104 template<Operator Op>
bool compare(
long lhs,
unsigned char rhs ) {
1105 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1109 template<Operator Op,
typename T>
bool compare(
long lhs, T* rhs ) {
1112 template<Operator Op,
typename T>
bool compare( T* lhs,
long rhs ) {
1117 template<Operator Op,
typename T>
bool compare(
int lhs, T* rhs ) {
1120 template<Operator Op,
typename T>
bool compare( T* lhs,
int rhs ) {
1124 #ifdef CATCH_CONFIG_CPP11_NULLPTR 1126 template<Operator Op,
typename T>
bool compare( std::nullptr_t, T* rhs ) {
1129 template<Operator Op,
typename T>
bool compare( T* lhs, std::nullptr_t ) {
1132 #endif // CATCH_CONFIG_CPP11_NULLPTR 1138 #pragma warning(pop) 1143 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1162 template<
typename T>
1168 std::string reconstructExpression(
AssertionInfo const& info )
const;
1172 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT
const& );
1173 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT
const& );
1177 struct ExprComponents {
1180 std::string lhs, rhs, op;
1182 std::ostringstream m_stream;
1191 template<
typename T>
1198 template<
typename RhsT>
1200 return captureExpression<Internal::IsEqualTo>( rhs );
1203 template<
typename RhsT>
1205 return captureExpression<Internal::IsNotEqualTo>( rhs );
1208 template<
typename RhsT>
1210 return captureExpression<Internal::IsLessThan>( rhs );
1213 template<
typename RhsT>
1215 return captureExpression<Internal::IsGreaterThan>( rhs );
1218 template<
typename RhsT>
1220 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1223 template<
typename RhsT>
1225 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1229 return captureExpression<Internal::IsEqualTo>( rhs );
1233 return captureExpression<Internal::IsNotEqualTo>( rhs );
1237 bool value = m_lhs ?
true :
false;
1246 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT
const& );
1247 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT
const& );
1248 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT
const& );
1249 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT
const& );
1250 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT
const& );
1251 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT
const& );
1254 template<Internal::Operator Op,
typename RhsT>
1276 template<
typename T>
1289 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED 1313 static unsigned int globalCount;
1320 : m_info( macroName, lineInfo, type )
1323 template<
typename T>
1344 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED 1348 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED 1370 return passed + failed;
1387 Totals diff = *
this - prevTotals;
1415 class ScopedMessageBuilder;
1422 virtual bool sectionStarted(
SectionInfo const& sectionInfo,
1423 Counts& assertions ) = 0;
1424 virtual void sectionEnded(
SectionInfo const& name,
Counts const& assertions,
double _durationInSeconds ) = 0;
1425 virtual void pushScopedMessage(
MessageInfo const& message ) = 0;
1426 virtual void popScopedMessage(
MessageInfo const& message ) = 0;
1428 virtual bool shouldDebugBreak()
const = 0;
1432 virtual std::string getCurrentTestName()
const = 0;
1438 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED 1443 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED 1445 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 1446 #define CATCH_PLATFORM_MAC 1447 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 1448 #define CATCH_PLATFORM_IPHONE 1449 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) 1450 #define CATCH_PLATFORM_WINDOWS 1453 #ifdef CATCH_PLATFORM_MAC 1456 #include <stdbool.h> 1457 #include <sys/types.h> 1459 #include <sys/sysctl.h> 1472 struct kinfo_proc info;
1478 info.kp_proc.p_flag = 0;
1485 mib[2] = KERN_PROC_PID;
1490 size =
sizeof(info);
1491 junk = sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size, NULL, 0);
1496 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
1503 #if defined(__ppc64__) || defined(__ppc__) 1504 #define BreakIntoDebugger() \ 1505 if( Catch::isDebuggerActive() ) { \ 1506 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ 1507 : : : "memory","r0","r3","r4" ); \ 1510 #define BreakIntoDebugger() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );} 1516 #elif defined(_MSC_VER) 1517 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
1518 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { __debugbreak(); } 1520 return IsDebuggerPresent() != 0;
1522 #elif defined(__MINGW32__) 1523 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
1524 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
1525 #define BreakIntoDebugger() if (IsDebuggerPresent() ) { DebugBreak(); } 1527 return IsDebuggerPresent() != 0;
1534 #ifdef CATCH_PLATFORM_WINDOWS 1535 extern "C" __declspec(dllimport)
void __stdcall OutputDebugStringA(
const char* );
1537 ::OutputDebugStringA( text.c_str() );
1544 #endif // CATCH_PLATFORM_WINDOWS 1547 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED 1550 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED 1553 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED 1556 #define TWOBLUECUBES_CATCH_TEST_SPEC_H_INCLUDED 1559 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED 1565 #pragma clang diagnostic push 1566 #pragma clang diagnostic ignored "-Wpadded" 1575 std::string
const& _className,
1576 std::string
const& _description,
1577 std::set<std::string>
const& _tags,
1598 TestCase withName( std::string
const& _newName )
const;
1600 void invoke()
const;
1604 bool isHidden()
const;
1605 bool hasTag( std::string
const& tag )
const;
1606 bool matchesTags( std::string
const& tagPattern )
const;
1607 std::set<std::string>
const& getTags()
const;
1619 std::string
const& className,
1620 std::string
const& name,
1621 std::string
const& description,
1626 #pragma clang diagnostic pop 1630 #define TWOBLUECUBES_CATCH_TAGS_HPP_INCLUDED 1638 #pragma clang diagnostic ignored "-Wpadded" 1647 std::size_t pos = 0;
1648 while( pos < str.size() ) {
1651 std::size_t
end = str.find_first_of(
']', pos );
1652 if( end != std::string::npos ) {
1653 acceptTag( str.substr( pos+1, end-pos-1 ) );
1670 virtual void acceptTag( std::string
const& tag ) = 0;
1671 virtual void acceptChar(
char c ) = 0;
1685 void parse( std::string& description ) {
1687 description = m_remainder;
1691 virtual void acceptTag( std::string
const& tag ) {
1692 m_tags.insert(
toLower( tag ) );
1694 virtual void acceptChar(
char c ) {
1700 std::set<std::string>& m_tags;
1701 std::string m_remainder;
1707 : m_isNegated( false )
1710 Tag( std::string
const& name,
bool isNegated )
1712 m_isNegated( isNegated )
1722 bool operator ! ()
const {
1723 return m_name.empty();
1732 typedef std::map<std::string, Tag> TagMap;
1735 m_tags.insert( std::make_pair(
toLower( tag.
getName() ), tag ) );
1739 return m_tags.empty();
1742 bool matches( std::set<std::string>
const& tags )
const {
1743 TagMap::const_iterator it = m_tags.begin();
1744 TagMap::const_iterator itEnd = m_tags.end();
1745 for(; it != itEnd; ++it ) {
1746 bool found = tags.find( it->first ) != tags.end();
1747 if( found == it->second.isNegated() )
1759 bool matches( std::set<std::string>
const& tags )
const {
1760 std::vector<TagSet>::const_iterator it = m_tagSets.begin();
1761 std::vector<TagSet>::const_iterator itEnd = m_tagSets.end();
1762 for(; it != itEnd; ++it )
1763 if( it->matches( tags ) )
1771 std::vector<TagSet> m_tagSets;
1777 : m_isNegated( false ),
1784 virtual void acceptTag( std::string
const& tag ) {
1785 m_currentTagSet.add(
Tag( tag, m_isNegated ) );
1786 m_isNegated =
false;
1788 virtual void acceptChar(
char c ) {
1794 m_exp.m_tagSets.push_back( m_currentTagSet );
1798 virtual void endParse() {
1799 if( !m_currentTagSet.empty() )
1800 m_exp.m_tagSets.push_back( m_currentTagSet );
1824 enum WildcardPosition {
1826 WildcardAtStart = 1,
1828 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
1833 : m_stringToMatch(
toLower( testSpec ) ),
1834 m_filterType( matchBehaviour ),
1835 m_wildcardPosition( NoWildcard )
1838 if(
startsWith( m_stringToMatch,
"exclude:" ) ) {
1839 m_stringToMatch = m_stringToMatch.substr( 8 );
1842 else if(
startsWith( m_stringToMatch,
"~" ) ) {
1843 m_stringToMatch = m_stringToMatch.substr( 1 );
1852 m_stringToMatch = m_stringToMatch.substr( 1 );
1853 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtStart );
1855 if(
endsWith( m_stringToMatch,
"*" ) ) {
1856 m_stringToMatch = m_stringToMatch.substr( 0, m_stringToMatch.size()-1 );
1857 m_wildcardPosition = (WildcardPosition)( m_wildcardPosition | WildcardAtEnd );
1862 return m_filterType;
1871 #pragma clang diagnostic push 1872 #pragma clang diagnostic ignored "-Wunreachable-code" 1875 bool isMatch(
TestCase const& testCase )
const {
1879 switch( m_wildcardPosition ) {
1881 return m_stringToMatch == name;
1882 case WildcardAtStart:
1883 return endsWith( name, m_stringToMatch );
1886 case WildcardAtBothEnds:
1887 return contains( name, m_stringToMatch );
1889 throw std::logic_error(
"Unhandled wildcard type" );
1893 #pragma clang diagnostic pop 1896 std::string m_stringToMatch;
1898 WildcardPosition m_wildcardPosition;
1911 m_exclusionFilters.push_back( filter );
1913 m_inclusionFilters.push_back( filter );
1920 m_tagExpressions.push_back( exp );
1924 if( !m_tagExpressions.empty() ) {
1925 std::vector<TagExpression>::const_iterator it = m_tagExpressions.begin();
1926 std::vector<TagExpression>::const_iterator itEnd = m_tagExpressions.end();
1927 for(; it != itEnd; ++it )
1928 if( it->matches( testCase.
getTags() ) )
1934 if( !m_inclusionFilters.empty() ) {
1935 std::vector<TestCaseFilter>::const_iterator it = m_inclusionFilters.begin();
1936 std::vector<TestCaseFilter>::const_iterator itEnd = m_inclusionFilters.end();
1937 for(; it != itEnd; ++it )
1938 if( it->shouldInclude( testCase ) )
1943 else if( m_exclusionFilters.empty() && m_tagExpressions.empty() ) {
1947 std::vector<TestCaseFilter>::const_iterator it = m_exclusionFilters.begin();
1948 std::vector<TestCaseFilter>::const_iterator itEnd = m_exclusionFilters.end();
1949 for(; it != itEnd; ++it )
1950 if( !it->shouldInclude( testCase ) )
1955 std::vector<TagExpression> m_tagExpressions;
1956 std::vector<TestCaseFilter> m_inclusionFilters;
1957 std::vector<TestCaseFilter> m_exclusionFilters;
1964 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED 1992 virtual bool allowThrows()
const = 0;
1993 virtual std::ostream& stream()
const = 0;
1994 virtual std::string name()
const = 0;
1995 virtual bool includeSuccessfulResults()
const = 0;
1996 virtual bool shouldDebugBreak()
const = 0;
1997 virtual bool warnAboutMissingAssertions()
const = 0;
1998 virtual int abortAfter()
const = 0;
2004 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED 2007 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED 2009 #include <streambuf> 2019 #include <stdexcept> 2024 template<
typename WriterF,
size_t bufferSize=256>
2026 char data[bufferSize];
2031 setp( data, data +
sizeof(data) );
2039 int overflow(
int c ) {
2043 if( pbase() == epptr() )
2044 m_writer( std::string( 1, static_cast<char>( c ) ) );
2046 sputc( static_cast<char>( c ) );
2052 if( pbase() != pptr() ) {
2053 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
2054 setp( pbase(), epptr() );
2072 : streamBuf( NULL ), isOwned( false )
2075 Stream( std::streambuf* _streamBuf,
bool _isOwned )
2076 : streamBuf( _streamBuf ), isOwned( _isOwned )
2099 #ifndef CATCH_CONFIG_CONSOLE_WIDTH 2100 #define CATCH_CONFIG_CONSOLE_WIDTH 80 2108 : listTests( false ),
2110 listReporters( false ),
2111 showSuccessfulTests( false ),
2112 shouldDebugBreak( false ),
2148 virtual void dummy();
2152 : m_os(
std::cout.rdbuf() )
2157 m_os(
std::cout.rdbuf() )
2160 std::string groupName;
2161 for( std::size_t i = 0; i < data.
testsOrTags.size(); ++i ) {
2167 for( std::size_t i = 0; i < data.
testsOrTags.size(); ++i ) {
2174 m_filterSets.push_back( filters );
2179 m_os.rdbuf( std::cout.rdbuf() );
2184 m_data.outputFilename = filename;
2188 return m_data.outputFilename ;
2196 return m_data.processName;
2200 return m_data.shouldDebugBreak;
2204 m_os.rdbuf( buf ? buf : std::cout.rdbuf() );
2219 m_filterSets.push_back( filters );
2223 return m_data.abortAfter;
2226 std::vector<TestCaseFilters>
const&
filters()
const {
2227 return m_filterSets;
2234 virtual std::ostream&
stream()
const {
return m_os; }
2235 virtual std::string
name()
const {
return m_data.name.empty() ? m_data.processName : m_data.name; }
2244 mutable std::ostream m_os;
2245 std::vector<TestCaseFilters> m_filterSets;
2251 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED 2256 template<
typename T>
2261 : nullableValue( new( storage ) T( _value ) )
2264 : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
2274 nullableValue =
new( storage ) T( *_other );
2279 nullableValue =
new( storage ) T( _value );
2285 nullableValue->~T();
2286 nullableValue = NULL;
2295 return nullableValue ? *nullableValue : defaultValue;
2298 bool some()
const {
return nullableValue != NULL; }
2299 bool none()
const {
return nullableValue == NULL; }
2301 bool operator !()
const {
return nullableValue == NULL; }
2308 char storage[
sizeof(T)];
2322 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
2325 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
2327 std::ostream&
stream()
const {
return *m_stream; }
2331 std::ostream* m_stream;
2337 : shouldRedirectStdOut( false )
2343 template<
typename T>
2364 std::size_t _groupIndex,
2365 std::size_t _groupsCount )
2367 groupIndex( _groupIndex ),
2368 groupsCounts( _groupsCount )
2378 std::string
const& _description,
2381 description( _description ),
2382 lineInfo( _lineInfo )
2392 std::vector<MessageInfo>
const& _infoMessages,
2394 : assertionResult( _assertionResult ),
2395 infoMessages( _infoMessages ),
2398 if( assertionResult.hasMessage() ) {
2401 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
2402 builder << assertionResult.getMessage();
2405 infoMessages.push_back( builder.m_info );
2417 Counts const& _assertions,
2418 double _durationInSeconds,
2419 bool _missingAssertions )
2420 : sectionInfo( _sectionInfo ),
2421 assertions( _assertions ),
2422 durationInSeconds( _durationInSeconds ),
2423 missingAssertions( _missingAssertions )
2436 std::string
const& _stdOut,
2437 std::string
const& _stdErr,
2439 : testInfo( _testInfo ),
2443 aborting( _aborting )
2458 : groupInfo( _groupInfo ),
2460 aborting( _aborting )
2463 : groupInfo( _groupInfo ),
2477 : runInfo( _runInfo ),
2479 aborting( _aborting )
2482 : runInfo( _other.runInfo ),
2483 totals( _other.totals ),
2484 aborting( _other.aborting )
2501 virtual void noMatchingTestCases( std::string
const& spec ) = 0;
2503 virtual void testRunStarting(
TestRunInfo const& testRunInfo ) = 0;
2504 virtual void testGroupStarting(
GroupInfo const& groupInfo ) = 0;
2506 virtual void testCaseStarting(
TestCaseInfo const& testInfo ) = 0;
2507 virtual void sectionStarting(
SectionInfo const& sectionInfo ) = 0;
2509 virtual void assertionStarting(
AssertionInfo const& assertionInfo ) = 0;
2511 virtual bool assertionEnded(
AssertionStats const& assertionStats ) = 0;
2512 virtual void sectionEnded(
SectionStats const& sectionStats ) = 0;
2513 virtual void testCaseEnded(
TestCaseStats const& testCaseStats ) = 0;
2514 virtual void testGroupEnded(
TestGroupStats const& testGroupStats ) = 0;
2515 virtual void testRunEnded(
TestRunStats const& testRunStats ) = 0;
2521 : m_config( _config.fullConfig() ),
2522 stream( _config.stream() )
2530 currentTestRunInfo = _testRunInfo;
2533 currentGroupInfo = _groupInfo;
2537 currentTestCaseInfo = _testInfo;
2540 m_sectionStack.push_back( _sectionInfo );
2544 m_sectionStack.pop_back();
2547 currentTestCaseInfo.reset();
2548 assert( m_sectionStack.empty() );
2551 currentGroupInfo.reset();
2554 currentTestCaseInfo.reset();
2555 currentGroupInfo.reset();
2556 currentTestRunInfo.reset();
2570 template<
typename T,
typename ChildNodeT>
2572 explicit Node( T
const& _value ) : value( _value ) {}
2599 return node->stats.sectionInfo.lineInfo == other.
lineInfo;
2607 : m_config( _config.fullConfig() ),
2608 stream( _config.stream() )
2620 if( m_sectionStack.empty() ) {
2621 if( !m_rootSection )
2622 m_rootSection =
new SectionNode( incompleteStats );
2623 node = m_rootSection;
2627 SectionNode::ChildSections::const_iterator it =
2636 m_sectionStack.push_back( node );
2637 m_deepestSection = node;
2643 assert( !m_sectionStack.empty() );
2644 SectionNode& sectionNode = *m_sectionStack.back();
2645 sectionNode.
assertions.push_back( assertionStats );
2649 assert( !m_sectionStack.empty() );
2651 node.
stats = sectionStats;
2652 m_sectionStack.pop_back();
2656 assert( m_sectionStack.size() == 0 );
2657 node->children.push_back( m_rootSection );
2658 m_testCases.push_back( node );
2659 m_rootSection.
reset();
2661 assert( m_deepestSection );
2662 m_deepestSection->stdOut = testCaseStats.
stdOut;
2663 m_deepestSection->stdErr = testCaseStats.
stdErr;
2667 node->children.
swap( m_testCases );
2668 m_testGroups.push_back( node );
2672 node->children.
swap( m_testGroups );
2673 m_testRuns.push_back( node );
2676 virtual void testRunEnded() = 0;
2697 virtual bool shouldRedirectStdout()
const = 0;
2699 virtual void StartTesting() = 0;
2700 virtual void EndTesting(
Totals const& totals ) = 0;
2701 virtual void StartGroup( std::string
const& groupName ) = 0;
2702 virtual void EndGroup( std::string
const& groupName,
Totals const& totals ) = 0;
2703 virtual void StartTestCase(
TestCaseInfo const& testInfo ) = 0;
2704 virtual void EndTestCase(
TestCaseInfo const& testInfo,
Totals const& totals, std::string
const& stdOut, std::string
const& stdErr ) = 0;
2705 virtual void StartSection( std::string
const& sectionName, std::string
const& description ) = 0;
2706 virtual void EndSection( std::string
const& sectionName,
Counts const& assertions ) = 0;
2707 virtual void NoAssertionsInSection( std::string
const& sectionName ) = 0;
2708 virtual void NoAssertionsInTestCase( std::string
const& testName ) = 0;
2709 virtual void Aborted() = 0;
2716 virtual std::string getDescription()
const = 0;
2724 virtual FactoryMap
const& getFactories()
const = 0;
2727 inline std::string
trim( std::string
const& str ) {
2728 static char const* whitespaceChars =
"\n\r\t ";
2729 std::string::size_type start = str.find_first_not_of( whitespaceChars );
2730 std::string::size_type
end = str.find_last_not_of( whitespaceChars );
2732 return start != std::string::npos ? str.substr( start, 1+end-start ) :
"";
2755 virtual void registerReporter( std::string
const& name,
IReporterFactory* factory ) = 0;
2756 virtual void registerTest(
TestCase const& testInfo ) = 0;
2775 template<
typename MatcherT>
2777 std::string
const& matcherCallAsString ) {
2778 std::string matcherAsString = matcher.toString();
2779 if( matcherAsString ==
"{?}" )
2780 matcherAsString = matcherCallAsString;
2782 .
setRhs( matcherAsString )
2783 .
setOp(
"matches" );
2786 template<
typename MatcherT,
typename ArgT>
2789 std::string
const& matcherCallAsString ) {
2795 template<
typename MatcherT,
typename ArgT>
2798 std::string
const& matcherCallAsString ) {
2809 #define INTERNAL_CATCH_ASSERTIONINFO_NAME INTERNAL_CATCH_UNIQUE_NAME( __assertionInfo ) 2812 #define INTERNAL_CATCH_ACCEPT_EXPR( evaluatedExpr, resultDisposition, originalExpr ) \ 2813 if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \ 2814 if( internal_catch_action & Catch::ResultAction::Debug ) BreakIntoDebugger(); \ 2815 if( internal_catch_action & Catch::ResultAction::Abort ) throw Catch::TestFailureException(); \ 2816 if( !Catch::shouldContinueOnFailure( resultDisposition ) ) throw Catch::TestFailureException(); \ 2817 Catch::isTrue( false && originalExpr ); \ 2821 #define INTERNAL_CATCH_ACCEPT_INFO( expr, macroName, resultDisposition ) \ 2822 Catch::AssertionInfo INTERNAL_CATCH_ASSERTIONINFO_NAME( macroName, CATCH_INTERNAL_LINEINFO, expr, resultDisposition ); 2825 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \ 2827 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ 2829 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \ 2830 } catch( Catch::TestFailureException& ) { \ 2833 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \ 2834 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, expr ); \ 2836 } while( Catch::isTrue( false ) ) 2839 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \ 2840 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ 2841 if( Catch::getResultCapture().getLastResult()->succeeded() ) 2844 #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \ 2845 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \ 2846 if( !Catch::getResultCapture().getLastResult()->succeeded() ) 2849 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \ 2851 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ 2854 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ 2857 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), resultDisposition, false ); \ 2859 } while( Catch::isTrue( false ) ) 2862 #define INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ 2864 if( Catch::getCurrentContext().getConfig()->allowThrows() ) { \ 2866 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \ 2869 catch( Catch::TestFailureException& ) { \ 2872 catch( exceptionType ) { \ 2873 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::Ok ), resultDisposition, false ); \ 2877 #define INTERNAL_CATCH_THROWS( expr, exceptionType, resultDisposition, macroName ) \ 2879 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ 2880 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ 2881 } while( Catch::isTrue( false ) ) 2884 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \ 2886 INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \ 2887 INTERNAL_CATCH_THROWS_IMPL( expr, exceptionType, resultDisposition ) \ 2889 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ 2890 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ 2892 } while( Catch::isTrue( false ) ) 2895 #define INTERNAL_CATCH_MSG( log, messageType, resultDisposition, macroName ) \ 2897 INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \ 2898 INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \ 2899 } while( Catch::isTrue( false ) ) 2902 #define INTERNAL_CATCH_INFO( log, macroName ) \ 2903 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; 2906 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ 2908 INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \ 2910 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \ 2911 } catch( Catch::TestFailureException& ) { \ 2914 INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \ 2915 resultDisposition | Catch::ResultDisposition::ContinueOnFailure, false ); \ 2917 } while( Catch::isTrue( false ) ) 2920 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED 2923 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED 2925 #ifdef CATCH_PLATFORM_WINDOWS 2926 typedef unsigned long long uint64_t;
2937 unsigned int getElapsedNanoseconds()
const;
2938 unsigned int getElapsedMilliseconds()
const;
2939 double getElapsedSeconds()
const;
2954 std::string
const& name,
2955 std::string
const& description =
"" )
2956 : m_info( name, description, lineInfo ),
2963 if( m_sectionIncluded )
2969 return m_sectionIncluded;
2977 bool m_sectionIncluded;
2983 #ifdef CATCH_CONFIG_VARIADIC_MACROS 2984 #define INTERNAL_CATCH_SECTION( ... ) \ 2985 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) 2987 #define INTERNAL_CATCH_SECTION( name, desc ) \ 2988 if( Catch::Section INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::Section( CATCH_INTERNAL_LINEINFO, name, desc ) ) 2992 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED 3001 template<
typename T>
3004 virtual T getValue( std::size_t index )
const = 0;
3005 virtual std::size_t size ()
const = 0;
3008 template<
typename T>
3014 return m_from+
static_cast<int>( index );
3018 return static_cast<std::size_t
>( 1+m_to-m_from );
3027 template<
typename T>
3033 m_values.push_back( value );
3037 return m_values[index];
3041 return m_values.size();
3045 std::vector<T> m_values;
3048 template<
typename T>
3055 : m_fileInfo( other.m_fileInfo ),
3062 m_fileInfo = fileInfo;
3070 operator T ()
const {
3073 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
3074 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
3075 for(
size_t index = 0; it != itEnd; ++it )
3078 if( overallIndex >= index && overallIndex < index + generator->size() )
3080 return generator->
getValue( overallIndex-index );
3082 index += generator->
size();
3089 m_totalSize += generator->
size();
3090 m_composed.push_back( generator );
3100 valuesGen->
add( value );
3108 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
3109 m_totalSize += other.m_totalSize;
3110 other.m_composed.clear();
3113 std::vector<const IGenerator<T>*> m_composed;
3114 std::string m_fileInfo;
3118 namespace Generators
3120 template<
typename T>
3127 template<
typename T>
3131 valuesGen->
add( val1 );
3132 valuesGen->
add( val2 );
3133 generators.
add( valuesGen );
3137 template<
typename T>
3141 valuesGen->
add( val1 );
3142 valuesGen->
add( val2 );
3143 valuesGen->
add( val3 );
3144 generators.
add( valuesGen );
3148 template<
typename T>
3152 valuesGen->
add( val1 );
3153 valuesGen->
add( val2 );
3154 valuesGen->
add( val3 );
3155 valuesGen->
add( val4 );
3156 generators.
add( valuesGen );
3162 using namespace Generators;
3166 #define INTERNAL_CATCH_LINESTR2( line ) #line 3167 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) 3169 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) 3172 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED 3182 virtual std::string translate()
const = 0;
3192 template<
typename T>
3196 ExceptionTranslator( std::string(*translateFunction)( T& ) )
3197 : m_translateFunction( translateFunction )
3200 virtual std::string translate()
const {
3205 return m_translateFunction( ex );
3210 std::string(*m_translateFunction)( T& );
3214 template<
typename T>
3217 (
new ExceptionTranslator<T>( translateFunction ) );
3223 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \ 3224 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \ 3225 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\ 3226 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ) 3229 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED 3240 : m_epsilon(
std::numeric_limits<float>::epsilon()*100 ),
3246 : m_epsilon( other.m_epsilon ),
3247 m_scale( other.m_scale ),
3248 m_value( other.m_value )
3258 approx.
scale( m_scale );
3264 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
3271 friend bool operator != (
double lhs,
Approx const& rhs ) {
3275 friend bool operator != (
Approx const& lhs,
double rhs ) {
3280 m_epsilon = newEpsilon;
3290 std::ostringstream oss;
3291 oss <<
"Approx( " << m_value <<
" )";
3304 return value.toString();
3310 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED 3313 namespace Matchers {
3316 template<
typename ExpressionT>
3323 virtual bool match( ExpressionT
const& expr )
const = 0;
3324 virtual std::string
toString()
const = 0;
3327 template<
typename DerivedT,
typename ExpressionT>
3337 template<
typename ExpressionT>
3345 m_matchers.push_back( matcher.
clone() );
3348 virtual bool match( ExpressionT
const& expr )
const 3350 for( std::size_t i = 0; i < m_matchers.size(); ++i )
3351 if( !m_matchers[i]->match( expr ) )
3356 std::ostringstream oss;
3358 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
3361 oss << m_matchers[i]->toString();
3368 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
3371 template<
typename ExpressionT>
3379 m_matchers.push_back( matcher.
clone() );
3382 virtual bool match( ExpressionT
const& expr )
const 3384 for( std::size_t i = 0; i < m_matchers.size(); ++i )
3385 if( m_matchers[i]->match( expr ) )
3390 std::ostringstream oss;
3392 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
3395 oss << m_matchers[i]->toString();
3402 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
3407 namespace StdString {
3409 inline std::string
makeString( std::string
const& str ) {
return str; }
3410 inline std::string
makeString(
const char* str ) {
return str ? std::string( str ) : std::string(); }
3413 Equals( std::string
const& str ) : m_str( str ){}
3418 virtual bool match( std::string
const& expr )
const {
3419 return m_str == expr;
3422 return "equals: \"" + m_str +
"\"";
3429 Contains( std::string
const& substr ) : m_substr( substr ){}
3434 virtual bool match( std::string
const& expr )
const {
3435 return expr.find( m_substr ) != std::string::npos;
3438 return "contains: \"" + m_substr +
"\"";
3450 virtual bool match( std::string
const& expr )
const {
3451 return expr.find( m_substr ) == 0;
3454 return "starts with: \"" + m_substr +
"\"";
3461 EndsWith( std::string
const& substr ) : m_substr( substr ){}
3466 virtual bool match( std::string
const& expr )
const {
3467 return expr.find( m_substr ) == expr.size() - m_substr.size();
3470 return "ends with: \"" + m_substr +
"\"";
3480 template<
typename ExpressionT>
3485 template<
typename ExpressionT>
3491 template<
typename ExpressionT>
3496 template<
typename ExpressionT>
3530 using namespace Matchers;
3537 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED 3552 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED 3554 #import <objc/runtime.h> 3576 class OcMethod :
public SharedImpl<ITestCase> {
3579 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
3581 virtual void invoke()
const {
3582 id obj = [[m_cls alloc] init];
3584 performOptionalSelector( obj,
@selector(setUp) );
3585 performOptionalSelector( obj, m_sel );
3586 performOptionalSelector( obj,
@selector(tearDown) );
3588 arcSafeRelease( obj );
3591 virtual ~OcMethod() {}
3599 inline bool startsWith( std::string
const& str, std::string
const& sub ) {
3600 return str.length() > sub.length() && str.substr( 0, sub.length() ) == sub;
3603 inline std::string getAnnotation( Class cls,
3604 std::string
const& annotationName,
3605 std::string
const& testCaseName ) {
3606 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3607 SEL sel = NSSelectorFromString( selStr );
3608 arcSafeRelease( selStr );
3609 id value = performOptionalSelector( cls, sel );
3611 return [(NSString*)value UTF8String];
3616 inline size_t registerTestMethods() {
3617 size_t noTestMethods = 0;
3618 int noClasses = objc_getClassList( NULL, 0 );
3620 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc(
sizeof(Class) * noClasses);
3621 objc_getClassList( classes, noClasses );
3623 for(
int c = 0; c < noClasses; c++ ) {
3624 Class cls = classes[c];
3627 Method* methods = class_copyMethodList( cls, &count );
3628 for( u_int m = 0; m < count ; m++ ) {
3629 SEL selector = method_getName(methods[m]);
3630 std::string methodName = sel_getName(selector);
3632 std::string testCaseName = methodName.substr( 15 );
3633 std::string name = Detail::getAnnotation( cls,
"Name", testCaseName );
3634 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
3635 const char* className = class_getName( cls );
3644 return noTestMethods;
3647 namespace Matchers {
3649 namespace NSStringMatchers {
3651 template<
typename MatcherT>
3652 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
3653 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
3654 StringHolder( StringHolder
const& other ) : m_substr( [other.m_substr copy] ){}
3656 arcSafeRelease( m_substr );
3663 Equals( NSString* substr ) : StringHolder( substr ){}
3665 virtual bool match( ExpressionType
const& str )
const {
3666 return (str != nil || m_substr == nil ) &&
3667 [str isEqualToString:m_substr];
3670 virtual std::string
toString()
const {
3676 Contains( NSString* substr ) : StringHolder( substr ){}
3678 virtual bool match( ExpressionType
const& str )
const {
3679 return (str != nil || m_substr == nil ) &&
3680 [str rangeOfString:m_substr].location != NSNotFound;
3683 virtual std::string
toString()
const {
3689 StartsWith( NSString* substr ) : StringHolder( substr ){}
3691 virtual bool match( ExpressionType
const& str )
const {
3692 return (str != nil || m_substr == nil ) &&
3693 [str rangeOfString:m_substr].location == 0;
3696 virtual std::string
toString()
const {
3701 EndsWith( NSString* substr ) : StringHolder( substr ){}
3703 virtual bool match( ExpressionType
const& str )
const {
3704 return (str != nil || m_substr == nil ) &&
3705 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
3708 virtual std::string
toString()
const {
3730 using namespace Matchers;
3735 #define OC_TEST_CASE( name, desc )\ 3736 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ 3740 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ 3744 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) 3748 #if defined( CATCH_CONFIG_MAIN ) || defined( CATCH_CONFIG_RUNNER ) 3750 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED 3756 #pragma clang diagnostic push 3757 #pragma clang diagnostic ignored "-Wweak-vtables" 3761 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED 3764 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED 3767 #define TWOBLUECUBES_CLARA_H_INCLUDED 3770 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED 3777 struct TextAttributes {
3779 : initialIndent( std::string::npos ),
3785 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value;
return *
this; }
3786 TextAttributes& setIndent( std::size_t _value ) { indent = _value;
return *
this; }
3787 TextAttributes& setWidth( std::size_t _value ) { width = _value;
return *
this; }
3788 TextAttributes& setTabChar(
char _value ) { tabChar = _value;
return *
this; }
3790 std::size_t initialIndent;
3798 Text( std::string
const& _str, TextAttributes
const& _attr = TextAttributes() );
3799 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos );
3801 typedef std::vector<std::string>::const_iterator const_iterator;
3803 const_iterator
begin()
const {
return lines.begin(); }
3804 const_iterator
end()
const {
return lines.end(); }
3805 std::string
const& last()
const {
return lines.back(); }
3806 std::size_t size()
const {
return lines.size(); }
3807 std::string
const& operator[]( std::size_t _index )
const {
return lines[_index]; }
3810 friend std::ostream&
operator << ( std::ostream& _stream, Text
const& _text );
3814 TextAttributes attr;
3815 std::vector<std::string> lines;
3822 template<
typename T>
struct RemoveConstRef{
typedef T type; };
3823 template<
typename T>
struct RemoveConstRef<T&>{
typedef T type; };
3824 template<
typename T>
struct RemoveConstRef<T const&>{
typedef T type; };
3825 template<
typename T>
struct RemoveConstRef<T const>{
typedef T type; };
3827 template<
typename T>
struct IsBool {
static const bool value =
false; };
3828 template<>
struct IsBool<bool> {
static const bool value =
true; };
3830 template<
typename T>
3831 void convertInto( std::string
const& _source, T& _dest ) {
3832 std::stringstream ss;
3836 throw std::runtime_error(
"Unable to convert " + _source +
" to destination type" );
3838 inline void convertInto( std::string
const& _source, std::string& _dest ) {
3841 inline void convertInto( std::string
const& _source,
bool& _dest ) {
3842 std::string sourceLC = _source;
3843 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
3844 if( sourceLC ==
"y" || sourceLC ==
"1" || sourceLC ==
"true" || sourceLC ==
"yes" || sourceLC ==
"on" )
3846 else if( sourceLC ==
"n" || sourceLC ==
"0" || sourceLC ==
"false" || sourceLC ==
"no" || sourceLC ==
"off" )
3849 throw std::runtime_error(
"Expected a boolean value but did not recognise:\n '" + _source +
"'" );
3851 inline void convertInto(
bool _source,
bool& _dest ) {
3854 template<
typename T>
3855 inline void convertInto(
bool, T& ) {
3856 throw std::runtime_error(
"Invalid conversion" );
3859 template<
typename ConfigT>
3860 struct IArgFunction {
3861 virtual ~IArgFunction() {}
3862 virtual void set( ConfigT& config, std::string
const& value )
const = 0;
3863 virtual void setFlag( ConfigT& config )
const = 0;
3864 virtual bool takesArg()
const = 0;
3865 virtual IArgFunction* clone()
const = 0;
3868 template<
typename ConfigT>
3869 class BoundArgFunction {
3871 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
3872 BoundArgFunction( BoundArgFunction
const& other ) : functionObj( other.functionObj->clone() ) {}
3873 BoundArgFunction& operator = ( BoundArgFunction
const& other ) {
3874 IArgFunction<ConfigT>* newFunctionObj = other.functionObj->clone();
3876 functionObj = newFunctionObj;
3879 ~BoundArgFunction() {
delete functionObj; }
3881 void set( ConfigT& config, std::string
const& value )
const {
3882 functionObj->set( config, value );
3884 void setFlag( ConfigT& config )
const {
3885 functionObj->setFlag( config );
3887 bool takesArg()
const {
return functionObj->takesArg(); }
3889 IArgFunction<ConfigT>* functionObj;
3892 template<
typename C>
3893 struct NullBinder : IArgFunction<C>{
3894 virtual void set( C&, std::string
const& )
const {}
3895 virtual void setFlag( C& )
const {}
3896 virtual bool takesArg()
const {
return true; }
3897 virtual IArgFunction<C>* clone()
const {
return new NullBinder( *
this ); }
3900 template<
typename C,
typename M>
3901 struct BoundDataMember : IArgFunction<C>{
3902 BoundDataMember( M C::* _member ) : member( _member ) {}
3903 virtual void set( C& p, std::string
const& stringValue )
const {
3904 convertInto( stringValue, p.*member );
3906 virtual void setFlag( C& p )
const {
3907 convertInto(
true, p.*member );
3909 virtual bool takesArg()
const {
return !IsBool<M>::value; }
3910 virtual IArgFunction<C>* clone()
const {
return new BoundDataMember( *
this ); }
3913 template<
typename C,
typename M>
3914 struct BoundUnaryMethod : IArgFunction<C>{
3915 BoundUnaryMethod(
void (C::*_member)( M ) ) : member( _member ) {}
3916 virtual void set( C& p, std::string
const& stringValue )
const {
3917 typename RemoveConstRef<M>::type value;
3918 convertInto( stringValue, value );
3919 (p.*member)( value );
3921 virtual void setFlag( C& p )
const {
3922 typename RemoveConstRef<M>::type value;
3923 convertInto(
true, value );
3924 (p.*member)( value );
3926 virtual bool takesArg()
const {
return !IsBool<M>::value; }
3927 virtual IArgFunction<C>* clone()
const {
return new BoundUnaryMethod( *
this ); }
3928 void (C::*member)( M );
3930 template<
typename C>
3931 struct BoundNullaryMethod : IArgFunction<C>{
3932 BoundNullaryMethod(
void (C::*_member)() ) : member( _member ) {}
3933 virtual void set( C& p, std::string
const& stringValue )
const {
3935 convertInto( stringValue, value );
3939 virtual void setFlag( C& p )
const {
3942 virtual bool takesArg()
const {
return false; }
3943 virtual IArgFunction<C>* clone()
const {
return new BoundNullaryMethod( *
this ); }
3944 void (C::*member)();
3947 template<
typename C>
3948 struct BoundUnaryFunction : IArgFunction<C>{
3949 BoundUnaryFunction(
void (*_function)( C& ) ) :
function( _function ) {}
3950 virtual void set( C& obj, std::string
const& stringValue )
const {
3952 convertInto( stringValue, value );
3956 virtual void setFlag( C& p )
const {
3959 virtual bool takesArg()
const {
return false; }
3960 virtual IArgFunction<C>* clone()
const {
return new BoundUnaryFunction( *
this ); }
3961 void (*
function)( C& );
3964 template<
typename C,
typename T>
3965 struct BoundBinaryFunction : IArgFunction<C>{
3966 BoundBinaryFunction(
void (*_function)( C&, T ) ) :
function( _function ) {}
3967 virtual void set( C& obj, std::string
const& stringValue )
const {
3968 typename RemoveConstRef<T>::type value;
3969 convertInto( stringValue, value );
3970 function( obj, value );
3972 virtual void setFlag( C& obj )
const {
3973 typename RemoveConstRef<T>::type value;
3974 convertInto(
true, value );
3975 function( obj, value );
3977 virtual bool takesArg()
const {
return !IsBool<T>::value; }
3978 virtual IArgFunction<C>* clone()
const {
return new BoundBinaryFunction( *
this ); }
3979 void (*
function)( C&, T );
3982 template<
typename C,
typename M>
3983 BoundArgFunction<C> makeBoundField( M C::* _member ) {
3984 return BoundArgFunction<C>(
new BoundDataMember<C,M>( _member ) );
3986 template<
typename C,
typename M>
3987 BoundArgFunction<C> makeBoundField(
void (C::*_member)( M ) ) {
3988 return BoundArgFunction<C>(
new BoundUnaryMethod<C,M>( _member ) );
3990 template<
typename C>
3991 BoundArgFunction<C> makeBoundField(
void (C::*_member)() ) {
3992 return BoundArgFunction<C>(
new BoundNullaryMethod<C>( _member ) );
3994 template<
typename C>
3995 BoundArgFunction<C> makeBoundField(
void (*_function)( C& ) ) {
3996 return BoundArgFunction<C>(
new BoundUnaryFunction<C>( _function ) );
3998 template<
typename C,
typename T>
3999 BoundArgFunction<C> makeBoundField(
void (*_function)( C&, T ) ) {
4000 return BoundArgFunction<C>(
new BoundBinaryFunction<C, T>( _function ) );
4005 Parser() : separators(
" \t=:" ) {}
4008 enum Type { Positional, ShortOpt, LongOpt };
4009 Token( Type _type, std::string
const& _data ) : type( _type ), data( _data ) {}
4014 void parseIntoTokens(
int argc,
char const *
const * argv, std::vector<Parser::Token>& tokens )
const {
4015 for(
int i = 1; i < argc; ++i )
4016 parseIntoTokens( argv[i] , tokens);
4018 void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens )
const {
4019 while( !arg.empty() ) {
4020 Parser::Token token( Parser::Token::Positional, arg );
4022 if( token.data[0] ==
'-' ) {
4023 if( token.data.size() > 1 && token.data[1] ==
'-' ) {
4024 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
4027 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
4028 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
4029 arg =
"-" + token.data.substr( 1 );
4030 token.data = token.data.substr( 0, 1 );
4034 if( token.type != Parser::Token::Positional ) {
4035 std::size_t pos = token.data.find_first_of( separators );
4036 if( pos != std::string::npos ) {
4037 arg = token.data.substr( pos+1 );
4038 token.data = token.data.substr( 0, pos );
4041 tokens.push_back( token );
4044 std::string separators;
4047 template<
typename ConfigT>
4051 Arg( Detail::BoundArgFunction<ConfigT>
const& _boundField ) : boundField( _boundField ), position( -1 ) {}
4053 bool hasShortName( std::string
const& shortName )
const {
4054 for( std::vector<std::string>::const_iterator
4055 it = shortNames.begin(), itEnd = shortNames.end();
4058 if( *it == shortName )
4062 bool hasLongName( std::string
const& _longName )
const {
4063 return _longName == longName;
4065 bool takesArg()
const {
4066 return !hint.empty();
4068 bool isFixedPositional()
const {
4069 return position != -1;
4071 bool isAnyPositional()
const {
4072 return position == -1 && shortNames.empty() && longName.empty();
4074 std::string dbgName()
const {
4075 if( !longName.empty() )
4076 return "--" + longName;
4077 if( !shortNames.empty() )
4078 return "-" + shortNames[0];
4079 return "positional args";
4081 void validate()
const {
4082 if( boundField.takesArg() && !takesArg() )
4083 throw std::logic_error( dbgName() +
" must specify an arg name" );
4085 std::string commands()
const {
4086 std::ostringstream oss;
4088 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4089 for(; it != itEnd; ++it ) {
4096 if( !longName.empty() ) {
4099 oss <<
"--" << longName;
4102 oss <<
" <" << hint <<
">";
4106 Detail::BoundArgFunction<ConfigT> boundField;
4107 std::vector<std::string> shortNames;
4108 std::string longName;
4109 std::string description;
4116 template<
typename F>
4117 ArgBinder( CommandLine* cl, F f )
4119 m_arg( Detail::makeBoundField( f ) )
4121 ArgBinder( ArgBinder& other )
4122 : m_cl( other.m_cl ),
4123 m_arg( other.m_arg )
4130 if( m_arg.isFixedPositional() ) {
4131 m_cl->m_positionalArgs.insert( std::make_pair( m_arg.position, m_arg ) );
4132 if( m_arg.position > m_cl->m_highestSpecifiedArgPosition )
4133 m_cl->m_highestSpecifiedArgPosition = m_arg.position;
4135 else if( m_arg.isAnyPositional() ) {
4136 if( m_cl->m_arg.get() )
4137 throw std::logic_error(
"Only one unpositional argument can be added" );
4138 m_cl->m_arg = std::auto_ptr<Arg>(
new Arg( m_arg ) );
4141 m_cl->m_options.push_back( m_arg );
4144 ArgBinder& shortOpt( std::string
const& name ) {
4145 m_arg.shortNames.push_back( name );
4148 ArgBinder& longOpt( std::string
const& name ) {
4149 m_arg.longName = name;
4152 ArgBinder& describe( std::string
const& description ) {
4153 m_arg.description = description;
4156 ArgBinder& hint( std::string
const& hint ) {
4160 ArgBinder& position(
int position ) {
4161 m_arg.position = position;
4172 : m_boundProcessName(
new Detail::NullBinder<ConfigT>() ),
4173 m_highestSpecifiedArgPosition( 0 )
4175 CommandLine( CommandLine
const& other )
4176 : m_boundProcessName( other.m_boundProcessName ),
4177 m_options ( other.m_options ),
4178 m_positionalArgs( other.m_positionalArgs ),
4179 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition )
4181 if( other.m_arg.get() )
4182 m_arg = std::auto_ptr<Arg>(
new Arg( *other.m_arg ) );
4185 template<
typename F>
4186 ArgBinder bind( F f ) {
4187 ArgBinder binder(
this, f );
4190 template<
typename F>
4191 void bindProcessName( F f ) {
4192 m_boundProcessName = Detail::makeBoundField( f );
4196 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4197 std::size_t maxWidth = 0;
4198 for( it = itBegin; it != itEnd; ++it )
4199 maxWidth = (std::max)( maxWidth, it->commands().size() );
4201 for( it = itBegin; it != itEnd; ++it ) {
4202 Catch::Text usage( it->commands(), Catch::TextAttributes()
4203 .setWidth( maxWidth+indent )
4204 .setIndent( indent ) );
4206 Catch::Text desc( it->description, Catch::TextAttributes()
4207 .setWidth( width - maxWidth -3 ) );
4209 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
4210 std::string usageCol = i < usage.size() ? usage[i] :
"";
4213 if( i < desc.size() && !desc[i].empty() )
4214 os << std::string( indent + 2 + maxWidth - usageCol.size(),
' ' )
4220 std::string optUsage()
const {
4221 std::ostringstream oss;
4226 void argSynopsis( std::ostream& os )
const {
4227 for(
int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4230 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4231 if( it != m_positionalArgs.end() )
4232 os <<
"<" << it->second.hint <<
">";
4233 else if( m_arg.get() )
4234 os <<
"<" << m_arg->hint <<
">";
4236 throw std::logic_error(
"non consecutive positional arguments with no floating args" );
4240 if( m_highestSpecifiedArgPosition > 1 )
4242 os <<
"[<" << m_arg->hint <<
"> ...]";
4245 std::string argSynopsis()
const {
4246 std::ostringstream oss;
4251 void usage( std::ostream& os, std::string
const& procName )
const {
4252 os <<
"usage:\n " << procName <<
" ";
4254 if( !m_options.empty() ) {
4255 os <<
" [options]\n\nwhere options are: \n";
4260 std::string usage( std::string
const& procName )
const {
4261 std::ostringstream oss;
4262 usage( oss, procName );
4266 std::vector<Parser::Token> parseInto(
int argc,
char const *
const * argv, ConfigT& config )
const {
4267 std::string processName = argv[0];
4268 std::size_t lastSlash = processName.find_last_of(
"/\\" );
4269 if( lastSlash != std::string::npos )
4270 processName = processName.substr( lastSlash+1 );
4271 m_boundProcessName.set( config, processName );
4272 std::vector<Parser::Token> tokens;
4274 parser.parseIntoTokens( argc, argv, tokens );
4275 return populate( tokens, config );
4278 std::vector<Parser::Token> populate( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
4279 if( m_options.empty() && m_positionalArgs.empty() )
4280 throw std::logic_error(
"No options or arguments specified" );
4282 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4283 unusedTokens = populateFixedArgs( unusedTokens, config );
4284 unusedTokens = populateFloatingArgs( unusedTokens, config );
4285 return unusedTokens;
4288 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
4289 std::vector<Parser::Token> unusedTokens;
4290 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4291 Parser::Token
const& token = tokens[i];
4292 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4293 for(; it != itEnd; ++it ) {
4294 Arg
const& arg = *it;
4297 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4298 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4299 if( arg.takesArg() ) {
4300 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
4301 throw std::domain_error(
"Expected argument to option " + token.data );
4302 arg.boundField.set( config, tokens[++i].data );
4305 arg.boundField.setFlag( config );
4310 catch( std::exception& ex ) {
4311 throw std::runtime_error( std::string( ex.what() ) +
"\n- while parsing: (" + arg.commands() +
")" );
4315 unusedTokens.push_back( token );
4317 return unusedTokens;
4319 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
4320 std::vector<Parser::Token> unusedTokens;
4322 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4323 Parser::Token
const& token = tokens[i];
4324 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4325 if( it != m_positionalArgs.end() )
4326 it->second.boundField.set( config, token.data );
4328 unusedTokens.push_back( token );
4329 if( token.type == Parser::Token::Positional )
4332 return unusedTokens;
4334 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token>
const& tokens, ConfigT& config )
const {
4337 std::vector<Parser::Token> unusedTokens;
4338 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4339 Parser::Token
const& token = tokens[i];
4340 if( token.type == Parser::Token::Positional )
4341 m_arg->boundField.set( config, token.data );
4343 unusedTokens.push_back( token );
4345 return unusedTokens;
4349 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4350 std::vector<Arg> m_options;
4351 std::map<int, Arg> m_positionalArgs;
4352 std::auto_ptr<Arg> m_arg;
4353 int m_highestSpecifiedArgPosition;
4361 inline void abortAfterX(
ConfigData& config,
int x ) {
4363 throw std::runtime_error(
"Value after -x or --abortAfter must be greater than zero" );
4366 inline void addTestOrTags(
ConfigData& config, std::string
const& _testSpec ) { config.
testsOrTags.push_back( _testSpec ); }
4368 inline void addWarning(
ConfigData& config, std::string
const& _warning ) {
4369 if( _warning ==
"NoAssertions" )
4372 throw std::runtime_error(
"Unrecognised warning: '" + _warning +
"'" );
4375 inline void setVerbosity(
ConfigData& config,
int level ) {
4379 inline void setShowDurations(
ConfigData& config,
bool _showDurations ) {
4385 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4387 Clara::CommandLine<ConfigData> cli;
4392 .describe(
"display usage information" )
4398 .describe(
"list all (or matching) test cases" )
4400 .longOpt(
"list-tests" );
4403 .describe(
"list all (or matching) tags" )
4405 .longOpt(
"list-tags" );
4408 .describe(
"list all reporters" )
4409 .longOpt(
"list-reporters" );
4412 .describe(
"include successful tests in output" )
4414 .longOpt(
"success" );
4417 .describe(
"break into debugger on failure" )
4419 .longOpt(
"break" );
4422 .describe(
"skip exception tests" )
4424 .longOpt(
"nothrow" );
4427 .describe(
"output filename" )
4430 .hint(
"filename" );
4433 .describe(
"reporter to use - defaults to console" )
4435 .longOpt(
"reporter" )
4440 .describe(
"suite name" )
4445 cli.bind( &abortAfterFirst )
4446 .describe(
"abort at first failure" )
4448 .longOpt(
"abort" );
4450 cli.bind( &abortAfterX )
4451 .describe(
"abort after x failures" )
4453 .longOpt(
"abortx" )
4454 .hint(
"number of failures" );
4456 cli.bind( &addWarning )
4457 .describe(
"enable warnings" )
4460 .hint(
"warning name" );
4468 cli.bind( &addTestOrTags )
4469 .describe(
"which test or tests to use" )
4470 .hint(
"test name, pattern or tags" );
4472 cli.bind( &setShowDurations )
4473 .describe(
"show test durations" )
4475 .longOpt(
"durations" )
4484 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED 4487 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED 4509 BrightRed = Bright | Red,
4510 BrightGreen = Bright | Green,
4511 LightGrey = Bright | Grey,
4512 BrightWhite = Bright | White,
4515 FileName = LightGrey,
4516 ResultError = BrightRed,
4517 ResultSuccess = BrightGreen,
4522 OriginalExpression = Cyan,
4523 ReconstructedExpression = Yellow,
4525 SecondaryText = LightGrey,
4530 Colour( Code _colourCode );
4534 static void use( Code _colourCode );
4537 static Detail::IColourImpl* impl;
4543 #include <algorithm> 4546 inline bool matchesFilters( std::vector<TestCaseFilters>
const& filters,
TestCase const& testCase ) {
4547 std::vector<TestCaseFilters>::const_iterator it = filters.begin();
4548 std::vector<TestCaseFilters>::const_iterator itEnd = filters.end();
4549 for(; it != itEnd; ++it )
4550 if( !it->shouldInclude( testCase ) )
4555 inline std::size_t listTests(
Config const& config ) {
4556 if( config.
filters().empty() )
4557 std::cout <<
"All available test cases:\n";
4559 std::cout <<
"Matching test cases:\n";
4561 std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
4564 std::size_t maxTagLen = 0;
4565 std::size_t maxNameLen = 0;
4566 for(; it != itEnd; ++it ) {
4567 if( matchesFilters( config.
filters(), *it ) ) {
4568 maxTagLen = (std::max)( it->getTestCaseInfo().tagsAsString.size(), maxTagLen );
4569 maxNameLen = (std::max)( it->getTestCaseInfo().name.size(), maxNameLen );
4576 if( maxTagLen > 30 )
4582 std::size_t matchedTests = 0;
4583 for( it = allTests.begin(); it != itEnd; ++it ) {
4584 if( matchesFilters( config.
filters(), *it ) ) {
4586 Text nameWrapper( it->getTestCaseInfo().name,
4588 .setWidth( maxNameLen )
4589 .setInitialIndent(2)
4592 Text tagsWrapper( it->getTestCaseInfo().tagsAsString,
4594 .setWidth( maxTagLen )
4595 .setInitialIndent(0)
4598 for( std::size_t i = 0; i < (std::max)( nameWrapper.size(), tagsWrapper.size() ); ++i ) {
4599 Colour::Code colour = Colour::None;
4600 if( it->getTestCaseInfo().isHidden )
4601 colour = Colour::SecondaryText;
4602 std::string nameCol;
4603 if( i < nameWrapper.size() ) {
4604 nameCol = nameWrapper[i];
4608 colour = Colour::SecondaryText;
4612 Colour colourGuard( colour );
4613 std::cout << nameCol;
4615 if( i < tagsWrapper.size() && !tagsWrapper[i].empty() ) {
4617 Colour colourGuard( Colour::SecondaryText );
4618 std::cout <<
" " << std::string( maxNameLen - nameCol.size(),
'.' ) <<
" ";
4621 std::cout << std::string( maxNameLen - nameCol.size(),
' ' ) <<
" ";
4623 std::cout << tagsWrapper[i];
4629 if( config.
filters().empty() )
4630 std::cout <<
pluralise( matchedTests,
"test case" ) <<
"\n" << std::endl;
4632 std::cout <<
pluralise( matchedTests,
"matching test case" ) <<
"\n" << std::endl;
4633 return matchedTests;
4636 inline std::size_t listTags(
Config const& config ) {
4637 if( config.
filters().empty() )
4638 std::cout <<
"All available tags:\n";
4640 std::cout <<
"Matching tags:\n";
4642 std::vector<TestCase>::const_iterator it = allTests.begin(), itEnd = allTests.end();
4644 std::map<std::string, int> tagCounts;
4646 std::size_t maxTagLen = 0;
4648 for(; it != itEnd; ++it ) {
4649 if( matchesFilters( config.
filters(), *it ) ) {
4650 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
4651 tagItEnd = it->getTestCaseInfo().tags.end();
4654 std::string tagName = *tagIt;
4655 maxTagLen = (std::max)( maxTagLen, tagName.size() );
4656 std::map<std::string, int>::iterator countIt = tagCounts.find( tagName );
4657 if( countIt == tagCounts.end() )
4658 tagCounts.insert( std::make_pair( tagName, 1 ) );
4668 for( std::map<std::string, int>::const_iterator countIt = tagCounts.begin(), countItEnd = tagCounts.end();
4669 countIt != countItEnd;
4671 Text wrapper(
"[" + countIt->first +
"]", TextAttributes()
4673 .setWidth( maxTagLen ) );
4674 std::cout << wrapper;
4675 std::size_t dots = 2;
4676 if( maxTagLen > wrapper.last().size() )
4677 dots += maxTagLen - wrapper.last().size();
4679 Colour colourGuard( Colour::SecondaryText );
4680 std::cout << std::string( dots,
'.' );
4682 std::cout << countIt->second
4685 std::cout <<
pluralise( tagCounts.size(),
"tag" ) <<
"\n" << std::endl;
4686 return tagCounts.size();
4689 inline std::size_t listReporters(
Config const& ) {
4690 std::cout <<
"Available reports:\n";
4692 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
4693 std::size_t maxNameLen = 0;
4694 for(it = itBegin; it != itEnd; ++it )
4695 maxNameLen = (std::max)( maxNameLen, it->first.size() );
4697 for(it = itBegin; it != itEnd; ++it ) {
4698 Text wrapper( it->second->getDescription(), TextAttributes()
4699 .setInitialIndent( 0 )
4700 .setIndent( 7+maxNameLen )
4705 << std::string( maxNameLen - it->first.size() + 2,
' ' )
4708 std::cout << std::endl;
4709 return factories.size();
4715 listedCount = listedCount.
valueOr(0) + listTests( config );
4717 listedCount = listedCount.
valueOr(0) + listTags( config );
4719 listedCount = listedCount.
valueOr(0) + listReporters( config );
4726 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED 4729 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED 4736 namespace SectionTracking {
4738 class TrackedSection {
4740 typedef std::map<std::string, TrackedSection> TrackedSections;
4750 TrackedSection( std::string
const& name, TrackedSection* parent )
4751 : m_name( name ), m_runState( NotStarted ), m_parent( parent )
4754 RunState runState()
const {
return m_runState; }
4756 void addChild( std::string
const& childName ) {
4757 m_children.insert( std::make_pair( childName, TrackedSection( childName,
this ) ) );
4759 TrackedSection* getChild( std::string
const& childName ) {
4760 return &m_children.find( childName )->second;
4764 if( m_runState == NotStarted )
4765 m_runState = Executing;
4768 for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
4771 if( it->second.runState() != Completed ) {
4772 m_runState = ExecutingChildren;
4775 m_runState = Completed;
4777 TrackedSection* getParent() {
4780 bool hasChildren()
const {
4781 return !m_children.empty();
4786 RunState m_runState;
4787 TrackedSections m_children;
4788 TrackedSection* m_parent;
4792 class TestCaseTracker {
4794 TestCaseTracker( std::string
const& testCaseName )
4795 : m_testCase( testCaseName, NULL ),
4796 m_currentSection( &m_testCase ),
4797 m_completedASectionThisRun(
false )
4800 bool enterSection( std::string
const& name ) {
4801 if( m_completedASectionThisRun )
4803 if( m_currentSection->runState() == TrackedSection::Executing ) {
4804 m_currentSection->addChild( name );
4808 TrackedSection* child = m_currentSection->getChild( name );
4809 if( child->runState() != TrackedSection::Completed ) {
4810 m_currentSection = child;
4811 m_currentSection->enter();
4817 void leaveSection() {
4818 m_currentSection->leave();
4819 m_currentSection = m_currentSection->getParent();
4820 assert( m_currentSection != NULL );
4821 m_completedASectionThisRun =
true;
4824 bool currentSectionHasChildren()
const {
4825 return m_currentSection->hasChildren();
4827 bool isCompleted()
const {
4828 return m_testCase.runState() == TrackedSection::Completed;
4833 Guard( TestCaseTracker& tracker )
4834 : m_tracker( tracker )
4836 m_tracker.enterTestCase();
4839 m_tracker.leaveTestCase();
4842 Guard( Guard
const& );
4843 void operator = ( Guard
const& );
4844 TestCaseTracker& m_tracker;
4848 void enterTestCase() {
4849 m_currentSection = &m_testCase;
4850 m_completedASectionThisRun =
false;
4853 void leaveTestCase() {
4857 TrackedSection m_testCase;
4858 TrackedSection* m_currentSection;
4859 bool m_completedASectionThisRun;
4864 using SectionTracking::TestCaseTracker;
4873 class StreamRedirect {
4876 StreamRedirect( std::ostream& stream, std::string& targetString )
4877 : m_stream( stream ),
4878 m_prevBuf( stream.rdbuf() ),
4879 m_targetString( targetString )
4881 stream.rdbuf( m_oss.rdbuf() );
4885 m_targetString += m_oss.str();
4886 m_stream.rdbuf( m_prevBuf );
4890 std::ostream& m_stream;
4891 std::streambuf* m_prevBuf;
4892 std::ostringstream m_oss;
4893 std::string& m_targetString;
4900 RunContext( RunContext
const& );
4901 void operator =( RunContext
const& );
4906 : m_runInfo( config->name() ),
4908 m_activeTestCase( NULL ),
4910 m_reporter( reporter ),
4911 m_prevRunner( &m_context.getRunner() ),
4912 m_prevResultCapture( &m_context.getResultCapture() ),
4913 m_prevConfig( m_context.getConfig() )
4915 m_context.setRunner(
this );
4916 m_context.setConfig( m_config );
4917 m_context.setResultCapture(
this );
4918 m_reporter->testRunStarting( m_runInfo );
4921 virtual ~RunContext() {
4922 m_reporter->testRunEnded(
TestRunStats( m_runInfo, m_totals, aborting() ) );
4923 m_context.setRunner( m_prevRunner );
4924 m_context.setConfig( NULL );
4925 m_context.setResultCapture( m_prevResultCapture );
4926 m_context.setConfig( m_prevConfig );
4929 void testGroupStarting( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
4930 m_reporter->testGroupStarting(
GroupInfo( testSpec, groupIndex, groupsCount ) );
4932 void testGroupEnded( std::string
const& testSpec,
Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
4933 m_reporter->testGroupEnded(
TestGroupStats(
GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
4936 Totals runMatching( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
4942 testGroupStarting( testSpec, groupIndex, groupsCount );
4944 std::vector<TestCase>::const_iterator it = matchingTests.begin();
4945 std::vector<TestCase>::const_iterator itEnd = matchingTests.end();
4946 for(; it != itEnd; ++it )
4947 totals += runTest( *it );
4949 testGroupEnded( testSpec, totals, groupIndex, groupsCount );
4954 Totals prevTotals = m_totals;
4956 std::string redirectedCout;
4957 std::string redirectedCerr;
4961 m_reporter->testCaseStarting( testInfo );
4963 m_activeTestCase = &testCase;
4964 m_testCaseTracker = TestCaseTracker( testInfo.
name );
4968 runCurrentTest( redirectedCout, redirectedCerr );
4970 while( !m_testCaseTracker->isCompleted() && !aborting() );
4974 Totals deltaTotals = m_totals.
delta( prevTotals );
4982 m_activeTestCase = NULL;
4983 m_testCaseTracker.reset();
4995 m_lastAssertionInfo = assertionInfo;
4996 return actOnCurrentResult( assertionResult.
buildResult( assertionInfo ) );
5001 m_totals.assertions.passed++;
5003 else if( !result.
isOk() ) {
5004 m_totals.assertions.failed++;
5007 if( m_reporter->assertionEnded(
AssertionStats( result, m_messages, m_totals ) ) )
5011 m_lastAssertionInfo =
AssertionInfo(
"", m_lastAssertionInfo.lineInfo,
"{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
5014 virtual bool sectionStarted (
5019 std::ostringstream oss;
5020 oss << sectionInfo.
name <<
"@" << sectionInfo.
lineInfo;
5022 if( !m_testCaseTracker->enterSection( oss.str() ) )
5025 m_lastAssertionInfo.lineInfo = sectionInfo.
lineInfo;
5027 m_reporter->sectionStarting( sectionInfo );
5029 assertions = m_totals.assertions;
5033 bool testForMissingAssertions(
Counts& assertions ) {
5034 if( assertions.
total() != 0 ||
5035 !m_config->warnAboutMissingAssertions() ||
5036 m_testCaseTracker->currentSectionHasChildren() )
5038 m_totals.assertions.
failed++;
5043 virtual void sectionEnded(
SectionInfo const& info,
Counts const& prevAssertions,
double _durationInSeconds ) {
5044 if( std::uncaught_exception() ) {
5045 m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
5049 Counts assertions = m_totals.assertions - prevAssertions;
5050 bool missingAssertions = testForMissingAssertions( assertions );
5052 m_testCaseTracker->leaveSection();
5054 m_reporter->sectionEnded(
SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
5058 virtual void pushScopedMessage(
MessageInfo const& message ) {
5059 m_messages.push_back( message );
5062 virtual void popScopedMessage(
MessageInfo const& message ) {
5063 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
5066 virtual bool shouldDebugBreak()
const {
5067 return m_config->shouldDebugBreak();
5070 virtual std::string getCurrentTestName()
const {
5071 return m_activeTestCase
5072 ? m_activeTestCase->getTestCaseInfo().name
5077 return &m_lastResult;
5082 bool aborting()
const {
5083 return m_totals.assertions.failed ==
static_cast<std::size_t
>( m_config->abortAfter() );
5089 m_lastResult = result;
5090 assertionEnded( m_lastResult );
5094 if( !m_lastResult.isOk() ) {
5096 if( shouldDebugBreak() )
5104 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
5105 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5107 m_reporter->sectionStarting( testCaseSection );
5108 Counts prevAssertions = m_totals.assertions;
5109 double duration = 0;
5112 TestCaseTracker::Guard guard( *m_testCaseTracker );
5116 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
5117 StreamRedirect coutRedir( std::cout, redirectedCout );
5118 StreamRedirect cerrRedir( std::cerr, redirectedCerr );
5119 m_activeTestCase->invoke();
5122 m_activeTestCase->invoke();
5132 actOnCurrentResult( exResult.
buildResult( m_lastAssertionInfo ) );
5136 for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
5137 itEnd = m_unfinishedSections.end();
5140 sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
5141 m_unfinishedSections.clear();
5144 Counts assertions = m_totals.assertions - prevAssertions;
5145 bool missingAssertions = testForMissingAssertions( assertions );
5147 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
5148 m_reporter->sectionEnded( testCaseSectionStats );
5152 struct UnfinishedSections {
5153 UnfinishedSections(
SectionInfo const& _info,
Counts const& _prevAssertions,
double _durationInSeconds )
5154 : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
5159 double durationInSeconds;
5171 std::vector<MessageInfo> m_messages;
5176 std::vector<UnfinishedSections> m_unfinishedSections;
5182 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED 5188 Version(
unsigned int _majorVersion,
5189 unsigned int _minorVersion,
5190 unsigned int _buildNumber,
5191 std::string
const& _branchName )
5192 : majorVersion( _majorVersion ),
5193 minorVersion( _minorVersion ),
5194 buildNumber( _buildNumber ),
5195 branchName( _branchName )
5198 const unsigned int majorVersion;
5199 const unsigned int minorVersion;
5200 const unsigned int buildNumber;
5201 const std::string branchName;
5204 void operator=( Version
const& );
5207 extern Version libraryVersion;
5220 : m_config( config )
5228 std::vector<TestCaseFilters> filterGroups = m_config->filters();
5229 if( filterGroups.empty() ) {
5231 filterGroups.push_back( filterGroup );
5234 RunContext context( m_config.get(), m_reporter );
5238 for( std::size_t i=0; i < filterGroups.size() && !context.aborting(); ++i ) {
5239 context.testGroupStarting( filterGroups[i].getName(), i, filterGroups.size() );
5240 totals += runTestsForGroup( context, filterGroups[i] );
5241 context.testGroupEnded( filterGroups[i].getName(), totals, i, filterGroups.size() );
5250 int testsRunForGroup = 0;
5251 for(; it != itEnd; ++it ) {
5254 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
5256 if( context.aborting() )
5259 totals += context.runTest( *it );
5260 m_testsAlreadyRun.insert( *it );
5264 if( testsRunForGroup == 0 && !filterGroup.
getName().empty() )
5265 m_reporter->noMatchingTestCases( filterGroup.
getName() );
5273 if( !m_config->getFilename().empty() ) {
5274 m_ofs.open( m_config->getFilename().c_str() );
5275 if( m_ofs.fail() ) {
5276 std::ostringstream oss;
5277 oss <<
"Unable to open file: '" << m_config->getFilename() <<
"'";
5278 throw std::domain_error( oss.str() );
5280 m_config->setStreamBuf( m_ofs.rdbuf() );
5283 void makeReporter() {
5284 std::string reporterName = m_config->getReporterName().empty()
5286 : m_config->getReporterName();
5290 std::ostringstream oss;
5291 oss <<
"No reporter registered with name: '" << reporterName <<
"'";
5292 throw std::domain_error( oss.str() );
5298 std::ofstream m_ofs;
5300 std::set<TestCase> m_testsAlreadyRun;
5304 static bool alreadyInstantiated;
5308 struct OnUnusedOptions {
enum DoWhat { Ignore, Fail }; };
5311 : m_cli( makeCommandLineParser() ) {
5312 if( alreadyInstantiated ) {
5313 std::string msg =
"Only one instance of Catch::Session can ever be used";
5314 std::cerr << msg << std::endl;
5315 throw std::logic_error( msg );
5317 alreadyInstantiated =
true;
5323 void showHelp( std::string
const& processName ) {
5324 std::cout <<
"\nCatch v" << libraryVersion.majorVersion <<
"." 5325 << libraryVersion.minorVersion <<
" build " 5326 << libraryVersion.buildNumber;
5327 if( libraryVersion.branchName !=
"master" )
5328 std::cout <<
" (" << libraryVersion.branchName <<
" branch)";
5331 m_cli.usage( std::cout, processName );
5332 std::cout <<
"For more detail usage please see the project docs\n" << std::endl;
5335 int applyCommandLine(
int argc,
char*
const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
5337 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
5338 if( unusedOptionBehaviour == OnUnusedOptions::Fail )
5339 enforceNoUsedTokens();
5340 if( m_configData.showHelp )
5341 showHelp( m_configData.processName );
5344 catch( std::exception& ex ) {
5346 Colour colourGuard( Colour::Red );
5347 std::cerr <<
"\nError in input:\n" 5348 << Text( ex.what(), TextAttributes().setIndent(2) )
5351 m_cli.usage( std::cout, m_configData.processName );
5352 return (std::numeric_limits<int>::max)();
5357 void useConfigData(
ConfigData const& _configData ) {
5358 m_configData = _configData;
5362 void enforceNoUsedTokens()
const {
5363 if( !m_unusedTokens.empty() ) {
5364 std::vector<Clara::Parser::Token>::const_iterator
5365 it = m_unusedTokens.begin(),
5366 itEnd = m_unusedTokens.end();
5368 for(; it != itEnd; ++it )
5369 msg +=
" unrecognised option: " + it->data +
"\n";
5370 throw std::runtime_error( msg.substr( 0, msg.size()-1 ) );
5374 int run(
int argc,
char*
const argv[] ) {
5376 int returnCode = applyCommandLine( argc, argv );
5377 if( returnCode == 0 )
5383 if( m_configData.showHelp )
5389 Runner runner( m_config );
5393 return static_cast<int>( *listed );
5395 return static_cast<int>( runner.runTests().assertions.failed );
5397 catch( std::exception& ex ) {
5398 std::cerr << ex.what() << std::endl;
5399 return (std::numeric_limits<int>::max)();
5403 Clara::CommandLine<ConfigData>
const& cli()
const {
5406 std::vector<Clara::Parser::Token>
const& unusedTokens()
const {
5407 return m_unusedTokens;
5410 return m_configData;
5414 m_config =
new Config( m_configData );
5419 Clara::CommandLine<ConfigData> m_cli;
5420 std::vector<Clara::Parser::Token> m_unusedTokens;
5425 bool Session::alreadyInstantiated =
false;
5430 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED 5433 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED 5444 TestRegistry() : m_unnamedCount( 0 ) {}
5445 virtual ~TestRegistry();
5447 virtual void registerTest(
TestCase const& testCase ) {
5450 std::ostringstream oss;
5451 oss <<
"Anonymous test case " << ++m_unnamedCount;
5452 return registerTest( testCase.
withName( oss.str() ) );
5455 if( m_functions.find( testCase ) == m_functions.end() ) {
5456 m_functions.insert( testCase );
5457 m_functionsInOrder.push_back( testCase );
5459 m_nonHiddenFunctions.push_back( testCase );
5462 TestCase const& prev = *m_functions.find( testCase );
5463 std::cerr <<
"error: TEST_CASE( \"" << name <<
"\" ) already defined.\n" 5470 virtual std::vector<TestCase>
const& getAllTests()
const {
5471 return m_functionsInOrder;
5474 virtual std::vector<TestCase>
const& getAllNonHiddenTests()
const {
5475 return m_nonHiddenFunctions;
5479 virtual std::vector<TestCase> getMatchingTestCases( std::string
const& rawTestSpec )
const {
5480 std::vector<TestCase> matchingTests;
5481 getMatchingTestCases( rawTestSpec, matchingTests );
5482 return matchingTests;
5486 virtual void getMatchingTestCases( std::string
const& rawTestSpec, std::vector<TestCase>& matchingTestsOut )
const {
5489 std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
5490 std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
5491 for(; it != itEnd; ++it ) {
5493 matchingTestsOut.push_back( *it );
5497 virtual void getMatchingTestCases(
TestCaseFilters const& filters, std::vector<TestCase>& matchingTestsOut )
const {
5498 std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin();
5499 std::vector<TestCase>::const_iterator itEnd = m_functionsInOrder.end();
5501 for(; it != itEnd; ++it )
5503 matchingTestsOut.push_back( *it );
5508 std::set<TestCase> m_functions;
5509 std::vector<TestCase> m_functionsInOrder;
5510 std::vector<TestCase> m_nonHiddenFunctions;
5511 size_t m_unnamedCount;
5516 class FreeFunctionTestCase :
public SharedImpl<ITestCase> {
5519 FreeFunctionTestCase(
TestFunction fun ) : m_fun( fun ) {}
5521 virtual void invoke()
const {
5526 virtual ~FreeFunctionTestCase();
5531 inline std::string extractClassName( std::string
const& classOrQualifiedMethodName ) {
5532 std::string className = classOrQualifiedMethodName;
5535 std::size_t lastColons = className.rfind(
"::" );
5536 std::size_t penultimateColons = className.rfind(
"::", lastColons-1 );
5537 if( penultimateColons == std::string::npos )
5538 penultimateColons = 1;
5539 className = className.substr( penultimateColons, lastColons-penultimateColons );
5549 registerTestCase(
new FreeFunctionTestCase(
function ),
"", nameAndDesc, lineInfo );
5555 char const* classOrQualifiedMethodName,
5561 extractClassName( classOrQualifiedMethodName ),
5570 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED 5580 virtual ~ReporterRegistry() {
5585 FactoryMap::const_iterator it = m_factories.find( name );
5586 if( it == m_factories.end() )
5591 void registerReporter( std::string
const& name,
IReporterFactory* factory ) {
5592 m_factories.insert( std::make_pair( name, factory ) );
5595 FactoryMap
const& getFactories()
const {
5600 FactoryMap m_factories;
5605 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED 5608 #import "Foundation/Foundation.h" 5615 ~ExceptionTranslatorRegistry() {
5620 m_translators.push_back( translator );
5630 @catch (NSException *exception) {
5631 return toString( [exception description] );
5637 catch( std::exception& ex ) {
5640 catch( std::string& msg ) {
5643 catch(
const char* msg ) {
5647 return tryTranslators( m_translators.begin() );
5651 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it )
const {
5652 if( it == m_translators.end() )
5653 return "Unknown exception";
5656 return (*it)->translate();
5659 return tryTranslators( it+1 );
5664 std::vector<const IExceptionTranslator*> m_translators;
5674 RegistryHub( RegistryHub
const& );
5675 void operator=( RegistryHub
const& );
5681 return m_reporterRegistry;
5684 return m_testCaseRegistry;
5687 return m_exceptionTranslatorRegistry;
5691 virtual void registerReporter( std::string
const& name,
IReporterFactory* factory ) {
5692 m_reporterRegistry.registerReporter( name, factory );
5694 virtual void registerTest(
TestCase const& testInfo ) {
5695 m_testCaseRegistry.registerTest( testInfo );
5698 m_exceptionTranslatorRegistry.registerTranslator( translator );
5702 TestRegistry m_testCaseRegistry;
5703 ReporterRegistry m_reporterRegistry;
5704 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
5708 inline RegistryHub*& getTheRegistryHub() {
5709 static RegistryHub* theRegistryHub = NULL;
5710 if( !theRegistryHub )
5711 theRegistryHub =
new RegistryHub();
5712 return theRegistryHub;
5717 return *getTheRegistryHub();
5720 return *getTheRegistryHub();
5723 delete getTheRegistryHub();
5724 getTheRegistryHub() = NULL;
5734 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED 5741 : m_lineInfo( lineInfo ) {
5742 std::ostringstream oss;
5743 oss << lineInfo <<
": function ";
5744 oss <<
"not implemented";
5749 return m_what.c_str();
5755 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED 5761 Context() : m_config( NULL ) {}
5762 Context( Context
const& );
5763 void operator=( Context
const& );
5767 return *m_resultCapture;
5769 virtual IRunner& getRunner() {
5772 virtual size_t getGeneratorIndex( std::string
const& fileInfo,
size_t totalSize ) {
5773 return getGeneratorsForCurrentTest()
5774 .getGeneratorInfo( fileInfo, totalSize )
5777 virtual bool advanceGeneratorsForCurrentTest() {
5779 return generators && generators->
moveNext();
5788 m_resultCapture = resultCapture;
5790 virtual void setRunner(
IRunner* runner ) {
5803 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
5804 m_generatorsByTestName.find( testName );
5805 return it != m_generatorsByTestName.end()
5815 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
5824 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
5828 Context* currentContext = NULL;
5831 if( !currentContext )
5832 currentContext =
new Context();
5833 return *currentContext;
5840 if( streamName ==
"stdout" )
return Stream( std::cout.rdbuf(),
false );
5841 if( streamName ==
"stderr" )
return Stream( std::cerr.rdbuf(),
false );
5844 throw std::domain_error(
"Unknown stream: " + streamName );
5848 delete currentContext;
5849 currentContext = NULL;
5854 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED 5856 namespace Catch {
namespace Detail {
5857 struct IColourImpl {
5858 virtual ~IColourImpl() {}
5859 virtual void use( Colour::Code _colourCode ) = 0;
5863 #if defined ( CATCH_PLATFORM_WINDOWS ) 5872 #include <windows.h> 5878 class Win32ColourImpl :
public Detail::IColourImpl {
5880 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
5882 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
5883 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
5884 originalAttributes = csbiInfo.wAttributes;
5887 virtual void use( Colour::Code _colourCode ) {
5888 switch( _colourCode ) {
5889 case Colour::None:
return setTextAttribute( originalAttributes );
5890 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
5891 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
5892 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
5893 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
5894 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
5895 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
5896 case Colour::Grey:
return setTextAttribute( 0 );
5898 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
5899 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
5900 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
5901 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
5903 case Colour::Bright:
throw std::logic_error(
"not a colour" );
5908 void setTextAttribute( WORD _textAttribute ) {
5909 SetConsoleTextAttribute( stdoutHandle, _textAttribute );
5911 HANDLE stdoutHandle;
5912 WORD originalAttributes;
5915 inline bool shouldUseColourForPlatform() {
5919 Win32ColourImpl platformColourImpl;
5924 #else // Not Windows - assumed to be POSIX compatible 5935 class PosixColourImpl :
public Detail::IColourImpl {
5937 virtual void use( Colour::Code _colourCode ) {
5938 switch( _colourCode ) {
5940 case Colour::White:
return setColour(
"[0m" );
5941 case Colour::Red:
return setColour(
"[0;31m" );
5942 case Colour::Green:
return setColour(
"[0;32m" );
5943 case Colour::Blue:
return setColour(
"[0:34m" );
5944 case Colour::Cyan:
return setColour(
"[0;36m" );
5945 case Colour::Yellow:
return setColour(
"[0;33m" );
5946 case Colour::Grey:
return setColour(
"[1;30m" );