11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
14 #define TWOBLUECUBES_CATCH_HPP_INCLUDED
17 # pragma clang system_header
18 #elif defined __GNUC__
19 # pragma GCC system_header
26 # pragma warning(push)
27 # pragma warning(disable: 161 1682)
29 # pragma clang diagnostic ignored "-Wglobal-constructors"
30 # pragma clang diagnostic ignored "-Wvariadic-macros"
31 # pragma clang diagnostic ignored "-Wc99-extensions"
32 # pragma clang diagnostic ignored "-Wunused-variable"
33 # pragma clang diagnostic push
34 # pragma clang diagnostic ignored "-Wpadded"
35 # pragma clang diagnostic ignored "-Wc++98-compat"
36 # pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
37 # pragma clang diagnostic ignored "-Wswitch-enum"
38 # pragma clang diagnostic ignored "-Wcovered-switch-default"
40 #elif defined __GNUC__
41 # pragma GCC diagnostic ignored "-Wvariadic-macros"
42 # pragma GCC diagnostic ignored "-Wunused-variable"
43 # pragma GCC diagnostic push
44 # pragma GCC diagnostic ignored "-Wpadded"
46 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
51 # ifndef CLARA_CONFIG_MAIN
52 # define CLARA_CONFIG_MAIN_NOT_DEFINED
53 # define CLARA_CONFIG_MAIN
58 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
61 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
63 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
64 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
65 #ifdef CATCH_CONFIG_COUNTER
66 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
68 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
71 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
72 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
85 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
115 #if defined(__cplusplus) && __cplusplus >= 201103L
116 # define CATCH_CPP11_OR_GREATER
121 # if __has_feature(cxx_nullptr)
122 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
125 # if __has_feature(cxx_noexcept)
126 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
129 # if defined(CATCH_CPP11_OR_GREATER)
130 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
143 #ifdef __EDG_VERSION__
157 # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
158 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
161 # if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
162 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
174 #if (_MSC_VER >= 1600)
175 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
176 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
179 #if (_MSC_VER >= 1900 )
180 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
181 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
189 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
190 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
191 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
192 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
194 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
199 #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
200 ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
201 ( defined __clang__ && __clang_major__ >= 3 )
203 #define CATCH_INTERNAL_CONFIG_COUNTER
211 #if defined(CATCH_CPP11_OR_GREATER)
213 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
214 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
217 # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
218 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
221 # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
222 # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
225 # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
226 # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
229 # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
230 # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
233 # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
234 # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
237 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
238 # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
241 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
242 # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
244 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
245 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
251 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
252 # define CATCH_CONFIG_CPP11_NULLPTR
254 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
255 # define CATCH_CONFIG_CPP11_NOEXCEPT
257 #if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
258 # define CATCH_CONFIG_CPP11_GENERATED_METHODS
260 #if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
261 # define CATCH_CONFIG_CPP11_IS_ENUM
263 #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
264 # define CATCH_CONFIG_CPP11_TUPLE
266 #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
267 # define CATCH_CONFIG_VARIADIC_MACROS
269 #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
270 # define CATCH_CONFIG_CPP11_LONG_LONG
272 #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
273 # define CATCH_CONFIG_CPP11_OVERRIDE
275 #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
276 # define CATCH_CONFIG_CPP11_UNIQUE_PTR
278 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
279 # define CATCH_CONFIG_COUNTER
282 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
283 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
287 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
288 # define CATCH_NOEXCEPT noexcept
289 # define CATCH_NOEXCEPT_IS(x) noexcept(x)
291 # define CATCH_NOEXCEPT throw()
292 # define CATCH_NOEXCEPT_IS(x)
296 #ifdef CATCH_CONFIG_CPP11_NULLPTR
297 # define CATCH_NULL nullptr
299 # define CATCH_NULL NULL
303 #ifdef CATCH_CONFIG_CPP11_OVERRIDE
304 # define CATCH_OVERRIDE override
306 # define CATCH_OVERRIDE
310 #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
311 # define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
313 # define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
326 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
352 template<
typename ContainerT>
354 typename ContainerT::const_iterator it = container.begin();
355 typename ContainerT::const_iterator itEnd = container.end();
356 for(; it != itEnd; ++it )
359 template<
typename AssociativeContainerT>
361 typename AssociativeContainerT::const_iterator it = container.begin();
362 typename AssociativeContainerT::const_iterator itEnd = container.end();
363 for(; it != itEnd; ++it )
367 bool startsWith( std::string
const& s, std::string
const& prefix );
368 bool endsWith( std::string
const& s, std::string
const& suffix );
369 bool contains( std::string
const& s, std::string
const& infix );
372 std::string
trim( std::string
const& str );
373 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis );
376 pluralise( std::size_t count, std::string
const& label );
389 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
405 inline bool isTrue(
bool value ){
return value; }
420 return std::string();
429 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
430 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
454 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
457 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
460 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
484 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
487 #pragma clang diagnostic push
488 #pragma clang diagnostic ignored "-Wpadded"
504 Ptr(
Ptr const& other ) : m_p( other.m_p ){
544 template<
typename T = IShared>
563 #pragma clang diagnostic pop
574 struct IResultCapture;
576 struct IGeneratorsForTest;
606 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
609 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
633 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const&
config );
654 void (C::*m_method)();
660 NameAndDesc(
const char* _name =
"",
const char* _description=
"" )
661 : name( _name ), description( _description )
670 char const* className,
683 (
void (C::*method)(),
684 char const* className,
709 #ifdef CATCH_CONFIG_VARIADIC_MACROS
711 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
712 static void TestName(); \
713 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
714 static void TestName()
715 #define INTERNAL_CATCH_TESTCASE( ... ) \
716 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
719 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
720 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
723 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
725 struct TestName : ClassName{ \
728 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
730 void TestName::test()
731 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
732 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
735 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
736 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
740 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
741 static void TestName(); \
742 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
743 static void TestName()
744 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
745 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
748 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
749 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
752 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
754 struct TestCaseName : ClassName{ \
757 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
759 void TestCaseName::test()
760 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
761 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
764 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
765 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
769 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
772 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
775 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
788 ExpressionFailed = FailureBit | 1,
789 ExplicitFailure = FailureBit | 2,
796 FatalErrorCondition = 0x200 | FailureBit
811 ContinueOnFailure = 0x02,
827 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
838 std::string
const& _capturedExpression,
861 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
889 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
896 template<
typename ExpressionT>
class AllOf;
897 template<
typename ExpressionT>
class AnyOf;
898 template<
typename ExpressionT>
class Not;
901 template<
typename ExpressionT>
908 virtual bool match( ExpressionT
const& expr )
const = 0;
916 template<
typename DerivedT,
typename ExpressionT>
925 template<
typename ExpressionT>
929 Not(
Not const& other ) : m_matcher( other.m_matcher ) {}
932 return !m_matcher->match( expr );
936 return "not " + m_matcher->toString();
942 template<
typename ExpressionT>
947 AllOf(
AllOf const& other ) : m_matchers( other.m_matchers ) {}
950 m_matchers.push_back( matcher.
clone() );
953 virtual bool match( ExpressionT
const& expr )
const
955 for( std::size_t i = 0; i < m_matchers.size(); ++i )
956 if( !m_matchers[i]->match( expr ) )
961 std::ostringstream oss;
963 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
966 oss << m_matchers[i]->toString();
973 AllOf allOfExpr( *
this );
974 allOfExpr.
add( other );
982 template<
typename ExpressionT>
987 AnyOf(
AnyOf const& other ) : m_matchers( other.m_matchers ) {}
990 m_matchers.push_back( matcher.
clone() );
993 virtual bool match( ExpressionT
const& expr )
const
995 for( std::size_t i = 0; i < m_matchers.size(); ++i )
996 if( m_matchers[i]->match( expr ) )
1001 std::ostringstream oss;
1003 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1006 oss << m_matchers[i]->toString();
1013 AnyOf anyOfExpr( *
this );
1014 anyOfExpr.
add( other );
1024 template<
typename ExpressionT>
1027 allOfExpr.
add( *
this );
1028 allOfExpr.
add( other );
1032 template<
typename ExpressionT>
1035 anyOfExpr.
add( *
this );
1036 anyOfExpr.
add( other );
1040 template<
typename ExpressionT>
1045 namespace StdString {
1047 inline std::string
makeString( std::string
const& str ) {
return str; }
1048 inline std::string
makeString(
const char* str ) {
return str ? std::string( str ) : std::string(); }
1053 : m_caseSensitivity( caseSensitivity ),
1054 m_str( adjustString( str ) )
1065 ?
" (case insensitive)"
1074 : m_data( str, caseSensitivity )
1080 virtual bool match( std::string
const& expr )
const {
1081 return m_data.m_str == m_data.adjustString( expr );;
1084 return "equals: \"" + m_data.m_str +
"\"" + m_data.toStringSuffix();
1092 : m_data( substr, caseSensitivity ){}
1097 virtual bool match( std::string
const& expr )
const {
1098 return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
1101 return "contains: \"" + m_data.m_str +
"\"" + m_data.toStringSuffix();
1109 : m_data( substr, caseSensitivity ){}
1115 virtual bool match( std::string
const& expr )
const {
1116 return startsWith( m_data.adjustString( expr ), m_data.m_str );
1119 return "starts with: \"" + m_data.m_str +
"\"" + m_data.toStringSuffix();
1127 : m_data( substr, caseSensitivity ){}
1132 virtual bool match( std::string
const& expr )
const {
1133 return endsWith( m_data.adjustString( expr ), m_data.m_str );
1136 return "ends with: \"" + m_data.m_str +
"\"" + m_data.toStringSuffix();
1146 template<
typename ExpressionT>
1151 template<
typename ExpressionT>
1156 template<
typename ExpressionT>
1162 template<
typename ExpressionT>
1167 template<
typename ExpressionT>
1201 using namespace Matchers;
1211 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1216 oss << other.
oss.str();
1220 oss << other.
oss.str();
1230 char const* capturedExpression,
1232 char const* secondArg =
"" );
1234 template<
typename T>
1238 template<
typename T>
1240 m_stream.oss << value;
1244 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT
const& );
1245 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT
const& );
1286 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1289 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
1292 #pragma warning(push)
1293 #pragma warning(disable:4389)
1299 namespace Internal {
1318 template<
typename T>
1322 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1328 template<
typename T1,
typename T2, Operator Op>
1331 template<
typename T1,
typename T2>
1337 template<
typename T1,
typename T2>
1343 template<
typename T1,
typename T2>
1349 template<
typename T1,
typename T2>
1355 template<
typename T1,
typename T2>
1361 template<
typename T1,
typename T2>
1368 template<Operator Op,
typename T1,
typename T2>
1377 template<Operator Op,
typename T1,
typename T2>
1383 template<Operator Op>
bool compare(
unsigned int lhs,
int rhs ) {
1384 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1386 template<Operator Op>
bool compare(
unsigned long lhs,
int rhs ) {
1387 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1389 template<Operator Op>
bool compare(
unsigned char lhs,
int rhs ) {
1390 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
1394 template<Operator Op>
bool compare(
unsigned int lhs,
long rhs ) {
1395 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1397 template<Operator Op>
bool compare(
unsigned long lhs,
long rhs ) {
1398 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1400 template<Operator Op>
bool compare(
unsigned char lhs,
long rhs ) {
1401 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
1405 template<Operator Op>
bool compare(
int lhs,
unsigned int rhs ) {
1406 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1408 template<Operator Op>
bool compare(
int lhs,
unsigned long rhs ) {
1409 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1411 template<Operator Op>
bool compare(
int lhs,
unsigned char rhs ) {
1412 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
1416 template<Operator Op>
bool compare(
long lhs,
unsigned int rhs ) {
1417 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1419 template<Operator Op>
bool compare(
long lhs,
unsigned long rhs ) {
1420 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1422 template<Operator Op>
bool compare(
long lhs,
unsigned char rhs ) {
1423 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1427 template<Operator Op,
typename T>
bool compare(
long lhs,
T* rhs ) {
1430 template<Operator Op,
typename T>
bool compare(
T* lhs,
long rhs ) {
1435 template<Operator Op,
typename T>
bool compare(
int lhs,
T* rhs ) {
1438 template<Operator Op,
typename T>
bool compare(
T* lhs,
int rhs ) {
1442 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1444 template<Operator Op>
bool compare(
long long lhs,
unsigned int rhs ) {
1445 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1447 template<Operator Op>
bool compare(
long long lhs,
unsigned long rhs ) {
1448 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1450 template<Operator Op>
bool compare(
long long lhs,
unsigned long long rhs ) {
1451 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1453 template<Operator Op>
bool compare(
long long lhs,
unsigned char rhs ) {
1454 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
1458 template<Operator Op>
bool compare(
unsigned long long lhs,
int rhs ) {
1459 return applyEvaluator<Op>(
static_cast<long>( lhs ), rhs );
1461 template<Operator Op>
bool compare(
unsigned long long lhs,
long rhs ) {
1462 return applyEvaluator<Op>(
static_cast<long>( lhs ), rhs );
1464 template<Operator Op>
bool compare(
unsigned long long lhs,
long long rhs ) {
1465 return applyEvaluator<Op>(
static_cast<long>( lhs ), rhs );
1467 template<Operator Op>
bool compare(
unsigned long long lhs,
char rhs ) {
1468 return applyEvaluator<Op>(
static_cast<long>( lhs ), rhs );
1472 template<Operator Op,
typename T>
bool compare(
long long lhs,
T* rhs ) {
1473 return Evaluator<T*, T*, Op>::evaluate(
reinterpret_cast<T*
>( lhs ), rhs );
1475 template<Operator Op,
typename T>
bool compare(
T* lhs,
long long rhs ) {
1476 return Evaluator<T*, T*, Op>::evaluate( lhs,
reinterpret_cast<T*
>( rhs ) );
1480 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1483 return Evaluator<T*, T*, Op>::evaluate(
nullptr, rhs );
1486 return Evaluator<T*, T*, Op>::evaluate( lhs,
nullptr );
1494 #pragma warning(pop)
1498 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1508 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1510 #import <Foundation/Foundation.h>
1512 #ifdef __has_feature
1513 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1515 #define CATCH_ARC_ENABLED 0
1518 void arcSafeRelease( NSObject* obj );
1519 id performOptionalSelector(
id obj,
SEL sel );
1521 #if !CATCH_ARC_ENABLED
1522 inline void arcSafeRelease( NSObject* obj ) {
1525 inline id performOptionalSelector(
id obj,
SEL sel ) {
1526 if( [obj respondsToSelector: sel] )
1527 return [obj performSelector: sel];
1530 #define CATCH_UNSAFE_UNRETAINED
1531 #define CATCH_ARC_STRONG
1533 inline void arcSafeRelease( NSObject* ){}
1534 inline id performOptionalSelector(
id obj,
SEL sel ) {
1536 #pragma clang diagnostic push
1537 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1539 if( [obj respondsToSelector: sel] )
1540 return [obj performSelector: sel];
1542 #pragma clang diagnostic pop
1546 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1547 #define CATCH_ARC_STRONG __strong
1552 #ifdef CATCH_CONFIG_CPP11_TUPLE
1556 #ifdef CATCH_CONFIG_CPP11_IS_ENUM
1557 #include <type_traits>
1563 template<
typename T>
1584 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1585 std::string
toString(
long long value );
1586 std::string
toString(
unsigned long long value );
1589 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1594 std::string
toString( NSString
const *
const& nsstring );
1595 std::string
toString( NSString * CATCH_ARC_STRONG
const& nsstring );
1596 std::string
toString( NSObject*
const& nsObject );
1615 template<
typename T>
1617 static std::ostream &
s;
1622 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1623 template<
typename T,
1624 bool IsEnum = std::is_enum<T>::value
1626 struct EnumStringMaker
1631 template<
typename T>
1632 struct EnumStringMaker<
T,true>
1634 static std::string convert(
T const& v )
1637 static_cast<typename std::underlying_type<T>::type
>(v)
1644 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1645 template<
typename T>
1646 static std::string convert(
T const& v )
1648 return EnumStringMaker<T>::convert( v );
1651 template<
typename T>
1658 template<
typename T>
1660 std::ostringstream oss;
1668 template<
typename T>
1675 template<
typename T>
1679 template<
typename T>
1681 template<
typename U>
1690 template<
typename R,
typename C>
1701 template<
typename InputIterator>
1702 std::string
rangeToString( InputIterator first, InputIterator last );
1712 template<
typename T,
typename Allocator>
1713 std::string
toString( std::vector<T,Allocator>
const& v ) {
1717 #ifdef CATCH_CONFIG_CPP11_TUPLE
1720 namespace TupleDetail {
1724 bool = (N < std::tuple_size<Tuple>::value)
1726 struct ElementPrinter {
1727 static void print(
const Tuple& tuple, std::ostream& os )
1729 os << ( N ?
", " :
" " )
1731 ElementPrinter<Tuple,N+1>::print(tuple,os);
1739 struct ElementPrinter<Tuple,N,false> {
1740 static void print(
const Tuple&, std::ostream& ) {}
1745 template<
typename ...Types>
1746 struct StringMaker<
std::tuple<Types...>> {
1748 static std::string convert(
const std::tuple<Types...>& tuple )
1750 std::ostringstream os;
1752 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1760 template<
typename T>
1773 template<
typename T>
1779 template<
typename InputIterator>
1781 std::ostringstream oss;
1783 if( first != last ) {
1785 for( ++first ; first != last ; ++first )
1799 template<
typename T>
1802 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1808 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1813 template<
typename RhsT>
1815 return captureExpression<Internal::IsEqualTo>( rhs );
1818 template<
typename RhsT>
1820 return captureExpression<Internal::IsNotEqualTo>( rhs );
1823 template<
typename RhsT>
1825 return captureExpression<Internal::IsLessThan>( rhs );
1828 template<
typename RhsT>
1830 return captureExpression<Internal::IsGreaterThan>( rhs );
1833 template<
typename RhsT>
1835 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1838 template<
typename RhsT>
1840 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1844 return captureExpression<Internal::IsEqualTo>( rhs );
1848 return captureExpression<Internal::IsNotEqualTo>( rhs );
1852 bool value = m_lhs ? true :
false;
1855 .setResultType( value )
1861 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator + ( RhsT
const& );
1862 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator - ( RhsT
const& );
1863 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator / ( RhsT
const& );
1864 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator * ( RhsT
const& );
1865 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT
const& );
1866 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT
const& );
1869 template<Internal::Operator Op,
typename RhsT>
1888 template<
typename T>
1890 return ExpressionLhs<T const&>( *
this, operand );
1894 return ExpressionLhs<bool>( *
this, value );
1900 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1931 : m_info( macroName, lineInfo, type )
1934 template<
typename T>
1956 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1963 class AssertionResult;
1964 struct AssertionInfo;
1966 struct SectionEndInfo;
1968 class ScopedMessageBuilder;
1977 Counts& assertions ) = 0;
1993 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
1996 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1998 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1999 #define CATCH_PLATFORM_MAC
2000 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
2001 #define CATCH_PLATFORM_IPHONE
2002 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
2003 #define CATCH_PLATFORM_WINDOWS
2014 #ifdef CATCH_PLATFORM_MAC
2019 #if defined(__ppc64__) || defined(__ppc__)
2020 #define CATCH_BREAK_INTO_DEBUGGER() \
2021 if( Catch::isDebuggerActive() ) { \
2022 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
2023 : : : "memory","r0","r3","r4" ); \
2026 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
2030 #elif defined(_MSC_VER)
2031 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
2032 #elif defined(__MINGW32__)
2033 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
2034 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
2037 #ifndef CATCH_BREAK_INTO_DEBUGGER
2038 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
2042 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2058 #define INTERNAL_CATCH_REACT( resultBuilder ) \
2059 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2060 resultBuilder.react();
2063 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
2065 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2067 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2068 ( __catchResult <= expr ).endExpression(); \
2071 __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
2073 INTERNAL_CATCH_REACT( __catchResult ) \
2074 } while( Catch::isTrue( false && static_cast<bool>(expr) ) )
2077 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2078 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2079 if( Catch::getResultCapture().getLastResult()->succeeded() )
2082 #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2083 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2084 if( !Catch::getResultCapture().getLastResult()->succeeded() )
2087 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
2089 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2092 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2095 __catchResult.useActiveException( resultDisposition ); \
2097 INTERNAL_CATCH_REACT( __catchResult ) \
2098 } while( Catch::alwaysFalse() )
2101 #define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
2103 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
2104 if( __catchResult.allowThrows() ) \
2107 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2110 __catchResult.captureExpectedException( matcher ); \
2113 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2114 INTERNAL_CATCH_REACT( __catchResult ) \
2115 } while( Catch::alwaysFalse() )
2118 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
2120 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2121 if( __catchResult.allowThrows() ) \
2124 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2126 catch( exceptionType ) { \
2127 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2130 __catchResult.useActiveException( resultDisposition ); \
2133 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2134 INTERNAL_CATCH_REACT( __catchResult ) \
2135 } while( Catch::alwaysFalse() )
2138 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2139 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
2141 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2142 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2143 __catchResult.captureResult( messageType ); \
2144 INTERNAL_CATCH_REACT( __catchResult ) \
2145 } while( Catch::alwaysFalse() )
2147 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
2149 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2150 __catchResult << log + ::Catch::StreamEndStop(); \
2151 __catchResult.captureResult( messageType ); \
2152 INTERNAL_CATCH_REACT( __catchResult ) \
2153 } while( Catch::alwaysFalse() )
2157 #define INTERNAL_CATCH_INFO( log, macroName ) \
2158 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
2161 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
2163 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
2165 std::string matcherAsString = (matcher).toString(); \
2167 .setLhs( Catch::toString( arg ) ) \
2168 .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
2169 .setOp( "matches" ) \
2170 .setResultType( (matcher).match( arg ) ); \
2171 __catchResult.captureExpression(); \
2173 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
2175 INTERNAL_CATCH_REACT( __catchResult ) \
2176 } while( Catch::alwaysFalse() )
2179 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2182 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2185 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2192 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
2209 return passed + failed + failedButOk;
2212 return failed == 0 && failedButOk == 0;
2233 Totals diff = *
this - prevTotals;
2259 std::string
const& _name,
2260 std::string
const& _description = std::string() );
2269 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2280 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2282 #ifdef CATCH_PLATFORM_WINDOWS
2283 typedef unsigned long long uint64_t;
2314 operator bool()
const;
2327 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2328 #define INTERNAL_CATCH_SECTION( ... ) \
2329 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2331 #define INTERNAL_CATCH_SECTION( name, desc ) \
2332 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
2336 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2345 template<
typename T>
2349 virtual std::size_t
size ()
const = 0;
2352 template<
typename T>
2358 return m_from+
static_cast<int>( index );
2362 return static_cast<std::size_t
>( 1+m_to-m_from );
2371 template<
typename T>
2377 m_values.push_back( value );
2381 return m_values[index];
2385 return m_values.size();
2392 template<
typename T>
2399 : m_fileInfo( other.m_fileInfo ),
2406 m_fileInfo = fileInfo;
2414 operator T ()
const {
2417 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2418 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2419 for(
size_t index = 0; it != itEnd; ++it )
2422 if( overallIndex >= index && overallIndex < index + generator->
size() )
2424 return generator->getValue( overallIndex-index );
2444 valuesGen->
add( value );
2452 std::copy( other.
m_composed.begin(), other.
m_composed.end(), std::back_inserter( m_composed ) );
2462 namespace Generators
2464 template<
typename T>
2471 template<
typename T>
2475 valuesGen->
add( val1 );
2476 valuesGen->
add( val2 );
2477 generators.
add( valuesGen );
2481 template<
typename T>
2485 valuesGen->
add( val1 );
2486 valuesGen->
add( val2 );
2487 valuesGen->
add( val3 );
2488 generators.
add( valuesGen );
2492 template<
typename T>
2496 valuesGen->
add( val1 );
2497 valuesGen->
add( val2 );
2498 valuesGen->
add( val3 );
2499 valuesGen->
add( val4 );
2500 generators.
add( valuesGen );
2506 using namespace Generators;
2510 #define INTERNAL_CATCH_LINESTR2( line ) #line
2511 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2513 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2516 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2522 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2529 struct ITestCaseRegistry;
2530 struct IExceptionTranslatorRegistry;
2531 struct IExceptionTranslator;
2532 struct IReporterRegistry;
2533 struct IReporterFactory;
2567 virtual std::string
translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const = 0;
2577 template<
typename T>
2582 : m_translateFunction( translateFunction )
2585 virtual std::string
translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const CATCH_OVERRIDE {
2590 return (*it)->translate( it+1, itEnd );
2593 return m_translateFunction( ex );
2598 std::string(*m_translateFunction)(
T& );
2602 template<
typename T>
2611 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2612 static std::string translatorName( signature ); \
2613 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
2614 static std::string translatorName( signature )
2616 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
2619 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2630 : m_epsilon(
std::numeric_limits<float>::epsilon()*100 ),
2636 : m_epsilon( other.m_epsilon ),
2637 m_scale( other.m_scale ),
2638 m_value( other.m_value )
2648 approx.
scale( m_scale );
2670 m_epsilon = newEpsilon;
2680 std::ostringstream oss;
2700 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
2703 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
2722 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
2724 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2729 template<
typename T>
2734 : nullableValue(
new( storage )
T( _value ) )
2737 : nullableValue( _other ?
new( storage )
T( *_other ) :
CATCH_NULL )
2745 if( &_other !=
this ) {
2748 nullableValue =
new( storage )
T( *_other );
2754 nullableValue =
new( storage )
T( _value );
2760 nullableValue->~T();
2770 return nullableValue ? *nullableValue : defaultValue;
2783 char storage[
sizeof(
T)];
2793 virtual std::string
expandAliases( std::string
const& unexpandedTestSpec )
const = 0;
2803 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2809 #pragma clang diagnostic push
2810 #pragma clang diagnostic ignored "-Wpadded"
2821 ShouldFail = 1 << 2,
2827 std::string
const& _className,
2828 std::string
const& _description,
2829 std::set<std::string>
const& _tags,
2837 bool throws()
const;
2873 std::string
const& className,
2874 std::string
const& name,
2875 std::string
const& description,
2880 #pragma clang diagnostic pop
2886 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2888 #import <objc/runtime.h>
2910 class OcMethod :
public SharedImpl<ITestCase> {
2913 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2915 virtual void invoke()
const {
2916 id obj = [[m_cls alloc] init];
2918 performOptionalSelector( obj,
@selector(setUp) );
2919 performOptionalSelector( obj, m_sel );
2920 performOptionalSelector( obj,
@selector(tearDown) );
2922 arcSafeRelease( obj );
2925 virtual ~OcMethod() {}
2933 inline std::string getAnnotation( Class cls,
2934 std::string
const& annotationName,
2935 std::string
const& testCaseName ) {
2936 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2937 SEL sel = NSSelectorFromString( selStr );
2938 arcSafeRelease( selStr );
2939 id value = performOptionalSelector( cls, sel );
2941 return [(NSString*)value UTF8String];
2946 inline size_t registerTestMethods() {
2947 size_t noTestMethods = 0;
2948 int noClasses = objc_getClassList(
CATCH_NULL, 0 );
2950 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc(
sizeof(Class) * noClasses);
2951 objc_getClassList( classes, noClasses );
2953 for(
int c = 0; c < noClasses; c++ ) {
2954 Class cls = classes[c];
2957 Method* methods = class_copyMethodList( cls, &count );
2958 for( u_int m = 0; m < count ; m++ ) {
2959 SEL selector = method_getName(methods[m]);
2960 std::string methodName = sel_getName(selector);
2961 if(
startsWith( methodName,
"Catch_TestCase_" ) ) {
2962 std::string testCaseName = methodName.substr( 15 );
2963 std::string name = Detail::getAnnotation( cls,
"Name", testCaseName );
2964 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
2965 const char* className = class_getName( cls );
2974 return noTestMethods;
2977 namespace Matchers {
2979 namespace NSStringMatchers {
2981 template<
typename MatcherT>
2982 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
2983 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2984 StringHolder( StringHolder
const& other ) : m_substr( [other.m_substr copy] ){}
2986 arcSafeRelease( m_substr );
2993 Equals( NSString* substr ) : StringHolder( substr ){}
2995 virtual bool match( ExpressionType
const& str )
const {
2996 return (str != nil || m_substr == nil ) &&
2997 [str isEqualToString:m_substr];
3000 virtual std::string
toString()
const {
3001 return "equals string: " +
Catch::toString( m_substr );
3006 Contains( NSString* substr ) : StringHolder( substr ){}
3008 virtual bool match( ExpressionType
const& str )
const {
3009 return (str != nil || m_substr == nil ) &&
3010 [str rangeOfString:m_substr].location != NSNotFound;
3013 virtual std::string
toString()
const {
3014 return "contains string: " +
Catch::toString( m_substr );
3019 StartsWith( NSString* substr ) : StringHolder( substr ){}
3021 virtual bool match( ExpressionType
const& str )
const {
3022 return (str != nil || m_substr == nil ) &&
3023 [str rangeOfString:m_substr].location == 0;
3026 virtual std::string
toString()
const {
3027 return "starts with: " +
Catch::toString( m_substr );
3031 EndsWith( NSString* substr ) : StringHolder( substr ){}
3033 virtual bool match( ExpressionType
const& str )
const {
3034 return (str != nil || m_substr == nil ) &&
3035 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
3038 virtual std::string
toString()
const {
3039 return "ends with: " +
Catch::toString( m_substr );
3060 using namespace Matchers;
3065 #define OC_TEST_CASE( name, desc )\
3066 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
3070 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
3074 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3080 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
3086 #pragma clang diagnostic push
3087 #pragma clang diagnostic ignored "-Wweak-vtables"
3091 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
3094 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3097 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3100 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
3103 #pragma clang diagnostic push
3104 #pragma clang diagnostic ignored "-Wpadded"
3108 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
3111 #pragma clang diagnostic push
3112 #pragma clang diagnostic ignored "-Wpadded"
3116 #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3120 class WildcardPattern {
3121 enum WildcardPosition {
3123 WildcardAtStart = 1,
3125 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3131 : m_caseSensitivity( caseSensitivity ),
3132 m_wildcard( NoWildcard ),
3133 m_pattern( adjustCase( pattern ) )
3136 m_pattern = m_pattern.substr( 1 );
3137 m_wildcard = WildcardAtStart;
3140 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3141 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
3144 virtual ~WildcardPattern();
3145 virtual bool matches( std::string
const& str )
const {
3146 switch( m_wildcard ) {
3148 return m_pattern == adjustCase( str );
3149 case WildcardAtStart:
3150 return endsWith( adjustCase( str ), m_pattern );
3152 return startsWith( adjustCase( str ), m_pattern );
3153 case WildcardAtBothEnds:
3154 return contains( adjustCase( str ), m_pattern );
3158 #pragma clang diagnostic push
3159 #pragma clang diagnostic ignored "-Wunreachable-code"
3161 throw std::logic_error(
"Unknown enum" );
3163 #pragma clang diagnostic pop
3167 std::string adjustCase( std::string
const& str )
const {
3171 WildcardPosition m_wildcard;
3172 std::string m_pattern;
3182 struct Pattern : SharedImpl<> {
3184 virtual bool matches( TestCaseInfo
const& testCase )
const = 0;
3186 class NamePattern :
public Pattern {
3188 NamePattern( std::string
const& name )
3189 : m_wildcardPattern(
toLower( name ), CaseSensitive::
No )
3191 virtual ~NamePattern();
3192 virtual bool matches( TestCaseInfo
const& testCase )
const {
3193 return m_wildcardPattern.matches(
toLower( testCase.name ) );
3196 WildcardPattern m_wildcardPattern;
3199 class TagPattern :
public Pattern {
3201 TagPattern( std::string
const& tag ) : m_tag(
toLower( tag ) ) {}
3202 virtual ~TagPattern();
3203 virtual bool matches( TestCaseInfo
const& testCase )
const {
3204 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
3210 class ExcludedPattern :
public Pattern {
3212 ExcludedPattern( Ptr<Pattern>
const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3213 virtual ~ExcludedPattern();
3214 virtual bool matches( TestCaseInfo
const& testCase )
const {
return !m_underlyingPattern->matches( testCase ); }
3216 Ptr<Pattern> m_underlyingPattern;
3220 std::vector<Ptr<Pattern> > m_patterns;
3222 bool matches( TestCaseInfo
const& testCase )
const {
3224 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
3225 if( !(*it)->matches( testCase ) )
3232 bool hasFilters()
const {
3233 return !m_filters.empty();
3235 bool matches( TestCaseInfo
const& testCase )
const {
3237 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3238 if( it->matches( testCase ) )
3244 std::vector<Filter> m_filters;
3246 friend class TestSpecParser;
3251 #pragma clang diagnostic pop
3256 class TestSpecParser {
3257 enum Mode{
None,
Name, QuotedName, Tag };
3260 std::size_t m_start, m_pos;
3262 TestSpec::Filter m_currentFilter;
3263 TestSpec m_testSpec;
3264 ITagAliasRegistry
const* m_tagAliases;
3267 TestSpecParser( ITagAliasRegistry
const& tagAliases ) : m_tagAliases( &tagAliases ) {}
3269 TestSpecParser& parse( std::string
const& arg ) {
3271 m_exclusion =
false;
3272 m_start = std::string::npos;
3273 m_arg = m_tagAliases->expandAliases( arg );
3274 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3275 visitChar( m_arg[m_pos] );
3276 if( m_mode ==
Name )
3277 addPattern<TestSpec::NamePattern>();
3280 TestSpec testSpec() {
3285 void visitChar(
char c ) {
3286 if( m_mode ==
None ) {
3289 case '~': m_exclusion =
true;
return;
3290 case '[':
return startNewMode( Tag, ++m_pos );
3291 case '"':
return startNewMode( QuotedName, ++m_pos );
3292 default: startNewMode(
Name, m_pos );
break;
3295 if( m_mode ==
Name ) {
3297 addPattern<TestSpec::NamePattern>();
3300 else if( c ==
'[' ) {
3301 if( subString() ==
"exclude:" )
3304 addPattern<TestSpec::NamePattern>();
3305 startNewMode( Tag, ++m_pos );
3308 else if( m_mode == QuotedName && c ==
'"' )
3309 addPattern<TestSpec::NamePattern>();
3310 else if( m_mode == Tag && c ==
']' )
3311 addPattern<TestSpec::TagPattern>();
3313 void startNewMode( Mode mode, std::size_t
start ) {
3317 std::string subString()
const {
return m_arg.substr( m_start, m_pos - m_start ); }
3318 template<
typename T>
3320 std::string token = subString();
3323 token = token.substr( 8 );
3325 if( !token.empty() ) {
3326 Ptr<TestSpec::Pattern> pattern =
new T( token );
3328 pattern =
new TestSpec::ExcludedPattern( pattern );
3329 m_currentFilter.m_patterns.push_back( pattern );
3331 m_exclusion =
false;
3335 if( !m_currentFilter.m_patterns.empty() ) {
3336 m_testSpec.m_filters.push_back( m_currentFilter );
3337 m_currentFilter = TestSpec::Filter();
3341 inline TestSpec parseTestSpec( std::string
const& arg ) {
3348 #pragma clang diagnostic pop
3352 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3360 struct Verbosity {
enum Level {
3366 struct WarnAbout {
enum What {
3371 struct ShowDurations {
enum OrNot {
3376 struct RunTests {
enum InWhatOrder {
3378 InLexicographicalOrder,
3381 struct UseColour {
enum YesOrNo {
3389 struct IConfig : IShared {
3393 virtual bool allowThrows()
const = 0;
3394 virtual std::ostream& stream()
const = 0;
3395 virtual std::string name()
const = 0;
3396 virtual bool includeSuccessfulResults()
const = 0;
3397 virtual bool shouldDebugBreak()
const = 0;
3398 virtual bool warnAboutMissingAssertions()
const = 0;
3399 virtual int abortAfter()
const = 0;
3400 virtual bool showInvisibles()
const = 0;
3401 virtual ShowDurations::OrNot showDurations()
const = 0;
3402 virtual TestSpec
const& testSpec()
const = 0;
3403 virtual RunTests::InWhatOrder runOrder()
const = 0;
3404 virtual unsigned int rngSeed()
const = 0;
3405 virtual UseColour::YesOrNo useColour()
const = 0;
3410 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3413 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
3415 #include <streambuf>
3419 class StreamBufBase :
public std::streambuf {
3425 #include <streambuf>
3431 std::ostream& cout();
3432 std::ostream& cerr();
3436 virtual
std::ostream& stream() const = 0;
3439 class FileStream : public IStream {
3440 mutable std::ofstream m_ofs;
3442 FileStream( std::string
const& filename );
3448 class CoutStream : public IStream {
3449 mutable std::ostream m_os;
3458 class DebugOutStream : public IStream {
3459 std::auto_ptr<StreamBufBase> m_streamBuf;
3460 mutable std::ostream m_os;
3476 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
3477 #define CATCH_CONFIG_CONSOLE_WIDTH 80
3485 : listTests( false ),
3487 listReporters( false ),
3488 listTestNamesOnly( false ),
3489 showSuccessfulTests( false ),
3490 shouldDebugBreak( false ),
3493 showInvisibles( false ),
3494 filenamesAsTags( false ),
3497 verbosity( Verbosity::
Normal ),
3498 warnings( WarnAbout::Nothing ),
3499 showDurations( ShowDurations::DefaultForReporter ),
3500 runOrder( RunTests::InDeclarationOrder ),
3501 useColour( UseColour::Auto )
3507 bool listTestNamesOnly;
3509 bool showSuccessfulTests;
3510 bool shouldDebugBreak;
3513 bool showInvisibles;
3514 bool filenamesAsTags;
3519 Verbosity::Level verbosity;
3520 WarnAbout::What warnings;
3521 ShowDurations::OrNot showDurations;
3522 RunTests::InWhatOrder runOrder;
3523 UseColour::YesOrNo useColour;
3525 std::string outputFilename;
3527 std::string processName;
3529 std::vector<std::string> reporterNames;
3530 std::vector<std::string> testsOrTags;
3533 class Config :
public SharedImpl<IConfig> {
3535 Config( Config
const& other );
3536 Config& operator = ( Config
const& other );
3537 virtual void dummy();
3543 Config( ConfigData
const&
data )
3545 m_stream( openStream() )
3547 if( !
data.testsOrTags.empty() ) {
3549 for( std::size_t i = 0; i <
data.testsOrTags.size(); ++i )
3550 parser.parse(
data.testsOrTags[i] );
3551 m_testSpec = parser.testSpec();
3558 std::string
const& getFilename()
const {
3559 return m_data.outputFilename ;
3562 bool listTests()
const {
return m_data.listTests; }
3563 bool listTestNamesOnly()
const {
return m_data.listTestNamesOnly; }
3564 bool listTags()
const {
return m_data.listTags; }
3565 bool listReporters()
const {
return m_data.listReporters; }
3567 std::string getProcessName()
const {
return m_data.processName; }
3569 bool shouldDebugBreak()
const {
return m_data.shouldDebugBreak; }
3571 std::vector<std::string> getReporterNames()
const {
return m_data.reporterNames; }
3573 int abortAfter()
const {
return m_data.abortAfter; }
3575 TestSpec
const& testSpec()
const {
return m_testSpec; }
3577 bool showHelp()
const {
return m_data.showHelp; }
3578 bool showInvisibles()
const {
return m_data.showInvisibles; }
3581 virtual bool allowThrows()
const {
return !m_data.noThrow; }
3582 virtual std::ostream& stream()
const {
return m_stream->stream(); }
3583 virtual std::string name()
const {
return m_data.name.empty() ? m_data.processName : m_data.name; }
3584 virtual bool includeSuccessfulResults()
const {
return m_data.showSuccessfulTests; }
3585 virtual bool warnAboutMissingAssertions()
const {
return m_data.warnings & WarnAbout::NoAssertions; }
3586 virtual ShowDurations::OrNot showDurations()
const {
return m_data.showDurations; }
3587 virtual RunTests::InWhatOrder runOrder()
const {
return m_data.runOrder; }
3588 virtual unsigned int rngSeed()
const {
return m_data.rngSeed; }
3589 virtual UseColour::YesOrNo useColour()
const {
return m_data.useColour; }
3593 IStream
const* openStream() {
3594 if( m_data.outputFilename.empty() )
3595 return new CoutStream();
3596 else if( m_data.outputFilename[0] ==
'%' ) {
3597 if( m_data.outputFilename ==
"%debug" )
3598 return new DebugOutStream();
3600 throw std::domain_error(
"Unrecognised stream: " + m_data.outputFilename );
3603 return new FileStream( m_data.outputFilename );
3607 std::auto_ptr<IStream const> m_stream;
3608 TestSpec m_testSpec;
3614 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3617 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
3618 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3619 #undef CLARA_CONFIG_CONSOLE_WIDTH
3621 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3624 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
3630 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
3632 #ifndef STITCH_CLARA_OPEN_NAMESPACE
3633 #define TWOBLUECUBES_CLARA_H_INCLUDED
3634 #define STITCH_CLARA_OPEN_NAMESPACE
3635 #define STITCH_CLARA_CLOSE_NAMESPACE
3637 #define STITCH_CLARA_CLOSE_NAMESPACE }
3640 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
3645 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
3646 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3647 #define TBC_TEXT_FORMAT_H_INCLUDED
3653 #include <algorithm>
3656 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3657 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
3662 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
3663 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
3665 const unsigned int consoleWidth = 80;
3668 struct TextAttributes {
3670 : initialIndent(
std::string::npos ),
3672 width( consoleWidth-1 ),
3676 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value;
return *
this; }
3677 TextAttributes& setIndent( std::size_t _value ) { indent = _value;
return *
this; }
3678 TextAttributes& setWidth( std::size_t _value ) { width = _value;
return *
this; }
3679 TextAttributes& setTabChar(
char _value ) { tabChar = _value;
return *
this; }
3681 std::size_t initialIndent;
3689 Text( std::string
const& _str, TextAttributes
const& _attr = TextAttributes() )
3692 std::string wrappableChars =
" [({.,/|\\-";
3693 std::size_t indent = _attr.initialIndent != std::string::npos
3694 ? _attr.initialIndent
3696 std::string remainder = _str;
3698 while( !remainder.empty() ) {
3699 if( lines.size() >= 1000 ) {
3700 lines.push_back(
"... message truncated due to excessive size" );
3703 std::size_t tabPos = std::string::npos;
3704 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
3705 std::size_t pos = remainder.find_first_of(
'\n' );
3706 if( pos <= width ) {
3709 pos = remainder.find_last_of( _attr.tabChar, width );
3710 if( pos != std::string::npos ) {
3712 if( remainder[width] ==
'\n' )
3714 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
3717 if( width == remainder.size() ) {
3718 spliceLine( indent, remainder, width );
3720 else if( remainder[width] ==
'\n' ) {
3721 spliceLine( indent, remainder, width );
3722 if( width <= 1 || remainder.size() != 1 )
3723 remainder = remainder.substr( 1 );
3724 indent = _attr.indent;
3727 pos = remainder.find_last_of( wrappableChars, width );
3728 if( pos != std::string::npos && pos > 0 ) {
3729 spliceLine( indent, remainder, pos );
3730 if( remainder[0] ==
' ' )
3731 remainder = remainder.substr( 1 );
3734 spliceLine( indent, remainder, width-1 );
3735 lines.back() += "-";
3737 if( lines.size() == 1 )
3738 indent = _attr.indent;
3739 if( tabPos != std::string::npos )
3745 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
3746 lines.push_back( std::string( _indent,
' ' ) + _remainder.substr( 0, _pos ) );
3747 _remainder = _remainder.substr( _pos );
3750 typedef std::vector<std::string>::const_iterator const_iterator;
3752 const_iterator begin()
const {
return lines.begin(); }
3753 const_iterator end()
const {
return lines.end(); }
3754 std::string
const& last()
const {
return lines.back(); }
3755 std::size_t
size()
const {
return lines.size(); }
3756 std::string
const& operator[]( std::size_t _index )
const {
return lines[_index]; }
3758 std::ostringstream oss;
3763 inline friend std::ostream&
operator << ( std::ostream& _stream,
Text const& _text ) {
3764 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
3765 it != itEnd; ++it ) {
3766 if( it != _text.begin() )
3775 TextAttributes attr;
3776 std::vector<std::string> lines;
3781 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3790 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
3794 #ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3795 #define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3819 #if __has_feature(cxx_nullptr)
3820 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3823 #if __has_feature(cxx_noexcept)
3824 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3833 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
3834 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3846 #if (_MSC_VER >= 1600)
3847 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3848 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
3851 #if (_MSC_VER >= 1900 )
3852 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3853 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3862 #if defined(__cplusplus) && __cplusplus >= 201103L
3864 #define CLARA_CPP11_OR_GREATER
3866 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
3867 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3870 #ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3871 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3874 #ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3875 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3878 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
3879 #define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
3881 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
3882 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
3888 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
3889 #define CLARA_CONFIG_CPP11_NULLPTR
3891 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
3892 #define CLARA_CONFIG_CPP11_NOEXCEPT
3894 #if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11)
3895 #define CLARA_CONFIG_CPP11_GENERATED_METHODS
3897 #if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
3898 #define CLARA_CONFIG_CPP11_OVERRIDE
3900 #if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11)
3901 #define CLARA_CONFIG_CPP11_UNIQUE_PTR
3905 #if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
3906 #define CLARA_NOEXCEPT noexcept
3907 # define CLARA_NOEXCEPT_IS(x) noexcept(x)
3909 #define CLARA_NOEXCEPT throw()
3910 # define CLARA_NOEXCEPT_IS(x)
3914 #ifdef CLARA_CONFIG_CPP11_NULLPTR
3915 #define CLARA_NULL nullptr
3917 #define CLARA_NULL NULL
3921 #ifdef CLARA_CONFIG_CPP11_OVERRIDE
3922 #define CLARA_OVERRIDE override
3924 #define CLARA_OVERRIDE
3928 #ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
3929 # define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
3931 # define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
3940 #include <stdexcept>
3943 #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
3944 #define CLARA_PLATFORM_WINDOWS
3948 #ifdef STITCH_CLARA_OPEN_NAMESPACE
3949 STITCH_CLARA_OPEN_NAMESPACE
3954 struct UnpositionalTag {};
3956 extern UnpositionalTag
_;
3958 #ifdef CLARA_CONFIG_MAIN
3964 #ifdef CLARA_CONSOLE_WIDTH
3965 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
3967 const unsigned int consoleWidth = 80;
3970 using namespace Tbc;
3972 inline bool startsWith( std::string
const& str, std::string
const& prefix ) {
3973 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
3976 template<
typename T>
struct RemoveConstRef{
typedef T type; };
3977 template<
typename T>
struct RemoveConstRef<
T&>{
typedef T type; };
3978 template<
typename T>
struct RemoveConstRef<
T const&>{
typedef T type; };
3979 template<
typename T>
struct RemoveConstRef<
T const>{
typedef T type; };
3981 template<
typename T>
struct IsBool {
static const bool value =
false; };
3982 template<>
struct IsBool<bool> {
static const bool value =
true; };
3984 template<
typename T>
3985 void convertInto( std::string
const& _source,
T& _dest ) {
3986 std::stringstream ss;
3990 throw std::runtime_error(
"Unable to convert " + _source +
" to destination type" );
3992 inline void convertInto( std::string
const& _source, std::string& _dest ) {
3995 inline void convertInto( std::string
const& _source,
bool& _dest ) {
3996 std::string sourceLC = _source;
3997 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
3998 if( sourceLC ==
"y" || sourceLC ==
"1" || sourceLC ==
"true" || sourceLC ==
"yes" || sourceLC ==
"on" )
4000 else if( sourceLC ==
"n" || sourceLC ==
"0" || sourceLC ==
"false" || sourceLC ==
"no" || sourceLC ==
"off" )
4003 throw std::runtime_error(
"Expected a boolean value but did not recognise:\n '" + _source +
"'" );
4006 template<
typename ConfigT>
4007 struct IArgFunction {
4008 virtual ~IArgFunction() {}
4009 #ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
4010 IArgFunction() =
default;
4011 IArgFunction( IArgFunction
const& ) =
default;
4013 virtual void set( ConfigT&
config, std::string
const& value )
const = 0;
4014 virtual bool takesArg()
const = 0;
4015 virtual IArgFunction* clone()
const = 0;
4018 template<
typename ConfigT>
4019 class BoundArgFunction {
4021 BoundArgFunction() : functionObj( CLARA_NULL ) {}
4022 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
4023 BoundArgFunction( BoundArgFunction
const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
4024 BoundArgFunction& operator = ( BoundArgFunction
const& other ) {
4025 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
4027 functionObj = newFunctionObj;
4030 ~BoundArgFunction() {
delete functionObj; }
4032 void set( ConfigT&
config, std::string
const& value )
const {
4033 functionObj->set(
config, value );
4035 bool takesArg()
const {
return functionObj->takesArg(); }
4037 bool isSet()
const {
4038 return functionObj != CLARA_NULL;
4041 IArgFunction<ConfigT>* functionObj;
4044 template<
typename C>
4045 struct NullBinder : IArgFunction<C>{
4046 virtual void set( C&, std::string
const& )
const {}
4047 virtual bool takesArg()
const {
return true; }
4048 virtual IArgFunction<C>* clone()
const {
return new NullBinder( *
this ); }
4051 template<
typename C,
typename M>
4052 struct BoundDataMember : IArgFunction<C>{
4053 BoundDataMember( M C::* _member ) : member( _member ) {}
4054 virtual void set( C& p, std::string
const& stringValue )
const {
4055 convertInto( stringValue, p.*member );
4057 virtual bool takesArg()
const {
return !IsBool<M>::value; }
4058 virtual IArgFunction<C>* clone()
const {
return new BoundDataMember( *
this ); }
4061 template<
typename C,
typename M>
4062 struct BoundUnaryMethod : IArgFunction<C>{
4063 BoundUnaryMethod(
void (C::*_member)( M ) ) : member( _member ) {}
4064 virtual void set( C& p, std::string
const& stringValue )
const {
4065 typename RemoveConstRef<M>::type value;
4066 convertInto( stringValue, value );
4067 (p.*member)( value );
4069 virtual bool takesArg()
const {
return !IsBool<M>::value; }
4070 virtual IArgFunction<C>* clone()
const {
return new BoundUnaryMethod( *
this ); }
4071 void (C::*member)( M );
4073 template<
typename C>
4074 struct BoundNullaryMethod : IArgFunction<C>{
4075 BoundNullaryMethod(
void (C::*_member)() ) : member( _member ) {}
4076 virtual void set( C& p, std::string
const& stringValue )
const {
4078 convertInto( stringValue, value );
4082 virtual bool takesArg()
const {
return false; }
4083 virtual IArgFunction<C>* clone()
const {
return new BoundNullaryMethod( *
this ); }
4084 void (C::*member)();
4087 template<
typename C>
4088 struct BoundUnaryFunction : IArgFunction<C>{
4089 BoundUnaryFunction(
void (*_function)( C& ) ) : function( _function ) {}
4090 virtual void set( C& obj, std::string
const& stringValue )
const {
4092 convertInto( stringValue, value );
4096 virtual bool takesArg()
const {
return false; }
4097 virtual IArgFunction<C>* clone()
const {
return new BoundUnaryFunction( *
this ); }
4098 void (*
function)( C& );
4101 template<
typename C,
typename T>
4102 struct BoundBinaryFunction : IArgFunction<C>{
4103 BoundBinaryFunction(
void (*_function)( C&,
T ) ) : function( _function ) {}
4104 virtual void set( C& obj, std::string
const& stringValue )
const {
4105 typename RemoveConstRef<T>::type value;
4106 convertInto( stringValue, value );
4107 function( obj, value );
4109 virtual bool takesArg()
const {
return !IsBool<T>::value; }
4110 virtual IArgFunction<C>* clone()
const {
return new BoundBinaryFunction( *
this ); }
4111 void (*
function)( C&,
T );
4116 inline std::vector<std::string> argsToVector(
int argc,
char const*
const*
const argv ) {
4117 std::vector<std::string> args(
static_cast<std::size_t
>( argc ) );
4118 for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
4125 enum Mode {
None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
4132 enum Type { Positional, ShortOpt, LongOpt };
4133 Token(
Type _type, std::string
const& _data ) : type( _type ),
data( _data ) {}
4138 Parser() : mode(
None ), from( 0 ), inQuotes( false ){}
4140 void parseIntoTokens( std::vector<std::string>
const& args, std::vector<Token>& tokens ) {
4141 const std::string doubleDash =
"--";
4142 for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
4143 parseIntoTokens( args[i], tokens);
4146 void parseIntoTokens( std::string
const& arg, std::vector<Token>& tokens ) {
4147 for( std::size_t i = 0; i <= arg.size(); ++i ) {
4150 inQuotes = !inQuotes;
4151 mode = handleMode( i, c, arg, tokens );
4154 Mode handleMode( std::size_t i,
char c, std::string
const& arg, std::vector<Token>& tokens ) {
4156 case None:
return handleNone( i, c );
4157 case MaybeShortOpt:
return handleMaybeShortOpt( i, c );
4160 case SlashOpt:
return handleOpt( i, c, arg, tokens );
4161 case Positional:
return handlePositional( i, c, arg, tokens );
4162 default:
throw std::logic_error(
"Unknown mode" );
4166 Mode handleNone( std::size_t i,
char c ) {
4172 case '-':
return MaybeShortOpt;
4173 #ifdef CLARA_PLATFORM_WINDOWS
4174 case '/': from = i+1;
return SlashOpt;
4176 default: from = i;
return Positional;
4179 Mode handleMaybeShortOpt( std::size_t i,
char c ) {
4181 case '-': from = i+1;
return LongOpt;
4182 default: from = i;
return ShortOpt;
4185 Mode handleOpt( std::size_t i,
char c, std::string
const& arg, std::vector<Token>& tokens ) {
4186 if( std::string(
" \t:=\0", 5 ).
find( c ) == std::string::npos )
4189 std::string optName = arg.substr( from, i-from );
4190 if( mode == ShortOpt )
4191 for( std::size_t j = 0; j < optName.size(); ++j )
4192 tokens.push_back(
Token(
Token::ShortOpt, optName.substr( j, 1 ) ) );
4193 else if( mode == SlashOpt && optName.size() == 1 )
4194 tokens.push_back(
Token( Token::ShortOpt, optName ) );
4196 tokens.push_back(
Token( Token::LongOpt, optName ) );
4199 Mode handlePositional( std::size_t i,
char c, std::string
const& arg, std::vector<Token>& tokens ) {
4200 if( inQuotes || std::string(
" \t\0", 3 ).
find( c ) == std::string::npos )
4203 std::string
data = arg.substr( from, i-from );
4204 tokens.push_back(
Token( Token::Positional,
data ) );
4209 template<
typename ConfigT>
4210 struct CommonArgProperties {
4211 CommonArgProperties() {}
4212 CommonArgProperties( Detail::BoundArgFunction<ConfigT>
const& _boundField ) : boundField( _boundField ) {}
4214 Detail::BoundArgFunction<ConfigT> boundField;
4215 std::string description;
4217 std::string placeholder;
4219 bool takesArg()
const {
4220 return !placeholder.empty();
4222 void validate()
const {
4223 if( !boundField.isSet() )
4224 throw std::logic_error(
"option not bound" );
4227 struct OptionArgProperties {
4228 std::vector<std::string> shortNames;
4229 std::string longName;
4231 bool hasShortName( std::string
const& shortName )
const {
4232 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4234 bool hasLongName( std::string
const& _longName )
const {
4235 return _longName == longName;
4238 struct PositionalArgProperties {
4239 PositionalArgProperties() : position( -1 ) {}
4242 bool isFixedPositional()
const {
4243 return position != -1;
4247 template<
typename ConfigT>
4250 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
4252 Arg( Detail::BoundArgFunction<ConfigT>
const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
4254 using CommonArgProperties<ConfigT>::placeholder;
4256 std::string dbgName()
const {
4257 if( !longName.empty() )
4258 return "--" + longName;
4259 if( !shortNames.empty() )
4260 return "-" + shortNames[0];
4261 return "positional args";
4263 std::string commands()
const {
4264 std::ostringstream oss;
4266 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4267 for(; it != itEnd; ++it ) {
4274 if( !longName.empty() ) {
4277 oss <<
"--" << longName;
4279 if( !placeholder.empty() )
4280 oss <<
" <" << placeholder <<
">";
4285 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
4287 friend void addOptName( Arg& arg, std::string
const& optName )
4289 if( optName.empty() )
4292 if( !arg.longName.empty() )
4293 throw std::logic_error(
"Only one long opt may be specified. '"
4295 +
"' already specified, now attempting to add '"
4297 arg.longName = optName.substr( 2 );
4300 arg.shortNames.push_back( optName.substr( 1 ) );
4302 throw std::logic_error(
"option must begin with - or --. Option was: '" + optName +
"'" );
4304 friend void setPositionalArg( Arg& arg,
int position )
4306 arg.position = position;
4311 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
4314 template<
typename C,
typename M>
4315 void bind( M C::* field, std::string
const& placeholder ) {
4316 m_arg->boundField =
new Detail::BoundDataMember<C,M>( field );
4317 m_arg->placeholder = placeholder;
4320 template<
typename C>
4321 void bind(
bool C::* field ) {
4322 m_arg->boundField =
new Detail::BoundDataMember<C,bool>( field );
4326 template<
typename C,
typename M>
4327 void bind(
void (C::* unaryMethod)( M ), std::string
const& placeholder ) {
4328 m_arg->boundField =
new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4329 m_arg->placeholder = placeholder;
4333 template<
typename C>
4334 void bind(
void (C::* unaryMethod)(
bool ) ) {
4335 m_arg->boundField =
new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
4339 template<
typename C>
4340 void bind(
void (C::* nullaryMethod)() ) {
4341 m_arg->boundField =
new Detail::BoundNullaryMethod<C>( nullaryMethod );
4345 template<
typename C>
4346 void bind(
void (* unaryFunction)( C& ) ) {
4347 m_arg->boundField =
new Detail::BoundUnaryFunction<C>( unaryFunction );
4351 template<
typename C,
typename T>
4352 void bind(
void (* binaryFunction)( C&,
T ), std::string
const& placeholder ) {
4353 m_arg->boundField =
new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4354 m_arg->placeholder = placeholder;
4357 ArgBuilder& describe( std::string
const& description ) {
4358 m_arg->description = description;
4361 ArgBuilder& detail( std::string
const& detail ) {
4362 m_arg->detail = detail;
4370 class OptBuilder :
public ArgBuilder {
4372 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
4373 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4375 OptBuilder& operator[]( std::string
const& optName ) {
4376 addOptName( *ArgBuilder::m_arg, optName );
4384 : m_boundProcessName(
new Detail::NullBinder<ConfigT>() ),
4385 m_highestSpecifiedArgPosition( 0 ),
4386 m_throwOnUnrecognisedTokens( false )
4388 CommandLine( CommandLine
const& other )
4389 : m_boundProcessName( other.m_boundProcessName ),
4390 m_options ( other.m_options ),
4391 m_positionalArgs( other.m_positionalArgs ),
4392 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4393 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
4395 if( other.m_floatingArg.get() )
4396 m_floatingArg.reset(
new Arg( *other.m_floatingArg ) );
4399 CommandLine& setThrowOnUnrecognisedTokens(
bool shouldThrow =
true ) {
4400 m_throwOnUnrecognisedTokens = shouldThrow;
4404 OptBuilder operator[]( std::string
const& optName ) {
4405 m_options.push_back( Arg() );
4406 addOptName( m_options.back(), optName );
4407 OptBuilder builder( &m_options.back() );
4411 ArgBuilder operator[](
int position ) {
4412 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4413 if( position > m_highestSpecifiedArgPosition )
4414 m_highestSpecifiedArgPosition = position;
4415 setPositionalArg( m_positionalArgs[position], position );
4416 ArgBuilder builder( &m_positionalArgs[position] );
4421 ArgBuilder operator[]( UnpositionalTag ) {
4422 if( m_floatingArg.get() )
4423 throw std::logic_error(
"Only one unpositional argument can be added" );
4424 m_floatingArg.reset(
new Arg() );
4425 ArgBuilder builder( m_floatingArg.get() );
4429 template<
typename C,
typename M>
4430 void bindProcessName( M C::* field ) {
4431 m_boundProcessName =
new Detail::BoundDataMember<C,M>( field );
4433 template<
typename C,
typename M>
4434 void bindProcessName(
void (C::*_unaryMethod)( M ) ) {
4435 m_boundProcessName =
new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
4438 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth )
const {
4439 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4440 std::size_t maxWidth = 0;
4441 for( it = itBegin; it != itEnd; ++it )
4442 maxWidth = (
std::max)( maxWidth, it->commands().size() );
4444 for( it = itBegin; it != itEnd; ++it ) {
4445 Detail::Text usage( it->commands(), Detail::TextAttributes()
4446 .setWidth( maxWidth+indent )
4447 .setIndent( indent ) );
4448 Detail::Text desc( it->description, Detail::TextAttributes()
4449 .setWidth( width - maxWidth - 3 ) );
4451 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
4452 std::string usageCol = i < usage.size() ? usage[i] :
"";
4455 if( i < desc.size() && !desc[i].empty() )
4456 os << std::string( indent + 2 + maxWidth - usageCol.size(),
' ' )
4462 std::string optUsage()
const {
4463 std::ostringstream oss;
4468 void argSynopsis( std::ostream& os )
const {
4469 for(
int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4472 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4473 if( it != m_positionalArgs.end() )
4474 os <<
"<" << it->second.placeholder <<
">";
4475 else if( m_floatingArg.get() )
4476 os <<
"<" << m_floatingArg->placeholder <<
">";
4478 throw std::logic_error(
"non consecutive positional arguments with no floating args" );
4481 if( m_floatingArg.get() ) {
4482 if( m_highestSpecifiedArgPosition > 1 )
4484 os <<
"[<" << m_floatingArg->placeholder <<
"> ...]";
4487 std::string argSynopsis()
const {
4488 std::ostringstream oss;
4493 void usage( std::ostream& os, std::string
const& procName )
const {
4495 os <<
"usage:\n " << procName <<
" ";
4497 if( !m_options.empty() ) {
4498 os <<
" [options]\n\nwhere options are: \n";
4503 std::string usage( std::string
const& procName )
const {
4504 std::ostringstream oss;
4505 usage( oss, procName );
4509 ConfigT parse( std::vector<std::string>
const& args )
const {
4511 parseInto( args,
config );
4515 std::vector<Parser::Token> parseInto( std::vector<std::string>
const& args, ConfigT&
config )
const {
4516 std::string processName = args[0];
4517 std::size_t lastSlash = processName.find_last_of(
"/\\" );
4518 if( lastSlash != std::string::npos )
4519 processName = processName.substr( lastSlash+1 );
4520 m_boundProcessName.set(
config, processName );
4521 std::vector<Parser::Token> tokens;
4523 parser.parseIntoTokens( args, tokens );
4524 return populate( tokens,
config );
4527 std::vector<Parser::Token> populate( std::vector<Parser::Token>
const& tokens, ConfigT&
config )
const {
4529 std::vector<Parser::Token> unusedTokens = populateOptions( tokens,
config );
4530 unusedTokens = populateFixedArgs( unusedTokens,
config );
4531 unusedTokens = populateFloatingArgs( unusedTokens,
config );
4532 return unusedTokens;
4535 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token>
const& tokens, ConfigT&
config )
const {
4536 std::vector<Parser::Token> unusedTokens;
4537 std::vector<std::string> errors;
4538 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4539 Parser::Token
const& token = tokens[i];
4540 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4541 for(; it != itEnd; ++it ) {
4542 Arg const& arg = *it;
4545 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4546 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4547 if( arg.takesArg() ) {
4548 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
4549 errors.push_back(
"Expected argument to option: " + token.data );
4551 arg.boundField.set( config, tokens[++i].data );
4554 arg.boundField.set( config,
"true" );
4559 catch( std::exception& ex ) {
4560 errors.push_back( std::string( ex.what() ) +
"\n- while parsing: (" + arg.commands() +
")" );
4564 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
4565 unusedTokens.push_back( token );
4566 else if( errors.empty() && m_throwOnUnrecognisedTokens )
4567 errors.push_back(
"unrecognised option: " + token.data );
4570 if( !errors.empty() ) {
4571 std::ostringstream oss;
4572 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4575 if( it != errors.begin() )
4579 throw std::runtime_error( oss.str() );
4581 return unusedTokens;
4583 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token>
const& tokens, ConfigT&
config )
const {
4584 std::vector<Parser::Token> unusedTokens;
4586 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4587 Parser::Token
const& token = tokens[i];
4588 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4589 if( it != m_positionalArgs.end() )
4590 it->second.boundField.set(
config, token.data );
4592 unusedTokens.push_back( token );
4593 if( token.type == Parser::Token::Positional )
4596 return unusedTokens;
4598 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token>
const& tokens, ConfigT&
config )
const {
4599 if( !m_floatingArg.get() )
4601 std::vector<Parser::Token> unusedTokens;
4602 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4603 Parser::Token
const& token = tokens[i];
4604 if( token.type == Parser::Token::Positional )
4605 m_floatingArg->boundField.set(
config, token.data );
4607 unusedTokens.push_back( token );
4609 return unusedTokens;
4612 void validate()
const
4614 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
4615 throw std::logic_error(
"No options or arguments specified" );
4617 for(
typename std::vector<Arg>::const_iterator it = m_options.begin(),
4618 itEnd = m_options.end();
4624 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4625 std::vector<Arg> m_options;
4626 std::map<int, Arg> m_positionalArgs;
4627 ArgAutoPtr m_floatingArg;
4628 int m_highestSpecifiedArgPosition;
4629 bool m_throwOnUnrecognisedTokens;
4634 STITCH_CLARA_CLOSE_NAMESPACE
4635 #undef STITCH_CLARA_OPEN_NAMESPACE
4636 #undef STITCH_CLARA_CLOSE_NAMESPACE
4639 #undef STITCH_CLARA_OPEN_NAMESPACE
4642 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4643 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4644 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4651 inline void abortAfterFirst( ConfigData&
config ) {
config.abortAfter = 1; }
4652 inline void abortAfterX( ConfigData&
config,
int x ) {
4654 throw std::runtime_error(
"Value after -x or --abortAfter must be greater than zero" );
4657 inline void addTestOrTags( ConfigData&
config, std::string
const& _testSpec ) {
config.testsOrTags.push_back( _testSpec ); }
4658 inline void addReporterName( ConfigData&
config, std::string
const& _reporterName ) {
config.reporterNames.push_back( _reporterName ); }
4660 inline void addWarning( ConfigData&
config, std::string
const& _warning ) {
4661 if( _warning ==
"NoAssertions" )
4662 config.warnings =
static_cast<WarnAbout::What
>(
config.warnings | WarnAbout::NoAssertions );
4664 throw std::runtime_error(
"Unrecognised warning: '" + _warning +
"'" );
4666 inline void setOrder( ConfigData&
config, std::string
const& order ) {
4668 config.runOrder = RunTests::InDeclarationOrder;
4670 config.runOrder = RunTests::InLexicographicalOrder;
4672 config.runOrder = RunTests::InRandomOrder;
4674 throw std::runtime_error(
"Unrecognised ordering: '" + order +
"'" );
4676 inline void setRngSeed( ConfigData&
config, std::string
const& seed ) {
4677 if( seed ==
"time" ) {
4678 config.rngSeed =
static_cast<unsigned int>( std::time(0) );
4681 std::stringstream ss;
4685 throw std::runtime_error(
"Argment to --rng-seed should be the word 'time' or a number" );
4688 inline void setVerbosity( ConfigData&
config,
int level ) {
4690 config.verbosity =
static_cast<Verbosity::Level
>( level );
4692 inline void setShowDurations( ConfigData&
config,
bool _showDurations ) {
4693 config.showDurations = _showDurations
4694 ? ShowDurations::Always
4695 : ShowDurations::Never;
4697 inline void setUseColour( ConfigData&
config, std::string
const& value ) {
4698 std::string mode =
toLower( value );
4701 config.useColour = UseColour::Yes;
4702 else if( mode ==
"no" )
4704 else if( mode ==
"auto" )
4705 config.useColour = UseColour::Auto;
4707 throw std::runtime_error(
"colour mode must be one of: auto, yes or no" );
4709 inline void forceColour( ConfigData&
config ) {
4710 config.useColour = UseColour::Yes;
4712 inline void loadTestNamesFromFile( ConfigData&
config, std::string
const& _filename ) {
4713 std::ifstream f( _filename.c_str() );
4715 throw std::domain_error(
"Unable to load input file: " + _filename );
4718 while( std::getline( f, line ) ) {
4720 if( !line.empty() && !
startsWith( line,
"#" ) )
4721 addTestOrTags(
config,
"\"" + line +
"\"," );
4725 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4727 using namespace Clara;
4728 CommandLine<ConfigData> cli;
4730 cli.bindProcessName( &ConfigData::processName );
4732 cli["-?"]["-h"]["--help"]
4733 .describe(
"display usage information" )
4734 .bind( &ConfigData::showHelp );
4736 cli["-l"]["--list-tests"]
4737 .describe(
"list all/matching test cases" )
4738 .bind( &ConfigData::listTests );
4740 cli["-t"]["--list-tags"]
4741 .describe(
"list all/matching tags" )
4742 .bind( &ConfigData::listTags );
4744 cli["-s"]["--success"]
4745 .describe(
"include successful tests in output" )
4746 .bind( &ConfigData::showSuccessfulTests );
4748 cli["-b"]["--break"]
4749 .describe(
"break into debugger on failure" )
4750 .bind( &ConfigData::shouldDebugBreak );
4752 cli["-e"]["--nothrow"]
4753 .describe(
"skip exception tests" )
4754 .bind( &ConfigData::noThrow );
4756 cli["-i"]["--invisibles"]
4757 .describe(
"show invisibles (tabs, newlines)" )
4758 .bind( &ConfigData::showInvisibles );
4761 .describe(
"output filename" )
4762 .bind( &ConfigData::outputFilename,
"filename" );
4764 cli["-r"]["--reporter"]
4766 .describe(
"reporter to use (defaults to console)" )
4767 .bind( &addReporterName,
"name" );
4770 .describe(
"suite name" )
4771 .bind( &ConfigData::name,
"name" );
4773 cli["-a"]["--abort"]
4774 .describe(
"abort at first failure" )
4775 .bind( &abortAfterFirst );
4777 cli["-x"]["--abortx"]
4778 .describe(
"abort after x failures" )
4779 .bind( &abortAfterX,
"no. failures" );
4782 .describe(
"enable warnings" )
4783 .bind( &addWarning,
"warning name" );
4793 .describe(
"which test or tests to use" )
4794 .bind( &addTestOrTags,
"test name, pattern or tags" );
4796 cli["-d"]["--durations"]
4797 .describe(
"show test durations" )
4798 .bind( &setShowDurations,
"yes|no" );
4800 cli["-f"]["--input-file"]
4801 .describe(
"load test names to run from a file" )
4802 .bind( &loadTestNamesFromFile,
"filename" );
4804 cli["-#"]["--filenames-as-tags"]
4805 .describe(
"adds a tag for the filename" )
4806 .bind( &ConfigData::filenamesAsTags );
4809 cli["--list-test-names-only"]
4810 .describe(
"list all/matching test cases names only" )
4811 .bind( &ConfigData::listTestNamesOnly );
4813 cli["--list-reporters"]
4814 .describe(
"list all reporters" )
4815 .bind( &ConfigData::listReporters );
4818 .describe(
"test case order (defaults to decl)" )
4819 .bind( &setOrder,
"decl|lex|rand" );
4822 .describe(
"set a specific seed for random numbers" )
4823 .bind( &setRngSeed,
"'time'|number" );
4825 cli["--force-colour"]
4826 .describe(
"force colourised output (deprecated)" )
4827 .bind( &forceColour );
4830 .describe(
"should output be colourised" )
4831 .bind( &setUseColour,
"yes|no" );
4839 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4842 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
4844 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4846 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
4849 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4850 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4851 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4852 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4855 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4858 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4864 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4865 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4870 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4871 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4873 const unsigned int consoleWidth = 80;
4876 struct TextAttributes {
4878 : initialIndent(
std::string::npos ),
4880 width( consoleWidth-1 ),
4884 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value;
return *
this; }
4885 TextAttributes& setIndent( std::size_t _value ) { indent = _value;
return *
this; }
4886 TextAttributes& setWidth( std::size_t _value ) { width = _value;
return *
this; }
4887 TextAttributes& setTabChar(
char _value ) { tabChar = _value;
return *
this; }
4889 std::size_t initialIndent;
4897 Text( std::string
const& _str, TextAttributes
const& _attr = TextAttributes() )
4900 std::string wrappableChars =
" [({.,/|\\-";
4901 std::size_t indent = _attr.initialIndent != std::string::npos
4902 ? _attr.initialIndent
4904 std::string remainder = _str;
4906 while( !remainder.empty() ) {
4907 if( lines.size() >= 1000 ) {
4908 lines.push_back(
"... message truncated due to excessive size" );
4911 std::size_t tabPos = std::string::npos;
4912 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4913 std::size_t pos = remainder.find_first_of(
'\n' );
4914 if( pos <= width ) {
4917 pos = remainder.find_last_of( _attr.tabChar, width );
4918 if( pos != std::string::npos ) {
4920 if( remainder[width] ==
'\n' )
4922 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4925 if( width == remainder.size() ) {
4926 spliceLine( indent, remainder, width );
4928 else if( remainder[width] ==
'\n' ) {
4929 spliceLine( indent, remainder, width );
4930 if( width <= 1 || remainder.size() != 1 )
4931 remainder = remainder.substr( 1 );
4932 indent = _attr.indent;
4935 pos = remainder.find_last_of( wrappableChars, width );
4936 if( pos != std::string::npos && pos > 0 ) {
4937 spliceLine( indent, remainder, pos );
4938 if( remainder[0] ==
' ' )
4939 remainder = remainder.substr( 1 );
4942 spliceLine( indent, remainder, width-1 );
4943 lines.back() += "-";
4945 if( lines.size() == 1 )
4946 indent = _attr.indent;
4947 if( tabPos != std::string::npos )
4953 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4954 lines.push_back( std::string( _indent,
' ' ) + _remainder.substr( 0, _pos ) );
4955 _remainder = _remainder.substr( _pos );
4958 typedef std::vector<std::string>::const_iterator const_iterator;
4960 const_iterator begin()
const {
return lines.begin(); }
4961 const_iterator end()
const {
return lines.end(); }
4962 std::string
const& last()
const {
return lines.back(); }
4963 std::size_t
size()
const {
return lines.size(); }
4964 std::string
const& operator[]( std::size_t _index )
const {
return lines[_index]; }
4966 std::ostringstream oss;
4971 inline friend std::ostream&
operator << ( std::ostream& _stream,
Text const& _text ) {
4972 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4973 it != itEnd; ++it ) {
4974 if( it != _text.begin() )
4983 TextAttributes attr;
4984 std::vector<std::string> lines;
4989 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4994 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4998 using Tbc::TextAttributes;
5002 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
5030 ResultExpectedFailure = Warning,
5035 OriginalExpression =
Cyan,
5036 ReconstructedExpression =
Yellow,
5043 Colour( Code _colourCode );
5044 Colour( Colour
const& other );
5048 static void use( Code _colourCode );
5054 inline std::ostream&
operator << ( std::ostream& os, Colour
const& ) {
return os; }
5059 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5068 struct ReporterConfig {
5069 explicit ReporterConfig( Ptr<IConfig const>
const& _fullConfig )
5070 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
5072 ReporterConfig( Ptr<IConfig const>
const& _fullConfig, std::ostream& _stream )
5073 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
5075 std::ostream& stream()
const {
return *m_stream; }
5076 Ptr<IConfig const> fullConfig()
const {
return m_fullConfig; }
5079 std::ostream* m_stream;
5080 Ptr<IConfig const> m_fullConfig;
5083 struct ReporterPreferences {
5084 ReporterPreferences()
5085 : shouldRedirectStdOut( false )
5088 bool shouldRedirectStdOut;
5091 template<
typename T>
5092 struct LazyStat : Option<
T> {
5093 LazyStat() : used( false ) {}
5094 LazyStat& operator=(
T const& _value ) {
5106 struct TestRunInfo {
5107 TestRunInfo( std::string
const& _name ) : name( _name ) {}
5112 std::size_t _groupIndex,
5113 std::size_t _groupsCount )
5115 groupIndex( _groupIndex ),
5116 groupsCounts( _groupsCount )
5120 std::size_t groupIndex;
5121 std::size_t groupsCounts;
5124 struct AssertionStats {
5125 AssertionStats( AssertionResult
const& _assertionResult,
5126 std::vector<MessageInfo>
const& _infoMessages,
5127 Totals
const& _totals )
5128 : assertionResult( _assertionResult ),
5129 infoMessages( _infoMessages ),
5132 if( assertionResult.hasMessage() ) {
5135 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
5136 builder << assertionResult.getMessage();
5137 builder.m_info.message = builder.m_stream.str();
5139 infoMessages.push_back( builder.m_info );
5142 virtual ~AssertionStats();
5144 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5145 AssertionStats( AssertionStats
const& ) =
default;
5146 AssertionStats( AssertionStats && ) =
default;
5147 AssertionStats& operator = ( AssertionStats
const& ) =
default;
5148 AssertionStats& operator = ( AssertionStats && ) =
default;
5151 AssertionResult assertionResult;
5152 std::vector<MessageInfo> infoMessages;
5156 struct SectionStats {
5157 SectionStats( SectionInfo
const& _sectionInfo,
5158 Counts
const& _assertions,
5159 double _durationInSeconds,
5160 bool _missingAssertions )
5161 : sectionInfo( _sectionInfo ),
5162 assertions( _assertions ),
5163 durationInSeconds( _durationInSeconds ),
5164 missingAssertions( _missingAssertions )
5166 virtual ~SectionStats();
5167 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5168 SectionStats( SectionStats
const& ) =
default;
5169 SectionStats( SectionStats && ) =
default;
5170 SectionStats& operator = ( SectionStats
const& ) =
default;
5171 SectionStats& operator = ( SectionStats && ) =
default;
5174 SectionInfo sectionInfo;
5176 double durationInSeconds;
5177 bool missingAssertions;
5180 struct TestCaseStats {
5181 TestCaseStats( TestCaseInfo
const& _testInfo,
5182 Totals
const& _totals,
5183 std::string
const& _stdOut,
5184 std::string
const& _stdErr,
5190 aborting( _aborting )
5192 virtual ~TestCaseStats();
5194 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5195 TestCaseStats( TestCaseStats
const& ) =
default;
5196 TestCaseStats( TestCaseStats && ) =
default;
5197 TestCaseStats& operator = ( TestCaseStats
const& ) =
default;
5198 TestCaseStats& operator = ( TestCaseStats && ) =
default;
5208 struct TestGroupStats {
5209 TestGroupStats(
GroupInfo const& _groupInfo,
5210 Totals
const& _totals,
5212 : groupInfo( _groupInfo ),
5214 aborting( _aborting )
5216 TestGroupStats(
GroupInfo const& _groupInfo )
5217 : groupInfo( _groupInfo ),
5220 virtual ~TestGroupStats();
5222 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5223 TestGroupStats( TestGroupStats
const& ) =
default;
5224 TestGroupStats( TestGroupStats && ) =
default;
5225 TestGroupStats& operator = ( TestGroupStats
const& ) =
default;
5226 TestGroupStats& operator = ( TestGroupStats && ) =
default;
5234 struct TestRunStats {
5235 TestRunStats( TestRunInfo
const& _runInfo,
5236 Totals
const& _totals,
5238 : runInfo( _runInfo ),
5240 aborting( _aborting )
5242 virtual ~TestRunStats();
5244 # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
5245 TestRunStats( TestRunStats
const& _other )
5246 : runInfo( _other.runInfo ),
5247 totals( _other.totals ),
5248 aborting( _other.aborting )
5251 TestRunStats( TestRunStats
const& ) =
default;
5252 TestRunStats( TestRunStats && ) =
default;
5253 TestRunStats& operator = ( TestRunStats
const& ) =
default;
5254 TestRunStats& operator = ( TestRunStats && ) =
default;
5257 TestRunInfo runInfo;
5262 class MultipleReporters;
5264 struct IStreamingReporter : IShared {
5265 virtual ~IStreamingReporter();
5270 virtual ReporterPreferences getPreferences()
const = 0;
5272 virtual void noMatchingTestCases( std::string
const& spec ) = 0;
5274 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
5275 virtual void testGroupStarting(
GroupInfo const& groupInfo ) = 0;
5277 virtual void testCaseStarting( TestCaseInfo
const&
testInfo ) = 0;
5278 virtual void sectionStarting( SectionInfo
const& sectionInfo ) = 0;
5280 virtual void assertionStarting( AssertionInfo
const& assertionInfo ) = 0;
5283 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
5285 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
5286 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
5287 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
5288 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
5290 virtual void skipTest( TestCaseInfo
const&
testInfo ) = 0;
5292 virtual MultipleReporters* tryAsMulti() {
return CATCH_NULL; }
5295 struct IReporterFactory : IShared {
5296 virtual ~IReporterFactory();
5297 virtual IStreamingReporter* create( ReporterConfig
const&
config )
const = 0;
5298 virtual std::string getDescription()
const = 0;
5301 struct IReporterRegistry {
5302 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5303 typedef std::vector<Ptr<IReporterFactory> > Listeners;
5305 virtual ~IReporterRegistry();
5306 virtual IStreamingReporter* create( std::string
const& name, Ptr<IConfig const>
const&
config )
const = 0;
5307 virtual FactoryMap
const& getFactories()
const = 0;
5308 virtual Listeners
const& getListeners()
const = 0;
5311 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter>
const& existingReporter, Ptr<IStreamingReporter>
const& additionalReporter );
5316 #include <algorithm>
5320 inline std::size_t listTests( Config
const&
config ) {
5322 TestSpec testSpec =
config.testSpec();
5323 if(
config.testSpec().hasFilters() )
5324 Catch::cout() <<
"Matching test cases:\n";
5326 Catch::cout() <<
"All available test cases:\n";
5330 std::size_t matchedTests = 0;
5331 TextAttributes nameAttr, tagsAttr;
5332 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5333 tagsAttr.setIndent( 6 );
5336 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5340 TestCaseInfo
const& testCaseInfo = it->getTestCaseInfo();
5341 Colour::Code colour = testCaseInfo.isHidden()
5342 ? Colour::SecondaryText
5344 Colour colourGuard( colour );
5346 Catch::cout() <<
Text( testCaseInfo.name, nameAttr ) << std::endl;
5347 if( !testCaseInfo.tags.empty() )
5348 Catch::cout() <<
Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
5351 if( !
config.testSpec().hasFilters() )
5352 Catch::cout() << pluralise( matchedTests,
"test case" ) <<
"\n" << std::endl;
5354 Catch::cout() << pluralise( matchedTests,
"matching test case" ) <<
"\n" << std::endl;
5355 return matchedTests;
5358 inline std::size_t listTestsNamesOnly( Config
const&
config ) {
5359 TestSpec testSpec =
config.testSpec();
5360 if( !
config.testSpec().hasFilters() )
5362 std::size_t matchedTests = 0;
5364 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5368 TestCaseInfo
const& testCaseInfo = it->getTestCaseInfo();
5369 Catch::cout() << testCaseInfo.name << std::endl;
5371 return matchedTests;
5375 TagInfo() : count ( 0 ) {}
5376 void add( std::string
const& spelling ) {
5378 spellings.insert( spelling );
5380 std::string all()
const {
5382 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5385 out += "[" + *it + "]";
5388 std::set<std::string> spellings;
5392 inline std::size_t listTags( Config
const&
config ) {
5393 TestSpec testSpec =
config.testSpec();
5394 if(
config.testSpec().hasFilters() )
5395 Catch::cout() <<
"Tags for matching test cases:\n";
5397 Catch::cout() <<
"All available tags:\n";
5401 std::map<std::string, TagInfo> tagCounts;
5404 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5407 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5408 tagItEnd = it->getTestCaseInfo().tags.end();
5411 std::string tagName = *tagIt;
5412 std::string lcaseTagName =
toLower( tagName );
5413 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
5414 if( countIt == tagCounts.end() )
5415 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5416 countIt->second.add( tagName );
5420 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5421 countItEnd = tagCounts.end();
5422 countIt != countItEnd;
5424 std::ostringstream oss;
5425 oss <<
" " << std::setw(2) << countIt->second.count <<
" ";
5426 Text wrapper( countIt->second.all(), TextAttributes()
5427 .setInitialIndent( 0 )
5428 .setIndent( oss.str().size() )
5429 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
5430 Catch::cout() << oss.str() << wrapper <<
"\n";
5432 Catch::cout() << pluralise( tagCounts.size(),
"tag" ) <<
"\n" << std::endl;
5433 return tagCounts.size();
5436 inline std::size_t listReporters( Config
const& ) {
5437 Catch::cout() <<
"Available reporters:\n";
5439 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5440 std::size_t maxNameLen = 0;
5441 for(it = itBegin; it != itEnd; ++it )
5442 maxNameLen = (
std::max)( maxNameLen, it->first.
size() );
5444 for(it = itBegin; it != itEnd; ++it ) {
5445 Text wrapper( it->second->getDescription(), TextAttributes()
5446 .setInitialIndent( 0 )
5447 .setIndent( 7+maxNameLen )
5448 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
5449 Catch::cout() <<
" "
5452 << std::string( maxNameLen - it->first.size() + 2,
' ' )
5455 Catch::cout() << std::endl;
5456 return factories.size();
5459 inline Option<std::size_t> list( Config
const&
config ) {
5460 Option<std::size_t> listedCount;
5462 listedCount = listedCount.valueOr(0) + listTests(
config );
5463 if(
config.listTestNamesOnly() )
5464 listedCount = listedCount.valueOr(0) + listTestsNamesOnly(
config );
5466 listedCount = listedCount.valueOr(0) + listTags(
config );
5467 if(
config.listReporters() )
5468 listedCount = listedCount.valueOr(0) + listReporters(
config );
5475 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
5478 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
5486 namespace TestCaseTracking {
5488 struct ITracker : SharedImpl<> {
5489 virtual ~ITracker();
5492 virtual std::string name()
const = 0;
5495 virtual bool isComplete()
const = 0;
5496 virtual bool isSuccessfullyCompleted()
const = 0;
5497 virtual bool isOpen()
const = 0;
5498 virtual bool hasChildren()
const = 0;
5500 virtual ITracker& parent() = 0;
5503 virtual void close() = 0;
5504 virtual void fail() = 0;
5505 virtual void markAsNeedingAnotherRun() = 0;
5507 virtual void addChild( Ptr<ITracker>
const& child ) = 0;
5508 virtual ITracker* findChild( std::string
const& name ) = 0;
5509 virtual void openChild() = 0;
5512 virtual bool isSectionTracker()
const = 0;
5513 virtual bool isIndexTracker()
const = 0;
5516 class TrackerContext {
5524 Ptr<ITracker> m_rootTracker;
5525 ITracker* m_currentTracker;
5526 RunState m_runState;
5530 static TrackerContext& instance() {
5531 static TrackerContext s_instance;
5537 m_runState( NotStarted )
5540 ITracker& startRun();
5543 m_rootTracker.reset();
5545 m_runState = NotStarted;
5549 m_currentTracker = m_rootTracker.get();
5550 m_runState = Executing;
5552 void completeCycle() {
5553 m_runState = CompletedCycle;
5556 bool completedCycle()
const {
5557 return m_runState == CompletedCycle;
5559 ITracker& currentTracker() {
5560 return *m_currentTracker;
5562 void setCurrentTracker( ITracker* tracker ) {
5563 m_currentTracker = tracker;
5567 class TrackerBase :
public ITracker {
5574 CompletedSuccessfully,
5577 class TrackerHasName {
5580 TrackerHasName( std::string
const& name ) : m_name( name ) {}
5581 bool operator ()( Ptr<ITracker>
const& tracker ) {
5582 return tracker->name() == m_name;
5585 typedef std::vector<Ptr<ITracker> > Children;
5587 TrackerContext& m_ctx;
5589 Children m_children;
5590 CycleState m_runState;
5592 TrackerBase( std::string
const& name, TrackerContext& ctx, ITracker* parent )
5596 m_runState( NotStarted )
5598 virtual ~TrackerBase();
5604 return m_runState == CompletedSuccessfully || m_runState == Failed;
5607 return m_runState == CompletedSuccessfully;
5610 return m_runState != NotStarted && !isComplete();
5613 return !m_children.empty();
5616 virtual void addChild( Ptr<ITracker>
const& child )
CATCH_OVERRIDE {
5617 m_children.push_back( child );
5620 virtual ITracker* findChild( std::string
const& name )
CATCH_OVERRIDE {
5621 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) );
5622 return( it != m_children.end() )
5632 if( m_runState != ExecutingChildren ) {
5633 m_runState = ExecutingChildren;
5635 m_parent->openChild();
5639 virtual bool isSectionTracker() const
CATCH_OVERRIDE {
return false; }
5640 virtual bool isIndexTracker() const
CATCH_OVERRIDE {
return false; }
5643 m_runState = Executing;
5646 m_parent->openChild();
5652 while( &m_ctx.currentTracker() !=
this )
5653 m_ctx.currentTracker().close();
5655 switch( m_runState ) {
5657 case CompletedSuccessfully:
5659 throw std::logic_error(
"Illogical state" );
5661 case NeedsAnotherRun:
5665 m_runState = CompletedSuccessfully;
5667 case ExecutingChildren:
5668 if( m_children.empty() || m_children.back()->isComplete() )
5669 m_runState = CompletedSuccessfully;
5673 throw std::logic_error(
"Unexpected state" );
5676 m_ctx.completeCycle();
5679 m_runState = Failed;
5681 m_parent->markAsNeedingAnotherRun();
5683 m_ctx.completeCycle();
5686 m_runState = NeedsAnotherRun;
5689 void moveToParent() {
5691 m_ctx.setCurrentTracker( m_parent );
5694 m_ctx.setCurrentTracker(
this );
5698 class SectionTracker :
public TrackerBase {
5700 SectionTracker( std::string
const& name, TrackerContext& ctx, ITracker* parent )
5701 : TrackerBase( name, ctx, parent )
5703 virtual ~SectionTracker();
5705 virtual bool isSectionTracker() const
CATCH_OVERRIDE {
return true; }
5707 static SectionTracker& acquire( TrackerContext& ctx, std::string
const& name ) {
5710 ITracker& currentTracker = ctx.currentTracker();
5711 if( ITracker* childTracker = currentTracker.findChild( name ) ) {
5712 assert( childTracker );
5713 assert( childTracker->isSectionTracker() );
5714 section =
static_cast<SectionTracker*
>( childTracker );
5717 section =
new SectionTracker( name, ctx, ¤tTracker );
5718 currentTracker.addChild( section );
5720 if( !ctx.completedCycle() && !section->isComplete() ) {
5728 class IndexTracker :
public TrackerBase {
5732 IndexTracker( std::string
const& name, TrackerContext& ctx, ITracker* parent,
int size )
5733 : TrackerBase( name, ctx, parent ),
5737 virtual ~IndexTracker();
5739 virtual bool isIndexTracker() const
CATCH_OVERRIDE {
return true; }
5741 static IndexTracker& acquire( TrackerContext& ctx, std::string
const& name,
int size ) {
5744 ITracker& currentTracker = ctx.currentTracker();
5745 if( ITracker* childTracker = currentTracker.findChild( name ) ) {
5746 assert( childTracker );
5747 assert( childTracker->isIndexTracker() );
5748 tracker =
static_cast<IndexTracker*
>( childTracker );
5751 tracker =
new IndexTracker( name, ctx, ¤tTracker,
size );
5752 currentTracker.addChild( tracker );
5755 if( !ctx.completedCycle() && !tracker->isComplete() ) {
5756 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
5757 tracker->moveNext();
5764 int index()
const {
return m_index; }
5773 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
5774 m_runState = Executing;
5778 inline ITracker& TrackerContext::startRun() {
5779 m_rootTracker =
new SectionTracker(
"{root}", *
this,
CATCH_NULL );
5781 m_runState = Executing;
5782 return *m_rootTracker;
5787 using TestCaseTracking::ITracker;
5788 using TestCaseTracking::TrackerContext;
5789 using TestCaseTracking::SectionTracker;
5790 using TestCaseTracking::IndexTracker;
5795 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
5800 inline void fatal( std::string
const& message,
int exitCode ) {
5802 IResultCapture* resultCapture = context.getResultCapture();
5803 resultCapture->handleFatalErrorCondition( message );
5811 #if defined ( CATCH_PLATFORM_WINDOWS )
5815 struct FatalConditionHandler {
5827 struct SignalDefs {
int id;
const char* name; };
5828 extern SignalDefs signalDefs[];
5829 SignalDefs signalDefs[] = {
5830 { SIGINT,
"SIGINT - Terminal interrupt signal" },
5831 { SIGILL,
"SIGILL - Illegal instruction signal" },
5832 { SIGFPE,
"SIGFPE - Floating point error signal" },
5833 { SIGSEGV,
"SIGSEGV - Segmentation violation signal" },
5834 { SIGTERM,
"SIGTERM - Termination request signal" },
5835 { SIGABRT,
"SIGABRT - Abort (abnormal termination) signal" }
5838 struct FatalConditionHandler {
5840 static void handleSignal(
int sig ) {
5841 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i )
5842 if( sig == signalDefs[i].
id )
5843 fatal( signalDefs[i].name, -sig );
5844 fatal(
"<unknown signal>", -sig );
5847 FatalConditionHandler() : m_isSet( true ) {
5848 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i )
5849 signal( signalDefs[i].id, handleSignal );
5851 ~FatalConditionHandler() {
5856 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i )
5857 signal( signalDefs[i].id, SIG_DFL );
5874 class StreamRedirect {
5877 StreamRedirect( std::ostream& stream, std::string& targetString )
5878 : m_stream( stream ),
5879 m_prevBuf( stream.rdbuf() ),
5880 m_targetString( targetString )
5882 stream.rdbuf( m_oss.rdbuf() );
5886 m_targetString += m_oss.str();
5887 m_stream.rdbuf( m_prevBuf );
5891 std::ostream& m_stream;
5892 std::streambuf* m_prevBuf;
5893 std::ostringstream m_oss;
5894 std::string& m_targetString;
5899 class RunContext :
public IResultCapture,
public IRunner {
5901 RunContext( RunContext
const& );
5902 void operator =( RunContext
const& );
5906 explicit RunContext( Ptr<IConfig const>
const& _config, Ptr<IStreamingReporter>
const& reporter )
5907 : m_runInfo( _config->name() ),
5910 m_config( _config ),
5911 m_reporter( reporter )
5913 m_context.setRunner(
this );
5914 m_context.setConfig( m_config );
5915 m_context.setResultCapture(
this );
5916 m_reporter->testRunStarting( m_runInfo );
5919 virtual ~RunContext() {
5920 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
5923 void testGroupStarting( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
5924 m_reporter->testGroupStarting(
GroupInfo( testSpec, groupIndex, groupsCount ) );
5926 void testGroupEnded( std::string
const& testSpec, Totals
const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
5927 m_reporter->testGroupEnded( TestGroupStats(
GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
5930 Totals runTest( TestCase
const& testCase ) {
5931 Totals prevTotals = m_totals;
5933 std::string redirectedCout;
5934 std::string redirectedCerr;
5936 TestCaseInfo
testInfo = testCase.getTestCaseInfo();
5938 m_reporter->testCaseStarting(
testInfo );
5940 m_activeTestCase = &testCase;
5943 m_trackerContext.startRun();
5945 m_trackerContext.startCycle();
5946 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext,
testInfo.name );
5947 runCurrentTest( redirectedCout, redirectedCerr );
5949 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
5954 Totals deltaTotals = m_totals.delta( prevTotals );
5955 if(
testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
5956 deltaTotals.assertions.failed++;
5957 deltaTotals.testCases.passed--;
5958 deltaTotals.testCases.failed++;
5960 m_totals.testCases += deltaTotals.testCases;
5961 m_reporter->testCaseEnded( TestCaseStats(
testInfo,
5973 Ptr<IConfig const>
config()
const {
5979 virtual void assertionEnded( AssertionResult
const& result ) {
5981 m_totals.assertions.passed++;
5983 else if( !result.isOk() ) {
5984 m_totals.assertions.failed++;
5987 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
5991 m_lastAssertionInfo = AssertionInfo(
"", m_lastAssertionInfo.lineInfo,
"{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
5992 m_lastResult = result;
5995 virtual bool sectionStarted (
5996 SectionInfo
const& sectionInfo,
6000 std::ostringstream oss;
6001 oss << sectionInfo.name <<
"@" << sectionInfo.lineInfo;
6003 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() );
6004 if( !sectionTracker.isOpen() )
6006 m_activeSections.push_back( §ionTracker );
6008 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
6010 m_reporter->sectionStarting( sectionInfo );
6012 assertions = m_totals.assertions;
6016 bool testForMissingAssertions( Counts& assertions ) {
6017 if( assertions.total() != 0 )
6019 if( !m_config->warnAboutMissingAssertions() )
6021 if( m_trackerContext.currentTracker().hasChildren() )
6023 m_totals.assertions.failed++;
6024 assertions.failed++;
6028 virtual void sectionEnded( SectionEndInfo
const& endInfo ) {
6029 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
6030 bool missingAssertions = testForMissingAssertions( assertions );
6032 if( !m_activeSections.empty() ) {
6033 m_activeSections.back()->close();
6034 m_activeSections.pop_back();
6037 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
6041 virtual void sectionEndedEarly( SectionEndInfo
const& endInfo ) {
6042 if( m_unfinishedSections.empty() )
6043 m_activeSections.back()->fail();
6045 m_activeSections.back()->close();
6046 m_activeSections.pop_back();
6048 m_unfinishedSections.push_back( endInfo );
6051 virtual void pushScopedMessage( MessageInfo
const& message ) {
6052 m_messages.push_back( message );
6055 virtual void popScopedMessage( MessageInfo
const& message ) {
6056 m_messages.erase(
std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
6059 virtual std::string getCurrentTestName()
const {
6060 return m_activeTestCase
6061 ? m_activeTestCase->getTestCaseInfo().name
6065 virtual const AssertionResult* getLastResult()
const {
6066 return &m_lastResult;
6069 virtual void handleFatalErrorCondition( std::string
const& message ) {
6070 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
6072 resultBuilder << message;
6074 #ifdef HAVE_EXECINFO
6077 const int size =
static_cast<int>(backtrace(array, 15));
6078 char **strings = backtrace_symbols(array,
size);
6079 for (
int i = 0; i <
size; i++)
6080 resultBuilder << strings[i];
6086 resultBuilder.captureExpression();
6088 handleUnfinishedSections();
6091 TestCaseInfo
const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6092 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6095 assertions.failed = 1;
6096 SectionStats testCaseSectionStats( testCaseSection, assertions, 0,
false );
6097 m_reporter->sectionEnded( testCaseSectionStats );
6099 TestCaseInfo
testInfo = m_activeTestCase->getTestCaseInfo();
6102 deltaTotals.testCases.failed = 1;
6103 m_reporter->testCaseEnded( TestCaseStats(
testInfo,
6108 m_totals.testCases.failed++;
6109 testGroupEnded(
"", m_totals, 1, 1 );
6110 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals,
false ) );
6115 bool aborting()
const {
6116 return m_totals.assertions.failed ==
static_cast<std::size_t
>( m_config->abortAfter() );
6121 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
6122 TestCaseInfo
const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6123 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6124 m_reporter->sectionStarting( testCaseSection );
6125 Counts prevAssertions = m_totals.assertions;
6126 double duration = 0;
6134 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
6135 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
6136 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
6137 invokeActiveTestCase();
6140 invokeActiveTestCase();
6142 duration = timer.getElapsedSeconds();
6144 catch( TestFailureException& ) {
6148 makeUnexpectedResultBuilder().useActiveException();
6150 m_testCaseTracker->close();
6151 handleUnfinishedSections();
6154 Counts assertions = m_totals.assertions - prevAssertions;
6155 bool missingAssertions = testForMissingAssertions( assertions );
6157 if( testCaseInfo.okToFail() ) {
6158 std::swap( assertions.failedButOk, assertions.failed );
6159 m_totals.assertions.failed -= assertions.failedButOk;
6160 m_totals.assertions.failedButOk += assertions.failedButOk;
6163 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
6164 m_reporter->sectionEnded( testCaseSectionStats );
6167 void invokeActiveTestCase() {
6168 FatalConditionHandler fatalConditionHandler;
6169 m_activeTestCase->invoke();
6170 fatalConditionHandler.reset();
6175 ResultBuilder makeUnexpectedResultBuilder()
const {
6176 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
6177 m_lastAssertionInfo.lineInfo,
6178 m_lastAssertionInfo.capturedExpression.c_str(),
6179 m_lastAssertionInfo.resultDisposition );
6182 void handleUnfinishedSections() {
6185 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
6186 itEnd = m_unfinishedSections.rend();
6189 sectionEnded( *it );
6190 m_unfinishedSections.clear();
6193 TestRunInfo m_runInfo;
6194 IMutableContext& m_context;
6195 TestCase
const* m_activeTestCase;
6196 ITracker* m_testCaseTracker;
6197 ITracker* m_currentSectionTracker;
6198 AssertionResult m_lastResult;
6200 Ptr<IConfig const> m_config;
6202 Ptr<IStreamingReporter> m_reporter;
6203 std::vector<MessageInfo> m_messages;
6204 AssertionInfo m_lastAssertionInfo;
6205 std::vector<SectionEndInfo> m_unfinishedSections;
6206 std::vector<ITracker*> m_activeSections;
6207 TrackerContext m_trackerContext;
6214 throw std::logic_error(
"No result capture instance" );
6220 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6226 Version(
unsigned int _majorVersion,
6227 unsigned int _minorVersion,
6228 unsigned int _patchNumber,
6229 std::string
const& _branchName,
6230 unsigned int _buildNumber );
6232 unsigned int const majorVersion;
6233 unsigned int const minorVersion;
6234 unsigned int const patchNumber;
6237 std::string
const branchName;
6238 unsigned int const buildNumber;
6240 friend std::ostream&
operator << ( std::ostream& os, Version
const& version );
6243 void operator=( Version
const& );
6246 extern Version libraryVersion;
6255 Ptr<IStreamingReporter> createReporter( std::string
const& reporterName, Ptr<Config>
const&
config ) {
6258 std::ostringstream oss;
6259 oss <<
"No reporter registered with name: '" << reporterName <<
"'";
6260 throw std::domain_error( oss.str() );
6265 Ptr<IStreamingReporter> makeReporter( Ptr<Config>
const&
config ) {
6266 std::vector<std::string> reporters =
config->getReporterNames();
6267 if( reporters.empty() )
6268 reporters.push_back(
"console" );
6270 Ptr<IStreamingReporter> reporter;
6271 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
6274 reporter = addReporter( reporter, createReporter( *it,
config ) );
6277 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const>
const&
config, Ptr<IStreamingReporter> reporters ) {
6279 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6282 reporters = addReporter(reporters, (*it)->create( ReporterConfig(
config ) ) );
6286 Totals runTests( Ptr<Config>
const&
config ) {
6288 Ptr<IConfig const> iconfig =
config.get();
6290 Ptr<IStreamingReporter> reporter = makeReporter(
config );
6291 reporter = addListeners( iconfig, reporter );
6293 RunContext context( iconfig, reporter );
6297 context.testGroupStarting(
config->name(), 1, 1 );
6299 TestSpec testSpec =
config->testSpec();
6300 if( !testSpec.hasFilters() )
6304 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
6307 if( !context.aborting() &&
matchTest( *it, testSpec, *iconfig ) )
6308 totals += context.runTest( *it );
6310 reporter->skipTest( *it );
6313 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
6317 void applyFilenamesAsTags( IConfig
const&
config ) {
6319 for(std::size_t i = 0; i < tests.size(); ++i ) {
6320 TestCase& test =
const_cast<TestCase&
>( tests[i] );
6321 std::set<std::string> tags = test.tags;
6323 std::string filename = test.lineInfo.file;
6324 std::string::size_type lastSlash = filename.find_last_of(
"\\/" );
6325 if( lastSlash != std::string::npos )
6326 filename = filename.substr( lastSlash+1 );
6328 std::string::size_type lastDot = filename.find_last_of(
"." );
6329 if( lastDot != std::string::npos )
6330 filename = filename.substr( 0, lastDot );
6332 tags.insert(
"#" + filename );
6333 setTags( test, tags );
6337 class Session : NonCopyable {
6338 static bool alreadyInstantiated;
6342 struct OnUnusedOptions {
enum DoWhat { Ignore, Fail }; };
6345 : m_cli( makeCommandLineParser() ) {
6346 if( alreadyInstantiated ) {
6347 std::string
msg =
"Only one instance of Catch::Session can ever be used";
6348 Catch::cerr() <<
msg << std::endl;
6349 throw std::logic_error(
msg );
6351 alreadyInstantiated =
true;
6357 void showHelp( std::string
const& processName ) {
6358 Catch::cout() <<
"\nCatch v" << libraryVersion <<
"\n";
6360 m_cli.usage( Catch::cout(), processName );
6361 Catch::cout() <<
"For more detail usage please see the project docs\n" << std::endl;
6364 int applyCommandLine(
int argc,
char const*
const*
const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
6366 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
6367 m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
6368 if( m_configData.showHelp )
6369 showHelp( m_configData.processName );
6372 catch( std::exception& ex ) {
6376 <<
"\nError(s) in input:\n"
6377 <<
Text( ex.what(), TextAttributes().setIndent(2) )
6380 m_cli.usage( Catch::cout(), m_configData.processName );
6381 return (std::numeric_limits<int>::max)();
6386 void useConfigData( ConfigData
const& _configData ) {
6387 m_configData = _configData;
6391 int run(
int argc,
char const*
const*
const argv ) {
6393 int returnCode = applyCommandLine( argc, argv );
6394 if( returnCode == 0 )
6400 if( m_configData.showHelp )
6409 if( m_configData.filenamesAsTags )
6410 applyFilenamesAsTags( *m_config );
6413 if( Option<std::size_t> listed = list(
config() ) )
6414 return static_cast<int>( *listed );
6416 return static_cast<int>( runTests( m_config ).assertions.failed );
6418 catch( std::exception& ex ) {
6419 Catch::cerr() << ex.what() << std::endl;
6420 return (std::numeric_limits<int>::max)();
6424 Clara::CommandLine<ConfigData>
const& cli()
const {
6427 std::vector<Clara::Parser::Token>
const& unusedTokens()
const {
6428 return m_unusedTokens;
6430 ConfigData& configData() {
6431 return m_configData;
6435 m_config =
new Config( m_configData );
6439 Clara::CommandLine<ConfigData> m_cli;
6440 std::vector<Clara::Parser::Token> m_unusedTokens;
6441 ConfigData m_configData;
6442 Ptr<Config> m_config;
6445 bool Session::alreadyInstantiated =
false;
6450 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
6453 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
6459 #include <algorithm>
6464 bool operator() (TestCase i,TestCase j)
const {
return (i<j);}
6466 struct RandomNumberGenerator {
6467 int operator()(
int n )
const {
return std::rand() % n; }
6470 inline std::vector<TestCase> sortTests( IConfig
const&
config, std::vector<TestCase>
const& unsortedTestCases ) {
6472 std::vector<TestCase> sorted = unsortedTestCases;
6474 switch(
config.runOrder() ) {
6475 case RunTests::InLexicographicalOrder:
6476 std::sort( sorted.begin(), sorted.end(), LexSort() );
6478 case RunTests::InRandomOrder:
6482 RandomNumberGenerator rng;
6483 std::random_shuffle( sorted.begin(), sorted.end(), rng );
6486 case RunTests::InDeclarationOrder:
6492 bool matchTest( TestCase
const& testCase, TestSpec
const& testSpec, IConfig
const&
config ) {
6493 return testSpec.matches( testCase ) && (
config.allowThrows() || !testCase.throws() );
6496 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions ) {
6497 std::set<TestCase> seenFunctions;
6498 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
6501 std::pair<std::set<TestCase>::const_iterator,
bool> prev = seenFunctions.insert( *it );
6505 <<
"error: TEST_CASE( \"" << it->name <<
"\" ) already defined.\n"
6506 <<
"\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo <<
"\n"
6507 <<
"\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
6513 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const&
config ) {
6514 std::vector<TestCase> filtered;
6515 filtered.reserve( testCases.size() );
6516 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
6520 filtered.push_back( *it );
6527 class TestRegistry :
public ITestCaseRegistry {
6530 : m_currentSortOrder( RunTests::InDeclarationOrder ),
6533 virtual ~TestRegistry();
6535 virtual void registerTest( TestCase
const& testCase ) {
6536 std::string name = testCase.getTestCaseInfo().name;
6538 std::ostringstream oss;
6539 oss <<
"Anonymous test case " << ++m_unnamedCount;
6540 return registerTest( testCase.withName( oss.str() ) );
6542 m_functions.push_back( testCase );
6545 virtual std::vector<TestCase>
const& getAllTests()
const {
6548 virtual std::vector<TestCase>
const& getAllTestsSorted( IConfig
const&
config )
const {
6549 if( m_sortedFunctions.empty() )
6550 enforceNoDuplicateTestCases( m_functions );
6552 if( m_currentSortOrder !=
config.runOrder() || m_sortedFunctions.empty() ) {
6553 m_sortedFunctions = sortTests(
config, m_functions );
6554 m_currentSortOrder =
config.runOrder();
6556 return m_sortedFunctions;
6560 std::vector<TestCase> m_functions;
6561 mutable RunTests::InWhatOrder m_currentSortOrder;
6562 mutable std::vector<TestCase> m_sortedFunctions;
6563 size_t m_unnamedCount;
6564 std::ios_base::Init m_ostreamInit;
6569 class FreeFunctionTestCase :
public SharedImpl<ITestCase> {
6572 FreeFunctionTestCase(
TestFunction fun ) : m_fun( fun ) {}
6574 virtual void invoke()
const {
6579 virtual ~FreeFunctionTestCase();
6584 inline std::string extractClassName( std::string
const& classOrQualifiedMethodName ) {
6585 std::string className = classOrQualifiedMethodName;
6588 std::size_t lastColons = className.rfind(
"::" );
6589 std::size_t penultimateColons = className.rfind(
"::", lastColons-1 );
6590 if( penultimateColons == std::string::npos )
6591 penultimateColons = 1;
6592 className = className.substr( penultimateColons, lastColons-penultimateColons );
6598 ( ITestCase* testCase,
6599 char const* classOrQualifiedMethodName,
6600 NameAndDesc
const& nameAndDesc,
6601 SourceLineInfo
const& lineInfo ) {
6606 extractClassName( classOrQualifiedMethodName ),
6608 nameAndDesc.description,
6613 SourceLineInfo
const& lineInfo,
6614 NameAndDesc
const& nameAndDesc ) {
6615 registerTestCase(
new FreeFunctionTestCase(
function ),
"", nameAndDesc, lineInfo );
6622 SourceLineInfo
const& lineInfo,
6623 NameAndDesc
const& nameAndDesc ) {
6632 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
6638 class ReporterRegistry :
public IReporterRegistry {
6644 virtual IStreamingReporter* create( std::string
const& name, Ptr<IConfig const>
const&
config )
const CATCH_OVERRIDE {
6645 FactoryMap::const_iterator it = m_factories.find( name );
6646 if( it == m_factories.end() )
6648 return it->second->create( ReporterConfig(
config ) );
6651 void registerReporter( std::string
const& name, Ptr<IReporterFactory>
const& factory ) {
6652 m_factories.insert( std::make_pair( name, factory ) );
6654 void registerListener( Ptr<IReporterFactory>
const& factory ) {
6655 m_listeners.push_back( factory );
6666 FactoryMap m_factories;
6667 Listeners m_listeners;
6672 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
6675 #import "Foundation/Foundation.h"
6680 class ExceptionTranslatorRegistry :
public IExceptionTranslatorRegistry {
6682 ~ExceptionTranslatorRegistry() {
6686 virtual void registerTranslator(
const IExceptionTranslator*
translator ) {
6695 return tryTranslators();
6697 @catch (NSException *exception) {
6701 return tryTranslators();
6704 catch( TestFailureException& ) {
6707 catch( std::exception& ex ) {
6710 catch( std::string&
msg ) {
6713 catch(
const char*
msg ) {
6717 return "Unknown exception";
6721 std::string tryTranslators()
const {
6722 if( m_translators.empty() )
6725 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
6729 std::vector<const IExceptionTranslator*> m_translators;
6737 class RegistryHub :
public IRegistryHub,
public IMutableRegistryHub {
6739 RegistryHub( RegistryHub
const& );
6740 void operator=( RegistryHub
const& );
6745 virtual IReporterRegistry
const& getReporterRegistry() const
CATCH_OVERRIDE {
6746 return m_reporterRegistry;
6748 virtual ITestCaseRegistry
const& getTestCaseRegistry() const
CATCH_OVERRIDE {
6749 return m_testCaseRegistry;
6751 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry()
CATCH_OVERRIDE {
6752 return m_exceptionTranslatorRegistry;
6757 m_reporterRegistry.registerReporter( name, factory );
6759 virtual void registerListener( Ptr<IReporterFactory>
const& factory )
CATCH_OVERRIDE {
6760 m_reporterRegistry.registerListener( factory );
6763 m_testCaseRegistry.registerTest(
testInfo );
6766 m_exceptionTranslatorRegistry.registerTranslator(
translator );
6770 TestRegistry m_testCaseRegistry;
6771 ReporterRegistry m_reporterRegistry;
6772 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
6776 inline RegistryHub*& getTheRegistryHub() {
6777 static RegistryHub* theRegistryHub =
CATCH_NULL;
6778 if( !theRegistryHub )
6779 theRegistryHub =
new RegistryHub();
6780 return theRegistryHub;
6785 return *getTheRegistryHub();
6788 return *getTheRegistryHub();
6791 delete getTheRegistryHub();
6802 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
6809 : m_lineInfo( lineInfo ) {
6810 std::ostringstream oss;
6811 oss << lineInfo <<
": function ";
6812 oss <<
"not implemented";
6816 const char* NotImplementedException::what() const
CATCH_NOEXCEPT {
6817 return m_what.c_str();
6823 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
6826 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
6828 #include <stdexcept>
6834 template<
typename WriterF,
size_t bufferSize=256>
6835 class StreamBufImpl :
public StreamBufBase {
6836 char data[bufferSize];
6849 int overflow(
int c ) {
6853 if( pbase() == epptr() )
6854 m_writer( std::string( 1,
static_cast<char>( c ) ) );
6856 sputc(
static_cast<char>( c ) );
6862 if( pbase() != pptr() ) {
6863 m_writer( std::string( pbase(),
static_cast<std::string::size_type
>( pptr() - pbase() ) ) );
6864 setp( pbase(), epptr() );
6872 FileStream::FileStream( std::string
const& filename ) {
6873 m_ofs.open( filename.c_str() );
6874 if( m_ofs.fail() ) {
6875 std::ostringstream oss;
6876 oss <<
"Unable to open file: '" << filename <<
"'";
6877 throw std::domain_error( oss.str() );
6881 std::ostream& FileStream::stream()
const {
6885 struct OutputDebugWriter {
6887 void operator()( std::string
const&str ) {
6892 DebugOutStream::DebugOutStream()
6893 : m_streamBuf(
new StreamBufImpl<OutputDebugWriter>() ),
6894 m_os( m_streamBuf.
get() )
6897 std::ostream& DebugOutStream::stream()
const {
6903 CoutStream::CoutStream()
6904 : m_os(
Catch::cout().rdbuf() )
6907 std::ostream& CoutStream::stream()
const {
6911 #ifndef CATCH_CONFIG_NOSTDOUT
6912 std::ostream& cout() {
6915 std::ostream& cerr() {
6923 class Context :
public IMutableContext {
6926 Context( Context
const& );
6927 void operator=( Context
const& );
6931 return m_resultCapture;
6933 virtual IRunner* getRunner() {
6936 virtual size_t getGeneratorIndex( std::string
const& fileInfo,
size_t totalSize ) {
6937 return getGeneratorsForCurrentTest()
6938 .getGeneratorInfo( fileInfo, totalSize )
6941 virtual bool advanceGeneratorsForCurrentTest() {
6942 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6943 return generators && generators->moveNext();
6946 virtual Ptr<IConfig const> getConfig()
const {
6951 virtual void setResultCapture( IResultCapture* resultCapture ) {
6952 m_resultCapture = resultCapture;
6954 virtual void setRunner( IRunner* runner ) {
6957 virtual void setConfig( Ptr<IConfig const>
const&
config ) {
6964 IGeneratorsForTest* findGeneratorsForCurrentTest() {
6967 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
6968 m_generatorsByTestName.find( testName );
6969 return it != m_generatorsByTestName.end()
6974 IGeneratorsForTest& getGeneratorsForCurrentTest() {
6975 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6979 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
6985 Ptr<IConfig const> m_config;
6987 IResultCapture* m_resultCapture;
6988 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
6995 if( !currentContext )
6996 currentContext =
new Context();
6997 return *currentContext;
7004 delete currentContext;
7010 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
7015 struct IColourImpl {
7016 virtual ~IColourImpl() {}
7017 virtual void use( Colour::Code _colourCode ) = 0;
7020 struct NoColourImpl : IColourImpl {
7021 void use( Colour::Code ) {}
7023 static IColourImpl* instance() {
7024 static NoColourImpl s_instance;
7032 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
7033 # ifdef CATCH_PLATFORM_WINDOWS
7034 # define CATCH_CONFIG_COLOUR_WINDOWS
7036 # define CATCH_CONFIG_COLOUR_ANSI
7040 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS )
7049 #include <windows.h>
7055 class Win32ColourImpl :
public IColourImpl {
7057 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
7059 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7060 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
7061 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
7062 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
7065 virtual void use( Colour::Code _colourCode ) {
7066 switch( _colourCode ) {
7067 case Colour::None:
return setTextAttribute( originalForegroundAttributes );
7068 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7069 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
7070 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
7071 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
7072 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
7073 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
7077 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
7078 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
7079 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7086 void setTextAttribute( WORD _textAttribute ) {
7087 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
7089 HANDLE stdoutHandle;
7090 WORD originalForegroundAttributes;
7091 WORD originalBackgroundAttributes;
7094 IColourImpl* platformColourInstance() {
7095 static Win32ColourImpl s_instance;
7098 UseColour::YesOrNo colourMode =
config
7101 if( colourMode == UseColour::Auto )
7105 return colourMode == UseColour::Yes
7107 : NoColourImpl::instance();
7113 #elif defined( CATCH_CONFIG_COLOUR_ANSI )
7124 class PosixColourImpl :
public IColourImpl {
7126 virtual void use( Colour::Code _colourCode ) {
7127 switch( _colourCode ) {
7145 static IColourImpl* instance() {
7146 static PosixColourImpl s_instance;
7151 void setColour(
const char* _escapeCode ) {
7152 Catch::cout() <<
'\033' << _escapeCode;
7156 IColourImpl* platformColourInstance() {
7158 UseColour::YesOrNo colourMode =
config
7161 if( colourMode == UseColour::Auto )
7165 return colourMode == UseColour::Yes
7166 ? PosixColourImpl::instance()
7167 : NoColourImpl::instance();
7177 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
7185 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
7186 Colour::Colour( Colour
const& _other ) : m_moved( false ) {
const_cast<Colour&
>( _other ).m_moved =
true; }
7187 Colour::~Colour(){
if( !m_moved ) use(
None ); }
7189 void Colour::use( Code _colourCode ) {
7190 static IColourImpl* impl = platformColourInstance();
7191 impl->use( _colourCode );
7197 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
7205 struct GeneratorInfo : IGeneratorInfo {
7207 GeneratorInfo( std::size_t
size )
7213 if( ++m_currentIndex == m_size ) {
7220 std::size_t getCurrentIndex()
const {
7221 return m_currentIndex;
7225 std::size_t m_currentIndex;
7230 class GeneratorsForTest :
public IGeneratorsForTest {
7233 ~GeneratorsForTest() {
7237 IGeneratorInfo& getGeneratorInfo( std::string
const& fileInfo, std::size_t
size ) {
7238 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
7239 if( it == m_generatorsByName.end() ) {
7240 IGeneratorInfo*
info =
new GeneratorInfo(
size );
7241 m_generatorsByName.insert( std::make_pair( fileInfo,
info ) );
7242 m_generatorsInOrder.push_back(
info );
7249 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
7250 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
7251 for(; it != itEnd; ++it ) {
7252 if( (*it)->moveNext() )
7259 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
7260 std::vector<IGeneratorInfo*> m_generatorsInOrder;
7265 return new GeneratorsForTest();
7271 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
7276 SourceLineInfo
const& _lineInfo,
7277 std::string
const& _capturedExpression,
7279 : macroName( _macroName ),
7280 lineInfo( _lineInfo ),
7281 capturedExpression( _capturedExpression ),
7282 resultDisposition( _resultDisposition )
7285 AssertionResult::AssertionResult() {}
7287 AssertionResult::AssertionResult( AssertionInfo
const&
info, AssertionResultData
const&
data )
7289 m_resultData(
data )
7292 AssertionResult::~AssertionResult() {}
7295 bool AssertionResult::succeeded()
const {
7304 ResultWas::OfType AssertionResult::getResultType()
const {
7305 return m_resultData.resultType;
7308 bool AssertionResult::hasExpression()
const {
7309 return !m_info.capturedExpression.empty();
7312 bool AssertionResult::hasMessage()
const {
7313 return !m_resultData.message.empty();
7316 std::string AssertionResult::getExpression()
const {
7318 return "!" + m_info.capturedExpression;
7320 return m_info.capturedExpression;
7322 std::string AssertionResult::getExpressionInMacro()
const {
7323 if( m_info.macroName.empty() )
7324 return m_info.capturedExpression;
7326 return m_info.macroName + "( " + m_info.capturedExpression + " )";
7329 bool AssertionResult::hasExpandedExpression()
const {
7330 return hasExpression() && getExpandedExpression() != getExpression();
7333 std::string AssertionResult::getExpandedExpression()
const {
7334 return m_resultData.reconstructedExpression;
7337 std::string AssertionResult::getMessage()
const {
7338 return m_resultData.message;
7340 SourceLineInfo AssertionResult::getSourceInfo()
const {
7341 return m_info.lineInfo;
7344 std::string AssertionResult::getTestMacroName()
const {
7345 return m_info.macroName;
7351 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
7360 else if( tag ==
"!throws" )
7362 else if( tag ==
"!shouldfail" )
7364 else if( tag ==
"!mayfail" )
7369 inline bool isReservedTag( std::string
const& tag ) {
7370 return parseSpecialTag( tag ) ==
TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
7372 inline void enforceNotReservedTag( std::string
const& tag, SourceLineInfo
const& _lineInfo ) {
7373 if( isReservedTag( tag ) ) {
7377 <<
"Tag name [" << tag <<
"] not allowed.\n"
7378 <<
"Tag names starting with non alpha-numeric characters are reserved\n";
7381 Colour colourGuard( Colour::FileName );
7382 Catch::cerr() << _lineInfo << std::endl;
7389 std::string
const& _className,
7390 std::string
const& _name,
7391 std::string
const& _descOrTags,
7392 SourceLineInfo
const& _lineInfo )
7397 std::set<std::string> tags;
7398 std::string desc, tag;
7400 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
7401 char c = _descOrTags[i];
7414 enforceNotReservedTag( tag, _lineInfo );
7425 tags.insert(
"hide" );
7429 TestCaseInfo
info( _name, _className, desc, tags, _lineInfo );
7430 return TestCase( _testCase,
info );
7433 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string>
const& tags )
7435 testCaseInfo.tags = tags;
7436 testCaseInfo.lcaseTags.clear();
7438 std::ostringstream oss;
7439 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
7440 oss <<
"[" << *it <<
"]";
7441 std::string lcaseTag =
toLower( *it );
7442 testCaseInfo.properties =
static_cast<TestCaseInfo::SpecialProperties
>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
7443 testCaseInfo.lcaseTags.insert( lcaseTag );
7445 testCaseInfo.tagsAsString = oss.str();
7448 TestCaseInfo::TestCaseInfo( std::string
const& _name,
7449 std::string
const& _className,
7450 std::string
const& _description,
7451 std::set<std::string>
const& _tags,
7452 SourceLineInfo
const& _lineInfo )
7454 className( _className ),
7455 description( _description ),
7456 lineInfo( _lineInfo ),
7459 setTags( *
this, _tags );
7462 TestCaseInfo::TestCaseInfo( TestCaseInfo
const& other )
7463 : name( other.name ),
7464 className( other.className ),
7465 description( other.description ),
7467 lcaseTags( other.lcaseTags ),
7468 tagsAsString( other.tagsAsString ),
7469 lineInfo( other.lineInfo ),
7470 properties( other.properties )
7473 bool TestCaseInfo::isHidden()
const {
7474 return ( properties & IsHidden ) != 0;
7476 bool TestCaseInfo::throws()
const {
7477 return ( properties & Throws ) != 0;
7479 bool TestCaseInfo::okToFail()
const {
7480 return ( properties & (ShouldFail | MayFail ) ) != 0;
7482 bool TestCaseInfo::expectedToFail()
const {
7483 return ( properties & (ShouldFail ) ) != 0;
7486 TestCase::TestCase( ITestCase* testCase, TestCaseInfo
const&
info ) : TestCaseInfo(
info ), test( testCase ) {}
7488 TestCase::TestCase( TestCase
const& other )
7489 : TestCaseInfo( other ),
7493 TestCase TestCase::withName( std::string
const& _newName )
const {
7494 TestCase other( *
this );
7495 other.name = _newName;
7499 void TestCase::swap( TestCase& other ) {
7500 test.swap( other.test );
7501 name.swap( other.name );
7502 className.swap( other.className );
7503 description.swap( other.description );
7504 tags.swap( other.tags );
7505 lcaseTags.swap( other.lcaseTags );
7506 tagsAsString.swap( other.tagsAsString );
7507 std::swap( TestCaseInfo::properties,
static_cast<TestCaseInfo&
>( other ).properties );
7508 std::swap( lineInfo, other.lineInfo );
7511 void TestCase::invoke()
const {
7516 return test.get() == other.test.get() &&
7517 name == other.name &&
7518 className == other.className;
7522 return name < other.name;
7524 TestCase& TestCase::operator = ( TestCase
const& other ) {
7525 TestCase temp( other );
7530 TestCaseInfo
const& TestCase::getTestCaseInfo()
const
7538 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
7543 (
unsigned int _majorVersion,
7544 unsigned int _minorVersion,
7545 unsigned int _patchNumber,
7546 std::string
const& _branchName,
7547 unsigned int _buildNumber )
7548 : majorVersion( _majorVersion ),
7549 minorVersion( _minorVersion ),
7550 patchNumber( _patchNumber ),
7551 branchName( _branchName ),
7552 buildNumber( _buildNumber )
7555 std::ostream&
operator << ( std::ostream& os, Version
const& version ) {
7556 os << version.majorVersion <<
"."
7557 << version.minorVersion <<
"."
7558 << version.patchNumber;
7560 if( !version.branchName.empty() ) {
7561 os <<
"-" << version.branchName
7562 <<
"." << version.buildNumber;
7567 Version libraryVersion( 1, 5, 1,
"", 0 );
7572 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
7577 SourceLineInfo
const& _lineInfo,
7579 : macroName( _macroName ),
7580 lineInfo( _lineInfo ),
7582 sequence( ++globalCount )
7586 unsigned int MessageInfo::globalCount = 0;
7590 ScopedMessage::ScopedMessage( MessageBuilder
const& builder )
7591 : m_info( builder.m_info )
7593 m_info.message = builder.m_stream.str();
7596 ScopedMessage::ScopedMessage( ScopedMessage
const& other )
7597 : m_info( other.m_info )
7600 ScopedMessage::~ScopedMessage() {
7607 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
7610 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
7615 struct IReporter : IShared {
7616 virtual ~IReporter();
7618 virtual bool shouldRedirectStdout()
const = 0;
7620 virtual void StartTesting() = 0;
7621 virtual void EndTesting( Totals
const& totals ) = 0;
7622 virtual void StartGroup( std::string
const& groupName ) = 0;
7623 virtual void EndGroup( std::string
const& groupName, Totals
const& totals ) = 0;
7624 virtual void StartTestCase( TestCaseInfo
const&
testInfo ) = 0;
7625 virtual void EndTestCase( TestCaseInfo
const&
testInfo, Totals
const& totals, std::string
const& stdOut, std::string
const& stdErr ) = 0;
7626 virtual void StartSection( std::string
const& sectionName, std::string
const& description ) = 0;
7627 virtual void EndSection( std::string
const& sectionName, Counts
const& assertions ) = 0;
7628 virtual void NoAssertionsInSection( std::string
const& sectionName ) = 0;
7629 virtual void NoAssertionsInTestCase( std::string
const& testName ) = 0;
7630 virtual void Aborted() = 0;
7631 virtual void Result( AssertionResult
const& result ) = 0;
7634 class LegacyReporterAdapter :
public SharedImpl<IStreamingReporter>
7637 LegacyReporterAdapter( Ptr<IReporter>
const& legacyReporter );
7638 virtual ~LegacyReporterAdapter();
7640 virtual ReporterPreferences getPreferences()
const;
7641 virtual void noMatchingTestCases( std::string
const& );
7642 virtual void testRunStarting( TestRunInfo
const& );
7643 virtual void testGroupStarting(
GroupInfo const& groupInfo );
7644 virtual void testCaseStarting( TestCaseInfo
const&
testInfo );
7645 virtual void sectionStarting( SectionInfo
const& sectionInfo );
7646 virtual void assertionStarting( AssertionInfo
const& );
7647 virtual bool assertionEnded( AssertionStats
const& assertionStats );
7648 virtual void sectionEnded( SectionStats
const& sectionStats );
7649 virtual void testCaseEnded( TestCaseStats
const& testCaseStats );
7650 virtual void testGroupEnded( TestGroupStats
const& testGroupStats );
7651 virtual void testRunEnded( TestRunStats
const& testRunStats );
7652 virtual void skipTest( TestCaseInfo
const& );
7655 Ptr<IReporter> m_legacyReporter;
7661 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter>
const& legacyReporter )
7662 : m_legacyReporter( legacyReporter )
7664 LegacyReporterAdapter::~LegacyReporterAdapter() {}
7666 ReporterPreferences LegacyReporterAdapter::getPreferences()
const {
7667 ReporterPreferences prefs;
7668 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
7672 void LegacyReporterAdapter::noMatchingTestCases( std::string
const& ) {}
7673 void LegacyReporterAdapter::testRunStarting( TestRunInfo
const& ) {
7674 m_legacyReporter->StartTesting();
7676 void LegacyReporterAdapter::testGroupStarting(
GroupInfo const& groupInfo ) {
7677 m_legacyReporter->StartGroup( groupInfo.
name );
7679 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo
const&
testInfo ) {
7680 m_legacyReporter->StartTestCase(
testInfo );
7682 void LegacyReporterAdapter::sectionStarting( SectionInfo
const& sectionInfo ) {
7683 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
7685 void LegacyReporterAdapter::assertionStarting( AssertionInfo
const& ) {
7689 bool LegacyReporterAdapter::assertionEnded( AssertionStats
const& assertionStats ) {
7690 if( assertionStats.assertionResult.getResultType() !=
ResultWas::Ok ) {
7691 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
7698 AssertionResult result = rb.build();
7699 m_legacyReporter->Result( result );
7703 m_legacyReporter->Result( assertionStats.assertionResult );
7706 void LegacyReporterAdapter::sectionEnded( SectionStats
const& sectionStats ) {
7707 if( sectionStats.missingAssertions )
7708 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
7709 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
7711 void LegacyReporterAdapter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
7712 m_legacyReporter->EndTestCase
7713 ( testCaseStats.testInfo,
7714 testCaseStats.totals,
7715 testCaseStats.stdOut,
7716 testCaseStats.stdErr );
7718 void LegacyReporterAdapter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
7719 if( testGroupStats.aborting )
7720 m_legacyReporter->Aborted();
7721 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
7723 void LegacyReporterAdapter::testRunEnded( TestRunStats
const& testRunStats ) {
7724 m_legacyReporter->EndTesting( testRunStats.totals );
7726 void LegacyReporterAdapter::skipTest( TestCaseInfo
const& ) {
7733 #pragma clang diagnostic push
7734 #pragma clang diagnostic ignored "-Wc++11-long-long"
7737 #ifdef CATCH_PLATFORM_WINDOWS
7738 #include <windows.h>
7740 #include <sys/time.h>
7746 #ifdef CATCH_PLATFORM_WINDOWS
7747 uint64_t getCurrentTicks() {
7748 static uint64_t hz=0, hzo=0;
7750 QueryPerformanceFrequency(
reinterpret_cast<LARGE_INTEGER*
>( &hz ) );
7751 QueryPerformanceCounter(
reinterpret_cast<LARGE_INTEGER*
>( &hzo ) );
7754 QueryPerformanceCounter(
reinterpret_cast<LARGE_INTEGER*
>( &t ) );
7755 return ((t-hzo)*1000000)/hz;
7758 uint64_t getCurrentTicks() {
7761 return static_cast<uint64_t
>( t.tv_sec ) * 1000000ull +
static_cast<uint64_t
>( t.tv_usec );
7770 return static_cast<unsigned int>(getCurrentTicks() -
m_ticks);
7782 #pragma clang diagnostic pop
7785 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
7789 bool startsWith( std::string
const& s, std::string
const& prefix ) {
7790 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
7792 bool endsWith( std::string
const& s, std::string
const& suffix ) {
7793 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
7795 bool contains( std::string
const& s, std::string
const& infix ) {
7796 return s.find( infix ) != std::string::npos;
7799 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
7801 std::string
toLower( std::string
const& s ) {
7806 std::string
trim( std::string
const& str ) {
7807 static char const* whitespaceChars =
"\n\r\t ";
7808 std::string::size_type
start = str.find_first_not_of( whitespaceChars );
7809 std::string::size_type end = str.find_last_not_of( whitespaceChars );
7811 return start != std::string::npos ? str.substr(
start, 1+end-
start ) :
"";
7814 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis ) {
7815 bool replaced =
false;
7816 std::size_t i = str.find( replaceThis );
7817 while( i != std::string::npos ) {
7819 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.
size() );
7820 if( i < str.size()-withThis.size() )
7821 i = str.find( replaceThis, i+withThis.size() );
7823 i = std::string::npos;
7833 std::ostream&
operator << ( std::ostream& os, pluralise
const& pluraliser ) {
7834 os << pluraliser.m_count <<
" " << pluraliser.m_label;
7835 if( pluraliser.m_count != 1 )
7840 SourceLineInfo::SourceLineInfo() : line( 0 ){}
7841 SourceLineInfo::SourceLineInfo(
char const* _file, std::size_t _line )
7845 SourceLineInfo::SourceLineInfo( SourceLineInfo
const& other )
7846 : file( other.file ),
7850 return file.empty();
7853 return line == other.line && file == other.file;
7856 return line < other.line || ( line == other.line && file < other.file );
7860 if(
config.rngSeed() != 0 )
7861 std::srand(
config.rngSeed() );
7867 std::ostream&
operator << ( std::ostream& os, SourceLineInfo
const&
info ) {
7869 os <<
info.file <<
"(" <<
info.line <<
")";
7871 os <<
info.file <<
":" <<
info.line;
7876 void throwLogicError( std::string
const& message, SourceLineInfo
const& locationInfo ) {
7877 std::ostringstream oss;
7878 oss << locationInfo <<
": Internal Catch error: '" << message <<
"'";
7880 throw std::logic_error( oss.str() );
7885 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
7890 ( SourceLineInfo
const& _lineInfo,
7891 std::string
const& _name,
7892 std::string
const& _description )
7894 description( _description ),
7895 lineInfo( _lineInfo )
7898 Section::Section( SectionInfo
const&
info )
7900 m_sectionIncluded(
getResultCapture().sectionStarted( m_info, m_assertions ) )
7905 Section::~Section() {
7906 if( m_sectionIncluded ) {
7907 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
7908 if( std::uncaught_exception() )
7916 Section::operator bool()
const {
7917 return m_sectionIncluded;
7923 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
7927 #ifdef CATCH_PLATFORM_MAC
7930 #include <stdbool.h>
7931 #include <sys/types.h>
7933 #include <sys/sysctl.h>
7945 struct kinfo_proc
info;
7951 info.kp_proc.p_flag = 0;
7958 mib[2] = KERN_PROC_PID;
7965 Catch::cerr() <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
7971 return ( (
info.kp_proc.p_flag & P_TRACED) != 0 );
7975 #elif defined(_MSC_VER)
7976 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7979 return IsDebuggerPresent() != 0;
7982 #elif defined(__MINGW32__)
7983 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7986 return IsDebuggerPresent() != 0;
7995 #ifdef CATCH_PLATFORM_WINDOWS
7996 extern "C" __declspec(dllimport)
void __stdcall OutputDebugStringA(
const char* );
7999 ::OutputDebugStringA( text.c_str() );
8006 Catch::cout() << text;
8012 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
8021 const int hexThreshold = 255;
8024 enum Arch { Big, Little };
8026 static Arch which() {
8029 char asChar[sizeof (int)];
8033 return ( u.asChar[
sizeof(
int)-1] == 1 ) ? Big : Little;
8041 int i = 0, end =
static_cast<int>(
size ), inc = 1;
8042 if( Endianness::which() == Endianness::Little ) {
8047 unsigned char const *bytes =
static_cast<unsigned char const *
>(object);
8048 std::ostringstream os;
8049 os <<
"0x" << std::setfill(
'0') << std::hex;
8050 for( ; i != end; i += inc )
8051 os <<
std::setw(2) << static_cast<unsigned>(bytes[i]);
8056 std::string
toString( std::string
const& value ) {
8057 std::string s = value;
8059 for(
size_t i = 0; i < s.size(); ++i ) {
8062 case '\n': subs =
"\\n";
break;
8063 case '\t': subs =
"\\t";
break;
8066 if( !subs.empty() ) {
8067 s = s.substr( 0, i ) + subs + s.substr( i+1 );
8072 return "\"" + s + "\"";
8074 std::string
toString( std::wstring
const& value ) {
8077 s.reserve( value.size() );
8078 for(
size_t i = 0; i < value.size(); ++i )
8079 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
8083 std::string
toString(
const char*
const value ) {
8084 return value ?
Catch::toString( std::string( value ) ) :
std::string(
"{null string}" );
8087 std::string
toString(
char*
const value ) {
8091 std::string
toString(
const wchar_t*
const value )
8093 return value ?
Catch::toString( std::wstring(value) ) :
std::string(
"{null string}" );
8096 std::string
toString(
wchar_t*
const value )
8101 std::string
toString(
int value ) {
8102 std::ostringstream oss;
8104 if( value > Detail::hexThreshold )
8105 oss <<
" (0x" << std::hex << value <<
")";
8109 std::string
toString(
unsigned long value ) {
8110 std::ostringstream oss;
8112 if( value > Detail::hexThreshold )
8113 oss <<
" (0x" << std::hex << value <<
")";
8117 std::string
toString(
unsigned int value ) {
8121 template<
typename T>
8122 std::string fpToString(
T value,
int precision ) {
8123 std::ostringstream oss;
8124 oss << std::setprecision( precision )
8127 std::string d = oss.str();
8128 std::size_t i = d.find_last_not_of(
'0' );
8129 if( i != std::string::npos && i != d.size()-1 ) {
8132 d = d.substr( 0, i+1 );
8137 std::string
toString(
const double value ) {
8138 return fpToString( value, 10 );
8140 std::string
toString(
const float value ) {
8141 return fpToString( value, 5 ) + "f";
8144 std::string
toString(
bool value ) {
8145 return value ?
"true" :
"false";
8148 std::string
toString(
char value ) {
8150 ?
toString(
static_cast<unsigned int>( value ) )
8154 std::string
toString(
signed char value ) {
8155 return toString(
static_cast<char>( value ) );
8158 std::string
toString(
unsigned char value ) {
8159 return toString(
static_cast<char>( value ) );
8162 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
8163 std::string
toString(
long long value ) {
8164 std::ostringstream oss;
8166 if( value > Detail::hexThreshold )
8167 oss <<
" (0x" << std::hex << value <<
")";
8170 std::string
toString(
unsigned long long value ) {
8171 std::ostringstream oss;
8173 if( value > Detail::hexThreshold )
8174 oss <<
" (0x" << std::hex << value <<
")";
8179 #ifdef CATCH_CONFIG_CPP11_NULLPTR
8186 std::string
toString( NSString
const *
const& nsstring ) {
8189 return "@" +
toString([nsstring UTF8String]);
8191 std::string
toString( NSString * CATCH_ARC_STRONG
const& nsstring ) {
8194 return "@" +
toString([nsstring UTF8String]);
8196 std::string
toString( NSObject*
const& nsObject ) {
8197 return toString( [nsObject description] );
8204 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
8208 std::string capturedExpressionWithSecondArgument( std::string
const& capturedExpression, std::string
const& secondArg ) {
8209 return secondArg.empty() || secondArg ==
"\"\""
8210 ? capturedExpression
8211 : capturedExpression + ", " + secondArg;
8214 SourceLineInfo
const& lineInfo,
8215 char const* capturedExpression,
8217 char const* secondArg )
8218 : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
8219 m_shouldDebugBreak( false ),
8220 m_shouldThrow( false )
8223 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
8224 m_data.resultType = result;
8227 ResultBuilder& ResultBuilder::setResultType(
bool result ) {
8228 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
8231 ResultBuilder& ResultBuilder::setLhs( std::string
const& lhs ) {
8232 m_exprComponents.lhs = lhs;
8235 ResultBuilder& ResultBuilder::setRhs( std::string
const& rhs ) {
8236 m_exprComponents.rhs = rhs;
8239 ResultBuilder& ResultBuilder::setOp( std::string
const& op ) {
8240 m_exprComponents.op = op;
8244 void ResultBuilder::endExpression() {
8245 m_exprComponents.testFalse =
isFalseTest( m_assertionInfo.resultDisposition );
8246 captureExpression();
8249 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
8250 m_assertionInfo.resultDisposition = resultDisposition;
8252 captureResult( ResultWas::ThrewException );
8255 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
8256 setResultType( resultType );
8257 captureExpression();
8259 void ResultBuilder::captureExpectedException( std::string
const& expectedMessage ) {
8260 if( expectedMessage.empty() )
8261 captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() );
8266 void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string>
const& matcher ) {
8268 assert( m_exprComponents.testFalse ==
false );
8269 AssertionResultData
data = m_data;
8270 data.resultType = ResultWas::Ok;
8271 data.reconstructedExpression = m_assertionInfo.capturedExpression;
8274 if( !matcher.match( actualMessage ) ) {
8275 data.resultType = ResultWas::ExpressionFailed;
8276 data.reconstructedExpression = actualMessage;
8278 AssertionResult result( m_assertionInfo,
data );
8279 handleResult( result );
8282 void ResultBuilder::captureExpression() {
8283 AssertionResult result = build();
8284 handleResult( result );
8286 void ResultBuilder::handleResult( AssertionResult
const& result )
8290 if( !result.isOk() ) {
8292 m_shouldDebugBreak =
true;
8294 m_shouldThrow =
true;
8297 void ResultBuilder::react() {
8302 bool ResultBuilder::shouldDebugBreak()
const {
return m_shouldDebugBreak; }
8305 AssertionResult ResultBuilder::build()
const
8309 AssertionResultData
data = m_data;
8312 if( m_exprComponents.testFalse ) {
8313 if(
data.resultType == ResultWas::Ok )
8314 data.resultType = ResultWas::ExpressionFailed;
8315 else if(
data.resultType == ResultWas::ExpressionFailed )
8316 data.resultType = ResultWas::Ok;
8319 data.message = m_stream.oss.str();
8320 data.reconstructedExpression = reconstructExpression();
8321 if( m_exprComponents.testFalse ) {
8322 if( m_exprComponents.op ==
"" )
8323 data.reconstructedExpression =
"!" +
data.reconstructedExpression;
8325 data.reconstructedExpression =
"!(" +
data.reconstructedExpression + ")";
8327 return AssertionResult( m_assertionInfo,
data );
8329 std::string ResultBuilder::reconstructExpression()
const {
8330 if( m_exprComponents.op ==
"" )
8331 return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
8332 else if( m_exprComponents.op ==
"matches" )
8333 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
8334 else if( m_exprComponents.op !=
"!" ) {
8335 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
8336 m_exprComponents.lhs.find(
"\n") == std::string::npos &&
8337 m_exprComponents.rhs.find(
"\n") == std::string::npos )
8338 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
8340 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
8343 return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}";
8349 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
8352 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
8358 class TagAliasRegistry :
public ITagAliasRegistry {
8360 virtual ~TagAliasRegistry();
8361 virtual Option<TagAlias>
find( std::string
const& alias )
const;
8362 virtual std::string expandAliases( std::string
const& unexpandedTestSpec )
const;
8363 void add(
char const* alias,
char const* tag, SourceLineInfo
const& lineInfo );
8364 static TagAliasRegistry&
get();
8367 std::map<std::string, TagAlias> m_registry;
8377 TagAliasRegistry::~TagAliasRegistry() {}
8380 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
8381 if( it != m_registry.end() )
8384 return Option<TagAlias>();
8387 std::string TagAliasRegistry::expandAliases( std::string
const& unexpandedTestSpec )
const {
8388 std::string expandedTestSpec = unexpandedTestSpec;
8389 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
8392 std::size_t pos = expandedTestSpec.find( it->first );
8393 if( pos != std::string::npos ) {
8394 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
8396 expandedTestSpec.substr( pos + it->first.
size() );
8399 return expandedTestSpec;
8402 void TagAliasRegistry::add(
char const* alias,
char const* tag, SourceLineInfo
const& lineInfo ) {
8405 std::ostringstream oss;
8406 oss <<
"error: tag alias, \"" << alias <<
"\" is not of the form [@alias name].\n" << lineInfo;
8407 throw std::domain_error( oss.str().c_str() );
8409 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
8410 std::ostringstream oss;
8411 oss <<
"error: tag alias, \"" << alias <<
"\" already registered.\n"
8412 <<
"\tFirst seen at " <<
find(alias)->lineInfo <<
"\n"
8413 <<
"\tRedefined at " << lineInfo;
8414 throw std::domain_error( oss.str().c_str() );
8419 static TagAliasRegistry instance;
8431 catch( std::exception& ex ) {
8433 Catch::cerr() << ex.what() << std::endl;
8441 #define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
8445 class MultipleReporters :
public SharedImpl<IStreamingReporter> {
8446 typedef std::vector<Ptr<IStreamingReporter> > Reporters;
8447 Reporters m_reporters;
8450 void add( Ptr<IStreamingReporter>
const& reporter ) {
8451 m_reporters.push_back( reporter );
8456 virtual ReporterPreferences getPreferences() const
CATCH_OVERRIDE {
8457 return m_reporters[0]->getPreferences();
8460 virtual void noMatchingTestCases( std::string
const& spec )
CATCH_OVERRIDE {
8461 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8464 (*it)->noMatchingTestCases( spec );
8467 virtual void testRunStarting( TestRunInfo
const& testRunInfo )
CATCH_OVERRIDE {
8468 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8471 (*it)->testRunStarting( testRunInfo );
8475 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8478 (*it)->testGroupStarting( groupInfo );
8482 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8485 (*it)->testCaseStarting(
testInfo );
8488 virtual void sectionStarting( SectionInfo
const& sectionInfo )
CATCH_OVERRIDE {
8489 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8492 (*it)->sectionStarting( sectionInfo );
8495 virtual void assertionStarting( AssertionInfo
const& assertionInfo )
CATCH_OVERRIDE {
8496 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8499 (*it)->assertionStarting( assertionInfo );
8503 virtual bool assertionEnded( AssertionStats
const& assertionStats )
CATCH_OVERRIDE {
8504 bool clearBuffer =
false;
8505 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8508 clearBuffer |= (*it)->assertionEnded( assertionStats );
8512 virtual void sectionEnded( SectionStats
const& sectionStats )
CATCH_OVERRIDE {
8513 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8516 (*it)->sectionEnded( sectionStats );
8519 virtual void testCaseEnded( TestCaseStats
const& testCaseStats )
CATCH_OVERRIDE {
8520 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8523 (*it)->testCaseEnded( testCaseStats );
8526 virtual void testGroupEnded( TestGroupStats
const& testGroupStats )
CATCH_OVERRIDE {
8527 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8530 (*it)->testGroupEnded( testGroupStats );
8533 virtual void testRunEnded( TestRunStats
const& testRunStats )
CATCH_OVERRIDE {
8534 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8537 (*it)->testRunEnded( testRunStats );
8541 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8553 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter>
const& existingReporter, Ptr<IStreamingReporter>
const& additionalReporter ) {
8554 Ptr<IStreamingReporter> resultingReporter;
8556 if( existingReporter ) {
8557 MultipleReporters* multi = existingReporter->tryAsMulti();
8559 multi =
new MultipleReporters;
8560 resultingReporter = Ptr<IStreamingReporter>( multi );
8561 if( existingReporter )
8562 multi->add( existingReporter );
8565 resultingReporter = existingReporter;
8566 multi->add( additionalReporter );
8569 resultingReporter = additionalReporter;
8571 return resultingReporter;
8577 #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
8580 #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
8586 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
8588 StreamingReporterBase( ReporterConfig
const& _config )
8589 : m_config( _config.fullConfig() ),
8590 stream( _config.stream() )
8592 m_reporterPrefs.shouldRedirectStdOut =
false;
8595 virtual ReporterPreferences getPreferences() const
CATCH_OVERRIDE {
8596 return m_reporterPrefs;
8603 virtual void testRunStarting( TestRunInfo
const& _testRunInfo )
CATCH_OVERRIDE {
8604 currentTestRunInfo = _testRunInfo;
8607 currentGroupInfo = _groupInfo;
8610 virtual void testCaseStarting( TestCaseInfo
const& _testInfo )
CATCH_OVERRIDE {
8611 currentTestCaseInfo = _testInfo;
8613 virtual void sectionStarting( SectionInfo
const& _sectionInfo )
CATCH_OVERRIDE {
8614 m_sectionStack.push_back( _sectionInfo );
8617 virtual void sectionEnded( SectionStats
const& )
CATCH_OVERRIDE {
8618 m_sectionStack.pop_back();
8620 virtual void testCaseEnded( TestCaseStats
const& )
CATCH_OVERRIDE {
8621 currentTestCaseInfo.reset();
8623 virtual void testGroupEnded( TestGroupStats
const& )
CATCH_OVERRIDE {
8624 currentGroupInfo.reset();
8626 virtual void testRunEnded( TestRunStats
const& )
CATCH_OVERRIDE {
8627 currentTestCaseInfo.reset();
8628 currentGroupInfo.reset();
8629 currentTestRunInfo.reset();
8637 Ptr<IConfig const> m_config;
8638 std::ostream& stream;
8640 LazyStat<TestRunInfo> currentTestRunInfo;
8641 LazyStat<GroupInfo> currentGroupInfo;
8642 LazyStat<TestCaseInfo> currentTestCaseInfo;
8644 std::vector<SectionInfo> m_sectionStack;
8645 ReporterPreferences m_reporterPrefs;
8648 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
8649 template<
typename T,
typename ChildNodeT>
8650 struct Node : SharedImpl<> {
8651 explicit Node(
T const& _value ) : value( _value ) {}
8654 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
8656 ChildNodes children;
8658 struct SectionNode : SharedImpl<> {
8659 explicit SectionNode( SectionStats
const& _stats ) : stats( _stats ) {}
8660 virtual ~SectionNode();
8662 bool operator == ( SectionNode
const& other )
const {
8663 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
8665 bool operator == ( Ptr<SectionNode>
const& other )
const {
8670 typedef std::vector<Ptr<SectionNode> > ChildSections;
8671 typedef std::vector<AssertionStats> Assertions;
8672 ChildSections childSections;
8673 Assertions assertions;
8678 struct BySectionInfo {
8679 BySectionInfo( SectionInfo
const& other ) : m_other( other ) {}
8680 BySectionInfo( BySectionInfo
const& other ) : m_other( other.m_other ) {}
8681 bool operator() ( Ptr<SectionNode>
const& node )
const {
8682 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
8685 void operator=( BySectionInfo
const& );
8686 SectionInfo
const& m_other;
8689 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
8690 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
8691 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
8693 CumulativeReporterBase( ReporterConfig
const& _config )
8694 : m_config( _config.fullConfig() ),
8695 stream( _config.stream() )
8697 m_reporterPrefs.shouldRedirectStdOut =
false;
8699 ~CumulativeReporterBase();
8701 virtual ReporterPreferences getPreferences() const
CATCH_OVERRIDE {
8702 return m_reporterPrefs;
8705 virtual void testRunStarting( TestRunInfo
const& )
CATCH_OVERRIDE {}
8708 virtual void testCaseStarting( TestCaseInfo
const& )
CATCH_OVERRIDE {}
8710 virtual void sectionStarting( SectionInfo
const& sectionInfo )
CATCH_OVERRIDE {
8711 SectionStats incompleteStats( sectionInfo, Counts(), 0,
false );
8712 Ptr<SectionNode> node;
8713 if( m_sectionStack.empty() ) {
8714 if( !m_rootSection )
8715 m_rootSection =
new SectionNode( incompleteStats );
8716 node = m_rootSection;
8719 SectionNode& parentNode = *m_sectionStack.back();
8720 SectionNode::ChildSections::const_iterator it =
8721 std::find_if( parentNode.childSections.begin(),
8722 parentNode.childSections.end(),
8723 BySectionInfo( sectionInfo ) );
8724 if( it == parentNode.childSections.end() ) {
8725 node =
new SectionNode( incompleteStats );
8726 parentNode.childSections.push_back( node );
8731 m_sectionStack.push_back( node );
8732 m_deepestSection = node;
8735 virtual void assertionStarting( AssertionInfo
const& )
CATCH_OVERRIDE {}
8737 virtual bool assertionEnded( AssertionStats
const& assertionStats )
CATCH_OVERRIDE {
8738 assert( !m_sectionStack.empty() );
8739 SectionNode& sectionNode = *m_sectionStack.back();
8740 sectionNode.assertions.push_back( assertionStats );
8743 virtual void sectionEnded( SectionStats
const& sectionStats )
CATCH_OVERRIDE {
8744 assert( !m_sectionStack.empty() );
8745 SectionNode& node = *m_sectionStack.back();
8746 node.stats = sectionStats;
8747 m_sectionStack.pop_back();
8749 virtual void testCaseEnded( TestCaseStats
const& testCaseStats )
CATCH_OVERRIDE {
8750 Ptr<TestCaseNode> node =
new TestCaseNode( testCaseStats );
8751 assert( m_sectionStack.size() == 0 );
8752 node->children.push_back( m_rootSection );
8753 m_testCases.push_back( node );
8754 m_rootSection.reset();
8756 assert( m_deepestSection );
8757 m_deepestSection->stdOut = testCaseStats.stdOut;
8758 m_deepestSection->stdErr = testCaseStats.stdErr;
8760 virtual void testGroupEnded( TestGroupStats
const& testGroupStats )
CATCH_OVERRIDE {
8761 Ptr<TestGroupNode> node =
new TestGroupNode( testGroupStats );
8762 node->children.swap( m_testCases );
8763 m_testGroups.push_back( node );
8765 virtual void testRunEnded( TestRunStats
const& testRunStats )
CATCH_OVERRIDE {
8766 Ptr<TestRunNode> node =
new TestRunNode( testRunStats );
8767 node->children.swap( m_testGroups );
8768 m_testRuns.push_back( node );
8769 testRunEndedCumulative();
8771 virtual void testRunEndedCumulative() = 0;
8775 Ptr<IConfig const> m_config;
8776 std::ostream& stream;
8777 std::vector<AssertionStats> m_assertions;
8778 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
8779 std::vector<Ptr<TestCaseNode> > m_testCases;
8780 std::vector<Ptr<TestGroupNode> > m_testGroups;
8782 std::vector<Ptr<TestRunNode> > m_testRuns;
8784 Ptr<SectionNode> m_rootSection;
8785 Ptr<SectionNode> m_deepestSection;
8786 std::vector<Ptr<SectionNode> > m_sectionStack;
8787 ReporterPreferences m_reporterPrefs;
8792 char const* getLineOfChars() {
8793 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
8795 memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
8796 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
8801 struct TestEventListenerBase : StreamingReporterBase {
8802 TestEventListenerBase( ReporterConfig
const& _config )
8803 : StreamingReporterBase( _config )
8806 virtual void assertionStarting( AssertionInfo
const& )
CATCH_OVERRIDE {}
8807 virtual bool assertionEnded( AssertionStats
const& )
CATCH_OVERRIDE {
8815 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
8819 template<
typename T>
8820 class LegacyReporterRegistrar {
8822 class ReporterFactory :
public IReporterFactory {
8823 virtual IStreamingReporter* create( ReporterConfig
const&
config )
const {
8824 return new LegacyReporterAdapter(
new T(
config ) );
8827 virtual std::string getDescription()
const {
8828 return T::getDescription();
8834 LegacyReporterRegistrar( std::string
const& name ) {
8839 template<
typename T>
8840 class ReporterRegistrar {
8842 class ReporterFactory :
public SharedImpl<IReporterFactory> {
8855 virtual IStreamingReporter* create( ReporterConfig
const&
config )
const {
8859 virtual std::string getDescription()
const {
8860 return T::getDescription();
8866 ReporterRegistrar( std::string
const& name ) {
8871 template<
typename T>
8872 class ListenerRegistrar {
8874 class ListenerFactory :
public SharedImpl<IReporterFactory> {
8876 virtual IStreamingReporter* create( ReporterConfig
const&
config )
const {
8879 virtual std::string getDescription()
const {
8886 ListenerRegistrar() {
8892 #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
8893 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
8895 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
8896 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
8898 #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
8899 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
8902 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
8913 enum ForWhat { ForTextNodes, ForAttributes };
8915 XmlEncode( std::string
const& str, ForWhat forWhat = ForTextNodes )
8917 m_forWhat( forWhat )
8920 void encodeTo( std::ostream& os )
const {
8925 for( std::size_t i = 0; i < m_str.size(); ++ i ) {
8928 case '<': os <<
"<";
break;
8929 case '&': os <<
"&";
break;
8933 if( i > 2 && m_str[i-1] ==
']' && m_str[i-2] ==
']' )
8940 if( m_forWhat == ForAttributes )
8948 if ( ( c <
'\x09' ) || ( c >
'\x0D' && c <
'\x20') || c==
'\x7F' )
8949 os <<
"&#x" << std::uppercase << std::hex <<
static_cast<int>( c );
8956 friend std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode ) {
8957 xmlEncode.encodeTo( os );
8969 class ScopedElement {
8971 ScopedElement( XmlWriter* writer )
8972 : m_writer( writer )
8975 ScopedElement( ScopedElement
const& other )
8976 : m_writer( other.m_writer ){
8982 m_writer->endElement();
8985 ScopedElement& writeText( std::string
const& text,
bool indent =
true ) {
8986 m_writer->writeText( text, indent );
8990 template<
typename T>
8991 ScopedElement& writeAttribute( std::string
const& name,
T const& attribute ) {
8992 m_writer->writeAttribute( name, attribute );
8997 mutable XmlWriter* m_writer;
9001 : m_tagIsOpen( false ),
9002 m_needsNewline( false ),
9003 m_os( &
Catch::cout() )
9006 XmlWriter( std::ostream& os )
9007 : m_tagIsOpen( false ),
9008 m_needsNewline( false ),
9013 while( !m_tags.empty() )
9017 XmlWriter& startElement( std::string
const& name ) {
9019 newlineIfNecessary();
9020 stream() << m_indent <<
"<" << name;
9021 m_tags.push_back( name );
9027 ScopedElement scopedElement( std::string
const& name ) {
9028 ScopedElement scoped(
this );
9029 startElement( name );
9033 XmlWriter& endElement() {
9034 newlineIfNecessary();
9035 m_indent = m_indent.substr( 0, m_indent.size()-2 );
9038 m_tagIsOpen =
false;
9041 stream() << m_indent <<
"</" << m_tags.back() <<
">\n";
9047 XmlWriter& writeAttribute( std::string
const& name, std::string
const& attribute ) {
9048 if( !name.empty() && !attribute.empty() )
9049 stream() <<
" " << name <<
"=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) <<
"\"";
9053 XmlWriter& writeAttribute( std::string
const& name,
bool attribute ) {
9054 stream() <<
" " << name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
"\"";
9058 template<
typename T>
9059 XmlWriter& writeAttribute( std::string
const& name,
T const& attribute ) {
9060 std::ostringstream oss;
9062 return writeAttribute( name, oss.str() );
9065 XmlWriter& writeText( std::string
const& text,
bool indent =
true ) {
9066 if( !text.empty() ){
9067 bool tagWasOpen = m_tagIsOpen;
9069 if( tagWasOpen && indent )
9070 stream() << m_indent;
9071 stream() << XmlEncode( text );
9072 m_needsNewline =
true;
9077 XmlWriter& writeComment( std::string
const& text ) {
9079 stream() << m_indent <<
"<!--" << text <<
"-->";
9080 m_needsNewline =
true;
9084 XmlWriter& writeBlankLine() {
9090 void setStream( std::ostream& os ) {
9095 XmlWriter( XmlWriter
const& );
9096 void operator=( XmlWriter
const& );
9098 std::ostream& stream() {
9102 void ensureTagClosed() {
9105 m_tagIsOpen =
false;
9109 void newlineIfNecessary() {
9110 if( m_needsNewline ) {
9112 m_needsNewline =
false;
9117 bool m_needsNewline;
9118 std::vector<std::string> m_tags;
9119 std::string m_indent;
9126 #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
9130 # pragma warning(pop)
9132 # pragma clang diagnostic pop
9134 #elif defined __GNUC__
9135 # pragma GCC diagnostic pop
9140 class XmlReporter :
public StreamingReporterBase {
9142 XmlReporter( ReporterConfig
const& _config )
9143 : StreamingReporterBase( _config ),
9146 m_reporterPrefs.shouldRedirectStdOut =
true;
9151 static
std::
string getDescription() {
9152 return "Reports test results as an XML document";
9157 virtual void noMatchingTestCases( std::string
const& s )
CATCH_OVERRIDE {
9158 StreamingReporterBase::noMatchingTestCases( s );
9162 StreamingReporterBase::testRunStarting(
testInfo );
9163 m_xml.setStream( stream );
9164 m_xml.startElement(
"Catch" );
9165 if( !m_config->name().empty() )
9166 m_xml.writeAttribute(
"name", m_config->name() );
9170 StreamingReporterBase::testGroupStarting( groupInfo );
9171 m_xml.startElement(
"Group" )
9172 .writeAttribute(
"name", groupInfo.
name );
9176 StreamingReporterBase::testCaseStarting(
testInfo);
9177 m_xml.startElement(
"TestCase" ).writeAttribute(
"name",
trim(
testInfo.name ) );
9179 if ( m_config->showDurations() == ShowDurations::Always )
9180 m_testCaseTimer.start();
9183 virtual void sectionStarting( SectionInfo
const& sectionInfo )
CATCH_OVERRIDE {
9184 StreamingReporterBase::sectionStarting( sectionInfo );
9185 if( m_sectionDepth++ > 0 ) {
9186 m_xml.startElement(
"Section" )
9187 .writeAttribute(
"name",
trim( sectionInfo.name ) )
9188 .writeAttribute(
"description", sectionInfo.description );
9192 virtual void assertionStarting( AssertionInfo
const& )
CATCH_OVERRIDE { }
9194 virtual bool assertionEnded( AssertionStats
const& assertionStats )
CATCH_OVERRIDE {
9195 const AssertionResult& assertionResult = assertionStats.assertionResult;
9198 if( assertionStats.assertionResult.getResultType() !=
ResultWas::Ok ) {
9199 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
9203 m_xml.scopedElement(
"Info" )
9204 .writeText( it->message );
9206 m_xml.scopedElement(
"Warning" )
9207 .writeText( it->message );
9213 if( !m_config->includeSuccessfulResults() &&
isOk(assertionResult.getResultType()) )
9217 if( assertionResult.hasExpression() ) {
9218 m_xml.startElement(
"Expression" )
9219 .writeAttribute(
"success", assertionResult.succeeded() )
9220 .writeAttribute(
"type", assertionResult.getTestMacroName() )
9221 .writeAttribute(
"filename", assertionResult.getSourceInfo().file )
9222 .writeAttribute(
"line", assertionResult.getSourceInfo().line );
9224 m_xml.scopedElement(
"Original" )
9225 .writeText( assertionResult.getExpression() );
9226 m_xml.scopedElement(
"Expanded" )
9227 .writeText( assertionResult.getExpandedExpression() );
9231 switch( assertionResult.getResultType() ) {
9233 m_xml.scopedElement(
"Exception" )
9234 .writeAttribute(
"filename", assertionResult.getSourceInfo().file )
9235 .writeAttribute(
"line", assertionResult.getSourceInfo().line )
9236 .writeText( assertionResult.getMessage() );
9239 m_xml.scopedElement(
"Fatal Error Condition" )
9240 .writeAttribute(
"filename", assertionResult.getSourceInfo().file )
9241 .writeAttribute(
"line", assertionResult.getSourceInfo().line )
9242 .writeText( assertionResult.getMessage() );
9245 m_xml.scopedElement(
"Info" )
9246 .writeText( assertionResult.getMessage() );
9252 m_xml.scopedElement(
"Failure" )
9253 .writeText( assertionResult.getMessage() );
9259 if( assertionResult.hasExpression() )
9265 virtual void sectionEnded( SectionStats
const& sectionStats )
CATCH_OVERRIDE {
9266 StreamingReporterBase::sectionEnded( sectionStats );
9267 if( --m_sectionDepth > 0 ) {
9268 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResults" );
9269 e.writeAttribute(
"successes", sectionStats.assertions.passed );
9270 e.writeAttribute(
"failures", sectionStats.assertions.failed );
9271 e.writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
9273 if ( m_config->showDurations() == ShowDurations::Always )
9274 e.writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
9280 virtual void testCaseEnded( TestCaseStats
const& testCaseStats )
CATCH_OVERRIDE {
9281 StreamingReporterBase::testCaseEnded( testCaseStats );
9282 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResult" );
9283 e.writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
9285 if ( m_config->showDurations() == ShowDurations::Always )
9286 e.writeAttribute(
"durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
9291 virtual void testGroupEnded( TestGroupStats
const& testGroupStats )
CATCH_OVERRIDE {
9292 StreamingReporterBase::testGroupEnded( testGroupStats );
9294 m_xml.scopedElement(
"OverallResults" )
9295 .writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
9296 .writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
9297 .writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
9301 virtual void testRunEnded( TestRunStats
const& testRunStats )
CATCH_OVERRIDE {
9302 StreamingReporterBase::testRunEnded( testRunStats );
9303 m_xml.scopedElement(
"OverallResults" )
9304 .writeAttribute(
"successes", testRunStats.totals.assertions.passed )
9305 .writeAttribute(
"failures", testRunStats.totals.assertions.failed )
9306 .writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
9311 Timer m_testCaseTimer;
9316 INTERNAL_CATCH_REGISTER_REPORTER(
"xml", XmlReporter )
9321 #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
9327 class JunitReporter :
public CumulativeReporterBase {
9329 JunitReporter( ReporterConfig
const& _config )
9330 : CumulativeReporterBase( _config ),
9331 xml( _config.stream() )
9333 m_reporterPrefs.shouldRedirectStdOut =
true;
9338 static
std::
string getDescription() {
9339 return "Reports test results in an XML format that looks like Ant's junitreport target";
9342 virtual void noMatchingTestCases( std::string
const& )
CATCH_OVERRIDE {}
9344 virtual void testRunStarting( TestRunInfo
const& runInfo )
CATCH_OVERRIDE {
9345 CumulativeReporterBase::testRunStarting( runInfo );
9346 xml.startElement(
"testsuites" );
9351 stdOutForSuite.str(
"");
9352 stdErrForSuite.str(
"");
9353 unexpectedExceptions = 0;
9354 CumulativeReporterBase::testGroupStarting( groupInfo );
9357 virtual bool assertionEnded( AssertionStats
const& assertionStats )
CATCH_OVERRIDE {
9359 unexpectedExceptions++;
9360 return CumulativeReporterBase::assertionEnded( assertionStats );
9363 virtual void testCaseEnded( TestCaseStats
const& testCaseStats )
CATCH_OVERRIDE {
9364 stdOutForSuite << testCaseStats.stdOut;
9365 stdErrForSuite << testCaseStats.stdErr;
9366 CumulativeReporterBase::testCaseEnded( testCaseStats );
9369 virtual void testGroupEnded( TestGroupStats
const& testGroupStats )
CATCH_OVERRIDE {
9370 double suiteTime = suiteTimer.getElapsedSeconds();
9371 CumulativeReporterBase::testGroupEnded( testGroupStats );
9372 writeGroup( *m_testGroups.back(), suiteTime );
9379 void writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
9380 XmlWriter::ScopedElement e = xml.scopedElement(
"testsuite" );
9381 TestGroupStats
const& stats = groupNode.value;
9382 xml.writeAttribute(
"name", stats.groupInfo.name );
9383 xml.writeAttribute(
"errors", unexpectedExceptions );
9384 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
9385 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
9386 xml.writeAttribute(
"hostname",
"tbd" );
9387 if( m_config->showDurations() == ShowDurations::Never )
9388 xml.writeAttribute(
"time",
"" );
9390 xml.writeAttribute(
"time", suiteTime );
9391 xml.writeAttribute(
"timestamp",
"tbd" );
9394 for( TestGroupNode::ChildNodes::const_iterator
9395 it = groupNode.children.begin(), itEnd = groupNode.children.end();
9398 writeTestCase( **it );
9400 xml.scopedElement(
"system-out" ).writeText(
trim( stdOutForSuite.str() ),
false );
9401 xml.scopedElement(
"system-err" ).writeText(
trim( stdErrForSuite.str() ),
false );
9404 void writeTestCase( TestCaseNode
const& testCaseNode ) {
9405 TestCaseStats
const& stats = testCaseNode.value;
9409 assert( testCaseNode.children.size() == 1 );
9410 SectionNode
const& rootSection = *testCaseNode.children.front();
9412 std::string className = stats.testInfo.className;
9414 if( className.empty() ) {
9415 if( rootSection.childSections.empty() )
9416 className =
"global";
9418 writeSection( className,
"", rootSection );
9421 void writeSection( std::string
const& className,
9422 std::string
const& rootName,
9423 SectionNode
const& sectionNode ) {
9424 std::string name =
trim( sectionNode.stats.sectionInfo.name );
9425 if( !rootName.empty() )
9426 name = rootName + "/" + name;
9428 if( !sectionNode.assertions.empty() ||
9429 !sectionNode.stdOut.empty() ||
9430 !sectionNode.stdErr.empty() ) {
9431 XmlWriter::ScopedElement e = xml.scopedElement(
"testcase" );
9432 if( className.empty() ) {
9433 xml.writeAttribute(
"classname", name );
9434 xml.writeAttribute(
"name",
"root" );
9437 xml.writeAttribute(
"classname", className );
9438 xml.writeAttribute(
"name", name );
9440 xml.writeAttribute(
"time",
Catch::toString( sectionNode.stats.durationInSeconds ) );
9442 writeAssertions( sectionNode );
9444 if( !sectionNode.stdOut.empty() )
9445 xml.scopedElement(
"system-out" ).writeText(
trim( sectionNode.stdOut ),
false );
9446 if( !sectionNode.stdErr.empty() )
9447 xml.scopedElement(
"system-err" ).writeText(
trim( sectionNode.stdErr ),
false );
9449 for( SectionNode::ChildSections::const_iterator
9450 it = sectionNode.childSections.begin(),
9451 itEnd = sectionNode.childSections.end();
9454 if( className.empty() )
9455 writeSection( name,
"", **it );
9457 writeSection( className, name, **it );
9460 void writeAssertions( SectionNode
const& sectionNode ) {
9461 for( SectionNode::Assertions::const_iterator
9462 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
9465 writeAssertion( *it );
9467 void writeAssertion( AssertionStats
const& stats ) {
9468 AssertionResult
const& result = stats.assertionResult;
9469 if( !result.isOk() ) {
9470 std::string elementName;
9471 switch( result.getResultType() ) {
9474 elementName =
"error";
9477 elementName =
"failure";
9480 elementName =
"failure";
9483 elementName =
"failure";
9493 elementName =
"internalError";
9497 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
9499 xml.writeAttribute(
"message", result.getExpandedExpression() );
9500 xml.writeAttribute(
"type", result.getTestMacroName() );
9502 std::ostringstream oss;
9503 if( !result.getMessage().empty() )
9504 oss << result.getMessage() <<
"\n";
9505 for( std::vector<MessageInfo>::const_iterator
9506 it = stats.infoMessages.begin(),
9507 itEnd = stats.infoMessages.end();
9511 oss << it->message <<
"\n";
9513 oss <<
"at " << result.getSourceInfo();
9514 xml.writeText( oss.str(),
false );
9520 std::ostringstream stdOutForSuite;
9521 std::ostringstream stdErrForSuite;
9522 unsigned int unexpectedExceptions;
9525 INTERNAL_CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
9530 #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
9534 struct ConsoleReporter : StreamingReporterBase {
9535 ConsoleReporter( ReporterConfig
const& _config )
9536 : StreamingReporterBase( _config ),
9537 m_headerPrinted( false )
9541 static
std::
string getDescription() {
9542 return "Reports test results as plain lines of text";
9545 virtual void noMatchingTestCases( std::string
const& spec )
CATCH_OVERRIDE {
9546 stream <<
"No test cases matched '" << spec <<
"'" << std::endl;
9549 virtual void assertionStarting( AssertionInfo
const& )
CATCH_OVERRIDE {
9552 virtual bool assertionEnded( AssertionStats
const& _assertionStats )
CATCH_OVERRIDE {
9553 AssertionResult
const& result = _assertionStats.assertionResult;
9555 bool printInfoMessages =
true;
9558 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
9561 printInfoMessages =
false;
9566 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
9568 stream << std::endl;
9572 virtual void sectionStarting( SectionInfo
const& _sectionInfo )
CATCH_OVERRIDE {
9573 m_headerPrinted =
false;
9574 StreamingReporterBase::sectionStarting( _sectionInfo );
9576 virtual void sectionEnded( SectionStats
const& _sectionStats )
CATCH_OVERRIDE {
9577 if( _sectionStats.missingAssertions ) {
9579 Colour colour( Colour::ResultError );
9580 if( m_sectionStack.size() > 1 )
9581 stream <<
"\nNo assertions in section";
9583 stream <<
"\nNo assertions in test case";
9584 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" << std::endl;
9586 if( m_headerPrinted ) {
9587 if( m_config->showDurations() == ShowDurations::Always )
9588 stream <<
"Completed in " << _sectionStats.durationInSeconds <<
"s" << std::endl;
9589 m_headerPrinted =
false;
9592 if( m_config->showDurations() == ShowDurations::Always )
9593 stream << _sectionStats.sectionInfo.name <<
" completed in " << _sectionStats.durationInSeconds <<
"s" << std::endl;
9595 StreamingReporterBase::sectionEnded( _sectionStats );
9598 virtual void testCaseEnded( TestCaseStats
const& _testCaseStats )
CATCH_OVERRIDE {
9599 StreamingReporterBase::testCaseEnded( _testCaseStats );
9600 m_headerPrinted =
false;
9602 virtual void testGroupEnded( TestGroupStats
const& _testGroupStats )
CATCH_OVERRIDE {
9603 if( currentGroupInfo.used ) {
9604 printSummaryDivider();
9605 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
9606 printTotals( _testGroupStats.totals );
9607 stream <<
"\n" << std::endl;
9609 StreamingReporterBase::testGroupEnded( _testGroupStats );
9611 virtual void testRunEnded( TestRunStats
const& _testRunStats )
CATCH_OVERRIDE {
9612 printTotalsDivider( _testRunStats.totals );
9613 printTotals( _testRunStats.totals );
9614 stream << std::endl;
9615 StreamingReporterBase::testRunEnded( _testRunStats );
9620 class AssertionPrinter {
9621 void operator= ( AssertionPrinter
const& );
9623 AssertionPrinter( std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages )
9624 : stream( _stream ),
9626 result( _stats.assertionResult ),
9627 colour( Colour::
None ),
9628 message( result.getMessage() ),
9629 messages( _stats.infoMessages ),
9630 printInfoMessages( _printInfoMessages )
9632 switch( result.getResultType() ) {
9634 colour = Colour::Success;
9635 passOrFail =
"PASSED";
9637 if( _stats.infoMessages.size() == 1 )
9638 messageLabel =
"with message";
9639 if( _stats.infoMessages.size() > 1 )
9640 messageLabel =
"with messages";
9643 if( result.isOk() ) {
9644 colour = Colour::Success;
9645 passOrFail =
"FAILED - but was ok";
9649 passOrFail =
"FAILED";
9651 if( _stats.infoMessages.size() == 1 )
9652 messageLabel =
"with message";
9653 if( _stats.infoMessages.size() > 1 )
9654 messageLabel =
"with messages";
9658 passOrFail =
"FAILED";
9659 messageLabel =
"due to unexpected exception with message";
9663 passOrFail =
"FAILED";
9664 messageLabel =
"due to a fatal error condition";
9668 passOrFail =
"FAILED";
9669 messageLabel =
"because no exception was thrown where one was expected";
9672 messageLabel =
"info";
9675 messageLabel =
"warning";
9678 passOrFail =
"FAILED";
9680 if( _stats.infoMessages.size() == 1 )
9681 messageLabel =
"explicitly with message";
9682 if( _stats.infoMessages.size() > 1 )
9683 messageLabel =
"explicitly with messages";
9689 passOrFail =
"** internal error **";
9695 void print()
const {
9697 if( stats.totals.assertions.total() > 0 ) {
9701 printOriginalExpression();
9702 printReconstructedExpression();
9711 void printResultType()
const {
9712 if( !passOrFail.empty() ) {
9713 Colour colourGuard( colour );
9714 stream << passOrFail <<
":\n";
9717 void printOriginalExpression()
const {
9718 if( result.hasExpression() ) {
9719 Colour colourGuard( Colour::OriginalExpression );
9721 stream << result.getExpressionInMacro();
9725 void printReconstructedExpression()
const {
9726 if( result.hasExpandedExpression() ) {
9727 stream <<
"with expansion:\n";
9728 Colour colourGuard( Colour::ReconstructedExpression );
9729 stream <<
Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) <<
"\n";
9732 void printMessage()
const {
9733 if( !messageLabel.empty() )
9734 stream << messageLabel <<
":" <<
"\n";
9735 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
9740 stream <<
Text( it->message, TextAttributes().setIndent(2) ) <<
"\n";
9743 void printSourceInfo()
const {
9744 Colour colourGuard( Colour::FileName );
9745 stream << result.getSourceInfo() <<
": ";
9748 std::ostream& stream;
9749 AssertionStats
const& stats;
9750 AssertionResult
const& result;
9751 Colour::Code colour;
9752 std::string passOrFail;
9753 std::string messageLabel;
9754 std::string message;
9755 std::vector<MessageInfo> messages;
9756 bool printInfoMessages;
9761 if( !currentTestRunInfo.used )
9763 if( !currentGroupInfo.used )
9764 lazyPrintGroupInfo();
9766 if( !m_headerPrinted ) {
9767 printTestCaseAndSectionHeader();
9768 m_headerPrinted =
true;
9771 void lazyPrintRunInfo() {
9772 stream <<
"\n" << getLineOfChars<'~'>() <<
"\n";
9773 Colour colour( Colour::SecondaryText );
9774 stream << currentTestRunInfo->name
9775 <<
" is a Catch v" << libraryVersion <<
" host application.\n"
9776 <<
"Run with -? for options\n\n";
9778 if( m_config->rngSeed() != 0 )
9779 stream <<
"Randomness seeded to: " << m_config->rngSeed() <<
"\n\n";
9781 currentTestRunInfo.used =
true;
9783 void lazyPrintGroupInfo() {
9784 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
9785 printClosedHeader(
"Group: " + currentGroupInfo->name );
9786 currentGroupInfo.used =
true;
9789 void printTestCaseAndSectionHeader() {
9790 assert( !m_sectionStack.empty() );
9791 printOpenHeader( currentTestCaseInfo->name );
9793 if( m_sectionStack.size() > 1 ) {
9794 Colour colourGuard( Colour::Headers );
9796 std::vector<SectionInfo>::const_iterator
9797 it = m_sectionStack.begin()+1,
9798 itEnd = m_sectionStack.end();
9799 for( ; it != itEnd; ++it )
9800 printHeaderString( it->name, 2 );
9803 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
9805 if( !lineInfo.empty() ){
9806 stream << getLineOfChars<
'-'>() <<
"\n";
9807 Colour colourGuard( Colour::FileName );
9808 stream << lineInfo <<
"\n";
9810 stream << getLineOfChars<'.'>() <<
"\n" << std::endl;
9813 void printClosedHeader( std::string
const& _name ) {
9814 printOpenHeader( _name );
9815 stream << getLineOfChars<
'.'>() <<
"\n";
9817 void printOpenHeader( std::string
const& _name ) {
9818 stream << getLineOfChars<
'-'>() <<
"\n";
9820 Colour colourGuard( Colour::Headers );
9821 printHeaderString( _name );
9827 void printHeaderString( std::string
const& _string, std::size_t indent = 0 ) {
9828 std::size_t i = _string.find(
": " );
9829 if( i != std::string::npos )
9833 stream <<
Text( _string, TextAttributes()
9834 .setIndent( indent+i)
9835 .setInitialIndent( indent ) ) <<
"\n";
9838 struct SummaryColumn {
9840 SummaryColumn( std::string
const& _label, Colour::Code _colour )
9844 SummaryColumn addRow( std::size_t count ) {
9845 std::ostringstream oss;
9847 std::string row = oss.str();
9848 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
9849 while( it->size() < row.size() )
9851 while( it->size() > row.size() )
9854 rows.push_back( row );
9859 Colour::Code colour;
9860 std::vector<std::string> rows;
9864 void printTotals( Totals
const& totals ) {
9865 if( totals.testCases.total() == 0 ) {
9866 stream << Colour( Colour::Warning ) <<
"No tests ran\n";
9868 else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
9869 stream << Colour( Colour::ResultSuccess ) <<
"All tests passed";
9871 << pluralise( totals.assertions.passed,
"assertion" ) <<
" in "
9872 << pluralise( totals.testCases.passed,
"test case" ) <<
")"
9877 std::vector<SummaryColumn> columns;
9879 .addRow( totals.testCases.total() )
9880 .addRow( totals.assertions.total() ) );
9881 columns.push_back( SummaryColumn(
"passed", Colour::Success )
9882 .addRow( totals.testCases.passed )
9883 .addRow( totals.assertions.passed ) );
9884 columns.push_back( SummaryColumn(
"failed", Colour::ResultError )
9885 .addRow( totals.testCases.failed )
9886 .addRow( totals.assertions.failed ) );
9887 columns.push_back( SummaryColumn(
"failed as expected", Colour::ResultExpectedFailure )
9888 .addRow( totals.testCases.failedButOk )
9889 .addRow( totals.assertions.failedButOk ) );
9891 printSummaryRow(
"test cases", columns, 0 );
9892 printSummaryRow(
"assertions", columns, 1 );
9895 void printSummaryRow( std::string
const& label, std::vector<SummaryColumn>
const& cols, std::size_t row ) {
9896 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
9897 std::string value = it->rows[row];
9898 if( it->label.empty() ) {
9899 stream << label <<
": ";
9903 stream << Colour( Colour::Warning ) <<
"- none -";
9905 else if( value !=
"0" ) {
9907 stream << Colour( it->colour )
9908 << value <<
" " << it->label;
9914 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
9915 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
9916 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
9918 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
9919 if( i > j && i > k )
9927 void printTotalsDivider( Totals
const& totals ) {
9928 if( totals.testCases.total() > 0 ) {
9929 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
9930 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
9931 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
9932 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
9933 findMax( failedRatio, failedButOkRatio, passedRatio )++;
9934 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
9935 findMax( failedRatio, failedButOkRatio, passedRatio )--;
9937 stream << Colour(
Colour::Error ) << std::string( failedRatio,
'=' );
9938 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio,
'=' );
9939 if( totals.testCases.allPassed() )
9940 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio,
'=' );
9942 stream << Colour( Colour::Success ) << std::string( passedRatio,
'=' );
9945 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1,
'=' );
9949 void printSummaryDivider() {
9950 stream << getLineOfChars<
'-'>() <<
"\n";
9954 bool m_headerPrinted;
9957 INTERNAL_CATCH_REGISTER_REPORTER(
"console", ConsoleReporter )
9962 #define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
9966 struct CompactReporter : StreamingReporterBase {
9968 CompactReporter( ReporterConfig
const& _config )
9969 : StreamingReporterBase( _config )
9972 virtual ~CompactReporter();
9974 static std::string getDescription() {
9975 return "Reports test results on a single line, suitable for IDEs";
9978 virtual ReporterPreferences getPreferences()
const {
9979 ReporterPreferences prefs;
9980 prefs.shouldRedirectStdOut =
false;
9984 virtual void noMatchingTestCases( std::string
const& spec ) {
9985 stream <<
"No test cases matched '" << spec <<
"'" << std::endl;
9988 virtual void assertionStarting( AssertionInfo
const& ) {
9991 virtual bool assertionEnded( AssertionStats
const& _assertionStats ) {
9992 AssertionResult
const& result = _assertionStats.assertionResult;
9994 bool printInfoMessages =
true;
9997 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
10000 printInfoMessages =
false;
10003 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
10006 stream << std::endl;
10010 virtual void testRunEnded( TestRunStats
const& _testRunStats ) {
10011 printTotals( _testRunStats.totals );
10012 stream <<
"\n" << std::endl;
10013 StreamingReporterBase::testRunEnded( _testRunStats );
10017 class AssertionPrinter {
10018 void operator= ( AssertionPrinter
const& );
10020 AssertionPrinter( std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages )
10021 : stream( _stream )
10023 , result( _stats.assertionResult )
10024 , messages( _stats.infoMessages )
10025 , itMessage( _stats.infoMessages.begin() )
10026 , printInfoMessages( _printInfoMessages )
10032 itMessage = messages.begin();
10034 switch( result.getResultType() ) {
10036 printResultType( Colour::ResultSuccess, passedString() );
10037 printOriginalExpression();
10038 printReconstructedExpression();
10039 if ( ! result.hasExpression() )
10042 printRemainingMessages();
10045 if( result.isOk() )
10046 printResultType( Colour::ResultSuccess, failedString() + std::string(
" - but was ok" ) );
10049 printOriginalExpression();
10050 printReconstructedExpression();
10051 printRemainingMessages();
10055 printIssue(
"unexpected exception with message:" );
10057 printExpressionWas();
10058 printRemainingMessages();
10062 printIssue(
"fatal error condition with message:" );
10064 printExpressionWas();
10065 printRemainingMessages();
10069 printIssue(
"expected exception, got none" );
10070 printExpressionWas();
10071 printRemainingMessages();
10076 printRemainingMessages();
10081 printRemainingMessages();
10085 printIssue(
"explicitly" );
10100 static Colour::Code dimColour() {
return Colour::FileName; }
10102 #ifdef CATCH_PLATFORM_MAC
10103 static const char* failedString() {
return "FAILED"; }
10104 static const char* passedString() {
return "PASSED"; }
10106 static const char* failedString() {
return "failed"; }
10107 static const char* passedString() {
return "passed"; }
10110 void printSourceInfo()
const {
10111 Colour colourGuard( Colour::FileName );
10112 stream << result.getSourceInfo() <<
":";
10115 void printResultType( Colour::Code colour, std::string passOrFail )
const {
10116 if( !passOrFail.empty() ) {
10118 Colour colourGuard( colour );
10119 stream <<
" " << passOrFail;
10125 void printIssue( std::string issue )
const {
10126 stream <<
" " << issue;
10129 void printExpressionWas() {
10130 if( result.hasExpression() ) {
10133 Colour colour( dimColour() );
10134 stream <<
" expression was:";
10136 printOriginalExpression();
10140 void printOriginalExpression()
const {
10141 if( result.hasExpression() ) {
10142 stream <<
" " << result.getExpression();
10146 void printReconstructedExpression()
const {
10147 if( result.hasExpandedExpression() ) {
10149 Colour colour( dimColour() );
10150 stream <<
" for: ";
10152 stream << result.getExpandedExpression();
10156 void printMessage() {
10157 if ( itMessage != messages.end() ) {
10158 stream <<
" '" << itMessage->message <<
"'";
10163 void printRemainingMessages( Colour::Code colour = dimColour() ) {
10164 if ( itMessage == messages.end() )
10168 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
10169 const std::size_t N =
static_cast<std::size_t
>( std::distance( itMessage, itEnd ) );
10172 Colour colourGuard( colour );
10173 stream <<
" with " << pluralise( N,
"message" ) <<
":";
10176 for(; itMessage != itEnd; ) {
10179 stream <<
" '" << itMessage->message <<
"'";
10180 if ( ++itMessage != itEnd ) {
10181 Colour colourGuard( dimColour() );
10189 std::ostream& stream;
10190 AssertionStats
const& stats;
10191 AssertionResult
const& result;
10192 std::vector<MessageInfo> messages;
10193 std::vector<MessageInfo>::const_iterator itMessage;
10194 bool printInfoMessages;
10204 std::string bothOrAll( std::size_t count )
const {
10205 return count == 1 ?
"" : count == 2 ?
"both " :
"all " ;
10208 void printTotals(
const Totals& totals )
const {
10209 if( totals.testCases.total() == 0 ) {
10210 stream <<
"No tests ran.";
10212 else if( totals.testCases.failed == totals.testCases.total() ) {
10213 Colour colour( Colour::ResultError );
10214 const std::string qualify_assertions_failed =
10215 totals.assertions.failed == totals.assertions.total() ?
10216 bothOrAll( totals.assertions.failed ) :
"";
10218 "Failed " << bothOrAll( totals.testCases.failed )
10219 << pluralise( totals.testCases.failed,
"test case" ) <<
", "
10220 "failed " << qualify_assertions_failed <<
10221 pluralise( totals.assertions.failed,
"assertion" ) <<
".";
10223 else if( totals.assertions.total() == 0 ) {
10225 "Passed " << bothOrAll( totals.testCases.total() )
10226 << pluralise( totals.testCases.total(),
"test case" )
10227 <<
" (no assertions).";
10229 else if( totals.assertions.failed ) {
10230 Colour colour( Colour::ResultError );
10232 "Failed " << pluralise( totals.testCases.failed,
"test case" ) <<
", "
10233 "failed " << pluralise( totals.assertions.failed,
"assertion" ) <<
".";
10236 Colour colour( Colour::ResultSuccess );
10238 "Passed " << bothOrAll( totals.testCases.passed )
10239 << pluralise( totals.testCases.passed,
"test case" ) <<
10240 " with " << pluralise( totals.assertions.passed,
"assertion" ) <<
".";
10245 INTERNAL_CATCH_REGISTER_REPORTER(
"compact", CompactReporter )
10267 IReporter::~IReporter() {}
10268 IReporterFactory::~IReporterFactory() {}
10269 IReporterRegistry::~IReporterRegistry() {}
10270 IStreamingReporter::~IStreamingReporter() {}
10271 AssertionStats::~AssertionStats() {}
10272 SectionStats::~SectionStats() {}
10273 TestCaseStats::~TestCaseStats() {}
10274 TestGroupStats::~TestGroupStats() {}
10275 TestRunStats::~TestRunStats() {}
10276 CumulativeReporterBase::SectionNode::~SectionNode() {}
10277 CumulativeReporterBase::~CumulativeReporterBase() {}
10279 StreamingReporterBase::~StreamingReporterBase() {}
10280 ConsoleReporter::~ConsoleReporter() {}
10281 CompactReporter::~CompactReporter() {}
10284 IConfig::~IConfig() {}
10285 XmlReporter::~XmlReporter() {}
10286 JunitReporter::~JunitReporter() {}
10287 TestRegistry::~TestRegistry() {}
10288 FreeFunctionTestCase::~FreeFunctionTestCase() {}
10291 WildcardPattern::~WildcardPattern() {}
10292 TestSpec::Pattern::~Pattern() {}
10293 TestSpec::NamePattern::~NamePattern() {}
10294 TestSpec::TagPattern::~TagPattern() {}
10295 TestSpec::ExcludedPattern::~ExcludedPattern() {}
10302 void Config::dummy() {}
10304 namespace TestCaseTracking {
10305 ITracker::~ITracker() {}
10306 TrackerBase::~TrackerBase() {}
10307 SectionTracker::~SectionTracker() {}
10308 IndexTracker::~IndexTracker() {}
10313 #pragma clang diagnostic pop
10318 #ifdef CATCH_CONFIG_MAIN
10320 #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
10325 int main (
int argc,
char * argv[]) {
10326 return Catch::Session().run( argc, argv );
10332 int main (
int argc,
char *
const argv[]) {
10333 #if !CATCH_ARC_ENABLED
10334 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
10337 Catch::registerTestMethods();
10338 int result = Catch::Session().run( argc, (
char*
const*)argv );
10340 #if !CATCH_ARC_ENABLED
10351 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
10352 # undef CLARA_CONFIG_MAIN
10358 #ifdef CATCH_CONFIG_PREFIX_ALL
10360 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
10361 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
10363 #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
10364 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
10365 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" )
10366 #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
10368 #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
10369 #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
10370 #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
10371 #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
10372 #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
10374 #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
10375 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
10376 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
10377 #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
10379 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
10380 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
10382 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
10383 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
10384 #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
10385 #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
10386 #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
10388 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10389 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
10390 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
10391 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
10392 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
10393 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
10394 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
10395 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
10397 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
10398 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
10399 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
10400 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
10401 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
10402 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
10403 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
10405 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
10407 #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
10408 #define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
10410 #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
10413 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10414 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
10415 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
10417 #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
10418 #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
10420 #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
10421 #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
10422 #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
10423 #define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
10424 #define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
10429 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
10430 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
10432 #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
10433 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
10434 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
10435 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
10437 #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
10438 #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
10439 #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
10440 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
10441 #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
10443 #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
10444 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
10445 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
10446 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
10448 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
10449 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
10451 #define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
10452 #define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
10453 #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
10454 #define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
10455 #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
10457 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10458 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
10459 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
10460 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
10461 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
10462 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
10463 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
10464 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
10466 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
10467 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
10468 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
10469 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
10470 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
10471 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
10472 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
10474 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
10476 #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
10477 #define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
10479 #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
10483 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
10486 #ifdef CATCH_CONFIG_VARIADIC_MACROS
10487 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
10488 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
10490 #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
10491 #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
10493 #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
10494 #define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
10495 #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
10496 #define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
10497 #define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
#define CATCH_INTERNAL_ERROR(msg)
std::string getExpression() const
bool hasExpandedExpression() const
SourceLineInfo getSourceInfo() const
std::string getExpandedExpression() const
std::string getExpressionInMacro() const
std::string getTestMacroName() const
AssertionResult(AssertionInfo const &info, AssertionResultData const &data)
bool hasExpression() const
ResultWas::OfType getResultType() const
AssertionResultData m_resultData
std::string getMessage() const
BetweenGenerator(T from, T to)
virtual T getValue(std::size_t index) const
virtual std::size_t size() const
CompositeGenerator(CompositeGenerator &other)
CompositeGenerator & then(CompositeGenerator &other)
std::vector< const IGenerator< T > * > m_composed
CompositeGenerator & setFileInfo(const char *fileInfo)
CompositeGenerator & then(T value)
void add(const IGenerator< T > *generator)
void move(CompositeGenerator &other)
Approx & epsilon(double newEpsilon)
Approx operator()(double value)
Approx(Approx const &other)
std::string toString() const
Approx & scale(double newScale)
ExceptionTranslator(std::string(*translateFunction)(T &))
virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
ResultBuilder & captureExpression(RhsT const &rhs)
ExpressionLhs(ResultBuilder &rb, T lhs)
AllOf(AllOf const &other)
AllOf & add(Matcher< ExpressionT > const &matcher)
virtual std::string toString() const
virtual bool match(ExpressionT const &expr) const
std::vector< Ptr< Matcher< ExpressionT > > > m_matchers
virtual std::string toString() const
std::vector< Ptr< Matcher< ExpressionT > > > m_matchers
AnyOf & add(Matcher< ExpressionT > const &matcher)
AnyOf(AnyOf const &other)
virtual bool match(ExpressionT const &expr) const
virtual bool match(ExpressionT const &expr) const
Not(Matcher< ExpressionT > const &matcher)
virtual std::string toString() const
Ptr< Matcher< ExpressionT > > m_matcher
virtual void invoke() const
virtual ~MethodTestCase()
MethodTestCase(void(C::*method)())
NonCopyable(NonCopyable const &info)
NonCopyable & operator=(NonCopyable const &)
virtual const char * what() const
virtual ~NotImplementedException()
NotImplementedException(NotImplementedException const &)
SourceLineInfo m_lineInfo
NotImplementedException(SourceLineInfo const &lineInfo)
T const & operator*() const
Option & operator=(Option const &_other)
T valueOr(T const &defaultValue) const
const T * operator->() const
Option(Option const &_other)
void captureResult(ResultWas::OfType resultType)
AssertionResult build() const
void useActiveException(ResultDisposition::Flags resultDisposition=ResultDisposition::Normal)
ResultBuilder & setLhs(std::string const &lhs)
AssertionResultData m_data
AssertionInfo m_assertionInfo
bool shouldDebugBreak() const
void captureExpectedException(Matchers::Impl::Matcher< std::string > const &matcher)
ResultBuilder & setOp(std::string const &op)
ResultBuilder(char const *macroName, SourceLineInfo const &lineInfo, char const *capturedExpression, ResultDisposition::Flags resultDisposition, char const *secondArg="")
void captureExpectedException(std::string const &expectedMessage)
ResultBuilder & setRhs(std::string const &rhs)
ExpressionLhs< T const & > operator<=(T const &operand)
void handleResult(AssertionResult const &result)
ResultBuilder & setResultType(bool result)
std::string reconstructExpression() const
ResultBuilder & setResultType(ResultWas::OfType result)
void(SafeBool::* type)() const
static type makeSafe(bool value)
ScopedMessage(MessageBuilder const &builder)
ScopedMessage(ScopedMessage const &other)
Section(SectionInfo const &info)
TestCase(ITestCase *testCase, TestCaseInfo const &info)
TestCase withName(std::string const &_newName) const
TestCaseInfo const & getTestCaseInfo() const
TestCase(TestCase const &other)
void swap(TestCase &other)
unsigned int getElapsedMilliseconds() const
double getElapsedSeconds() const
unsigned int getElapsedMicroseconds() const
std::vector< T > m_values
virtual T getValue(std::size_t index) const
virtual std::size_t size() const
int main(int argc, char *argv[])
bool msg(InputEvent &event)
bool testInfo(InputEvent &event)
bool move(InputEvent &event)
bool info(InputEvent &event)
bool find(const std::string &key)
AttributesT get(const std::string &key)
std::string rawMemoryToString(const T &object)
const std::string unprintableString
std::string rangeToString(InputIterator first, InputIterator last)
FalseType testStreamable(FalseType)
std::string rawMemoryToString(const void *object, std::size_t size)
FalseType operator<<(std::ostream const &, BorgType const &)
std::string makeString(T const &value)
CompositeGenerator< T > between(T from, T to)
CompositeGenerator< T > values(T val1, T val2, T val3, T val4)
bool applyEvaluator(T1 const &lhs, T2 const &rhs)
bool compare(T *lhs, int rhs)
Impl::StdString::StartsWith StartsWith(const char *substr)
Impl::StdString::Equals Equals(const char *str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Impl::StdString::Contains Contains(const char *substr, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Impl::Generic::AnyOf< ExpressionT > AnyOf(Impl::Matcher< ExpressionT > const &m1, Impl::Matcher< ExpressionT > const &m2, Impl::Matcher< ExpressionT > const &m3)
Impl::Generic::AllOf< ExpressionT > AllOf(Impl::Matcher< ExpressionT > const &m1, Impl::Matcher< ExpressionT > const &m2, Impl::Matcher< ExpressionT > const &m3)
Impl::Generic::Not< ExpressionT > Not(Impl::Matcher< ExpressionT > const &m)
Impl::StdString::EndsWith EndsWith(const char *substr)
void toLowerInPlace(std::string &s)
std::string trim(std::string const &str)
std::string(* exceptionTranslateFunction)()
void seedRng(IConfig const &config)
std::vector< TestCase > const & getAllTestCasesSorted(IConfig const &config)
void registerTestCaseFunction(TestFunction function, SourceLineInfo const &lineInfo, NameAndDesc const &nameAndDesc)
std::string toString(std::vector< T, Allocator > const &v)
TestCase makeTestCase(ITestCase *testCase, std::string const &className, std::string const &name, std::string const &description, SourceLineInfo const &lineInfo)
IGeneratorsForTest * createGeneratorsForTest()
bool isOk(ResultWas::OfType resultType)
bool isJustInfo(int flags)
T const & operator+(T const &value, StreamEndStop)
bool startsWith(std::string const &s, std::string const &prefix)
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
void throwLogicError(std::string const &message, SourceLineInfo const &locationInfo)
bool shouldContinueOnFailure(int flags)
bool isFalseTest(int flags)
void registerTestCase(ITestCase *testCase, char const *className, NameAndDesc const &nameAndDesc, SourceLineInfo const &lineInfo)
bool contains(std::string const &s, std::string const &infix)
void writeToDebugConsole(std::string const &text)
bool matchTest(TestCase const &testCase, TestSpec const &testSpec, IConfig const &config)
void deleteAll(ContainerT &container)
ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
std::vector< TestCase > filterTests(std::vector< TestCase > const &testCases, TestSpec const &testSpec, IConfig const &config)
bool shouldSuppressFailure(int flags)
std::string toLower(std::string const &s)
IRegistryHub & getRegistryHub()
IMutableRegistryHub & getMutableRegistryHub()
IContext & getCurrentContext()
Stream createStream(std::string const &streamName)
bool endsWith(std::string const &s, std::string const &suffix)
std::string translateActiveException()
std::string toString(T const &value)
converts any type to a string
std::vector< const IExceptionTranslator * > ExceptionTranslators
void deleteAllValues(AssociativeContainerT &container)
IMutableContext & getCurrentMutableContext()
bool replaceInPlace(std::string &str, std::string const &replaceThis, std::string const &withThis)
IResultCapture & getResultCapture()
Resource *(&) generator(const void *const data)
void release(Resource *const res)
TcpNet::Socket open(IPaddress *const ip)
bool remove(const std::string &filename)
int close(File *const file)
int registerReporter(const char *name, int priority, IReporter *r)
bool operator>(const vector< _Ty, _Alloc > &_Left, const vector< _Ty, _Alloc > &_Right)
bool operator<=(const vector< _Ty, _Alloc > &_Left, const vector< _Ty, _Alloc > &_Right)
bool operator>=(const vector< _Ty, _Alloc > &_Left, const vector< _Ty, _Alloc > &_Right)
bool operator!=(const vector< _Ty, _Alloc > &_Left, const vector< _Ty, _Alloc > &_Right)
CInt operator-(size_t lhs, const CInt &rhs)
bool operator==(size_t lhs, const CInt &rhs)
bool operator<(size_t lhs, const CInt &rhs)
CInt operator*(size_t lhs, const CInt &rhs)
CInt operator/(size_t lhs, const CInt &rhs)
decltype(nullptr) typedef nullptr_t
ResultDisposition::Flags resultDisposition
AssertionInfo(std::string const &_macroName, SourceLineInfo const &_lineInfo, std::string const &_capturedExpression, ResultDisposition::Flags _resultDisposition)
std::string capturedExpression
ResultWas::OfType resultType
std::string reconstructedExpression
AutoReg(void(C::*method)(), char const *className, NameAndDesc const &nameAndDesc, SourceLineInfo const &lineInfo)
AutoReg(TestFunction function, SourceLineInfo const &lineInfo, NameAndDesc const &nameAndDesc)
CopyableStream(CopyableStream const &other)
CopyableStream & operator=(CopyableStream const &other)
std::size_t total() const
static std::string convert(T const &_value)
static std::string convert(T const &)
virtual size_t getGeneratorIndex(std::string const &fileInfo, size_t totalSize)=0
virtual IResultCapture * getResultCapture()=0
virtual bool advanceGeneratorsForCurrentTest()=0
virtual Ptr< IConfig const > getConfig() const =0
virtual IRunner * getRunner()=0
virtual ~IExceptionTranslatorRegistry()
virtual std::string translateActiveException() const =0
virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const =0
virtual ~IExceptionTranslator()
virtual bool moveNext()=0
virtual std::size_t getCurrentIndex() const =0
virtual ~IGeneratorInfo()
virtual std::size_t size() const =0
virtual T getValue(std::size_t index) const =0
virtual ~IGeneratorsForTest()
virtual IGeneratorInfo & getGeneratorInfo(std::string const &fileInfo, std::size_t size)=0
virtual bool moveNext()=0
virtual void setConfig(Ptr< IConfig const > const &config)=0
virtual void setResultCapture(IResultCapture *resultCapture)=0
virtual ~IMutableContext()
virtual void setRunner(IRunner *runner)=0
virtual void registerTest(TestCase const &testInfo)=0
virtual ~IMutableRegistryHub()
virtual void registerReporter(std::string const &name, Ptr< IReporterFactory > const &factory)=0
virtual void registerListener(Ptr< IReporterFactory > const &factory)=0
virtual void registerTranslator(const IExceptionTranslator *translator)=0
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry()=0
virtual IReporterRegistry const & getReporterRegistry() const =0
virtual ITestCaseRegistry const & getTestCaseRegistry() const =0
virtual ~IResultCapture()
virtual void popScopedMessage(MessageInfo const &message)=0
virtual void sectionEnded(SectionEndInfo const &endInfo)=0
virtual bool sectionStarted(SectionInfo const §ionInfo, Counts &assertions)=0
virtual void handleFatalErrorCondition(std::string const &message)=0
virtual void pushScopedMessage(MessageInfo const &message)=0
virtual const AssertionResult * getLastResult() const =0
virtual void assertionEnded(AssertionResult const &result)=0
virtual std::string getCurrentTestName() const =0
virtual void sectionEndedEarly(SectionEndInfo const &endInfo)=0
virtual bool aborting() const =0
virtual void release() const =0
virtual void addRef() const =0
virtual Option< TagAlias > find(std::string const &alias) const =0
virtual ~ITagAliasRegistry()
static ITagAliasRegistry const & get()
virtual std::string expandAliases(std::string const &unexpandedTestSpec) const =0
virtual std::vector< TestCase > const & getAllTestsSorted(IConfig const &config) const =0
virtual std::vector< TestCase > const & getAllTests() const =0
virtual ~ITestCaseRegistry()
virtual void invoke() const =0
static bool evaluate(T1 const &lhs, T2 const &rhs)
static bool evaluate(T1 const &lhs, T2 const &rhs)
static bool evaluate(T1 const &lhs, T2 const &rhs)
static bool evaluate(T1 const &lhs, T2 const &rhs)
static bool evaluate(T1 const &lhs, T2 const &rhs)
static bool evaluate(T1 const &lhs, T2 const &rhs)
static const char * getName()
static const char * getName()
static const char * getName()
static const char * getName()
static const char * getName()
static const char * getName()
static const char * getName()
virtual Ptr< Matcher< ExpressionT > > clone() const
virtual std::string toString() const =0
ExpressionT ExpressionType
virtual bool match(ExpressionT const &expr) const =0
virtual Ptr< Matcher > clone() const =0
std::string adjustString(std::string const &str) const
std::string toStringSuffix() const
CasedString(std::string const &str, CaseSensitive::Choice caseSensitivity)
CaseSensitive::Choice m_caseSensitivity
virtual bool match(std::string const &expr) const
Contains(std::string const &substr, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Contains(Contains const &other)
virtual std::string toString() const
virtual std::string toString() const
EndsWith(EndsWith const &other)
EndsWith(std::string const &substr, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
virtual bool match(std::string const &expr) const
Equals(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
virtual std::string toString() const
virtual bool match(std::string const &expr) const
Equals(Equals const &other)
StartsWith(std::string const &substr, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
StartsWith(StartsWith const &other)
virtual std::string toString() const
virtual bool match(std::string const &expr) const
std::ostringstream m_stream
MessageBuilder(std::string const ¯oName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
static unsigned int globalCount
MessageInfo(std::string const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
NameAndDesc(const char *_name="", const char *_description="")
RegistrarForTagAliases(char const *alias, char const *tag, SourceLineInfo const &lineInfo)
SectionEndInfo(SectionInfo const &_sectionInfo, Counts const &_prevAssertions, double _durationInSeconds)
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name, std::string const &_description=std::string())
virtual void addRef() const
virtual void release() const
SourceLineInfo(SourceLineInfo const &other)
SourceLineInfo(char const *_file, std::size_t _line)
bool operator==(SourceLineInfo const &other) const
bool operator<(SourceLineInfo const &other) const
static std::string convert(R C::*p)
static std::string convert(U *p)
TagAlias(std::string _tag, SourceLineInfo _lineInfo)
std::set< std::string > tags
std::set< std::string > lcaseTags
TestCaseInfo(std::string const &_name, std::string const &_className, std::string const &_description, std::set< std::string > const &_tags, SourceLineInfo const &_lineInfo)
bool expectedToFail() const
TestCaseInfo(TestCaseInfo const &other)
friend void setTags(TestCaseInfo &testCaseInfo, std::set< std::string > const &tags)
SpecialProperties properties
Totals delta(Totals const &prevTotals) const
pluralise(std::size_t count, std::string const &label)
friend std::ostream & operator<<(std::ostream &os, pluralise const &pluraliser)