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
19# pragma GCC system_header
24#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
29# pragma warning(disable: 161 1682)
31# pragma clang diagnostic ignored "-Wglobal-constructors"
32# pragma clang diagnostic ignored "-Wvariadic-macros"
33# pragma clang diagnostic ignored "-Wc99-extensions"
34# pragma clang diagnostic ignored "-Wunused-variable"
35# pragma clang diagnostic push
36# pragma clang diagnostic ignored "-Wpadded"
37# pragma clang diagnostic ignored "-Wc++98-compat"
38# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
39# pragma clang diagnostic ignored "-Wswitch-enum"
42# pragma GCC diagnostic ignored "-Wvariadic-macros"
43# pragma GCC diagnostic ignored "-Wunused-variable"
44# pragma GCC diagnostic push
45# pragma GCC diagnostic ignored "-Wpadded"
48#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
53# ifndef CLARA_CONFIG_MAIN
54# define CLARA_CONFIG_MAIN_NOT_DEFINED
55# define CLARA_CONFIG_MAIN
60#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
63#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
65#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
66#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
67#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
69#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
70#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
77#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
101# if __has_feature(cxx_nullptr)
102# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
105# if __has_feature(cxx_noexcept)
106# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
119#ifdef __EDG_VERSION__
133#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
134# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
143#if (_MSC_VER >= 1600)
144# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
147#if (_MSC_VER >= 1900 )
148#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
149#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
155#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
156 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
157 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
158 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
160#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
168#if (__cplusplus >= 201103L)
170# define CATCH_CPP11_OR_GREATER
172# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
173# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
176# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
177# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
180# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
181# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
184# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
185# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
188# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
189# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
192# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
193# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
199#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
200# define CATCH_CONFIG_CPP11_NULLPTR
202#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
203# define CATCH_CONFIG_CPP11_NOEXCEPT
205#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)
206# define CATCH_CONFIG_CPP11_GENERATED_METHODS
208#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)
209# define CATCH_CONFIG_CPP11_IS_ENUM
211#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
212# define CATCH_CONFIG_CPP11_TUPLE
214#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
215#define CATCH_CONFIG_VARIADIC_MACROS
219#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
220# define CATCH_NOEXCEPT noexcept
221# define CATCH_NOEXCEPT_IS(x) noexcept(x)
223# define CATCH_NOEXCEPT throw()
224# define CATCH_NOEXCEPT_IS(x)
230#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
256 template<
typename ContainerT>
258 typename ContainerT::const_iterator it = container.begin();
259 typename ContainerT::const_iterator itEnd = container.end();
260 for(; it != itEnd; ++it )
263 template<
typename AssociativeContainerT>
265 typename AssociativeContainerT::const_iterator it = container.begin();
266 typename AssociativeContainerT::const_iterator itEnd = container.end();
267 for(; it != itEnd; ++it )
271 bool startsWith( std::string
const& s, std::string
const& prefix );
272 bool endsWith( std::string
const& s, std::string
const& suffix );
273 bool contains( std::string
const& s, std::string
const& infix );
276 std::string
trim( std::string
const& str );
277 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis );
280 pluralise( std::size_t count, std::string
const& label );
293# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
309 inline bool isTrue(
bool value ){
return value; }
321 return std::string();
330#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
331#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
355#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
358#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
361#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
385#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
388#pragma clang diagnostic push
389#pragma clang diagnostic ignored "-Wpadded"
405 Ptr(
Ptr const& other ) : m_p( other.m_p ){
430 const T*
get()
const{
return m_p; }
433 bool operator !()
const {
return m_p == NULL; }
446 template<
typename T = IShared>
465#pragma clang diagnostic pop
476 struct IResultCapture;
478 struct IGeneratorsForTest;
508#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
511#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
552 void (C::*m_method)();
558 NameAndDesc(
const char* _name =
"",
const char* _description=
"" )
559 : name( _name ), description( _description )
574 char const* className,
584 char const* className,
597#ifdef CATCH_CONFIG_VARIADIC_MACROS
599 #define INTERNAL_CATCH_TESTCASE( ... ) \
600 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
601 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
602 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
605 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
606 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
609 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
611 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
614 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
616 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
620 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
621 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
622 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
623 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
626 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
627 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
630 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
632 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
635 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
637 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
642#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
645#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
648#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
661 ExpressionFailed = FailureBit | 1,
662 ExplicitFailure = FailureBit | 2,
664 Exception = 0x100 | FailureBit,
666 ThrewException = Exception | 1,
667 DidntThrowException = Exception | 2,
669 FatalErrorCondition = 0x200 | FailureBit
684 ContinueOnFailure = 0x02,
700#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
711 std::string
const& _capturedExpression,
734# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
767 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
772 oss << other.
oss.str();
776 oss << other.
oss.str();
786 char const* capturedExpression,
795 m_stream.oss << value;
799 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT
const& );
800 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT
const& );
838#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
841#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
845#pragma warning(disable:4389)
871 inline T&
opCast(T
const& t) {
return const_cast<T&
>(t); }
874#ifdef CATCH_CONFIG_CPP11_NULLPTR
875 inline std::nullptr_t
opCast(std::nullptr_t) {
return nullptr; }
880 template<
typename T1,
typename T2, Operator Op>
883 template<
typename T1,
typename T2>
885 static bool evaluate( T1
const& lhs, T2
const& rhs) {
889 template<
typename T1,
typename T2>
891 static bool evaluate( T1
const& lhs, T2
const& rhs ) {
895 template<
typename T1,
typename T2>
897 static bool evaluate( T1
const& lhs, T2
const& rhs ) {
901 template<
typename T1,
typename T2>
903 static bool evaluate( T1
const& lhs, T2
const& rhs ) {
907 template<
typename T1,
typename T2>
909 static bool evaluate( T1
const& lhs, T2
const& rhs ) {
913 template<
typename T1,
typename T2>
915 static bool evaluate( T1
const& lhs, T2
const& rhs ) {
920 template<Operator Op,
typename T1,
typename T2>
929 template<Operator Op,
typename T1,
typename T2>
930 bool compare( T1
const& lhs, T2
const& rhs ) {
935 template<Operator Op>
bool compare(
unsigned int lhs,
int rhs ) {
936 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
938 template<Operator Op>
bool compare(
unsigned long lhs,
int rhs ) {
939 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
941 template<Operator Op>
bool compare(
unsigned char lhs,
int rhs ) {
942 return applyEvaluator<Op>( lhs,
static_cast<unsigned int>( rhs ) );
946 template<Operator Op>
bool compare(
unsigned int lhs,
long rhs ) {
947 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
949 template<Operator Op>
bool compare(
unsigned long lhs,
long rhs ) {
950 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
952 template<Operator Op>
bool compare(
unsigned char lhs,
long rhs ) {
953 return applyEvaluator<Op>( lhs,
static_cast<unsigned long>( rhs ) );
957 template<Operator Op>
bool compare(
int lhs,
unsigned int rhs ) {
958 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
960 template<Operator Op>
bool compare(
int lhs,
unsigned long rhs ) {
961 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
963 template<Operator Op>
bool compare(
int lhs,
unsigned char rhs ) {
964 return applyEvaluator<Op>(
static_cast<unsigned int>( lhs ), rhs );
968 template<Operator Op>
bool compare(
long lhs,
unsigned int rhs ) {
969 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
971 template<Operator Op>
bool compare(
long lhs,
unsigned long rhs ) {
972 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
974 template<Operator Op>
bool compare(
long lhs,
unsigned char rhs ) {
975 return applyEvaluator<Op>(
static_cast<unsigned long>( lhs ), rhs );
979 template<Operator Op,
typename T>
bool compare(
long lhs, T* rhs ) {
982 template<Operator Op,
typename T>
bool compare( T* lhs,
long rhs ) {
987 template<Operator Op,
typename T>
bool compare(
int lhs, T* rhs ) {
990 template<Operator Op,
typename T>
bool compare( T* lhs,
int rhs ) {
994#ifdef CATCH_CONFIG_CPP11_NULLPTR
996 template<Operator Op,
typename T>
bool compare( std::nullptr_t, T* rhs ) {
997 return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
999 template<Operator Op,
typename T>
bool compare( T* lhs, std::nullptr_t ) {
1000 return Evaluator<T*, T*, Op>::evaluate( lhs, NULL );
1012#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1022#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1024#import <Foundation/Foundation.h>
1027#define CATCH_ARC_ENABLED __has_feature(objc_arc)
1029#define CATCH_ARC_ENABLED 0
1032void arcSafeRelease( NSObject* obj );
1033id performOptionalSelector(
id obj,
SEL sel );
1035#if !CATCH_ARC_ENABLED
1036inline void arcSafeRelease( NSObject* obj ) {
1039inline id performOptionalSelector(
id obj,
SEL sel ) {
1040 if( [obj respondsToSelector: sel] )
1041 return [obj performSelector: sel];
1044#define CATCH_UNSAFE_UNRETAINED
1045#define CATCH_ARC_STRONG
1047inline void arcSafeRelease( NSObject* ){}
1048inline id performOptionalSelector(
id obj,
SEL sel ) {
1050#pragma clang diagnostic push
1051#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1053 if( [obj respondsToSelector: sel] )
1054 return [obj performSelector: sel];
1056#pragma clang diagnostic pop
1060#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1061#define CATCH_ARC_STRONG __strong
1066#ifdef CATCH_CONFIG_CPP11_TUPLE
1070#ifdef CATCH_CONFIG_CPP11_IS_ENUM
1071#include <type_traits>
1078std::string
toString( T
const& value );
1098#ifdef CATCH_CONFIG_CPP11_NULLPTR
1099std::string
toString( std::nullptr_t );
1103 std::string
toString( NSString
const *
const& nsstring );
1104 std::string
toString( NSString * CATCH_ARC_STRONG
const& nsstring );
1105 std::string
toString( NSObject*
const& nsObject );
1124 template<
typename T>
1126 static std::ostream &
s;
1131#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1132 template<
typename T,
1133 bool IsEnum = std::is_enum<T>::value
1135 struct EnumStringMaker
1140 template<
typename T>
1141 struct EnumStringMaker<T,true>
1143 static std::string convert( T
const& v )
1146 static_cast<typename std::underlying_type<T>::type
>(v)
1153#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1154 template<
typename T>
1155 static std::string convert( T
const& v )
1157 return EnumStringMaker<T>::convert( v );
1160 template<
typename T>
1167 template<
typename T>
1169 std::ostringstream oss;
1177 template<
typename T>
1190 template<
typename U>
1199template<
typename R,
typename C>
1210 template<
typename InputIterator>
1211 std::string
rangeToString( InputIterator first, InputIterator last );
1221template<
typename T,
typename Allocator>
1226#ifdef CATCH_CONFIG_CPP11_TUPLE
1229namespace TupleDetail {
1233 bool = (N < std::tuple_size<Tuple>::value)
1235 struct ElementPrinter {
1236 static void print(
const Tuple& tuple, std::ostream& os )
1238 os << ( N ?
", " :
" " )
1240 ElementPrinter<Tuple,N+1>::print(tuple,os);
1248 struct ElementPrinter<Tuple,N,false> {
1249 static void print(
const Tuple&, std::ostream& ) {}
1254template<
typename ...Types>
1255struct StringMaker<
std::tuple<Types...>> {
1257 static std::string convert(
const std::tuple<Types...>& tuple )
1259 std::ostringstream os;
1261 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1269 template<
typename T>
1288 template<
typename InputIterator>
1290 std::ostringstream oss;
1292 if( first != last ) {
1294 for( ++first ; first != last ; ++first )
1311# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1317# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
1322 template<
typename RhsT>
1324 return captureExpression<Internal::IsEqualTo>( rhs );
1327 template<
typename RhsT>
1329 return captureExpression<Internal::IsNotEqualTo>( rhs );
1332 template<
typename RhsT>
1334 return captureExpression<Internal::IsLessThan>( rhs );
1337 template<
typename RhsT>
1339 return captureExpression<Internal::IsGreaterThan>( rhs );
1342 template<
typename RhsT>
1344 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1347 template<
typename RhsT>
1349 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1353 return captureExpression<Internal::IsEqualTo>( rhs );
1357 return captureExpression<Internal::IsNotEqualTo>( rhs );
1361 bool value = m_lhs ? true :
false;
1364 .setResultType( value )
1370 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator + ( RhsT
const& );
1371 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator - ( RhsT
const& );
1372 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator / ( RhsT
const& );
1373 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison&
operator * ( RhsT
const& );
1374 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT
const& );
1375 template<
typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT
const& );
1378 template<Internal::Operator Op,
typename RhsT>
1397 template<
typename T>
1399 return ExpressionLhs<T const&>( *
this, operand );
1403 return ExpressionLhs<bool>( *
this, value );
1409#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1440 : m_info( macroName, lineInfo, type )
1443 template<
typename T>
1465#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
1472 class AssertionResult;
1473 struct AssertionInfo;
1476 class ScopedMessageBuilder;
1485 Counts& assertions ) = 0;
1500#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
1503#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1505#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1506#define CATCH_PLATFORM_MAC
1507#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1508#define CATCH_PLATFORM_IPHONE
1509#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
1510#define CATCH_PLATFORM_WINDOWS
1521#ifdef CATCH_PLATFORM_MAC
1526 #if defined(__ppc64__) || defined(__ppc__)
1527 #define CATCH_BREAK_INTO_DEBUGGER() \
1528 if( Catch::isDebuggerActive() ) { \
1529 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1530 : : : "memory","r0","r3","r4" ); \
1533 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
1537#elif defined(_MSC_VER)
1538 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
1539#elif defined(__MINGW32__)
1540 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
1541 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
1544#ifndef CATCH_BREAK_INTO_DEBUGGER
1545#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
1549#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
1565#define INTERNAL_CATCH_REACT( resultBuilder ) \
1566 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
1567 resultBuilder.react();
1570#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
1572 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1574 ( __catchResult <= expr ).endExpression(); \
1577 __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
1579 INTERNAL_CATCH_REACT( __catchResult ) \
1580 } while( Catch::isTrue( false && (expr) ) )
1583#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
1584 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
1585 if( Catch::getResultCapture().getLastResult()->succeeded() )
1588#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
1589 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
1590 if( !Catch::getResultCapture().getLastResult()->succeeded() )
1593#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
1595 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1598 __catchResult.captureResult( Catch::ResultWas::Ok ); \
1601 __catchResult.useActiveException( resultDisposition ); \
1603 INTERNAL_CATCH_REACT( __catchResult ) \
1604 } while( Catch::alwaysFalse() )
1607#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \
1609 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1610 if( __catchResult.allowThrows() ) \
1613 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
1616 __catchResult.captureResult( Catch::ResultWas::Ok ); \
1619 __catchResult.captureResult( Catch::ResultWas::Ok ); \
1620 INTERNAL_CATCH_REACT( __catchResult ) \
1621 } while( Catch::alwaysFalse() )
1624#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
1626 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
1627 if( __catchResult.allowThrows() ) \
1630 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
1632 catch( exceptionType ) { \
1633 __catchResult.captureResult( Catch::ResultWas::Ok ); \
1636 __catchResult.useActiveException( resultDisposition ); \
1639 __catchResult.captureResult( Catch::ResultWas::Ok ); \
1640 INTERNAL_CATCH_REACT( __catchResult ) \
1641 } while( Catch::alwaysFalse() )
1644#ifdef CATCH_CONFIG_VARIADIC_MACROS
1645 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
1647 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
1648 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
1649 __catchResult.captureResult( messageType ); \
1650 INTERNAL_CATCH_REACT( __catchResult ) \
1651 } while( Catch::alwaysFalse() )
1653 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
1655 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
1656 __catchResult << log + ::Catch::StreamEndStop(); \
1657 __catchResult.captureResult( messageType ); \
1658 INTERNAL_CATCH_REACT( __catchResult ) \
1659 } while( Catch::alwaysFalse() )
1663#define INTERNAL_CATCH_INFO( log, macroName ) \
1664 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
1667#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
1669 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
1671 std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
1673 .setLhs( Catch::toString( arg ) ) \
1674 .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
1675 .setOp( "matches" ) \
1676 .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
1677 __catchResult.captureExpression(); \
1679 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
1681 INTERNAL_CATCH_REACT( __catchResult ) \
1682 } while( Catch::alwaysFalse() )
1685#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
1688#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
1695 std::string
const& _name,
1696 std::string
const& _description = std::string() );
1706#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
1713 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
1730 return passed + failed + failedButOk;
1733 return failed == 0 && failedButOk == 0;
1754 Totals diff = *
this - prevTotals;
1776#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
1778#ifdef CATCH_PLATFORM_WINDOWS
1779typedef unsigned long long uint64_t;
1810 operator bool()
const;
1823#ifdef CATCH_CONFIG_VARIADIC_MACROS
1824 #define INTERNAL_CATCH_SECTION( ... ) \
1825 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
1827 #define INTERNAL_CATCH_SECTION( name, desc ) \
1828 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
1832#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
1845 virtual std::size_t
size ()
const = 0;
1854 return m_from+
static_cast<int>( index );
1858 return static_cast<std::size_t
>( 1+m_to-m_from );
1873 m_values.push_back( value );
1877 return m_values[index];
1881 return m_values.size();
1895 : m_fileInfo( other.m_fileInfo ),
1902 m_fileInfo = fileInfo;
1910 operator T ()
const {
1915 for(
size_t index = 0; it != itEnd; ++it )
1918 if( overallIndex >= index && overallIndex < index + generator->size() )
1920 return generator->
getValue( overallIndex-index );
1922 index += generator->
size();
1929 m_totalSize += generator->
size();
1930 m_composed.push_back( generator );
1940 valuesGen->
add( value );
1948 std::copy( other.
m_composed.begin(), other.
m_composed.end(), std::back_inserter( m_composed ) );
1960 template<
typename T>
1967 template<
typename T>
1971 valuesGen->
add( val1 );
1972 valuesGen->
add( val2 );
1973 generators.
add( valuesGen );
1977 template<
typename T>
1981 valuesGen->
add( val1 );
1982 valuesGen->
add( val2 );
1983 valuesGen->
add( val3 );
1984 generators.
add( valuesGen );
1988 template<
typename T>
1992 valuesGen->
add( val1 );
1993 valuesGen->
add( val2 );
1994 valuesGen->
add( val3 );
1995 valuesGen->
add( val4 );
1996 generators.
add( valuesGen );
2002using namespace Generators;
2006#define INTERNAL_CATCH_LINESTR2( line ) #line
2007#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2009#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2012#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2016#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2023 struct ITestCaseRegistry;
2024 struct IExceptionTranslatorRegistry;
2025 struct IExceptionTranslator;
2026 struct IReporterRegistry;
2027 struct IReporterFactory;
2068 template<
typename T>
2073 : m_translateFunction( translateFunction )
2081 return m_translateFunction( ex );
2086 std::string(*m_translateFunction)( T& );
2090 template<
typename T>
2099#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2100 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2101 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2102 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2105#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2116 : m_epsilon(
std::numeric_limits<float>::epsilon()*100 ),
2122 : m_epsilon( other.m_epsilon ),
2123 m_scale( other.m_scale ),
2124 m_value( other.m_value )
2134 approx.
scale( m_scale );
2156 m_epsilon = newEpsilon;
2166 std::ostringstream oss;
2186#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
2192 template<
typename ExpressionT>
2199 virtual bool match( ExpressionT
const& expr )
const = 0;
2203 template<
typename DerivedT,
typename ExpressionT>
2213 template<
typename ExpressionT>
2221 m_matchers.push_back( matcher.
clone() );
2224 virtual bool match( ExpressionT
const& expr )
const
2226 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2227 if( !m_matchers[i]->match( expr ) )
2232 std::ostringstream oss;
2234 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2237 oss << m_matchers[i]->toString();
2247 template<
typename ExpressionT>
2255 m_matchers.push_back( matcher.
clone() );
2258 virtual bool match( ExpressionT
const& expr )
const
2260 for( std::size_t i = 0; i < m_matchers.size(); ++i )
2261 if( m_matchers[i]->match( expr ) )
2266 std::ostringstream oss;
2268 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
2271 oss << m_matchers[i]->toString();
2283 namespace StdString {
2285 inline std::string
makeString( std::string
const& str ) {
return str; }
2286 inline std::string
makeString(
const char* str ) {
return str ? std::string( str ) : std::string(); }
2289 Equals( std::string
const& str ) : m_str( str ){}
2294 virtual bool match( std::string
const& expr )
const {
2295 return m_str == expr;
2298 return "equals: \"" + m_str +
"\"";
2305 Contains( std::string
const& substr ) : m_substr( substr ){}
2310 virtual bool match( std::string
const& expr )
const {
2311 return expr.find( m_substr ) != std::string::npos;
2314 return "contains: \"" + m_substr +
"\"";
2326 virtual bool match( std::string
const& expr )
const {
2327 return expr.find( m_substr ) == 0;
2330 return "starts with: \"" + m_substr +
"\"";
2337 EndsWith( std::string
const& substr ) : m_substr( substr ){}
2342 virtual bool match( std::string
const& expr )
const {
2343 return expr.find( m_substr ) == expr.size() - m_substr.size();
2346 return "ends with: \"" + m_substr +
"\"";
2356 template<
typename ExpressionT>
2361 template<
typename ExpressionT>
2367 template<
typename ExpressionT>
2372 template<
typename ExpressionT>
2406using namespace Matchers;
2411#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
2414#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
2433#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
2435#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2440 template<
typename T>
2445 : nullableValue( new( storage ) T( _value ) )
2448 : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
2456 if( &_other !=
this ) {
2459 nullableValue =
new( storage ) T( *_other );
2465 nullableValue =
new( storage ) T( _value );
2471 nullableValue->~T();
2472 nullableValue = NULL;
2481 return nullableValue ? *nullableValue : defaultValue;
2484 bool some()
const {
return nullableValue != NULL; }
2485 bool none()
const {
return nullableValue == NULL; }
2487 bool operator !()
const {
return nullableValue == NULL; }
2494 char storage[
sizeof(T)];
2504 virtual std::string
expandAliases( std::string
const& unexpandedTestSpec )
const = 0;
2514#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2520#pragma clang diagnostic push
2521#pragma clang diagnostic ignored "-Wpadded"
2532 ShouldFail = 1 << 2,
2538 std::string
const& _className,
2539 std::string
const& _description,
2540 std::set<std::string>
const& _tags,
2546 bool throws()
const;
2582 std::string
const& className,
2583 std::string
const& name,
2584 std::string
const& description,
2589#pragma clang diagnostic pop
2595#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2597#import <objc/runtime.h>
2619 class OcMethod :
public SharedImpl<ITestCase> {
2622 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2624 virtual void invoke()
const {
2625 id obj = [[m_cls alloc] init];
2627 performOptionalSelector( obj,
@selector(setUp) );
2628 performOptionalSelector( obj, m_sel );
2629 performOptionalSelector( obj,
@selector(tearDown) );
2631 arcSafeRelease( obj );
2634 virtual ~OcMethod() {}
2642 inline std::string getAnnotation( Class cls,
2643 std::string
const& annotationName,
2644 std::string
const& testCaseName ) {
2645 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2646 SEL sel = NSSelectorFromString( selStr );
2647 arcSafeRelease( selStr );
2648 id value = performOptionalSelector( cls, sel );
2650 return [(NSString*)value UTF8String];
2655 inline size_t registerTestMethods() {
2656 size_t noTestMethods = 0;
2657 int noClasses = objc_getClassList( NULL, 0 );
2659 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc(
sizeof(Class) * noClasses);
2660 objc_getClassList( classes, noClasses );
2662 for(
int c = 0; c < noClasses; c++ ) {
2663 Class cls = classes[c];
2666 Method* methods = class_copyMethodList( cls, &count );
2667 for( u_int m = 0; m < count ; m++ ) {
2668 SEL selector = method_getName(methods[m]);
2669 std::string methodName = sel_getName(selector);
2670 if(
startsWith( methodName,
"Catch_TestCase_" ) ) {
2671 std::string testCaseName = methodName.substr( 15 );
2672 std::string name = Detail::getAnnotation( cls,
"Name", testCaseName );
2673 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
2674 const char* className = class_getName( cls );
2683 return noTestMethods;
2686 namespace Matchers {
2688 namespace NSStringMatchers {
2690 template<
typename MatcherT>
2691 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
2692 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2693 StringHolder( StringHolder
const& other ) : m_substr( [other.m_substr copy] ){}
2695 arcSafeRelease( m_substr );
2702 Equals( NSString* substr ) : StringHolder( substr ){}
2704 virtual bool match( ExpressionType
const& str )
const {
2705 return (str != nil || m_substr == nil ) &&
2706 [str isEqualToString:m_substr];
2709 virtual std::string
toString()
const {
2710 return "equals string: " +
Catch::toString( m_substr );
2715 Contains( NSString* substr ) : StringHolder( substr ){}
2717 virtual bool match( ExpressionType
const& str )
const {
2718 return (str != nil || m_substr == nil ) &&
2719 [str rangeOfString:m_substr].location != NSNotFound;
2722 virtual std::string
toString()
const {
2723 return "contains string: " +
Catch::toString( m_substr );
2728 StartsWith( NSString* substr ) : StringHolder( substr ){}
2730 virtual bool match( ExpressionType
const& str )
const {
2731 return (str != nil || m_substr == nil ) &&
2732 [str rangeOfString:m_substr].location == 0;
2735 virtual std::string
toString()
const {
2736 return "starts with: " +
Catch::toString( m_substr );
2740 EndsWith( NSString* substr ) : StringHolder( substr ){}
2742 virtual bool match( ExpressionType
const& str )
const {
2743 return (str != nil || m_substr == nil ) &&
2744 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
2747 virtual std::string
toString()
const {
2748 return "ends with: " +
Catch::toString( m_substr );
2769 using namespace Matchers;
2774#define OC_TEST_CASE( name, desc )\
2775+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
2779+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
2783-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
2789#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
2795#pragma clang diagnostic push
2796#pragma clang diagnostic ignored "-Wweak-vtables"
2800#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
2803#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2806#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
2809#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
2812#pragma clang diagnostic push
2813#pragma clang diagnostic ignored "-Wpadded"
2817#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
2820#pragma clang diagnostic push
2821#pragma clang diagnostic ignored "-Wpadded"
2830 struct Pattern : SharedImpl<> {
2832 virtual bool matches( TestCaseInfo
const& testCase )
const = 0;
2834 class NamePattern :
public Pattern {
2835 enum WildcardPosition {
2837 WildcardAtStart = 1,
2839 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
2843 NamePattern( std::string
const& name ) : m_name(
toLower( name ) ), m_wildcard( NoWildcard ) {
2845 m_name = m_name.substr( 1 );
2846 m_wildcard = WildcardAtStart;
2849 m_name = m_name.substr( 0, m_name.size()-1 );
2850 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
2853 virtual ~NamePattern();
2854 virtual bool matches( TestCaseInfo
const& testCase )
const {
2855 switch( m_wildcard ) {
2857 return m_name ==
toLower( testCase.name );
2858 case WildcardAtStart:
2862 case WildcardAtBothEnds:
2867#pragma clang diagnostic push
2868#pragma clang diagnostic ignored "-Wunreachable-code"
2870 throw std::logic_error(
"Unknown enum" );
2872#pragma clang diagnostic pop
2877 WildcardPosition m_wildcard;
2879 class TagPattern :
public Pattern {
2881 TagPattern( std::string
const& tag ) : m_tag(
toLower( tag ) ) {}
2882 virtual ~TagPattern();
2883 virtual bool matches( TestCaseInfo
const& testCase )
const {
2884 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
2889 class ExcludedPattern :
public Pattern {
2891 ExcludedPattern( Ptr<Pattern>
const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
2892 virtual ~ExcludedPattern();
2893 virtual bool matches( TestCaseInfo
const& testCase )
const {
return !m_underlyingPattern->matches( testCase ); }
2895 Ptr<Pattern> m_underlyingPattern;
2901 bool matches( TestCaseInfo
const& testCase )
const {
2903 for(
std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.
begin(), itEnd = m_patterns.
end(); it != itEnd; ++it )
2904 if( !(*it)->matches( testCase ) )
2911 bool hasFilters()
const {
2912 return !m_filters.
empty();
2914 bool matches( TestCaseInfo
const& testCase )
const {
2917 if( it->matches( testCase ) )
2925 friend class TestSpecParser;
2930#pragma clang diagnostic pop
2935 class TestSpecParser {
2936 enum Mode{ None, Name, QuotedName, Tag };
2939 std::size_t m_start, m_pos;
2941 TestSpec::Filter m_currentFilter;
2942 TestSpec m_testSpec;
2943 ITagAliasRegistry
const* m_tagAliases;
2946 TestSpecParser( ITagAliasRegistry
const& tagAliases ) : m_tagAliases( &tagAliases ) {}
2948 TestSpecParser& parse( std::string
const& arg ) {
2950 m_exclusion =
false;
2951 m_start = std::string::npos;
2952 m_arg = m_tagAliases->expandAliases( arg );
2953 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
2954 visitChar( m_arg[m_pos] );
2955 if( m_mode == Name )
2956 addPattern<TestSpec::NamePattern>();
2959 TestSpec testSpec() {
2964 void visitChar(
char c ) {
2965 if( m_mode == None ) {
2968 case '~': m_exclusion =
true;
return;
2969 case '[':
return startNewMode( Tag, ++m_pos );
2970 case '"':
return startNewMode( QuotedName, ++m_pos );
2971 default: startNewMode( Name, m_pos );
break;
2974 if( m_mode == Name ) {
2976 addPattern<TestSpec::NamePattern>();
2979 else if( c ==
'[' ) {
2980 if( subString() ==
"exclude:" )
2983 addPattern<TestSpec::NamePattern>();
2984 startNewMode( Tag, ++m_pos );
2987 else if( m_mode == QuotedName && c ==
'"' )
2988 addPattern<TestSpec::NamePattern>();
2989 else if( m_mode == Tag && c ==
']' )
2990 addPattern<TestSpec::TagPattern>();
2992 void startNewMode( Mode mode, std::size_t start ) {
2996 std::string subString()
const {
return m_arg.substr( m_start, m_pos - m_start ); }
2997 template<
typename T>
2999 std::string token = subString();
3002 token = token.substr( 8 );
3004 if( !token.empty() ) {
3005 Ptr<TestSpec::Pattern> pattern =
new T( token );
3007 pattern =
new TestSpec::ExcludedPattern( pattern );
3008 m_currentFilter.m_patterns.push_back( pattern );
3010 m_exclusion =
false;
3014 if( !m_currentFilter.m_patterns.empty() ) {
3015 m_testSpec.m_filters.push_back( m_currentFilter );
3016 m_currentFilter = TestSpec::Filter();
3020 inline TestSpec parseTestSpec( std::string
const& arg ) {
3027#pragma clang diagnostic pop
3031#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3039 struct Verbosity {
enum Level {
3045 struct WarnAbout {
enum What {
3050 struct ShowDurations {
enum OrNot {
3055 struct RunTests {
enum InWhatOrder {
3057 InLexicographicalOrder,
3063 struct IConfig : IShared {
3067 virtual bool allowThrows()
const = 0;
3068 virtual std::ostream& stream()
const = 0;
3069 virtual std::string name()
const = 0;
3070 virtual bool includeSuccessfulResults()
const = 0;
3071 virtual bool shouldDebugBreak()
const = 0;
3072 virtual bool warnAboutMissingAssertions()
const = 0;
3073 virtual int abortAfter()
const = 0;
3074 virtual bool showInvisibles()
const = 0;
3075 virtual ShowDurations::OrNot showDurations()
const = 0;
3076 virtual TestSpec
const& testSpec()
const = 0;
3077 virtual RunTests::InWhatOrder runOrder()
const = 0;
3078 virtual unsigned int rngSeed()
const = 0;
3079 virtual bool forceColour()
const = 0;
3084#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3089#pragma clang diagnostic ignored "-Wpadded"
3097 Stream( std::streambuf* _streamBuf,
bool _isOwned );
3100 std::streambuf* streamBuf;
3106 std::ostream&
cout();
3107 std::ostream&
cerr();
3116#ifndef CATCH_CONFIG_CONSOLE_WIDTH
3117#define CATCH_CONFIG_CONSOLE_WIDTH 80
3125 : listTests( false ),
3127 listReporters( false ),
3128 listTestNamesOnly( false ),
3129 showSuccessfulTests( false ),
3130 shouldDebugBreak( false ),
3133 showInvisibles( false ),
3134 forceColour( false ),
3137 verbosity( Verbosity::Normal ),
3138 warnings( WarnAbout::Nothing ),
3139 showDurations( ShowDurations::DefaultForReporter ),
3140 runOrder( RunTests::InDeclarationOrder )
3146 bool listTestNamesOnly;
3148 bool showSuccessfulTests;
3149 bool shouldDebugBreak;
3152 bool showInvisibles;
3156 unsigned int rngSeed;
3158 Verbosity::Level verbosity;
3159 WarnAbout::What warnings;
3160 ShowDurations::OrNot showDurations;
3161 RunTests::InWhatOrder runOrder;
3163 std::string reporterName;
3164 std::string outputFilename;
3166 std::string processName;
3171 class Config :
public SharedImpl<IConfig> {
3173 Config( Config
const& other );
3174 Config& operator = ( Config
const& other );
3175 virtual void dummy();
3182 Config( ConfigData
const& data )
3186 if( !data.testsOrTags.empty() ) {
3188 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
3189 parser.parse( data.testsOrTags[i] );
3190 m_testSpec = parser.testSpec();
3199 void setFilename( std::string
const& filename ) {
3200 m_data.outputFilename = filename;
3203 std::string
const& getFilename()
const {
3204 return m_data.outputFilename ;
3207 bool listTests()
const {
return m_data.listTests; }
3208 bool listTestNamesOnly()
const {
return m_data.listTestNamesOnly; }
3209 bool listTags()
const {
return m_data.listTags; }
3210 bool listReporters()
const {
return m_data.listReporters; }
3212 std::string getProcessName()
const {
return m_data.processName; }
3214 bool shouldDebugBreak()
const {
return m_data.shouldDebugBreak; }
3216 void setStreamBuf( std::streambuf* buf ) {
3220 void useStream( std::string
const& streamName ) {
3222 setStreamBuf( stream.streamBuf );
3227 std::string getReporterName()
const {
return m_data.reporterName; }
3229 int abortAfter()
const {
return m_data.abortAfter; }
3231 TestSpec
const& testSpec()
const {
return m_testSpec; }
3233 bool showHelp()
const {
return m_data.showHelp; }
3234 bool showInvisibles()
const {
return m_data.showInvisibles; }
3237 virtual bool allowThrows()
const {
return !m_data.noThrow; }
3238 virtual std::ostream& stream()
const {
return m_os; }
3239 virtual std::string name()
const {
return m_data.name.empty() ? m_data.processName : m_data.name; }
3240 virtual bool includeSuccessfulResults()
const {
return m_data.showSuccessfulTests; }
3241 virtual bool warnAboutMissingAssertions()
const {
return m_data.warnings & WarnAbout::NoAssertions; }
3242 virtual ShowDurations::OrNot showDurations()
const {
return m_data.showDurations; }
3243 virtual RunTests::InWhatOrder runOrder()
const {
return m_data.runOrder; }
3244 virtual unsigned int rngSeed()
const {
return m_data.rngSeed; }
3245 virtual bool forceColour()
const {
return m_data.forceColour; }
3251 mutable std::ostream m_os;
3252 TestSpec m_testSpec;
3258#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3261#ifdef CLARA_CONFIG_CONSOLE_WIDTH
3262#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3263#undef CLARA_CONFIG_CONSOLE_WIDTH
3265#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3268#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
3272#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
3274#ifndef STITCH_CLARA_OPEN_NAMESPACE
3275#define TWOBLUECUBES_CLARA_H_INCLUDED
3276#define STITCH_CLARA_OPEN_NAMESPACE
3277#define STITCH_CLARA_CLOSE_NAMESPACE
3279#define STITCH_CLARA_CLOSE_NAMESPACE }
3282#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
3287#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
3288#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3289#define TBC_TEXT_FORMAT_H_INCLUDED
3297#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3298namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
3303#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
3304 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
3306 const unsigned int consoleWidth = 80;
3309 struct TextAttributes {
3313 width( consoleWidth-1 ),
3317 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value;
return *
this; }
3318 TextAttributes& setIndent( std::size_t _value ) { indent = _value;
return *
this; }
3319 TextAttributes& setWidth( std::size_t _value ) { width = _value;
return *
this; }
3320 TextAttributes& setTabChar(
char _value ) { tabChar = _value;
return *
this; }
3322 std::size_t initialIndent;
3330 Text( std::string
const& _str, TextAttributes
const& _attr = TextAttributes() )
3333 std::string wrappableChars =
" [({.,/|\\-";
3334 std::size_t indent = _attr.initialIndent != std::string::npos
3335 ? _attr.initialIndent
3337 std::string remainder = _str;
3339 while( !remainder.empty() ) {
3340 if( lines.size() >= 1000 ) {
3341 lines.push_back(
"... message truncated due to excessive size" );
3344 std::size_t tabPos = std::string::npos;
3345 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
3346 std::size_t
pos = remainder.find_first_of(
'\n' );
3347 if(
pos <= width ) {
3350 pos = remainder.find_last_of( _attr.tabChar, width );
3351 if(
pos != std::string::npos ) {
3353 if( remainder[width] ==
'\n' )
3355 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
3358 if( width == remainder.size() ) {
3359 spliceLine( indent, remainder, width );
3361 else if( remainder[width] ==
'\n' ) {
3362 spliceLine( indent, remainder, width );
3363 if( width <= 1 || remainder.size() != 1 )
3364 remainder = remainder.substr( 1 );
3365 indent = _attr.indent;
3368 pos = remainder.find_last_of( wrappableChars, width );
3369 if(
pos != std::string::npos &&
pos > 0 ) {
3370 spliceLine( indent, remainder,
pos );
3371 if( remainder[0] ==
' ' )
3372 remainder = remainder.substr( 1 );
3375 spliceLine( indent, remainder, width-1 );
3376 lines.back() += "-";
3378 if( lines.size() == 1 )
3379 indent = _attr.indent;
3380 if( tabPos != std::string::npos )
3386 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
3387 lines.push_back( std::string( _indent,
' ' ) + _remainder.substr( 0, _pos ) );
3388 _remainder = _remainder.substr( _pos );
3393 const_iterator begin()
const {
return lines.
begin(); }
3394 const_iterator end()
const {
return lines.end(); }
3395 std::string
const& last()
const {
return lines.back(); }
3396 std::size_t size()
const {
return lines.size(); }
3397 std::string
const& operator[]( std::size_t _index )
const {
return lines[_index]; }
3399 std::ostringstream oss;
3404 inline friend std::ostream&
operator << ( std::ostream& _stream, Text
const& _text ) {
3405 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
3406 it != itEnd; ++it ) {
3407 if( it != _text.begin() )
3416 TextAttributes attr;
3422#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3431#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
3439#ifdef STITCH_CLARA_OPEN_NAMESPACE
3440STITCH_CLARA_OPEN_NAMESPACE
3445 struct UnpositionalTag {};
3447 extern UnpositionalTag _;
3449#ifdef CLARA_CONFIG_MAIN
3455#ifdef CLARA_CONSOLE_WIDTH
3456 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
3458 const unsigned int consoleWidth = 80;
3461 using namespace Tbc;
3463 inline bool startsWith( std::string
const& str, std::string
const& prefix ) {
3464 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
3467 template<
typename T>
struct RemoveConstRef{
typedef T type; };
3468 template<
typename T>
struct RemoveConstRef<T&>{
typedef T type; };
3469 template<
typename T>
struct RemoveConstRef<T const&>{
typedef T type; };
3470 template<
typename T>
struct RemoveConstRef<T const>{
typedef T type; };
3472 template<
typename T>
struct IsBool {
static const bool value =
false; };
3473 template<>
struct IsBool<bool> {
static const bool value =
true; };
3475 template<
typename T>
3476 void convertInto( std::string
const& _source, T& _dest ) {
3477 std::stringstream ss;
3481 throw std::runtime_error(
"Unable to convert " + _source +
" to destination type" );
3483 inline void convertInto( std::string
const& _source, std::string& _dest ) {
3486 inline void convertInto( std::string
const& _source,
bool& _dest ) {
3487 std::string sourceLC = _source;
3488 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
3489 if( sourceLC ==
"y" || sourceLC ==
"1" || sourceLC ==
"true" || sourceLC ==
"yes" || sourceLC ==
"on" )
3491 else if( sourceLC ==
"n" || sourceLC ==
"0" || sourceLC ==
"false" || sourceLC ==
"no" || sourceLC ==
"off" )
3494 throw std::runtime_error(
"Expected a boolean value but did not recognise:\n '" + _source +
"'" );
3496 inline void convertInto(
bool _source,
bool& _dest ) {
3499 template<
typename T>
3500 inline void convertInto(
bool, T& ) {
3501 throw std::runtime_error(
"Invalid conversion" );
3504 template<
typename ConfigT>
3505 struct IArgFunction {
3506 virtual ~IArgFunction() {}
3507# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
3508 IArgFunction() =
default;
3509 IArgFunction( IArgFunction
const& ) =
default;
3511 virtual void set( ConfigT& config, std::string
const& value )
const = 0;
3512 virtual void setFlag( ConfigT& config )
const = 0;
3513 virtual bool takesArg()
const = 0;
3514 virtual IArgFunction* clone()
const = 0;
3517 template<
typename ConfigT>
3518 class BoundArgFunction {
3520 BoundArgFunction() : functionObj( NULL ) {}
3521 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
3522 BoundArgFunction( BoundArgFunction
const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}
3523 BoundArgFunction& operator = ( BoundArgFunction
const& other ) {
3524 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL;
3526 functionObj = newFunctionObj;
3529 ~BoundArgFunction() {
delete functionObj; }
3531 void set( ConfigT& config, std::string
const& value )
const {
3532 functionObj->set( config, value );
3534 void setFlag( ConfigT& config )
const {
3535 functionObj->setFlag( config );
3537 bool takesArg()
const {
return functionObj->takesArg(); }
3539 bool isSet()
const {
3540 return functionObj != NULL;
3543 IArgFunction<ConfigT>* functionObj;
3546 template<
typename C>
3547 struct NullBinder : IArgFunction<C>{
3548 virtual void set( C&, std::string
const& )
const {}
3549 virtual void setFlag( C& )
const {}
3550 virtual bool takesArg()
const {
return true; }
3551 virtual IArgFunction<C>* clone()
const {
return new NullBinder( *
this ); }
3554 template<
typename C,
typename M>
3555 struct BoundDataMember : IArgFunction<C>{
3556 BoundDataMember( M C::* _member ) : member( _member ) {}
3557 virtual void set( C& p, std::string
const& stringValue )
const {
3558 convertInto( stringValue, p.*member );
3560 virtual void setFlag( C& p )
const {
3561 convertInto(
true, p.*member );
3563 virtual bool takesArg()
const {
return !IsBool<M>::value; }
3564 virtual IArgFunction<C>* clone()
const {
return new BoundDataMember( *
this ); }
3567 template<
typename C,
typename M>
3568 struct BoundUnaryMethod : IArgFunction<C>{
3569 BoundUnaryMethod(
void (C::*_member)( M ) ) : member( _member ) {}
3570 virtual void set( C& p, std::string
const& stringValue )
const {
3571 typename RemoveConstRef<M>::type value;
3572 convertInto( stringValue, value );
3573 (p.*member)( value );
3575 virtual void setFlag( C& p )
const {
3576 typename RemoveConstRef<M>::type value;
3577 convertInto(
true, value );
3578 (p.*member)( value );
3580 virtual bool takesArg()
const {
return !IsBool<M>::value; }
3581 virtual IArgFunction<C>* clone()
const {
return new BoundUnaryMethod( *
this ); }
3582 void (C::*member)( M );
3584 template<
typename C>
3585 struct BoundNullaryMethod : IArgFunction<C>{
3586 BoundNullaryMethod(
void (C::*_member)() ) : member( _member ) {}
3587 virtual void set( C& p, std::string
const& stringValue )
const {
3589 convertInto( stringValue, value );
3593 virtual void setFlag( C& p )
const {
3596 virtual bool takesArg()
const {
return false; }
3597 virtual IArgFunction<C>* clone()
const {
return new BoundNullaryMethod( *
this ); }
3598 void (C::*member)();
3601 template<
typename C>
3602 struct BoundUnaryFunction : IArgFunction<C>{
3603 BoundUnaryFunction(
void (*_function)( C& ) ) : function( _function ) {}
3604 virtual void set( C& obj, std::string
const& stringValue )
const {
3606 convertInto( stringValue, value );
3610 virtual void setFlag( C& p )
const {
3613 virtual bool takesArg()
const {
return false; }
3614 virtual IArgFunction<C>* clone()
const {
return new BoundUnaryFunction( *
this ); }
3615 void (*function)( C& );
3618 template<
typename C,
typename T>
3619 struct BoundBinaryFunction : IArgFunction<C>{
3620 BoundBinaryFunction(
void (*_function)( C&, T ) ) : function( _function ) {}
3621 virtual void set( C& obj, std::string
const& stringValue )
const {
3622 typename RemoveConstRef<T>::type value;
3623 convertInto( stringValue, value );
3624 function( obj, value );
3626 virtual void setFlag( C& obj )
const {
3627 typename RemoveConstRef<T>::type value;
3628 convertInto(
true, value );
3629 function( obj, value );
3631 virtual bool takesArg()
const {
return !IsBool<T>::value; }
3632 virtual IArgFunction<C>* clone()
const {
return new BoundBinaryFunction( *
this ); }
3633 void (*function)( C&, T );
3639 Parser() : separators(
" \t=:" ) {}
3642 enum Type { Positional, ShortOpt, LongOpt };
3643 Token( Type _type, std::string
const&
_data ) : type( _type ), data(
_data ) {}
3649 const std::string doubleDash =
"--";
3650 for(
int i = 1; i < argc && argv[i] != doubleDash; ++i )
3651 parseIntoTokens( argv[i] , tokens);
3654 while( !arg.empty() ) {
3655 Parser::Token token( Parser::Token::Positional, arg );
3657 if( token.data[0] ==
'-' ) {
3658 if( token.data.size() > 1 && token.data[1] ==
'-' ) {
3659 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
3662 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
3663 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
3664 arg =
"-" + token.data.substr( 1 );
3665 token.data = token.data.substr( 0, 1 );
3669 if( token.type != Parser::Token::Positional ) {
3670 std::size_t
pos = token.data.find_first_of( separators );
3671 if(
pos != std::string::npos ) {
3672 arg = token.data.substr(
pos+1 );
3673 token.data = token.data.substr( 0,
pos );
3679 std::string separators;
3682 template<
typename ConfigT>
3683 struct CommonArgProperties {
3684 CommonArgProperties() {}
3685 CommonArgProperties( Detail::BoundArgFunction<ConfigT>
const& _boundField ) : boundField( _boundField ) {}
3687 Detail::BoundArgFunction<ConfigT> boundField;
3688 std::string description;
3690 std::string placeholder;
3692 bool takesArg()
const {
3693 return !placeholder.empty();
3695 void validate()
const {
3696 if( !boundField.isSet() )
3697 throw std::logic_error(
"option not bound" );
3700 struct OptionArgProperties {
3702 std::string longName;
3704 bool hasShortName( std::string
const& shortName )
const {
3705 return std::find( shortNames.
begin(), shortNames.
end(), shortName ) != shortNames.
end();
3707 bool hasLongName( std::string
const& _longName )
const {
3708 return _longName == longName;
3711 struct PositionalArgProperties {
3712 PositionalArgProperties() : position( -1 ) {}
3715 bool isFixedPositional()
const {
3716 return position != -1;
3720 template<
typename ConfigT>
3723 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
3725 Arg( Detail::BoundArgFunction<ConfigT>
const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
3727 using CommonArgProperties<ConfigT>::placeholder;
3729 std::string dbgName()
const {
3730 if( !longName.empty() )
3731 return "--" + longName;
3732 if( !shortNames.
empty() )
3733 return "-" + shortNames[0];
3734 return "positional args";
3736 std::string commands()
const {
3737 std::ostringstream oss;
3740 for(; it != itEnd; ++it ) {
3747 if( !longName.empty() ) {
3750 oss <<
"--" << longName;
3752 if( !placeholder.empty() )
3753 oss <<
" <" << placeholder <<
">";
3759#if defined(__cplusplus) && __cplusplus > 199711L
3760 typedef std::unique_ptr<Arg> ArgAutoPtr;
3762 typedef std::auto_ptr<Arg> ArgAutoPtr;
3765 friend void addOptName( Arg& arg, std::string
const& optName )
3767 if( optName.empty() )
3770 if( !arg.longName.empty() )
3771 throw std::logic_error(
"Only one long opt may be specified. '"
3773 +
"' already specified, now attempting to add '"
3775 arg.longName = optName.substr( 2 );
3778 arg.shortNames.push_back( optName.substr( 1 ) );
3780 throw std::logic_error(
"option must begin with - or --. Option was: '" + optName +
"'" );
3782 friend void setPositionalArg( Arg& arg,
int position )
3784 arg.position = position;
3789 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
3792 template<
typename C,
typename M>
3793 void bind( M C::* field, std::string
const& placeholder ) {
3794 m_arg->boundField =
new Detail::BoundDataMember<C,M>( field );
3795 m_arg->placeholder = placeholder;
3798 template<
typename C>
3799 void bind(
bool C::* field ) {
3800 m_arg->boundField =
new Detail::BoundDataMember<C,bool>( field );
3804 template<
typename C,
typename M>
3805 void bind(
void (C::* unaryMethod)( M ), std::string
const& placeholder ) {
3806 m_arg->boundField =
new Detail::BoundUnaryMethod<C,M>( unaryMethod );
3807 m_arg->placeholder = placeholder;
3811 template<
typename C>
3812 void bind(
void (C::* unaryMethod)(
bool ) ) {
3813 m_arg->boundField =
new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
3817 template<
typename C>
3818 void bind(
void (C::* nullaryMethod)() ) {
3819 m_arg->boundField =
new Detail::BoundNullaryMethod<C>( nullaryMethod );
3823 template<
typename C>
3824 void bind(
void (* unaryFunction)( C& ) ) {
3825 m_arg->boundField =
new Detail::BoundUnaryFunction<C>( unaryFunction );
3829 template<
typename C,
typename T>
3830 void bind(
void (* binaryFunction)( C&, T ), std::string
const& placeholder ) {
3831 m_arg->boundField =
new Detail::BoundBinaryFunction<C, T>( binaryFunction );
3832 m_arg->placeholder = placeholder;
3835 ArgBuilder& describe( std::string
const& description ) {
3836 m_arg->description = description;
3839 ArgBuilder& detail( std::string
const& detail ) {
3840 m_arg->detail = detail;
3848 class OptBuilder :
public ArgBuilder {
3850 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
3851 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
3853 OptBuilder& operator[]( std::string
const& optName ) {
3854 addOptName( *ArgBuilder::m_arg, optName );
3862 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
3863 m_highestSpecifiedArgPosition( 0 ),
3864 m_throwOnUnrecognisedTokens( false )
3866 CommandLine( CommandLine
const& other )
3867 : m_boundProcessName( other.m_boundProcessName ),
3868 m_options ( other.m_options ),
3869 m_positionalArgs( other.m_positionalArgs ),
3870 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
3871 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
3873 if( other.m_floatingArg.get() )
3874 m_floatingArg.reset(
new Arg( *other.m_floatingArg ) );
3877 CommandLine& setThrowOnUnrecognisedTokens(
bool shouldThrow =
true ) {
3878 m_throwOnUnrecognisedTokens = shouldThrow;
3882 OptBuilder operator[]( std::string
const& optName ) {
3883 m_options.push_back( Arg() );
3884 addOptName( m_options.back(), optName );
3885 OptBuilder builder( &m_options.back() );
3889 ArgBuilder operator[](
int position ) {
3890 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
3891 if( position > m_highestSpecifiedArgPosition )
3892 m_highestSpecifiedArgPosition = position;
3893 setPositionalArg( m_positionalArgs[position], position );
3894 ArgBuilder builder( &m_positionalArgs[position] );
3899 ArgBuilder operator[]( UnpositionalTag ) {
3900 if( m_floatingArg.get() )
3901 throw std::logic_error(
"Only one unpositional argument can be added" );
3902 m_floatingArg.reset(
new Arg() );
3903 ArgBuilder builder( m_floatingArg.get() );
3907 template<
typename C,
typename M>
3908 void bindProcessName( M C::* field ) {
3909 m_boundProcessName =
new Detail::BoundDataMember<C,M>( field );
3911 template<
typename C,
typename M>
3912 void bindProcessName(
void (C::*_unaryMethod)( M ) ) {
3913 m_boundProcessName =
new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
3916 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth )
const {
3918 std::size_t maxWidth = 0;
3919 for( it = itBegin; it != itEnd; ++it )
3920 maxWidth = (
std::max)( maxWidth, it->commands().size() );
3922 for( it = itBegin; it != itEnd; ++it ) {
3923 Detail::Text usage( it->commands(), Detail::TextAttributes()
3924 .setWidth( maxWidth+indent )
3925 .setIndent( indent ) );
3926 Detail::Text desc( it->description, Detail::TextAttributes()
3927 .setWidth( width - maxWidth - 3 ) );
3929 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
3930 std::string usageCol = i < usage.size() ? usage[i] :
"";
3933 if( i < desc.size() && !desc[i].empty() )
3934 os << std::string( indent + 2 + maxWidth - usageCol.size(),
' ' )
3940 std::string optUsage()
const {
3941 std::ostringstream oss;
3946 void argSynopsis( std::ostream& os )
const {
3947 for(
int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
3950 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
3951 if( it != m_positionalArgs.end() )
3952 os <<
"<" << it->second.placeholder <<
">";
3953 else if( m_floatingArg.get() )
3954 os <<
"<" << m_floatingArg->placeholder <<
">";
3956 throw std::logic_error(
"non consecutive positional arguments with no floating args" );
3959 if( m_floatingArg.get() ) {
3960 if( m_highestSpecifiedArgPosition > 1 )
3962 os <<
"[<" << m_floatingArg->placeholder <<
"> ...]";
3965 std::string argSynopsis()
const {
3966 std::ostringstream oss;
3971 void usage( std::ostream& os, std::string
const& procName )
const {
3973 os <<
"usage:\n " << procName <<
" ";
3975 if( !m_options.empty() ) {
3976 os <<
" [options]\n\nwhere options are: \n";
3981 std::string usage( std::string
const& procName )
const {
3982 std::ostringstream oss;
3983 usage( oss, procName );
3987 ConfigT parse(
int argc,
char const *
const * argv )
const {
3989 parseInto( argc, argv, config );
3994 std::string processName = argv[0];
3995 std::size_t lastSlash = processName.find_last_of(
"/\\" );
3996 if( lastSlash != std::string::npos )
3997 processName = processName.substr( lastSlash+1 );
3998 m_boundProcessName.set( config, processName );
4001 parser.parseIntoTokens( argc, argv, tokens );
4002 return populate( tokens, config );
4008 unusedTokens = populateFixedArgs( unusedTokens, config );
4009 unusedTokens = populateFloatingArgs( unusedTokens, config );
4010 return unusedTokens;
4016 for( std::size_t i = 0; i < tokens.
size(); ++i ) {
4017 Parser::Token
const& token = tokens[i];
4019 for(; it != itEnd; ++it ) {
4020 Arg const& arg = *it;
4023 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4024 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4025 if( arg.takesArg() ) {
4026 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
4027 errors.push_back(
"Expected argument to option: " + token.data );
4029 arg.boundField.set( config, tokens[++i].data );
4032 arg.boundField.setFlag( config );
4037 catch( std::exception& ex ) {
4038 errors.push_back( std::string( ex.what() ) +
"\n- while parsing: (" + arg.commands() +
")" );
4042 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
4044 else if( errors.
empty() && m_throwOnUnrecognisedTokens )
4045 errors.
push_back(
"unrecognised option: " + token.data );
4048 if( !errors.
empty() ) {
4049 std::ostringstream oss;
4050 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4053 if( it != errors.begin() )
4057 throw std::runtime_error( oss.str() );
4059 return unusedTokens;
4064 for( std::size_t i = 0; i < tokens.
size(); ++i ) {
4065 Parser::Token
const& token = tokens[i];
4066 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4067 if( it != m_positionalArgs.end() )
4068 it->second.boundField.set( config, token.data );
4071 if( token.type == Parser::Token::Positional )
4074 return unusedTokens;
4077 if( !m_floatingArg.get() )
4080 for( std::size_t i = 0; i < tokens.
size(); ++i ) {
4081 Parser::Token
const& token = tokens[i];
4082 if( token.type == Parser::Token::Positional )
4083 m_floatingArg->boundField.set( config, token.data );
4087 return unusedTokens;
4090 void validate()
const
4092 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
4093 throw std::logic_error(
"No options or arguments specified" );
4096 itEnd = m_options.end();
4102 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4104 std::map<int, Arg> m_positionalArgs;
4105 ArgAutoPtr m_floatingArg;
4106 int m_highestSpecifiedArgPosition;
4107 bool m_throwOnUnrecognisedTokens;
4112STITCH_CLARA_CLOSE_NAMESPACE
4113#undef STITCH_CLARA_OPEN_NAMESPACE
4114#undef STITCH_CLARA_CLOSE_NAMESPACE
4117#undef STITCH_CLARA_OPEN_NAMESPACE
4120#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4121#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4122#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4129 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
4130 inline void abortAfterX( ConfigData& config,
int x ) {
4132 throw std::runtime_error(
"Value after -x or --abortAfter must be greater than zero" );
4133 config.abortAfter = x;
4135 inline void addTestOrTags( ConfigData& config, std::string
const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
4137 inline void addWarning( ConfigData& config, std::string
const& _warning ) {
4138 if( _warning ==
"NoAssertions" )
4139 config.warnings =
static_cast<WarnAbout::What
>( config.warnings | WarnAbout::NoAssertions );
4141 throw std::runtime_error(
"Unrecognised warning: '" + _warning +
"'" );
4143 inline void setOrder( ConfigData& config, std::string
const& order ) {
4145 config.runOrder = RunTests::InDeclarationOrder;
4147 config.runOrder = RunTests::InLexicographicalOrder;
4149 config.runOrder = RunTests::InRandomOrder;
4151 throw std::runtime_error(
"Unrecognised ordering: '" + order +
"'" );
4153 inline void setRngSeed( ConfigData& config, std::string
const& seed ) {
4154 if( seed ==
"time" ) {
4155 config.rngSeed =
static_cast<unsigned int>( std::time(0) );
4158 std::stringstream ss;
4160 ss >> config.rngSeed;
4162 throw std::runtime_error(
"Argment to --rng-seed should be the word 'time' or a number" );
4165 inline void setVerbosity( ConfigData& config,
int level ) {
4167 config.verbosity =
static_cast<Verbosity::Level
>( level );
4169 inline void setShowDurations( ConfigData& config,
bool _showDurations ) {
4170 config.showDurations = _showDurations
4171 ? ShowDurations::Always
4172 : ShowDurations::Never;
4174 inline void loadTestNamesFromFile( ConfigData& config, std::string
const& _filename ) {
4175 std::ifstream f( _filename.c_str() );
4177 throw std::domain_error(
"Unable to load input file: " + _filename );
4180 while( std::getline( f, line ) ) {
4182 if( !line.empty() && !
startsWith( line,
"#" ) )
4183 addTestOrTags( config,
"\"" + line +
"\"," );
4187 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4189 using namespace Clara;
4190 CommandLine<ConfigData> cli;
4192 cli.bindProcessName( &ConfigData::processName );
4194 cli["-?"]["-h"]["--help"]
4195 .describe(
"display usage information" )
4196 .bind( &ConfigData::showHelp );
4198 cli["-l"]["--list-tests"]
4199 .describe(
"list all/matching test cases" )
4200 .bind( &ConfigData::listTests );
4202 cli["-t"]["--list-tags"]
4203 .describe(
"list all/matching tags" )
4204 .bind( &ConfigData::listTags );
4206 cli["-s"]["--success"]
4207 .describe(
"include successful tests in output" )
4208 .bind( &ConfigData::showSuccessfulTests );
4210 cli["-b"]["--break"]
4211 .describe(
"break into debugger on failure" )
4212 .bind( &ConfigData::shouldDebugBreak );
4214 cli["-e"]["--nothrow"]
4215 .describe(
"skip exception tests" )
4216 .bind( &ConfigData::noThrow );
4218 cli["-i"]["--invisibles"]
4219 .describe(
"show invisibles (tabs, newlines)" )
4220 .bind( &ConfigData::showInvisibles );
4223 .describe(
"output filename" )
4224 .bind( &ConfigData::outputFilename,
"filename" );
4226 cli["-r"]["--reporter"]
4228 .describe(
"reporter to use (defaults to console)" )
4229 .bind( &ConfigData::reporterName,
"name" );
4232 .describe(
"suite name" )
4233 .bind( &ConfigData::name,
"name" );
4235 cli["-a"]["--abort"]
4236 .describe(
"abort at first failure" )
4237 .bind( &abortAfterFirst );
4239 cli["-x"]["--abortx"]
4240 .describe(
"abort after x failures" )
4241 .bind( &abortAfterX,
"no. failures" );
4244 .describe(
"enable warnings" )
4245 .bind( &addWarning,
"warning name" );
4255 .describe(
"which test or tests to use" )
4256 .bind( &addTestOrTags,
"test name, pattern or tags" );
4258 cli["-d"]["--durations"]
4259 .describe(
"show test durations" )
4260 .bind( &setShowDurations,
"yes/no" );
4262 cli["-f"]["--input-file"]
4263 .describe(
"load test names to run from a file" )
4264 .bind( &loadTestNamesFromFile,
"filename" );
4267 cli["--list-test-names-only"]
4268 .describe(
"list all/matching test cases names only" )
4269 .bind( &ConfigData::listTestNamesOnly );
4271 cli["--list-reporters"]
4272 .describe(
"list all reporters" )
4273 .bind( &ConfigData::listReporters );
4276 .describe(
"test case order (defaults to decl)" )
4277 .bind( &setOrder,
"decl|lex|rand" );
4280 .describe(
"set a specific seed for random numbers" )
4281 .bind( &setRngSeed,
"'time'|number" );
4283 cli["--force-colour"]
4284 .describe(
"force colourised output" )
4285 .bind( &ConfigData::forceColour );
4293#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4296#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
4298#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4300#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
4303#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4304# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4305# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4306# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4309# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4312#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4318#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4319namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4324#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4325 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4327 const unsigned int consoleWidth = 80;
4330 struct TextAttributes {
4334 width( consoleWidth-1 ),
4338 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value;
return *
this; }
4339 TextAttributes& setIndent( std::size_t _value ) { indent = _value;
return *
this; }
4340 TextAttributes& setWidth( std::size_t _value ) { width = _value;
return *
this; }
4341 TextAttributes& setTabChar(
char _value ) { tabChar = _value;
return *
this; }
4343 std::size_t initialIndent;
4351 Text( std::string
const& _str, TextAttributes
const& _attr = TextAttributes() )
4354 std::string wrappableChars =
" [({.,/|\\-";
4355 std::size_t indent = _attr.initialIndent != std::string::npos
4356 ? _attr.initialIndent
4358 std::string remainder = _str;
4360 while( !remainder.empty() ) {
4361 if( lines.size() >= 1000 ) {
4362 lines.push_back(
"... message truncated due to excessive size" );
4365 std::size_t tabPos = std::string::npos;
4366 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4367 std::size_t
pos = remainder.find_first_of(
'\n' );
4368 if(
pos <= width ) {
4371 pos = remainder.find_last_of( _attr.tabChar, width );
4372 if(
pos != std::string::npos ) {
4374 if( remainder[width] ==
'\n' )
4376 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4379 if( width == remainder.size() ) {
4380 spliceLine( indent, remainder, width );
4382 else if( remainder[width] ==
'\n' ) {
4383 spliceLine( indent, remainder, width );
4384 if( width <= 1 || remainder.size() != 1 )
4385 remainder = remainder.substr( 1 );
4386 indent = _attr.indent;
4389 pos = remainder.find_last_of( wrappableChars, width );
4390 if(
pos != std::string::npos &&
pos > 0 ) {
4391 spliceLine( indent, remainder,
pos );
4392 if( remainder[0] ==
' ' )
4393 remainder = remainder.substr( 1 );
4396 spliceLine( indent, remainder, width-1 );
4397 lines.back() += "-";
4399 if( lines.size() == 1 )
4400 indent = _attr.indent;
4401 if( tabPos != std::string::npos )
4407 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4408 lines.push_back( std::string( _indent,
' ' ) + _remainder.substr( 0, _pos ) );
4409 _remainder = _remainder.substr( _pos );
4414 const_iterator begin()
const {
return lines.
begin(); }
4415 const_iterator end()
const {
return lines.end(); }
4416 std::string
const& last()
const {
return lines.back(); }
4417 std::size_t size()
const {
return lines.size(); }
4418 std::string
const& operator[]( std::size_t _index )
const {
return lines[_index]; }
4420 std::ostringstream oss;
4425 inline friend std::ostream&
operator << ( std::ostream& _stream, Text
const& _text ) {
4426 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4427 it != itEnd; ++it ) {
4428 if( it != _text.begin() )
4437 TextAttributes attr;
4443#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4448#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4452 using Tbc::TextAttributes;
4456#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
4474 BrightRed = Bright | Red,
4475 BrightGreen = Bright | Green,
4476 LightGrey = Bright | Grey,
4477 BrightWhite = Bright | White,
4480 FileName = LightGrey,
4482 ResultError = BrightRed,
4483 ResultSuccess = BrightGreen,
4484 ResultExpectedFailure = Warning,
4489 OriginalExpression = Cyan,
4490 ReconstructedExpression = Yellow,
4492 SecondaryText = LightGrey,
4497 Colour( Code _colourCode );
4498 Colour( Colour
const& other );
4502 static void use( Code _colourCode );
4508 inline std::ostream&
operator << ( std::ostream& os, Colour
const& ) {
return os; }
4513#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
4522 struct ReporterConfig {
4523 explicit ReporterConfig( Ptr<IConfig>
const& _fullConfig )
4524 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
4526 ReporterConfig( Ptr<IConfig>
const& _fullConfig, std::ostream& _stream )
4527 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
4529 std::ostream& stream()
const {
return *m_stream; }
4530 Ptr<IConfig> fullConfig()
const {
return m_fullConfig; }
4533 std::ostream* m_stream;
4534 Ptr<IConfig> m_fullConfig;
4537 struct ReporterPreferences {
4538 ReporterPreferences()
4539 : shouldRedirectStdOut( false )
4542 bool shouldRedirectStdOut;
4545 template<
typename T>
4546 struct LazyStat : Option<T> {
4547 LazyStat() : used( false ) {}
4548 LazyStat& operator=( T
const& _value ) {
4549 Option<T>::operator=( _value );
4560 struct TestRunInfo {
4561 TestRunInfo( std::string
const& _name ) : name( _name ) {}
4565 GroupInfo( std::string
const& _name,
4566 std::size_t _groupIndex,
4567 std::size_t _groupsCount )
4569 groupIndex( _groupIndex ),
4570 groupsCounts( _groupsCount )
4574 std::size_t groupIndex;
4575 std::size_t groupsCounts;
4578 struct AssertionStats {
4579 AssertionStats( AssertionResult
const& _assertionResult,
4581 Totals
const& _totals )
4582 : assertionResult( _assertionResult ),
4583 infoMessages( _infoMessages ),
4586 if( assertionResult.hasMessage() ) {
4589 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
4590 builder << assertionResult.getMessage();
4591 builder.m_info.message = builder.m_stream.str();
4593 infoMessages.push_back( builder.m_info );
4596 virtual ~AssertionStats();
4598# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4599 AssertionStats( AssertionStats
const& ) =
default;
4600 AssertionStats( AssertionStats && ) =
default;
4601 AssertionStats& operator = ( AssertionStats
const& ) =
default;
4602 AssertionStats& operator = ( AssertionStats && ) =
default;
4605 AssertionResult assertionResult;
4610 struct SectionStats {
4611 SectionStats( SectionInfo
const& _sectionInfo,
4612 Counts
const& _assertions,
4613 double _durationInSeconds,
4614 bool _missingAssertions )
4615 : sectionInfo( _sectionInfo ),
4616 assertions( _assertions ),
4617 durationInSeconds( _durationInSeconds ),
4618 missingAssertions( _missingAssertions )
4620 virtual ~SectionStats();
4621# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4622 SectionStats( SectionStats
const& ) =
default;
4623 SectionStats( SectionStats && ) =
default;
4624 SectionStats& operator = ( SectionStats
const& ) =
default;
4625 SectionStats& operator = ( SectionStats && ) =
default;
4628 SectionInfo sectionInfo;
4630 double durationInSeconds;
4631 bool missingAssertions;
4634 struct TestCaseStats {
4635 TestCaseStats( TestCaseInfo
const& _testInfo,
4636 Totals
const& _totals,
4637 std::string
const& _stdOut,
4638 std::string
const& _stdErr,
4640 : testInfo( _testInfo ),
4644 aborting( _aborting )
4646 virtual ~TestCaseStats();
4648# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4649 TestCaseStats( TestCaseStats
const& ) =
default;
4650 TestCaseStats( TestCaseStats && ) =
default;
4651 TestCaseStats& operator = ( TestCaseStats
const& ) =
default;
4652 TestCaseStats& operator = ( TestCaseStats && ) =
default;
4655 TestCaseInfo testInfo;
4662 struct TestGroupStats {
4663 TestGroupStats( GroupInfo
const& _groupInfo,
4664 Totals
const& _totals,
4666 : groupInfo( _groupInfo ),
4668 aborting( _aborting )
4670 TestGroupStats( GroupInfo
const& _groupInfo )
4671 : groupInfo( _groupInfo ),
4674 virtual ~TestGroupStats();
4676# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
4677 TestGroupStats( TestGroupStats
const& ) =
default;
4678 TestGroupStats( TestGroupStats && ) =
default;
4679 TestGroupStats& operator = ( TestGroupStats
const& ) =
default;
4680 TestGroupStats& operator = ( TestGroupStats && ) =
default;
4683 GroupInfo groupInfo;
4688 struct TestRunStats {
4689 TestRunStats( TestRunInfo
const& _runInfo,
4690 Totals
const& _totals,
4692 : runInfo( _runInfo ),
4694 aborting( _aborting )
4696 virtual ~TestRunStats();
4698# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
4699 TestRunStats( TestRunStats
const& _other )
4700 : runInfo( _other.runInfo ),
4701 totals( _other.totals ),
4702 aborting( _other.aborting )
4705 TestRunStats( TestRunStats
const& ) =
default;
4706 TestRunStats( TestRunStats && ) =
default;
4707 TestRunStats& operator = ( TestRunStats
const& ) =
default;
4708 TestRunStats& operator = ( TestRunStats && ) =
default;
4711 TestRunInfo runInfo;
4716 struct IStreamingReporter : IShared {
4717 virtual ~IStreamingReporter();
4722 virtual ReporterPreferences getPreferences()
const = 0;
4724 virtual void noMatchingTestCases( std::string
const& spec ) = 0;
4726 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
4727 virtual void testGroupStarting( GroupInfo
const& groupInfo ) = 0;
4729 virtual void testCaseStarting( TestCaseInfo
const& testInfo ) = 0;
4730 virtual void sectionStarting( SectionInfo
const& sectionInfo ) = 0;
4732 virtual void assertionStarting( AssertionInfo
const& assertionInfo ) = 0;
4735 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
4736 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
4737 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
4738 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
4739 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
4741 virtual void skipTest( TestCaseInfo
const& testInfo ) = 0;
4744 struct IReporterFactory {
4745 virtual ~IReporterFactory();
4746 virtual IStreamingReporter* create( ReporterConfig
const& config )
const = 0;
4747 virtual std::string getDescription()
const = 0;
4750 struct IReporterRegistry {
4751 typedef std::map<std::string, IReporterFactory*> FactoryMap;
4753 virtual ~IReporterRegistry();
4754 virtual IStreamingReporter* create( std::string
const& name, Ptr<IConfig>
const& config )
const = 0;
4755 virtual FactoryMap
const& getFactories()
const = 0;
4765 inline std::size_t listTests( Config
const& config ) {
4767 TestSpec testSpec = config.testSpec();
4768 if( config.testSpec().hasFilters() )
4775 std::size_t matchedTests = 0;
4776 TextAttributes nameAttr, tagsAttr;
4777 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
4778 tagsAttr.setIndent( 6 );
4786 TestCaseInfo
const& testCaseInfo = it->getTestCaseInfo();
4787 Colour::Code colour = testCaseInfo.isHidden()
4788 ? Colour::SecondaryText
4790 Colour colourGuard( colour );
4793 if( !testCaseInfo.tags.empty() )
4797 if( !config.testSpec().hasFilters() )
4801 return matchedTests;
4804 inline std::size_t listTestsNamesOnly( Config
const& config ) {
4805 TestSpec testSpec = config.testSpec();
4806 if( !config.testSpec().hasFilters() )
4808 std::size_t matchedTests = 0;
4815 TestCaseInfo
const& testCaseInfo = it->getTestCaseInfo();
4818 return matchedTests;
4822 TagInfo() : count ( 0 ) {}
4823 void add( std::string
const& spelling ) {
4825 spellings.insert( spelling );
4827 std::string all()
const {
4829 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
4832 out += "[" + *it + "]";
4835 std::set<std::string> spellings;
4839 inline std::size_t listTags( Config
const& config ) {
4840 TestSpec testSpec = config.testSpec();
4841 if( config.testSpec().hasFilters() )
4842 Catch::cout() <<
"Tags for matching test cases:\n";
4848 std::map<std::string, TagInfo> tagCounts;
4855 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
4856 tagItEnd = it->getTestCaseInfo().tags.end();
4859 std::string tagName = *tagIt;
4860 std::string lcaseTagName =
toLower( tagName );
4861 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
4862 if( countIt == tagCounts.end() )
4863 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
4864 countIt->second.add( tagName );
4868 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
4869 countItEnd = tagCounts.end();
4870 countIt != countItEnd;
4872 std::ostringstream oss;
4873 oss <<
" " << std::setw(2) << countIt->second.count <<
" ";
4874 Text wrapper( countIt->second.all(), TextAttributes()
4875 .setInitialIndent( 0 )
4876 .setIndent( oss.str().size() )
4877 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
4881 return tagCounts.size();
4884 inline std::size_t listReporters( Config
const& ) {
4887 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.
begin(), itEnd = factories.end(), it;
4888 std::size_t maxNameLen = 0;
4889 for(it = itBegin; it != itEnd; ++it )
4890 maxNameLen = (
std::max)( maxNameLen, it->first.size() );
4892 for(it = itBegin; it != itEnd; ++it ) {
4893 Text wrapper( it->second->getDescription(), TextAttributes()
4894 .setInitialIndent( 0 )
4895 .setIndent( 7+maxNameLen )
4896 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
4900 << std::string( maxNameLen - it->first.size() + 2,
' ' )
4904 return factories.size();
4907 inline Option<std::size_t> list( Config
const& config ) {
4908 Option<std::size_t> listedCount;
4909 if( config.listTests() )
4910 listedCount = listedCount.valueOr(0) + listTests( config );
4911 if( config.listTestNamesOnly() )
4912 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
4913 if( config.listTags() )
4914 listedCount = listedCount.valueOr(0) + listTags( config );
4915 if( config.listReporters() )
4916 listedCount = listedCount.valueOr(0) + listReporters( config );
4923#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
4926#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
4933namespace SectionTracking {
4935 class TrackedSection {
4937 typedef std::map<std::string, TrackedSection> TrackedSections;
4947 TrackedSection( std::string
const& name, TrackedSection* parent )
4948 : m_name( name ), m_runState( NotStarted ), m_parent( parent )
4951 RunState runState()
const {
return m_runState; }
4953 TrackedSection* findChild( std::string
const& childName );
4954 TrackedSection* acquireChild( std::string
const& childName );
4957 if( m_runState == NotStarted )
4958 m_runState = Executing;
4962 TrackedSection* getParent() {
4965 bool hasChildren()
const {
4966 return !m_children.empty();
4971 RunState m_runState;
4972 TrackedSections m_children;
4973 TrackedSection* m_parent;
4976 inline TrackedSection* TrackedSection::findChild( std::string
const& childName ) {
4977 TrackedSections::iterator it = m_children.find( childName );
4978 return it != m_children.end()
4982 inline TrackedSection* TrackedSection::acquireChild( std::string
const& childName ) {
4983 if( TrackedSection* child = findChild( childName ) )
4985 m_children.insert( std::make_pair( childName, TrackedSection( childName,
this ) ) );
4986 return findChild( childName );
4988 inline void TrackedSection::leave() {
4989 for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
4992 if( it->second.runState() != Completed ) {
4993 m_runState = ExecutingChildren;
4996 m_runState = Completed;
4999 class TestCaseTracker {
5001 TestCaseTracker( std::string
const& testCaseName )
5002 : m_testCase( testCaseName, NULL ),
5003 m_currentSection( &m_testCase ),
5004 m_completedASectionThisRun( false )
5007 bool enterSection( std::string
const& name ) {
5008 TrackedSection* child = m_currentSection->acquireChild( name );
5009 if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )
5012 m_currentSection = child;
5013 m_currentSection->enter();
5016 void leaveSection() {
5017 m_currentSection->leave();
5018 m_currentSection = m_currentSection->getParent();
5019 assert( m_currentSection != NULL );
5020 m_completedASectionThisRun =
true;
5023 bool currentSectionHasChildren()
const {
5024 return m_currentSection->hasChildren();
5026 bool isCompleted()
const {
5027 return m_testCase.runState() == TrackedSection::Completed;
5032 Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {
5033 m_tracker.enterTestCase();
5036 m_tracker.leaveTestCase();
5039 Guard( Guard
const& );
5040 void operator = ( Guard
const& );
5041 TestCaseTracker& m_tracker;
5045 void enterTestCase() {
5046 m_currentSection = &m_testCase;
5047 m_completedASectionThisRun =
false;
5050 void leaveTestCase() {
5054 TrackedSection m_testCase;
5055 TrackedSection* m_currentSection;
5056 bool m_completedASectionThisRun;
5061using SectionTracking::TestCaseTracker;
5066#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
5071 inline void fatal( std::string
const& message,
int exitCode ) {
5073 IResultCapture* resultCapture = context.getResultCapture();
5074 resultCapture->handleFatalErrorCondition( message );
5082#if defined ( CATCH_PLATFORM_WINDOWS )
5086 struct FatalConditionHandler {
5098 struct SignalDefs {
int id;
const char* name; };
5099 extern SignalDefs signalDefs[];
5100 SignalDefs signalDefs[] = {
5101 { SIGINT,
"SIGINT - Terminal interrupt signal" },
5102 { SIGILL,
"SIGILL - Illegal instruction signal" },
5103 { SIGFPE,
"SIGFPE - Floating point error signal" },
5104 { SIGSEGV,
"SIGSEGV - Segmentation violation signal" },
5105 { SIGTERM,
"SIGTERM - Termination request signal" },
5106 { SIGABRT,
"SIGABRT - Abort (abnormal termination) signal" }
5109 struct FatalConditionHandler {
5111 static void handleSignal(
int sig ) {
5112 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i )
5113 if( sig == signalDefs[i].
id )
5114 fatal( signalDefs[i].name, -sig );
5115 fatal(
"<unknown signal>", -sig );
5118 FatalConditionHandler() : m_isSet( true ) {
5119 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i )
5120 signal( signalDefs[i].id, handleSignal );
5122 ~FatalConditionHandler() {
5127 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i )
5128 signal( signalDefs[i].id, SIG_DFL );
5145 class StreamRedirect {
5148 StreamRedirect( std::ostream& stream, std::string& targetString )
5149 : m_stream( stream ),
5150 m_prevBuf( stream.rdbuf() ),
5151 m_targetString( targetString )
5153 stream.rdbuf( m_oss.rdbuf() );
5157 m_targetString += m_oss.str();
5158 m_stream.rdbuf( m_prevBuf );
5162 std::ostream& m_stream;
5163 std::streambuf* m_prevBuf;
5164 std::ostringstream m_oss;
5165 std::string& m_targetString;
5170 class RunContext :
public IResultCapture,
public IRunner {
5172 RunContext( RunContext
const& );
5173 void operator =( RunContext
const& );
5177 explicit RunContext( Ptr<IConfig const>
const& config, Ptr<IStreamingReporter>
const& reporter )
5178 : m_runInfo( config->name() ),
5180 m_activeTestCase( NULL ),
5182 m_reporter( reporter ),
5183 m_prevRunner( m_context.getRunner() ),
5185 m_prevConfig( m_context.getConfig() )
5187 m_context.setRunner(
this );
5188 m_context.setConfig( m_config );
5189 m_context.setResultCapture(
this );
5190 m_reporter->testRunStarting( m_runInfo );
5193 virtual ~RunContext() {
5194 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
5195 m_context.setRunner( m_prevRunner );
5196 m_context.setConfig( NULL );
5197 m_context.setResultCapture( m_prevResultCapture );
5198 m_context.setConfig( m_prevConfig );
5201 void testGroupStarting( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
5202 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
5204 void testGroupEnded( std::string
const& testSpec, Totals
const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
5205 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
5208 Totals runTest( TestCase
const& testCase ) {
5209 Totals prevTotals = m_totals;
5211 std::string redirectedCout;
5212 std::string redirectedCerr;
5214 TestCaseInfo testInfo = testCase.getTestCaseInfo();
5216 m_reporter->testCaseStarting( testInfo );
5218 m_activeTestCase = &testCase;
5219 m_testCaseTracker = TestCaseTracker( testInfo.name );
5223 runCurrentTest( redirectedCout, redirectedCerr );
5225 while( !m_testCaseTracker->isCompleted() && !aborting() );
5229 Totals deltaTotals = m_totals.delta( prevTotals );
5230 m_totals.testCases += deltaTotals.testCases;
5231 m_reporter->testCaseEnded( TestCaseStats( testInfo,
5237 m_activeTestCase = NULL;
5238 m_testCaseTracker.reset();
5243 Ptr<IConfig const> config()
const {
5249 virtual void assertionEnded( AssertionResult
const& result ) {
5251 m_totals.assertions.passed++;
5253 else if( !result.isOk() ) {
5254 m_totals.assertions.failed++;
5257 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
5261 m_lastAssertionInfo = AssertionInfo(
"", m_lastAssertionInfo.lineInfo,
"{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
5262 m_lastResult = result;
5265 virtual bool sectionStarted (
5266 SectionInfo
const& sectionInfo,
5270 std::ostringstream oss;
5271 oss << sectionInfo.name <<
"@" << sectionInfo.lineInfo;
5273 if( !m_testCaseTracker->enterSection( oss.str() ) )
5276 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
5278 m_reporter->sectionStarting( sectionInfo );
5280 assertions = m_totals.assertions;
5284 bool testForMissingAssertions( Counts& assertions ) {
5285 if( assertions.total() != 0 ||
5286 !m_config->warnAboutMissingAssertions() ||
5287 m_testCaseTracker->currentSectionHasChildren() )
5289 m_totals.assertions.failed++;
5290 assertions.failed++;
5294 virtual void sectionEnded( SectionInfo
const& info, Counts
const& prevAssertions,
double _durationInSeconds ) {
5295 if( std::uncaught_exception() ) {
5296 m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
5300 Counts assertions = m_totals.assertions - prevAssertions;
5301 bool missingAssertions = testForMissingAssertions( assertions );
5303 m_testCaseTracker->leaveSection();
5305 m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
5309 virtual void pushScopedMessage( MessageInfo
const& message ) {
5310 m_messages.push_back( message );
5313 virtual void popScopedMessage( MessageInfo
const& message ) {
5314 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
5317 virtual std::string getCurrentTestName()
const {
5318 return m_activeTestCase
5319 ? m_activeTestCase->getTestCaseInfo().name
5323 virtual const AssertionResult* getLastResult()
const {
5324 return &m_lastResult;
5327 virtual void handleFatalErrorCondition( std::string
const& message ) {
5328 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
5330 resultBuilder << message;
5331 resultBuilder.captureExpression();
5333 handleUnfinishedSections();
5336 TestCaseInfo
const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5337 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
5340 assertions.failed = 1;
5341 SectionStats testCaseSectionStats( testCaseSection, assertions, 0,
false );
5342 m_reporter->sectionEnded( testCaseSectionStats );
5344 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
5347 deltaTotals.testCases.failed = 1;
5348 m_reporter->testCaseEnded( TestCaseStats( testInfo,
5353 m_totals.testCases.failed++;
5354 testGroupEnded(
"", m_totals, 1, 1 );
5355 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals,
false ) );
5360 bool aborting()
const {
5361 return m_totals.assertions.failed ==
static_cast<std::size_t
>( m_config->abortAfter() );
5366 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
5367 TestCaseInfo
const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
5368 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
5369 m_reporter->sectionStarting( testCaseSection );
5370 Counts prevAssertions = m_totals.assertions;
5371 double duration = 0;
5374 TestCaseTracker::Guard guard( *m_testCaseTracker );
5378 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
5379 StreamRedirect coutRedir(
Catch::cout(), redirectedCout );
5380 StreamRedirect cerrRedir(
Catch::cerr(), redirectedCerr );
5381 invokeActiveTestCase();
5384 invokeActiveTestCase();
5386 duration = timer.getElapsedSeconds();
5388 catch( TestFailureException& ) {
5392 makeUnexpectedResultBuilder().useActiveException();
5394 handleUnfinishedSections();
5397 Counts assertions = m_totals.assertions - prevAssertions;
5398 bool missingAssertions = testForMissingAssertions( assertions );
5400 if( testCaseInfo.okToFail() ) {
5401 std::swap( assertions.failedButOk, assertions.failed );
5402 m_totals.assertions.failed -= assertions.failedButOk;
5403 m_totals.assertions.failedButOk += assertions.failedButOk;
5406 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
5407 m_reporter->sectionEnded( testCaseSectionStats );
5410 void invokeActiveTestCase() {
5411 FatalConditionHandler fatalConditionHandler;
5412 m_activeTestCase->invoke();
5413 fatalConditionHandler.reset();
5418 ResultBuilder makeUnexpectedResultBuilder()
const {
5419 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
5420 m_lastAssertionInfo.lineInfo,
5421 m_lastAssertionInfo.capturedExpression.c_str(),
5422 m_lastAssertionInfo.resultDisposition );
5425 void handleUnfinishedSections() {
5429 itEnd = m_unfinishedSections.rend();
5432 sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
5433 m_unfinishedSections.clear();
5436 struct UnfinishedSections {
5437 UnfinishedSections( SectionInfo
const& _info, Counts
const& _prevAssertions,
double _durationInSeconds )
5438 : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
5442 Counts prevAssertions;
5443 double durationInSeconds;
5446 TestRunInfo m_runInfo;
5447 IMutableContext& m_context;
5448 TestCase
const* m_activeTestCase;
5449 Option<TestCaseTracker> m_testCaseTracker;
5450 AssertionResult m_lastResult;
5452 Ptr<IConfig const> m_config;
5454 Ptr<IStreamingReporter> m_reporter;
5456 IRunner* m_prevRunner;
5457 IResultCapture* m_prevResultCapture;
5458 Ptr<IConfig const> m_prevConfig;
5459 AssertionInfo m_lastAssertionInfo;
5467 throw std::logic_error(
"No result capture instance" );
5473#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
5479 Version(
unsigned int _majorVersion,
5480 unsigned int _minorVersion,
5481 unsigned int _patchNumber,
5482 std::string
const& _branchName,
5483 unsigned int _buildNumber );
5485 unsigned int const majorVersion;
5486 unsigned int const minorVersion;
5487 unsigned int const patchNumber;
5490 std::string
const branchName;
5491 unsigned int const buildNumber;
5493 friend std::ostream&
operator << ( std::ostream& os, Version
const& version );
5496 void operator=( Version
const& );
5499 extern Version libraryVersion;
5511 Runner( Ptr<Config>
const& config )
5512 : m_config( config )
5520 RunContext context( m_config.get(), m_reporter );
5524 context.testGroupStarting(
"all tests", 1, 1 );
5526 TestSpec testSpec = m_config->testSpec();
5527 if( !testSpec.hasFilters() )
5533 int testsRunForGroup = 0;
5538 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
5540 if( context.aborting() )
5543 totals += context.runTest( *it );
5544 m_testsAlreadyRun.insert( *it );
5553 m_reporter->skipTest( *it );
5555 context.testGroupEnded(
"all tests", totals, 1, 1 );
5562 if( !m_config->getFilename().empty() ) {
5563 m_ofs.open( m_config->getFilename().c_str() );
5564 if( m_ofs.fail() ) {
5565 std::ostringstream oss;
5566 oss <<
"Unable to open file: '" << m_config->getFilename() <<
"'";
5567 throw std::domain_error( oss.str() );
5569 m_config->setStreamBuf( m_ofs.rdbuf() );
5572 void makeReporter() {
5573 std::string reporterName = m_config->getReporterName().empty()
5575 : m_config->getReporterName();
5579 std::ostringstream oss;
5580 oss <<
"No reporter registered with name: '" << reporterName <<
"'";
5581 throw std::domain_error( oss.str() );
5586 Ptr<Config> m_config;
5587 std::ofstream m_ofs;
5588 Ptr<IStreamingReporter> m_reporter;
5589 std::set<TestCase> m_testsAlreadyRun;
5592 class Session : NonCopyable {
5593 static bool alreadyInstantiated;
5597 struct OnUnusedOptions {
enum DoWhat { Ignore, Fail }; };
5600 : m_cli( makeCommandLineParser() ) {
5601 if( alreadyInstantiated ) {
5602 std::string msg =
"Only one instance of Catch::Session can ever be used";
5604 throw std::logic_error( msg );
5606 alreadyInstantiated =
true;
5612 void showHelp( std::string
const& processName ) {
5613 Catch::cout() <<
"\nCatch v" << libraryVersion <<
"\n";
5619 int applyCommandLine(
int argc,
char*
const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
5621 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
5622 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
5623 if( m_configData.showHelp )
5624 showHelp( m_configData.processName );
5627 catch( std::exception& ex ) {
5629 Colour colourGuard( Colour::Red );
5631 <<
"\nError(s) in input:\n"
5632 << Text( ex.what(), TextAttributes().setIndent(2) )
5635 m_cli.usage(
Catch::cout(), m_configData.processName );
5636 return (std::numeric_limits<int>::max)();
5641 void useConfigData( ConfigData
const& _configData ) {
5642 m_configData = _configData;
5646 int run(
int argc,
char*
const argv[] ) {
5648 int returnCode = applyCommandLine( argc, argv );
5649 if( returnCode == 0 )
5655 if( m_configData.showHelp )
5662 std::srand( m_configData.rngSeed );
5664 Runner runner( m_config );
5667 if( Option<std::size_t> listed = list( config() ) )
5668 return static_cast<int>( *listed );
5670 return static_cast<int>( runner.runTests().assertions.failed );
5672 catch( std::exception& ex ) {
5674 return (std::numeric_limits<int>::max)();
5678 Clara::CommandLine<ConfigData>
const& cli()
const {
5682 return m_unusedTokens;
5684 ConfigData& configData() {
5685 return m_configData;
5689 m_config =
new Config( m_configData );
5694 Clara::CommandLine<ConfigData> m_cli;
5696 ConfigData m_configData;
5697 Ptr<Config> m_config;
5700 bool Session::alreadyInstantiated =
false;
5705#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
5708#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
5718 class TestRegistry :
public ITestCaseRegistry {
5720 bool operator() (TestCase i,TestCase j)
const {
return (i<j);}
5722 struct RandomNumberGenerator {
5723 int operator()(
int n )
const {
return std::rand() % n; }
5727 TestRegistry() : m_unnamedCount( 0 ) {}
5728 virtual ~TestRegistry();
5730 virtual void registerTest( TestCase
const& testCase ) {
5731 std::string name = testCase.getTestCaseInfo().name;
5733 std::ostringstream oss;
5734 oss <<
"Anonymous test case " << ++m_unnamedCount;
5735 return registerTest( testCase.withName( oss.str() ) );
5738 if( m_functions.find( testCase ) == m_functions.end() ) {
5739 m_functions.insert( testCase );
5740 m_functionsInOrder.push_back( testCase );
5741 if( !testCase.isHidden() )
5742 m_nonHiddenFunctions.push_back( testCase );
5745 TestCase
const& prev = *m_functions.find( testCase );
5747 Colour colourGuard( Colour::Red );
5748 Catch::cerr() <<
"error: TEST_CASE( \"" << name <<
"\" ) already defined.\n"
5749 <<
"\tFirst seen at " << prev.getTestCaseInfo().lineInfo <<
"\n"
5750 <<
"\tRedefined at " << testCase.getTestCaseInfo().lineInfo <<
std::endl;
5757 return m_functionsInOrder;
5761 return m_nonHiddenFunctions;
5764 virtual void getFilteredTests( TestSpec
const& testSpec, IConfig
const& config,
std::vector<TestCase>& matchingTestCases,
bool negated =
false )
const {
5767 itEnd = m_functionsInOrder.end();
5770 bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() );
5771 if( includeTest != negated )
5774 sortTests( config, matchingTestCases );
5781 switch( config.runOrder() ) {
5782 case RunTests::InLexicographicalOrder:
5783 std::sort( matchingTestCases.
begin(), matchingTestCases.
end(), LexSort() );
5785 case RunTests::InRandomOrder:
5787 RandomNumberGenerator rng;
5788 std::random_shuffle( matchingTestCases.
begin(), matchingTestCases.
end(), rng );
5791 case RunTests::InDeclarationOrder:
5796 std::set<TestCase> m_functions;
5799 size_t m_unnamedCount;
5804 class FreeFunctionTestCase :
public SharedImpl<ITestCase> {
5807 FreeFunctionTestCase(
TestFunction fun ) : m_fun( fun ) {}
5809 virtual void invoke()
const {
5814 virtual ~FreeFunctionTestCase();
5819 inline std::string extractClassName( std::string
const& classOrQualifiedMethodName ) {
5820 std::string className = classOrQualifiedMethodName;
5823 std::size_t lastColons = className.rfind(
"::" );
5824 std::size_t penultimateColons = className.rfind(
"::", lastColons-1 );
5825 if( penultimateColons == std::string::npos )
5826 penultimateColons = 1;
5827 className = className.substr( penultimateColons, lastColons-penultimateColons );
5835 SourceLineInfo
const& lineInfo,
5836 NameAndDesc
const& nameAndDesc ) {
5837 registerTestCase(
new FreeFunctionTestCase( function ),
"", nameAndDesc, lineInfo );
5843 char const* classOrQualifiedMethodName,
5844 NameAndDesc
const& nameAndDesc,
5845 SourceLineInfo
const& lineInfo ) {
5849 extractClassName( classOrQualifiedMethodName ),
5851 nameAndDesc.description,
5858#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
5864 class ReporterRegistry :
public IReporterRegistry {
5868 virtual ~ReporterRegistry() {
5872 virtual IStreamingReporter* create( std::string
const& name, Ptr<IConfig>
const& config )
const {
5873 FactoryMap::const_iterator it = m_factories.find( name );
5874 if( it == m_factories.end() )
5876 return it->second->create( ReporterConfig( config ) );
5879 void registerReporter( std::string
const& name, IReporterFactory* factory ) {
5880 m_factories.insert( std::make_pair( name, factory ) );
5883 FactoryMap
const& getFactories()
const {
5888 FactoryMap m_factories;
5893#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
5896#import "Foundation/Foundation.h"
5901 class ExceptionTranslatorRegistry :
public IExceptionTranslatorRegistry {
5903 ~ExceptionTranslatorRegistry() {
5907 virtual void registerTranslator(
const IExceptionTranslator* translator ) {
5908 m_translators.push_back( translator );
5918 @catch (NSException *exception) {
5925 catch( TestFailureException& ) {
5928 catch( std::exception& ex ) {
5931 catch( std::string& msg ) {
5934 catch(
const char* msg ) {
5938 return tryTranslators( m_translators.begin() );
5943 if( it == m_translators.end() )
5944 return "Unknown exception";
5947 return (*it)->translate();
5950 return tryTranslators( it+1 );
5963 class RegistryHub :
public IRegistryHub,
public IMutableRegistryHub {
5965 RegistryHub( RegistryHub
const& );
5966 void operator=( RegistryHub
const& );
5971 virtual IReporterRegistry
const& getReporterRegistry()
const {
5972 return m_reporterRegistry;
5974 virtual ITestCaseRegistry
const& getTestCaseRegistry()
const {
5975 return m_testCaseRegistry;
5977 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
5978 return m_exceptionTranslatorRegistry;
5982 virtual void registerReporter( std::string
const& name, IReporterFactory* factory ) {
5983 m_reporterRegistry.registerReporter( name, factory );
5985 virtual void registerTest( TestCase
const& testInfo ) {
5986 m_testCaseRegistry.registerTest( testInfo );
5988 virtual void registerTranslator(
const IExceptionTranslator* translator ) {
5989 m_exceptionTranslatorRegistry.registerTranslator( translator );
5993 TestRegistry m_testCaseRegistry;
5994 ReporterRegistry m_reporterRegistry;
5995 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
5999 inline RegistryHub*& getTheRegistryHub() {
6000 static RegistryHub* theRegistryHub = NULL;
6001 if( !theRegistryHub )
6002 theRegistryHub =
new RegistryHub();
6003 return theRegistryHub;
6008 return *getTheRegistryHub();
6011 return *getTheRegistryHub();
6014 delete getTheRegistryHub();
6015 getTheRegistryHub() = NULL;
6025#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
6032 : m_lineInfo( lineInfo ) {
6033 std::ostringstream oss;
6034 oss << lineInfo <<
": function ";
6035 oss <<
"not implemented";
6039 const char* NotImplementedException::what() const
CATCH_NOEXCEPT {
6040 return m_what.c_str();
6046#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
6049#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
6052#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
6058 class StreamBufBase :
public std::streambuf {
6070 template<
typename WriterF,
size_t bufferSize=256>
6071 class StreamBufImpl :
public StreamBufBase {
6072 char data[bufferSize];
6077 setp( data, data +
sizeof(data) );
6085 int overflow(
int c ) {
6089 if( pbase() == epptr() )
6090 m_writer( std::string( 1,
static_cast<char>( c ) ) );
6092 sputc(
static_cast<char>( c ) );
6098 if( pbase() != pptr() ) {
6099 m_writer( std::string( pbase(),
static_cast<std::string::size_type
>( pptr() - pbase() ) ) );
6100 setp( pbase(), epptr() );
6108 struct OutputDebugWriter {
6110 void operator()( std::string
const&str ) {
6116 : streamBuf( NULL ), isOwned( false )
6119 Stream::Stream( std::streambuf* _streamBuf,
bool _isOwned )
6120 : streamBuf( _streamBuf ), isOwned( _isOwned )
6123 void Stream::release() {
6131#ifndef CATCH_CONFIG_NOSTDOUT
6132 std::ostream&
cout() {
6135 std::ostream&
cerr() {
6143 class Context :
public IMutableContext {
6145 Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
6146 Context( Context
const& );
6147 void operator=( Context
const& );
6151 return m_resultCapture;
6153 virtual IRunner* getRunner() {
6156 virtual size_t getGeneratorIndex( std::string
const& fileInfo,
size_t totalSize ) {
6157 return getGeneratorsForCurrentTest()
6158 .getGeneratorInfo( fileInfo, totalSize )
6161 virtual bool advanceGeneratorsForCurrentTest() {
6162 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6163 return generators && generators->moveNext();
6166 virtual Ptr<IConfig const> getConfig()
const {
6171 virtual void setResultCapture( IResultCapture* resultCapture ) {
6172 m_resultCapture = resultCapture;
6174 virtual void setRunner( IRunner* runner ) {
6177 virtual void setConfig( Ptr<IConfig const>
const& config ) {
6184 IGeneratorsForTest* findGeneratorsForCurrentTest() {
6187 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
6188 m_generatorsByTestName.find( testName );
6189 return it != m_generatorsByTestName.end()
6194 IGeneratorsForTest& getGeneratorsForCurrentTest() {
6195 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6199 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
6205 Ptr<IConfig const> m_config;
6207 IResultCapture* m_resultCapture;
6208 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
6212 Context* currentContext = NULL;
6215 if( !currentContext )
6216 currentContext =
new Context();
6217 return *currentContext;
6224 if( streamName ==
"stdout" )
return Stream(
Catch::cout().rdbuf(),
false );
6225 if( streamName ==
"stderr" )
return Stream(
Catch::cerr().rdbuf(),
false );
6226 if( streamName ==
"debug" )
return Stream(
new StreamBufImpl<OutputDebugWriter>,
true );
6228 throw std::domain_error(
"Unknown stream: " + streamName );
6232 delete currentContext;
6233 currentContext = NULL;
6238#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
6243 struct IColourImpl {
6244 virtual ~IColourImpl() {}
6245 virtual void use( Colour::Code _colourCode ) = 0;
6248 struct NoColourImpl : IColourImpl {
6249 void use( Colour::Code ) {}
6251 static IColourImpl* instance() {
6252 static NoColourImpl s_instance;
6260#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
6261# ifdef CATCH_PLATFORM_WINDOWS
6262# define CATCH_CONFIG_COLOUR_WINDOWS
6264# define CATCH_CONFIG_COLOUR_ANSI
6268#if defined ( CATCH_CONFIG_COLOUR_WINDOWS )
6283 class Win32ColourImpl :
public IColourImpl {
6285 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
6287 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
6288 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
6289 originalAttributes = csbiInfo.wAttributes;
6292 virtual void use( Colour::Code _colourCode ) {
6293 switch( _colourCode ) {
6294 case Colour::None:
return setTextAttribute( originalAttributes );
6295 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6296 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
6297 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
6298 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
6299 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
6300 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
6301 case Colour::Grey:
return setTextAttribute( 0 );
6303 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
6304 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
6305 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
6306 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6308 case Colour::Bright:
throw std::logic_error(
"not a colour" );
6313 void setTextAttribute( WORD _textAttribute ) {
6314 SetConsoleTextAttribute( stdoutHandle, _textAttribute );
6316 HANDLE stdoutHandle;
6317 WORD originalAttributes;
6320 IColourImpl* platformColourInstance() {
6321 static Win32ColourImpl s_instance;
6328#elif defined( CATCH_CONFIG_COLOUR_ANSI )
6339 class PosixColourImpl :
public IColourImpl {
6341 virtual void use( Colour::Code _colourCode ) {
6342 switch( _colourCode ) {
6344 case Colour::White:
return setColour(
"[0m" );
6345 case Colour::Red:
return setColour(
"[0;31m" );
6346 case Colour::Green:
return setColour(
"[0;32m" );
6347 case Colour::Blue:
return setColour(
"[0:34m" );
6348 case Colour::Cyan:
return setColour(
"[0;36m" );
6349 case Colour::Yellow:
return setColour(
"[0;33m" );
6350 case Colour::Grey:
return setColour(
"[1;30m" );
6352 case Colour::LightGrey:
return setColour(
"[0;37m" );
6353 case Colour::BrightRed:
return setColour(
"[1;31m" );
6354 case Colour::BrightGreen:
return setColour(
"[1;32m" );
6355 case Colour::BrightWhite:
return setColour(
"[1;37m" );
6357 case Colour::Bright:
throw std::logic_error(
"not a colour" );
6360 static IColourImpl* instance() {
6361 static PosixColourImpl s_instance;
6366 void setColour(
const char* _escapeCode ) {
6371 IColourImpl* platformColourInstance() {
6373 return (config && config->forceColour()) || isatty(STDOUT_FILENO)
6374 ? PosixColourImpl::instance()
6375 : NoColourImpl::instance();
6385 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
6393 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
6394 Colour::Colour( Colour
const& _other ) : m_moved( false ) {
const_cast<Colour&
>( _other ).m_moved =
true; }
6395 Colour::~Colour(){
if( !m_moved ) use( None ); }
6397 void Colour::use( Code _colourCode ) {
6399 ? NoColourImpl::instance()
6400 : platformColourInstance();
6401 impl->use( _colourCode );
6407#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
6415 struct GeneratorInfo : IGeneratorInfo {
6417 GeneratorInfo( std::size_t size )
6423 if( ++m_currentIndex == m_size ) {
6430 std::size_t getCurrentIndex()
const {
6431 return m_currentIndex;
6435 std::size_t m_currentIndex;
6440 class GeneratorsForTest :
public IGeneratorsForTest {
6443 ~GeneratorsForTest() {
6447 IGeneratorInfo& getGeneratorInfo( std::string
const& fileInfo, std::size_t size ) {
6448 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
6449 if( it == m_generatorsByName.end() ) {
6450 IGeneratorInfo* info =
new GeneratorInfo( size );
6451 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
6452 m_generatorsInOrder.push_back( info );
6461 for(; it != itEnd; ++it ) {
6462 if( (*it)->moveNext() )
6469 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
6475 return new GeneratorsForTest();
6481#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
6486 SourceLineInfo
const& _lineInfo,
6487 std::string
const& _capturedExpression,
6489 : macroName( _macroName ),
6490 lineInfo( _lineInfo ),
6491 capturedExpression( _capturedExpression ),
6492 resultDisposition( _resultDisposition )
6495 AssertionResult::AssertionResult() {}
6497 AssertionResult::AssertionResult( AssertionInfo
const& info, AssertionResultData
const& data )
6499 m_resultData( data )
6502 AssertionResult::~AssertionResult() {}
6505 bool AssertionResult::succeeded()
const {
6514 ResultWas::OfType AssertionResult::getResultType()
const {
6515 return m_resultData.resultType;
6518 bool AssertionResult::hasExpression()
const {
6519 return !m_info.capturedExpression.empty();
6522 bool AssertionResult::hasMessage()
const {
6523 return !m_resultData.message.empty();
6526 std::string AssertionResult::getExpression()
const {
6528 return "!" + m_info.capturedExpression;
6530 return m_info.capturedExpression;
6532 std::string AssertionResult::getExpressionInMacro()
const {
6533 if( m_info.macroName.empty() )
6534 return m_info.capturedExpression;
6536 return m_info.macroName + "( " + m_info.capturedExpression + " )";
6539 bool AssertionResult::hasExpandedExpression()
const {
6540 return hasExpression() && getExpandedExpression() != getExpression();
6543 std::string AssertionResult::getExpandedExpression()
const {
6544 return m_resultData.reconstructedExpression;
6547 std::string AssertionResult::getMessage()
const {
6548 return m_resultData.message;
6550 SourceLineInfo AssertionResult::getSourceInfo()
const {
6551 return m_info.lineInfo;
6554 std::string AssertionResult::getTestMacroName()
const {
6555 return m_info.macroName;
6561#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
6570 else if( tag ==
"!throws" )
6572 else if( tag ==
"!shouldfail" )
6574 else if( tag ==
"!mayfail" )
6579 inline bool isReservedTag( std::string
const& tag ) {
6580 return parseSpecialTag( tag ) ==
TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
6582 inline void enforceNotReservedTag( std::string
const& tag, SourceLineInfo
const& _lineInfo ) {
6583 if( isReservedTag( tag ) ) {
6585 Colour colourGuard( Colour::Red );
6587 <<
"Tag name [" << tag <<
"] not allowed.\n"
6588 <<
"Tag names starting with non alpha-numeric characters are reserved\n";
6591 Colour colourGuard( Colour::FileName );
6599 std::string
const& _className,
6600 std::string
const& _name,
6601 std::string
const& _descOrTags,
6602 SourceLineInfo
const& _lineInfo )
6607 std::set<std::string> tags;
6608 std::string desc, tag;
6610 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
6611 char c = _descOrTags[i];
6624 enforceNotReservedTag( tag, _lineInfo );
6635 tags.insert(
"hide" );
6639 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
6640 return TestCase( _testCase, info );
6643 TestCaseInfo::TestCaseInfo( std::string
const& _name,
6644 std::string
const& _className,
6645 std::string
const& _description,
6646 std::set<std::string>
const& _tags,
6647 SourceLineInfo
const& _lineInfo )
6649 className( _className ),
6650 description( _description ),
6652 lineInfo( _lineInfo ),
6655 std::ostringstream oss;
6656 for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) {
6657 oss <<
"[" << *it <<
"]";
6658 std::string lcaseTag =
toLower( *it );
6659 properties =
static_cast<SpecialProperties
>( properties | parseSpecialTag( lcaseTag ) );
6660 lcaseTags.insert( lcaseTag );
6662 tagsAsString = oss.str();
6665 TestCaseInfo::TestCaseInfo( TestCaseInfo
const& other )
6666 : name( other.name ),
6667 className( other.className ),
6668 description( other.description ),
6670 lcaseTags( other.lcaseTags ),
6671 tagsAsString( other.tagsAsString ),
6672 lineInfo( other.lineInfo ),
6673 properties( other.properties )
6676 bool TestCaseInfo::isHidden()
const {
6677 return ( properties & IsHidden ) != 0;
6679 bool TestCaseInfo::throws()
const {
6680 return ( properties & Throws ) != 0;
6682 bool TestCaseInfo::okToFail()
const {
6683 return ( properties & (ShouldFail | MayFail ) ) != 0;
6685 bool TestCaseInfo::expectedToFail()
const {
6686 return ( properties & (ShouldFail ) ) != 0;
6689 TestCase::TestCase( ITestCase* testCase, TestCaseInfo
const& info ) : TestCaseInfo( info ), test( testCase ) {}
6691 TestCase::TestCase( TestCase
const& other )
6692 : TestCaseInfo( other ),
6696 TestCase TestCase::withName( std::string
const& _newName )
const {
6697 TestCase other( *
this );
6698 other.name = _newName;
6703 test.swap( other.test );
6704 name.swap( other.name );
6705 className.swap( other.className );
6706 description.swap( other.description );
6707 tags.swap( other.tags );
6708 lcaseTags.swap( other.lcaseTags );
6709 tagsAsString.swap( other.tagsAsString );
6710 std::swap( TestCaseInfo::properties,
static_cast<TestCaseInfo&
>( other ).properties );
6719 return test.get() == other.test.get() &&
6720 name == other.name &&
6721 className == other.className;
6725 return name < other.name;
6727 TestCase& TestCase::operator = ( TestCase
const& other ) {
6728 TestCase temp( other );
6733 TestCaseInfo
const& TestCase::getTestCaseInfo()
const
6741#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
6746 (
unsigned int _majorVersion,
6747 unsigned int _minorVersion,
6748 unsigned int _patchNumber,
6749 std::string
const& _branchName,
6750 unsigned int _buildNumber )
6751 : majorVersion( _majorVersion ),
6752 minorVersion( _minorVersion ),
6753 patchNumber( _patchNumber ),
6754 branchName( _branchName ),
6755 buildNumber( _buildNumber )
6758 std::ostream&
operator << ( std::ostream& os, Version
const& version ) {
6759 os << version.majorVersion <<
"."
6760 << version.minorVersion <<
"."
6761 << version.patchNumber;
6763 if( !version.branchName.empty() ) {
6764 os <<
"-" << version.branchName
6765 <<
"." << version.buildNumber;
6770 Version libraryVersion( 1, 2, 1,
"", 0 );
6775#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
6780 SourceLineInfo
const& _lineInfo,
6782 : macroName( _macroName ),
6783 lineInfo( _lineInfo ),
6785 sequence( ++globalCount )
6789 unsigned int MessageInfo::globalCount = 0;
6793 ScopedMessage::ScopedMessage( MessageBuilder
const& builder )
6794 : m_info( builder.m_info )
6796 m_info.message = builder.m_stream.str();
6799 ScopedMessage::ScopedMessage( ScopedMessage
const& other )
6800 : m_info( other.m_info )
6803 ScopedMessage::~ScopedMessage() {
6810#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
6813#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
6818 struct IReporter : IShared {
6819 virtual ~IReporter();
6821 virtual bool shouldRedirectStdout()
const = 0;
6823 virtual void StartTesting() = 0;
6824 virtual void EndTesting( Totals
const& totals ) = 0;
6825 virtual void StartGroup( std::string
const& groupName ) = 0;
6826 virtual void EndGroup( std::string
const& groupName, Totals
const& totals ) = 0;
6827 virtual void StartTestCase( TestCaseInfo
const& testInfo ) = 0;
6828 virtual void EndTestCase( TestCaseInfo
const& testInfo, Totals
const& totals, std::string
const& stdOut, std::string
const& stdErr ) = 0;
6829 virtual void StartSection( std::string
const& sectionName, std::string
const& description ) = 0;
6830 virtual void EndSection( std::string
const& sectionName, Counts
const& assertions ) = 0;
6831 virtual void NoAssertionsInSection( std::string
const& sectionName ) = 0;
6832 virtual void NoAssertionsInTestCase( std::string
const& testName ) = 0;
6833 virtual void Aborted() = 0;
6834 virtual void Result( AssertionResult
const& result ) = 0;
6837 class LegacyReporterAdapter :
public SharedImpl<IStreamingReporter>
6840 LegacyReporterAdapter( Ptr<IReporter>
const& legacyReporter );
6841 virtual ~LegacyReporterAdapter();
6843 virtual ReporterPreferences getPreferences()
const;
6844 virtual void noMatchingTestCases( std::string
const& );
6845 virtual void testRunStarting( TestRunInfo
const& );
6846 virtual void testGroupStarting( GroupInfo
const& groupInfo );
6847 virtual void testCaseStarting( TestCaseInfo
const& testInfo );
6848 virtual void sectionStarting( SectionInfo
const& sectionInfo );
6849 virtual void assertionStarting( AssertionInfo
const& );
6850 virtual bool assertionEnded( AssertionStats
const& assertionStats );
6851 virtual void sectionEnded( SectionStats
const& sectionStats );
6852 virtual void testCaseEnded( TestCaseStats
const& testCaseStats );
6853 virtual void testGroupEnded( TestGroupStats
const& testGroupStats );
6854 virtual void testRunEnded( TestRunStats
const& testRunStats );
6855 virtual void skipTest( TestCaseInfo
const& );
6858 Ptr<IReporter> m_legacyReporter;
6864 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter>
const& legacyReporter )
6865 : m_legacyReporter( legacyReporter )
6867 LegacyReporterAdapter::~LegacyReporterAdapter() {}
6869 ReporterPreferences LegacyReporterAdapter::getPreferences()
const {
6870 ReporterPreferences prefs;
6871 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
6875 void LegacyReporterAdapter::noMatchingTestCases( std::string
const& ) {}
6876 void LegacyReporterAdapter::testRunStarting( TestRunInfo
const& ) {
6877 m_legacyReporter->StartTesting();
6879 void LegacyReporterAdapter::testGroupStarting( GroupInfo
const& groupInfo ) {
6880 m_legacyReporter->StartGroup( groupInfo.name );
6882 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo
const& testInfo ) {
6883 m_legacyReporter->StartTestCase( testInfo );
6885 void LegacyReporterAdapter::sectionStarting( SectionInfo
const& sectionInfo ) {
6886 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
6888 void LegacyReporterAdapter::assertionStarting( AssertionInfo
const& ) {
6892 bool LegacyReporterAdapter::assertionEnded( AssertionStats
const& assertionStats ) {
6893 if( assertionStats.assertionResult.getResultType() !=
ResultWas::Ok ) {
6901 AssertionResult result = rb.build();
6902 m_legacyReporter->Result( result );
6906 m_legacyReporter->Result( assertionStats.assertionResult );
6909 void LegacyReporterAdapter::sectionEnded( SectionStats
const& sectionStats ) {
6910 if( sectionStats.missingAssertions )
6911 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
6912 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
6914 void LegacyReporterAdapter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
6915 m_legacyReporter->EndTestCase
6916 ( testCaseStats.testInfo,
6917 testCaseStats.totals,
6918 testCaseStats.stdOut,
6919 testCaseStats.stdErr );
6921 void LegacyReporterAdapter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
6922 if( testGroupStats.aborting )
6923 m_legacyReporter->Aborted();
6924 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
6926 void LegacyReporterAdapter::testRunEnded( TestRunStats
const& testRunStats ) {
6927 m_legacyReporter->EndTesting( testRunStats.totals );
6929 void LegacyReporterAdapter::skipTest( TestCaseInfo
const& ) {
6936#pragma clang diagnostic push
6937#pragma clang diagnostic ignored "-Wc++11-long-long"
6940#ifdef CATCH_PLATFORM_WINDOWS
6943#include <sys/time.h>
6949#ifdef CATCH_PLATFORM_WINDOWS
6950 uint64_t getCurrentTicks() {
6951 static uint64_t hz=0, hzo=0;
6953 QueryPerformanceFrequency(
reinterpret_cast<LARGE_INTEGER*
>( &hz ) );
6954 QueryPerformanceCounter(
reinterpret_cast<LARGE_INTEGER*
>( &hzo ) );
6957 QueryPerformanceCounter(
reinterpret_cast<LARGE_INTEGER*
>( &t ) );
6958 return ((t-hzo)*1000000)/hz;
6961 uint64_t getCurrentTicks() {
6963 gettimeofday(&t,NULL);
6964 return static_cast<uint64_t
>( t.tv_sec ) * 1000000ull +
static_cast<uint64_t
>( t.tv_usec );
6973 return static_cast<unsigned int>(getCurrentTicks() -
m_ticks);
6985#pragma clang diagnostic pop
6988#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
6992 bool startsWith( std::string
const& s, std::string
const& prefix ) {
6993 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
6995 bool endsWith( std::string
const& s, std::string
const& suffix ) {
6996 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
6998 bool contains( std::string
const& s, std::string
const& infix ) {
6999 return s.find( infix ) != std::string::npos;
7002 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
7004 std::string
toLower( std::string
const& s ) {
7009 std::string
trim( std::string
const& str ) {
7010 static char const* whitespaceChars =
"\n\r\t ";
7011 std::string::size_type start = str.find_first_not_of( whitespaceChars );
7012 std::string::size_type end = str.find_last_not_of( whitespaceChars );
7014 return start != std::string::npos ? str.substr( start, 1+end-start ) :
"";
7017 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis ) {
7018 bool replaced =
false;
7019 std::size_t i = str.find( replaceThis );
7020 while( i != std::string::npos ) {
7022 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
7023 if( i < str.size()-withThis.size() )
7024 i = str.find( replaceThis, i+withThis.size() );
7026 i = std::string::npos;
7036 std::ostream&
operator << ( std::ostream& os, pluralise
const& pluraliser ) {
7037 os << pluraliser.m_count <<
" " << pluraliser.m_label;
7038 if( pluraliser.m_count != 1 )
7043 SourceLineInfo::SourceLineInfo() : line( 0 ){}
7044 SourceLineInfo::SourceLineInfo(
char const* _file, std::size_t _line )
7048 SourceLineInfo::SourceLineInfo( SourceLineInfo
const& other )
7049 : file( other.file ),
7052 bool SourceLineInfo::empty()
const {
7053 return file.empty();
7056 return line == other.line && file == other.file;
7059 return line < other.line || ( line == other.line && file < other.file );
7062 std::ostream&
operator << ( std::ostream& os, SourceLineInfo
const& info ) {
7064 os << info.file <<
"(" << info.line <<
")";
7066 os << info.file <<
":" << info.line;
7071 void throwLogicError( std::string
const& message, SourceLineInfo
const& locationInfo ) {
7072 std::ostringstream oss;
7073 oss << locationInfo <<
": Internal Catch error: '" << message <<
"'";
7075 throw std::logic_error( oss.str() );
7080#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
7085 ( SourceLineInfo
const& _lineInfo,
7086 std::string
const& _name,
7087 std::string
const& _description )
7089 description( _description ),
7090 lineInfo( _lineInfo )
7093 Section::Section( SectionInfo
const& info )
7095 m_sectionIncluded(
getResultCapture().sectionStarted( m_info, m_assertions ) )
7100 Section::~Section() {
7101 if( m_sectionIncluded )
7106 Section::operator bool()
const {
7107 return m_sectionIncluded;
7113#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
7117#ifdef CATCH_PLATFORM_MAC
7120 #include <stdbool.h>
7121 #include <sys/types.h>
7123 #include <sys/sysctl.h>
7135 struct kinfo_proc info;
7141 info.kp_proc.p_flag = 0;
7148 mib[2] = KERN_PROC_PID;
7153 size =
sizeof(info);
7154 if( sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size, NULL, 0) != 0 ) {
7155 Catch::cerr() <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" <<
std::endl;
7161 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
7165#elif defined(_MSC_VER)
7166 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7169 return IsDebuggerPresent() != 0;
7172#elif defined(__MINGW32__)
7173 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7176 return IsDebuggerPresent() != 0;
7185#ifdef CATCH_PLATFORM_WINDOWS
7186 extern "C" __declspec(dllimport)
void __stdcall OutputDebugStringA(
const char* );
7189 ::OutputDebugStringA( text.c_str() );
7202#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
7212 enum Arch { Big, Little };
7214 static Arch which() {
7217 char asChar[sizeof (int)];
7221 return ( u.asChar[
sizeof(
int)-1] == 1 ) ? Big : Little;
7229 int i = 0, end =
static_cast<int>( size ), inc = 1;
7230 if( Endianness::which() == Endianness::Little ) {
7235 unsigned char const *bytes =
static_cast<unsigned char const *
>(
object);
7236 std::ostringstream os;
7237 os <<
"0x" << std::setfill(
'0') << std::hex;
7238 for( ; i != end; i += inc )
7239 os <<
std::setw(2) << static_cast<unsigned>(bytes[i]);
7244std::string
toString( std::string
const& value ) {
7245 std::string s = value;
7247 for(
size_t i = 0; i < s.size(); ++i ) {
7250 case '\n': subs =
"\\n";
break;
7251 case '\t': subs =
"\\t";
break;
7254 if( !subs.empty() ) {
7255 s = s.substr( 0, i ) + subs + s.substr( i+1 );
7260 return "\"" + s + "\"";
7262std::string
toString( std::wstring
const& value ) {
7265 s.reserve( value.size() );
7266 for(
size_t i = 0; i < value.size(); ++i )
7267 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
7271std::string
toString(
const char*
const value ) {
7275std::string
toString(
char*
const value ) {
7279std::string
toString(
const wchar_t*
const value )
7284std::string
toString(
wchar_t*
const value )
7290 std::ostringstream oss;
7293 oss <<
" (0x" << std::hex << value <<
")";
7297std::string
toString(
unsigned long value ) {
7298 std::ostringstream oss;
7301 oss <<
" (0x" << std::hex << value <<
")";
7305std::string
toString(
unsigned int value ) {
7310std::string fpToString( T value,
int precision ) {
7311 std::ostringstream oss;
7312 oss << std::setprecision( precision )
7315 std::string d = oss.str();
7316 std::size_t i = d.find_last_not_of(
'0' );
7317 if( i != std::string::npos && i != d.size()-1 ) {
7320 d = d.substr( 0, i+1 );
7325std::string
toString(
const double value ) {
7326 return fpToString( value, 10 );
7328std::string
toString(
const float value ) {
7329 return fpToString( value, 5 ) + "f";
7332std::string
toString(
bool value ) {
7333 return value ?
"true" :
"false";
7336std::string
toString(
char value ) {
7338 ?
toString(
static_cast<unsigned int>( value ) )
7342std::string
toString(
signed char value ) {
7343 return toString(
static_cast<char>( value ) );
7346std::string
toString(
unsigned char value ) {
7347 return toString(
static_cast<char>( value ) );
7350#ifdef CATCH_CONFIG_CPP11_NULLPTR
7351std::string
toString( std::nullptr_t ) {
7357 std::string
toString( NSString
const *
const& nsstring ) {
7360 return "@" +
toString([nsstring UTF8String]);
7362 std::string
toString( NSString * CATCH_ARC_STRONG
const& nsstring ) {
7365 return "@" +
toString([nsstring UTF8String]);
7367 std::string
toString( NSObject*
const& nsObject ) {
7368 return toString( [nsObject description] );
7375#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
7380 SourceLineInfo
const& lineInfo,
7381 char const* capturedExpression,
7383 : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ),
7384 m_shouldDebugBreak( false ),
7385 m_shouldThrow( false )
7388 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
7389 m_data.resultType = result;
7392 ResultBuilder& ResultBuilder::setResultType(
bool result ) {
7393 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
7396 ResultBuilder& ResultBuilder::setLhs( std::string
const& lhs ) {
7397 m_exprComponents.lhs = lhs;
7400 ResultBuilder& ResultBuilder::setRhs( std::string
const& rhs ) {
7401 m_exprComponents.rhs = rhs;
7404 ResultBuilder& ResultBuilder::setOp( std::string
const& op ) {
7405 m_exprComponents.op = op;
7409 void ResultBuilder::endExpression() {
7410 m_exprComponents.testFalse =
isFalseTest( m_assertionInfo.resultDisposition );
7411 captureExpression();
7414 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
7415 m_assertionInfo.resultDisposition = resultDisposition;
7417 captureResult( ResultWas::ThrewException );
7420 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
7421 setResultType( resultType );
7422 captureExpression();
7425 void ResultBuilder::captureExpression() {
7426 AssertionResult result = build();
7429 if( !result.isOk() ) {
7431 m_shouldDebugBreak =
true;
7432 if(
getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
7433 m_shouldThrow =
true;
7436 void ResultBuilder::react() {
7441 bool ResultBuilder::shouldDebugBreak()
const {
return m_shouldDebugBreak; }
7444 AssertionResult ResultBuilder::build()
const
7446 assert( m_data.resultType != ResultWas::Unknown );
7448 AssertionResultData data = m_data;
7451 if( m_exprComponents.testFalse ) {
7452 if( data.resultType == ResultWas::Ok )
7453 data.resultType = ResultWas::ExpressionFailed;
7454 else if( data.resultType == ResultWas::ExpressionFailed )
7455 data.resultType = ResultWas::Ok;
7458 data.message = m_stream.oss.str();
7459 data.reconstructedExpression = reconstructExpression();
7460 if( m_exprComponents.testFalse ) {
7461 if( m_exprComponents.op ==
"" )
7462 data.reconstructedExpression =
"!" + data.reconstructedExpression;
7464 data.reconstructedExpression =
"!(" + data.reconstructedExpression + ")";
7466 return AssertionResult( m_assertionInfo, data );
7468 std::string ResultBuilder::reconstructExpression()
const {
7469 if( m_exprComponents.op ==
"" )
7470 return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
7471 else if( m_exprComponents.op ==
"matches" )
7472 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
7473 else if( m_exprComponents.op !=
"!" ) {
7474 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
7475 m_exprComponents.lhs.find(
"\n") == std::string::npos &&
7476 m_exprComponents.rhs.find(
"\n") == std::string::npos )
7477 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
7479 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
7482 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}";
7488#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
7491#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
7497 class TagAliasRegistry :
public ITagAliasRegistry {
7499 virtual ~TagAliasRegistry();
7500 virtual Option<TagAlias> find( std::string
const& alias )
const;
7501 virtual std::string expandAliases( std::string
const& unexpandedTestSpec )
const;
7502 void add(
char const* alias,
char const* tag, SourceLineInfo
const& lineInfo );
7503 static TagAliasRegistry&
get();
7506 std::map<std::string, TagAlias> m_registry;
7516 TagAliasRegistry::~TagAliasRegistry() {}
7518 Option<TagAlias> TagAliasRegistry::find( std::string
const& alias )
const {
7519 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
7520 if( it != m_registry.end() )
7523 return Option<TagAlias>();
7526 std::string TagAliasRegistry::expandAliases( std::string
const& unexpandedTestSpec )
const {
7527 std::string expandedTestSpec = unexpandedTestSpec;
7528 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
7531 std::size_t
pos = expandedTestSpec.find( it->first );
7532 if(
pos != std::string::npos ) {
7533 expandedTestSpec = expandedTestSpec.substr( 0,
pos ) +
7535 expandedTestSpec.substr(
pos + it->first.size() );
7538 return expandedTestSpec;
7541 void TagAliasRegistry::add(
char const* alias,
char const* tag, SourceLineInfo
const& lineInfo ) {
7544 std::ostringstream oss;
7545 oss <<
"error: tag alias, \"" << alias <<
"\" is not of the form [@alias name].\n" << lineInfo;
7546 throw std::domain_error( oss.str().c_str() );
7548 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
7549 std::ostringstream oss;
7550 oss <<
"error: tag alias, \"" << alias <<
"\" already registered.\n"
7551 <<
"\tFirst seen at " << find(alias)->lineInfo <<
"\n"
7552 <<
"\tRedefined at " << lineInfo;
7553 throw std::domain_error( oss.str().c_str() );
7558 static TagAliasRegistry instance;
7570 catch( std::exception& ex ) {
7571 Colour colourGuard( Colour::Red );
7580#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
7583#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
7589 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
7591 StreamingReporterBase( ReporterConfig
const& _config )
7592 : m_config( _config.fullConfig() ),
7593 stream( _config.stream() )
7596 virtual ~StreamingReporterBase();
7598 virtual void noMatchingTestCases( std::string
const& ) {}
7600 virtual void testRunStarting( TestRunInfo
const& _testRunInfo ) {
7601 currentTestRunInfo = _testRunInfo;
7603 virtual void testGroupStarting( GroupInfo
const& _groupInfo ) {
7604 currentGroupInfo = _groupInfo;
7607 virtual void testCaseStarting( TestCaseInfo
const& _testInfo ) {
7608 currentTestCaseInfo = _testInfo;
7610 virtual void sectionStarting( SectionInfo
const& _sectionInfo ) {
7611 m_sectionStack.push_back( _sectionInfo );
7614 virtual void sectionEnded( SectionStats
const& ) {
7615 m_sectionStack.pop_back();
7617 virtual void testCaseEnded( TestCaseStats
const& ) {
7618 currentTestCaseInfo.reset();
7620 virtual void testGroupEnded( TestGroupStats
const& ) {
7621 currentGroupInfo.reset();
7623 virtual void testRunEnded( TestRunStats
const& ) {
7624 currentTestCaseInfo.reset();
7625 currentGroupInfo.reset();
7626 currentTestRunInfo.reset();
7629 virtual void skipTest( TestCaseInfo
const& ) {
7634 Ptr<IConfig> m_config;
7635 std::ostream& stream;
7637 LazyStat<TestRunInfo> currentTestRunInfo;
7638 LazyStat<GroupInfo> currentGroupInfo;
7639 LazyStat<TestCaseInfo> currentTestCaseInfo;
7644 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
7645 template<
typename T,
typename ChildNodeT>
7646 struct Node : SharedImpl<> {
7647 explicit Node( T
const& _value ) : value( _value ) {}
7652 ChildNodes children;
7654 struct SectionNode : SharedImpl<> {
7655 explicit SectionNode( SectionStats
const& _stats ) : stats( _stats ) {}
7656 virtual ~SectionNode();
7658 bool operator == ( SectionNode
const& other )
const {
7659 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
7661 bool operator == ( Ptr<SectionNode>
const& other )
const {
7668 ChildSections childSections;
7669 Assertions assertions;
7674 struct BySectionInfo {
7675 BySectionInfo( SectionInfo
const& other ) : m_other( other ) {}
7676 BySectionInfo( BySectionInfo
const& other ) : m_other( other.m_other ) {}
7677 bool operator() ( Ptr<SectionNode>
const& node )
const {
7678 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
7681 void operator=( BySectionInfo
const& );
7682 SectionInfo
const& m_other;
7685 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
7686 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
7687 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
7689 CumulativeReporterBase( ReporterConfig
const& _config )
7690 : m_config( _config.fullConfig() ),
7691 stream( _config.stream() )
7693 ~CumulativeReporterBase();
7695 virtual void testRunStarting( TestRunInfo
const& ) {}
7696 virtual void testGroupStarting( GroupInfo
const& ) {}
7698 virtual void testCaseStarting( TestCaseInfo
const& ) {}
7700 virtual void sectionStarting( SectionInfo
const& sectionInfo ) {
7701 SectionStats incompleteStats( sectionInfo, Counts(), 0,
false );
7702 Ptr<SectionNode> node;
7703 if( m_sectionStack.empty() ) {
7704 if( !m_rootSection )
7705 m_rootSection =
new SectionNode( incompleteStats );
7706 node = m_rootSection;
7709 SectionNode& parentNode = *m_sectionStack.back();
7710 SectionNode::ChildSections::const_iterator it =
7711 std::find_if( parentNode.childSections.begin(),
7712 parentNode.childSections.end(),
7713 BySectionInfo( sectionInfo ) );
7714 if( it == parentNode.childSections.end() ) {
7715 node =
new SectionNode( incompleteStats );
7716 parentNode.childSections.push_back( node );
7721 m_sectionStack.push_back( node );
7722 m_deepestSection = node;
7725 virtual void assertionStarting( AssertionInfo
const& ) {}
7727 virtual bool assertionEnded( AssertionStats
const& assertionStats ) {
7728 assert( !m_sectionStack.empty() );
7729 SectionNode& sectionNode = *m_sectionStack.back();
7730 sectionNode.assertions.push_back( assertionStats );
7733 virtual void sectionEnded( SectionStats
const& sectionStats ) {
7734 assert( !m_sectionStack.empty() );
7735 SectionNode& node = *m_sectionStack.back();
7736 node.stats = sectionStats;
7737 m_sectionStack.pop_back();
7739 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) {
7740 Ptr<TestCaseNode> node =
new TestCaseNode( testCaseStats );
7741 assert( m_sectionStack.size() == 0 );
7742 node->children.push_back( m_rootSection );
7743 m_testCases.push_back( node );
7744 m_rootSection.reset();
7746 assert( m_deepestSection );
7747 m_deepestSection->stdOut = testCaseStats.stdOut;
7748 m_deepestSection->stdErr = testCaseStats.stdErr;
7750 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) {
7751 Ptr<TestGroupNode> node =
new TestGroupNode( testGroupStats );
7752 node->children.swap( m_testCases );
7753 m_testGroups.push_back( node );
7755 virtual void testRunEnded( TestRunStats
const& testRunStats ) {
7756 Ptr<TestRunNode> node =
new TestRunNode( testRunStats );
7757 node->children.swap( m_testGroups );
7758 m_testRuns.push_back( node );
7759 testRunEndedCumulative();
7761 virtual void testRunEndedCumulative() = 0;
7763 virtual void skipTest( TestCaseInfo
const& ) {}
7765 Ptr<IConfig> m_config;
7766 std::ostream& stream;
7774 Ptr<SectionNode> m_rootSection;
7775 Ptr<SectionNode> m_deepestSection;
7781 char const* getLineOfChars() {
7782 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
7784 memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
7785 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
7793#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
7797 template<
typename T>
7798 class LegacyReporterRegistrar {
7800 class ReporterFactory :
public IReporterFactory {
7801 virtual IStreamingReporter* create( ReporterConfig
const& config )
const {
7802 return new LegacyReporterAdapter(
new T( config ) );
7805 virtual std::string getDescription()
const {
7806 return T::getDescription();
7812 LegacyReporterRegistrar( std::string
const& name ) {
7817 template<
typename T>
7818 class ReporterRegistrar {
7820 class ReporterFactory :
public IReporterFactory {
7833 virtual IStreamingReporter* create( ReporterConfig
const& config )
const {
7834 return new T( config );
7837 virtual std::string getDescription()
const {
7838 return T::getDescription();
7844 ReporterRegistrar( std::string
const& name ) {
7850#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
7851 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
7852#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
7853 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
7856#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
7867 class ScopedElement {
7869 ScopedElement( XmlWriter* writer )
7870 : m_writer( writer )
7873 ScopedElement( ScopedElement
const& other )
7874 : m_writer( other.m_writer ){
7875 other.m_writer = NULL;
7880 m_writer->endElement();
7883 ScopedElement& writeText( std::string
const& text,
bool indent =
true ) {
7884 m_writer->writeText( text, indent );
7888 template<
typename T>
7889 ScopedElement& writeAttribute( std::string
const& name, T
const& attribute ) {
7890 m_writer->writeAttribute( name, attribute );
7895 mutable XmlWriter* m_writer;
7899 : m_tagIsOpen( false ),
7900 m_needsNewline( false ),
7904 XmlWriter( std::ostream& os )
7905 : m_tagIsOpen( false ),
7906 m_needsNewline( false ),
7911 while( !m_tags.empty() )
7915 XmlWriter& startElement( std::string
const& name ) {
7917 newlineIfNecessary();
7918 stream() << m_indent <<
"<" << name;
7919 m_tags.push_back( name );
7925 ScopedElement scopedElement( std::string
const& name ) {
7926 ScopedElement scoped(
this );
7927 startElement( name );
7931 XmlWriter& endElement() {
7932 newlineIfNecessary();
7933 m_indent = m_indent.substr( 0, m_indent.size()-2 );
7936 m_tagIsOpen =
false;
7939 stream() << m_indent <<
"</" << m_tags.back() <<
">\n";
7945 XmlWriter& writeAttribute( std::string
const& name, std::string
const& attribute ) {
7946 if( !name.empty() && !attribute.empty() ) {
7947 stream() <<
" " << name <<
"=\"";
7948 writeEncodedText( attribute );
7954 XmlWriter& writeAttribute( std::string
const& name,
bool attribute ) {
7955 stream() <<
" " << name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
"\"";
7959 template<
typename T>
7960 XmlWriter& writeAttribute( std::string
const& name, T
const& attribute ) {
7962 stream() <<
" " << name <<
"=\"" << attribute <<
"\"";
7966 XmlWriter& writeText( std::string
const& text,
bool indent =
true ) {
7967 if( !text.empty() ){
7968 bool tagWasOpen = m_tagIsOpen;
7970 if( tagWasOpen && indent )
7971 stream() << m_indent;
7972 writeEncodedText( text );
7973 m_needsNewline =
true;
7978 XmlWriter& writeComment( std::string
const& text ) {
7980 stream() << m_indent <<
"<!--" << text <<
"-->";
7981 m_needsNewline =
true;
7985 XmlWriter& writeBlankLine() {
7991 void setStream( std::ostream& os ) {
7996 XmlWriter( XmlWriter
const& );
7997 void operator=( XmlWriter
const& );
7999 std::ostream& stream() {
8003 void ensureTagClosed() {
8006 m_tagIsOpen =
false;
8010 void newlineIfNecessary() {
8011 if( m_needsNewline ) {
8013 m_needsNewline =
false;
8017 void writeEncodedText( std::string
const& text ) {
8018 static const char* charsToEncode =
"<&\"";
8019 std::string mtext = text;
8020 std::string::size_type
pos = mtext.find_first_of( charsToEncode );
8021 while(
pos != std::string::npos ) {
8022 stream() << mtext.substr( 0,
pos );
8024 switch( mtext[
pos] ) {
8029 stream() <<
"&";
8032 stream() <<
""";
8035 mtext = mtext.substr(
pos+1 );
8036 pos = mtext.find_first_of( charsToEncode );
8042 bool m_needsNewline;
8044 std::string m_indent;
8050 class XmlReporter :
public StreamingReporterBase {
8052 XmlReporter( ReporterConfig
const& _config )
8053 : StreamingReporterBase( _config ),
8057 virtual ~XmlReporter();
8059 static std::string getDescription() {
8060 return "Reports test results as an XML document";
8064 virtual ReporterPreferences getPreferences()
const {
8065 ReporterPreferences prefs;
8066 prefs.shouldRedirectStdOut =
true;
8070 virtual void noMatchingTestCases( std::string
const& s ) {
8071 StreamingReporterBase::noMatchingTestCases( s );
8074 virtual void testRunStarting( TestRunInfo
const& testInfo ) {
8075 StreamingReporterBase::testRunStarting( testInfo );
8076 m_xml.setStream( stream );
8077 m_xml.startElement(
"Catch" );
8078 if( !m_config->name().empty() )
8079 m_xml.writeAttribute(
"name", m_config->name() );
8082 virtual void testGroupStarting( GroupInfo
const& groupInfo ) {
8083 StreamingReporterBase::testGroupStarting( groupInfo );
8084 m_xml.startElement(
"Group" )
8085 .writeAttribute(
"name", groupInfo.name );
8088 virtual void testCaseStarting( TestCaseInfo
const& testInfo ) {
8089 StreamingReporterBase::testCaseStarting(testInfo);
8090 m_xml.startElement(
"TestCase" ).writeAttribute(
"name",
trim( testInfo.name ) );
8092 if ( m_config->showDurations() == ShowDurations::Always )
8093 m_testCaseTimer.start();
8096 virtual void sectionStarting( SectionInfo
const& sectionInfo ) {
8097 StreamingReporterBase::sectionStarting( sectionInfo );
8098 if( m_sectionDepth++ > 0 ) {
8099 m_xml.startElement(
"Section" )
8100 .writeAttribute(
"name",
trim( sectionInfo.name ) )
8101 .writeAttribute(
"description", sectionInfo.description );
8105 virtual void assertionStarting( AssertionInfo
const& ) { }
8107 virtual bool assertionEnded( AssertionStats
const& assertionStats ) {
8108 const AssertionResult& assertionResult = assertionStats.assertionResult;
8111 if( assertionStats.assertionResult.getResultType() !=
ResultWas::Ok ) {
8116 m_xml.scopedElement(
"Info" )
8117 .writeText( it->message );
8119 m_xml.scopedElement(
"Warning" )
8120 .writeText( it->message );
8126 if( !m_config->includeSuccessfulResults() &&
isOk(assertionResult.getResultType()) )
8130 if( assertionResult.hasExpression() ) {
8131 m_xml.startElement(
"Expression" )
8132 .writeAttribute(
"success", assertionResult.succeeded() )
8133 .writeAttribute(
"type", assertionResult.getTestMacroName() )
8134 .writeAttribute(
"filename", assertionResult.getSourceInfo().file )
8135 .writeAttribute(
"line", assertionResult.getSourceInfo().line );
8137 m_xml.scopedElement(
"Original" )
8138 .writeText( assertionResult.getExpression() );
8139 m_xml.scopedElement(
"Expanded" )
8140 .writeText( assertionResult.getExpandedExpression() );
8144 switch( assertionResult.getResultType() ) {
8146 m_xml.scopedElement(
"Exception" )
8147 .writeAttribute(
"filename", assertionResult.getSourceInfo().file )
8148 .writeAttribute(
"line", assertionResult.getSourceInfo().line )
8149 .writeText( assertionResult.getMessage() );
8152 m_xml.scopedElement(
"Fatal Error Condition" )
8153 .writeAttribute(
"filename", assertionResult.getSourceInfo().file )
8154 .writeAttribute(
"line", assertionResult.getSourceInfo().line )
8155 .writeText( assertionResult.getMessage() );
8158 m_xml.scopedElement(
"Info" )
8159 .writeText( assertionResult.getMessage() );
8165 m_xml.scopedElement(
"Failure" )
8166 .writeText( assertionResult.getMessage() );
8172 if( assertionResult.hasExpression() )
8178 virtual void sectionEnded( SectionStats
const& sectionStats ) {
8179 StreamingReporterBase::sectionEnded( sectionStats );
8180 if( --m_sectionDepth > 0 ) {
8181 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResults" );
8182 e.writeAttribute(
"successes", sectionStats.assertions.passed );
8183 e.writeAttribute(
"failures", sectionStats.assertions.failed );
8184 e.writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
8186 if ( m_config->showDurations() == ShowDurations::Always )
8187 e.writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
8193 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) {
8194 StreamingReporterBase::testCaseEnded( testCaseStats );
8195 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResult" );
8196 e.writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
8198 if ( m_config->showDurations() == ShowDurations::Always )
8199 e.writeAttribute(
"durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
8204 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) {
8205 StreamingReporterBase::testGroupEnded( testGroupStats );
8207 m_xml.scopedElement(
"OverallResults" )
8208 .writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
8209 .writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
8210 .writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
8214 virtual void testRunEnded( TestRunStats
const& testRunStats ) {
8215 StreamingReporterBase::testRunEnded( testRunStats );
8216 m_xml.scopedElement(
"OverallResults" )
8217 .writeAttribute(
"successes", testRunStats.totals.assertions.passed )
8218 .writeAttribute(
"failures", testRunStats.totals.assertions.failed )
8219 .writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
8224 Timer m_testCaseTimer;
8229 INTERNAL_CATCH_REGISTER_REPORTER(
"xml", XmlReporter )
8234#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
8240 class JunitReporter :
public CumulativeReporterBase {
8242 JunitReporter( ReporterConfig
const& _config )
8243 : CumulativeReporterBase( _config ),
8244 xml( _config.stream() )
8249 static std::string getDescription() {
8250 return "Reports test results in an XML format that looks like Ant's junitreport target";
8253 virtual void noMatchingTestCases( std::string
const& ) {}
8255 virtual ReporterPreferences getPreferences()
const {
8256 ReporterPreferences prefs;
8257 prefs.shouldRedirectStdOut =
true;
8261 virtual void testRunStarting( TestRunInfo
const& runInfo ) {
8262 CumulativeReporterBase::testRunStarting( runInfo );
8263 xml.startElement(
"testsuites" );
8266 virtual void testGroupStarting( GroupInfo
const& groupInfo ) {
8268 stdOutForSuite.str(
"");
8269 stdErrForSuite.str(
"");
8270 unexpectedExceptions = 0;
8271 CumulativeReporterBase::testGroupStarting( groupInfo );
8274 virtual bool assertionEnded( AssertionStats
const& assertionStats ) {
8276 unexpectedExceptions++;
8277 return CumulativeReporterBase::assertionEnded( assertionStats );
8280 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) {
8281 stdOutForSuite << testCaseStats.stdOut;
8282 stdErrForSuite << testCaseStats.stdErr;
8283 CumulativeReporterBase::testCaseEnded( testCaseStats );
8286 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) {
8287 double suiteTime = suiteTimer.getElapsedSeconds();
8288 CumulativeReporterBase::testGroupEnded( testGroupStats );
8289 writeGroup( *m_testGroups.back(), suiteTime );
8292 virtual void testRunEndedCumulative() {
8296 void writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
8297 XmlWriter::ScopedElement e = xml.scopedElement(
"testsuite" );
8298 TestGroupStats
const& stats = groupNode.value;
8299 xml.writeAttribute(
"name", stats.groupInfo.name );
8300 xml.writeAttribute(
"errors", unexpectedExceptions );
8301 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
8302 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
8303 xml.writeAttribute(
"hostname",
"tbd" );
8304 if( m_config->showDurations() == ShowDurations::Never )
8305 xml.writeAttribute(
"time",
"" );
8307 xml.writeAttribute(
"time", suiteTime );
8308 xml.writeAttribute(
"timestamp",
"tbd" );
8311 for( TestGroupNode::ChildNodes::const_iterator
8312 it = groupNode.children.begin(), itEnd = groupNode.children.end();
8315 writeTestCase( **it );
8317 xml.scopedElement(
"system-out" ).writeText(
trim( stdOutForSuite.str() ),
false );
8318 xml.scopedElement(
"system-err" ).writeText(
trim( stdErrForSuite.str() ),
false );
8321 void writeTestCase( TestCaseNode
const& testCaseNode ) {
8322 TestCaseStats
const& stats = testCaseNode.value;
8326 assert( testCaseNode.children.size() == 1 );
8327 SectionNode
const& rootSection = *testCaseNode.children.front();
8329 std::string className = stats.testInfo.className;
8331 if( className.empty() ) {
8332 if( rootSection.childSections.empty() )
8333 className =
"global";
8335 writeSection( className,
"", rootSection );
8338 void writeSection( std::string
const& className,
8339 std::string
const& rootName,
8340 SectionNode
const& sectionNode ) {
8341 std::string name =
trim( sectionNode.stats.sectionInfo.name );
8342 if( !rootName.empty() )
8343 name = rootName + "/" + name;
8345 if( !sectionNode.assertions.empty() ||
8346 !sectionNode.stdOut.empty() ||
8347 !sectionNode.stdErr.empty() ) {
8348 XmlWriter::ScopedElement e = xml.scopedElement(
"testcase" );
8349 if( className.empty() ) {
8350 xml.writeAttribute(
"classname", name );
8351 xml.writeAttribute(
"name",
"root" );
8354 xml.writeAttribute(
"classname", className );
8355 xml.writeAttribute(
"name", name );
8357 xml.writeAttribute(
"time",
Catch::toString( sectionNode.stats.durationInSeconds ) );
8359 writeAssertions( sectionNode );
8361 if( !sectionNode.stdOut.empty() )
8362 xml.scopedElement(
"system-out" ).writeText(
trim( sectionNode.stdOut ),
false );
8363 if( !sectionNode.stdErr.empty() )
8364 xml.scopedElement(
"system-err" ).writeText(
trim( sectionNode.stdErr ),
false );
8366 for( SectionNode::ChildSections::const_iterator
8367 it = sectionNode.childSections.begin(),
8368 itEnd = sectionNode.childSections.end();
8371 if( className.empty() )
8372 writeSection( name,
"", **it );
8374 writeSection( className, name, **it );
8377 void writeAssertions( SectionNode
const& sectionNode ) {
8378 for( SectionNode::Assertions::const_iterator
8379 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
8382 writeAssertion( *it );
8384 void writeAssertion( AssertionStats
const& stats ) {
8385 AssertionResult
const& result = stats.assertionResult;
8386 if( !result.isOk() ) {
8387 std::string elementName;
8388 switch( result.getResultType() ) {
8391 elementName =
"error";
8394 elementName =
"failure";
8397 elementName =
"failure";
8400 elementName =
"failure";
8410 elementName =
"internalError";
8414 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
8416 xml.writeAttribute(
"message", result.getExpandedExpression() );
8417 xml.writeAttribute(
"type", result.getTestMacroName() );
8419 std::ostringstream oss;
8420 if( !result.getMessage().empty() )
8421 oss << result.getMessage() <<
"\n";
8423 it = stats.infoMessages.
begin(),
8424 itEnd = stats.infoMessages.end();
8428 oss << it->message <<
"\n";
8430 oss <<
"at " << result.getSourceInfo();
8431 xml.writeText( oss.str(),
false );
8437 std::ostringstream stdOutForSuite;
8438 std::ostringstream stdErrForSuite;
8439 unsigned int unexpectedExceptions;
8442 INTERNAL_CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
8447#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
8451 struct ConsoleReporter : StreamingReporterBase {
8452 ConsoleReporter( ReporterConfig
const& _config )
8453 : StreamingReporterBase( _config ),
8454 m_headerPrinted( false )
8457 virtual ~ConsoleReporter();
8458 static std::string getDescription() {
8459 return "Reports test results as plain lines of text";
8461 virtual ReporterPreferences getPreferences()
const {
8462 ReporterPreferences prefs;
8463 prefs.shouldRedirectStdOut =
false;
8467 virtual void noMatchingTestCases( std::string
const& spec ) {
8468 stream <<
"No test cases matched '" << spec <<
"'" <<
std::endl;
8471 virtual void assertionStarting( AssertionInfo
const& ) {
8474 virtual bool assertionEnded( AssertionStats
const& _assertionStats ) {
8475 AssertionResult
const& result = _assertionStats.assertionResult;
8477 bool printInfoMessages =
true;
8480 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
8483 printInfoMessages =
false;
8488 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
8494 virtual void sectionStarting( SectionInfo
const& _sectionInfo ) {
8495 m_headerPrinted =
false;
8496 StreamingReporterBase::sectionStarting( _sectionInfo );
8498 virtual void sectionEnded( SectionStats
const& _sectionStats ) {
8499 if( _sectionStats.missingAssertions ) {
8501 Colour colour( Colour::ResultError );
8502 if( m_sectionStack.size() > 1 )
8503 stream <<
"\nNo assertions in section";
8505 stream <<
"\nNo assertions in test case";
8506 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" <<
std::endl;
8508 if( m_headerPrinted ) {
8509 if( m_config->showDurations() == ShowDurations::Always )
8510 stream <<
"Completed in " << _sectionStats.durationInSeconds <<
"s" <<
std::endl;
8511 m_headerPrinted =
false;
8514 if( m_config->showDurations() == ShowDurations::Always )
8515 stream << _sectionStats.sectionInfo.name <<
" completed in " << _sectionStats.durationInSeconds <<
"s" <<
std::endl;
8517 StreamingReporterBase::sectionEnded( _sectionStats );
8520 virtual void testCaseEnded( TestCaseStats
const& _testCaseStats ) {
8521 StreamingReporterBase::testCaseEnded( _testCaseStats );
8522 m_headerPrinted =
false;
8524 virtual void testGroupEnded( TestGroupStats
const& _testGroupStats ) {
8525 if( currentGroupInfo.used ) {
8526 printSummaryDivider();
8527 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
8528 printTotals( _testGroupStats.totals );
8531 StreamingReporterBase::testGroupEnded( _testGroupStats );
8533 virtual void testRunEnded( TestRunStats
const& _testRunStats ) {
8534 printTotalsDivider( _testRunStats.totals );
8535 printTotals( _testRunStats.totals );
8537 StreamingReporterBase::testRunEnded( _testRunStats );
8542 class AssertionPrinter {
8543 void operator= ( AssertionPrinter
const& );
8545 AssertionPrinter( std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages )
8546 : stream( _stream ),
8548 result( _stats.assertionResult ),
8549 colour( Colour::None ),
8550 message( result.getMessage() ),
8551 messages( _stats.infoMessages ),
8552 printInfoMessages( _printInfoMessages )
8554 switch( result.getResultType() ) {
8556 colour = Colour::Success;
8557 passOrFail =
"PASSED";
8559 if( _stats.infoMessages.size() == 1 )
8560 messageLabel =
"with message";
8561 if( _stats.infoMessages.size() > 1 )
8562 messageLabel =
"with messages";
8565 if( result.isOk() ) {
8566 colour = Colour::Success;
8567 passOrFail =
"FAILED - but was ok";
8570 colour = Colour::Error;
8571 passOrFail =
"FAILED";
8573 if( _stats.infoMessages.size() == 1 )
8574 messageLabel =
"with message";
8575 if( _stats.infoMessages.size() > 1 )
8576 messageLabel =
"with messages";
8579 colour = Colour::Error;
8580 passOrFail =
"FAILED";
8581 messageLabel =
"due to unexpected exception with message";
8584 colour = Colour::Error;
8585 passOrFail =
"FAILED";
8586 messageLabel =
"due to a fatal error condition";
8589 colour = Colour::Error;
8590 passOrFail =
"FAILED";
8591 messageLabel =
"because no exception was thrown where one was expected";
8594 messageLabel =
"info";
8597 messageLabel =
"warning";
8600 passOrFail =
"FAILED";
8601 colour = Colour::Error;
8602 if( _stats.infoMessages.size() == 1 )
8603 messageLabel =
"explicitly with message";
8604 if( _stats.infoMessages.size() > 1 )
8605 messageLabel =
"explicitly with messages";
8611 passOrFail =
"** internal error **";
8612 colour = Colour::Error;
8617 void print()
const {
8619 if( stats.totals.assertions.total() > 0 ) {
8623 printOriginalExpression();
8624 printReconstructedExpression();
8633 void printResultType()
const {
8634 if( !passOrFail.empty() ) {
8635 Colour colourGuard( colour );
8636 stream << passOrFail <<
":\n";
8639 void printOriginalExpression()
const {
8640 if( result.hasExpression() ) {
8641 Colour colourGuard( Colour::OriginalExpression );
8643 stream << result.getExpressionInMacro();
8647 void printReconstructedExpression()
const {
8648 if( result.hasExpandedExpression() ) {
8649 stream <<
"with expansion:\n";
8650 Colour colourGuard( Colour::ReconstructedExpression );
8651 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) <<
"\n";
8654 void printMessage()
const {
8655 if( !messageLabel.empty() )
8656 stream << messageLabel <<
":" <<
"\n";
8662 stream << Text( it->message, TextAttributes().setIndent(2) ) <<
"\n";
8665 void printSourceInfo()
const {
8666 Colour colourGuard( Colour::FileName );
8667 stream << result.getSourceInfo() <<
": ";
8670 std::ostream& stream;
8671 AssertionStats
const& stats;
8672 AssertionResult
const& result;
8673 Colour::Code colour;
8674 std::string passOrFail;
8675 std::string messageLabel;
8676 std::string message;
8678 bool printInfoMessages;
8683 if( !currentTestRunInfo.used )
8685 if( !currentGroupInfo.used )
8686 lazyPrintGroupInfo();
8688 if( !m_headerPrinted ) {
8689 printTestCaseAndSectionHeader();
8690 m_headerPrinted =
true;
8693 void lazyPrintRunInfo() {
8694 stream <<
"\n" << getLineOfChars<'~'>() <<
"\n";
8695 Colour colour( Colour::SecondaryText );
8696 stream << currentTestRunInfo->name
8697 <<
" is a Catch v" << libraryVersion <<
" host application.\n"
8698 <<
"Run with -? for options\n\n";
8700 if( m_config->rngSeed() != 0 )
8701 stream <<
"Randomness seeded to: " << m_config->rngSeed() <<
"\n\n";
8703 currentTestRunInfo.used =
true;
8705 void lazyPrintGroupInfo() {
8706 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
8707 printClosedHeader(
"Group: " + currentGroupInfo->name );
8708 currentGroupInfo.used =
true;
8711 void printTestCaseAndSectionHeader() {
8712 assert( !m_sectionStack.empty() );
8713 printOpenHeader( currentTestCaseInfo->name );
8715 if( m_sectionStack.size() > 1 ) {
8716 Colour colourGuard( Colour::Headers );
8719 it = m_sectionStack.
begin()+1,
8720 itEnd = m_sectionStack.end();
8721 for( ; it != itEnd; ++it )
8722 printHeaderString( it->name, 2 );
8725 SourceLineInfo lineInfo = m_sectionStack.
front().lineInfo;
8727 if( !lineInfo.empty() ){
8728 stream << getLineOfChars<
'-'>() <<
"\n";
8729 Colour colourGuard( Colour::FileName );
8730 stream << lineInfo <<
"\n";
8732 stream << getLineOfChars<'.'>() <<
"\n" <<
std::endl;
8735 void printClosedHeader( std::string
const& _name ) {
8736 printOpenHeader( _name );
8737 stream << getLineOfChars<
'.'>() <<
"\n";
8739 void printOpenHeader( std::string
const& _name ) {
8740 stream << getLineOfChars<
'-'>() <<
"\n";
8742 Colour colourGuard( Colour::Headers );
8743 printHeaderString( _name );
8749 void printHeaderString( std::string
const& _string, std::size_t indent = 0 ) {
8750 std::size_t i = _string.find(
": " );
8751 if( i != std::string::npos )
8755 stream << Text( _string, TextAttributes()
8756 .setIndent( indent+i)
8757 .setInitialIndent( indent ) ) <<
"\n";
8760 struct SummaryColumn {
8762 SummaryColumn( std::string
const& _label, Colour::Code _colour )
8766 SummaryColumn addRow( std::size_t count ) {
8767 std::ostringstream oss;
8769 std::string row = oss.str();
8771 while( it->
size() < row.size() )
8773 while( it->
size() > row.size() )
8781 Colour::Code colour;
8786 void printTotals( Totals
const& totals ) {
8787 if( totals.testCases.total() == 0 ) {
8788 stream << Colour( Colour::Warning ) <<
"No tests ran\n";
8790 else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) {
8791 stream << Colour( Colour::ResultSuccess ) <<
"All tests passed";
8793 << pluralise( totals.assertions.passed,
"assertion" ) <<
" in "
8794 << pluralise( totals.testCases.passed,
"test case" ) <<
")"
8800 columns.
push_back( SummaryColumn(
"", Colour::None )
8801 .addRow( totals.testCases.total() )
8802 .addRow( totals.assertions.total() ) );
8803 columns.
push_back( SummaryColumn(
"passed", Colour::Success )
8804 .addRow( totals.testCases.passed )
8805 .addRow( totals.assertions.passed ) );
8806 columns.
push_back( SummaryColumn(
"failed", Colour::ResultError )
8807 .addRow( totals.testCases.failed )
8808 .addRow( totals.assertions.failed ) );
8809 columns.
push_back( SummaryColumn(
"failed as expected", Colour::ResultExpectedFailure )
8810 .addRow( totals.testCases.failedButOk )
8811 .addRow( totals.assertions.failedButOk ) );
8813 printSummaryRow(
"test cases", columns, 0 );
8814 printSummaryRow(
"assertions", columns, 1 );
8819 std::string value = it->rows[row];
8820 if( it->label.
empty() ) {
8821 stream << label <<
": ";
8825 stream << Colour( Colour::Warning ) <<
"- none -";
8827 else if( value !=
"0" ) {
8828 stream << Colour( Colour::LightGrey ) <<
" | ";
8829 stream << Colour( it->colour )
8830 << value <<
" " << it->label;
8836 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
8837 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
8838 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
8840 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
8841 if( i > j && i > k )
8849 void printTotalsDivider( Totals
const& totals ) {
8850 if( totals.testCases.total() > 0 ) {
8851 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
8852 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
8853 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
8854 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
8855 findMax( failedRatio, failedButOkRatio, passedRatio )++;
8856 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
8857 findMax( failedRatio, failedButOkRatio, passedRatio )--;
8859 stream << Colour( Colour::Error ) << std::string( failedRatio,
'=' );
8860 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio,
'=' );
8861 if( totals.testCases.allPassed() )
8862 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio,
'=' );
8864 stream << Colour( Colour::Success ) << std::string( passedRatio,
'=' );
8867 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1,
'=' );
8871 void printSummaryDivider() {
8872 stream << getLineOfChars<
'-'>() <<
"\n";
8876 bool m_headerPrinted;
8879 INTERNAL_CATCH_REGISTER_REPORTER(
"console", ConsoleReporter )
8884#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
8888 struct CompactReporter : StreamingReporterBase {
8890 CompactReporter( ReporterConfig
const& _config )
8891 : StreamingReporterBase( _config )
8894 virtual ~CompactReporter();
8896 static std::string getDescription() {
8897 return "Reports test results on a single line, suitable for IDEs";
8900 virtual ReporterPreferences getPreferences()
const {
8901 ReporterPreferences prefs;
8902 prefs.shouldRedirectStdOut =
false;
8906 virtual void noMatchingTestCases( std::string
const& spec ) {
8907 stream <<
"No test cases matched '" << spec <<
"'" <<
std::endl;
8910 virtual void assertionStarting( AssertionInfo
const& ) {
8913 virtual bool assertionEnded( AssertionStats
const& _assertionStats ) {
8914 AssertionResult
const& result = _assertionStats.assertionResult;
8916 bool printInfoMessages =
true;
8919 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
8922 printInfoMessages =
false;
8925 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
8932 virtual void testRunEnded( TestRunStats
const& _testRunStats ) {
8933 printTotals( _testRunStats.totals );
8935 StreamingReporterBase::testRunEnded( _testRunStats );
8939 class AssertionPrinter {
8940 void operator= ( AssertionPrinter
const& );
8942 AssertionPrinter( std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages )
8945 , result( _stats.assertionResult )
8946 , messages( _stats.infoMessages )
8947 , itMessage( _stats.infoMessages.begin() )
8948 , printInfoMessages( _printInfoMessages )
8954 itMessage = messages.begin();
8956 switch( result.getResultType() ) {
8958 printResultType( Colour::ResultSuccess, passedString() );
8959 printOriginalExpression();
8960 printReconstructedExpression();
8961 if ( ! result.hasExpression() )
8962 printRemainingMessages( Colour::None );
8964 printRemainingMessages();
8968 printResultType( Colour::ResultSuccess, failedString() + std::string(
" - but was ok" ) );
8970 printResultType( Colour::Error, failedString() );
8971 printOriginalExpression();
8972 printReconstructedExpression();
8973 printRemainingMessages();
8976 printResultType( Colour::Error, failedString() );
8977 printIssue(
"unexpected exception with message:" );
8979 printExpressionWas();
8980 printRemainingMessages();
8983 printResultType( Colour::Error, failedString() );
8984 printIssue(
"fatal error condition with message:" );
8986 printExpressionWas();
8987 printRemainingMessages();
8990 printResultType( Colour::Error, failedString() );
8991 printIssue(
"expected exception, got none" );
8992 printExpressionWas();
8993 printRemainingMessages();
8996 printResultType( Colour::None,
"info" );
8998 printRemainingMessages();
9001 printResultType( Colour::None,
"warning" );
9003 printRemainingMessages();
9006 printResultType( Colour::Error, failedString() );
9007 printIssue(
"explicitly" );
9008 printRemainingMessages( Colour::None );
9014 printResultType( Colour::Error,
"** internal error **" );
9022 static Colour::Code dimColour() {
return Colour::FileName; }
9024#ifdef CATCH_PLATFORM_MAC
9025 static const char* failedString() {
return "FAILED"; }
9026 static const char* passedString() {
return "PASSED"; }
9028 static const char* failedString() {
return "failed"; }
9029 static const char* passedString() {
return "passed"; }
9032 void printSourceInfo()
const {
9033 Colour colourGuard( Colour::FileName );
9034 stream << result.getSourceInfo() <<
":";
9037 void printResultType( Colour::Code colour, std::string passOrFail )
const {
9038 if( !passOrFail.empty() ) {
9040 Colour colourGuard( colour );
9041 stream <<
" " << passOrFail;
9047 void printIssue( std::string issue )
const {
9048 stream <<
" " << issue;
9051 void printExpressionWas() {
9052 if( result.hasExpression() ) {
9055 Colour colour( dimColour() );
9056 stream <<
" expression was:";
9058 printOriginalExpression();
9062 void printOriginalExpression()
const {
9063 if( result.hasExpression() ) {
9064 stream <<
" " << result.getExpression();
9068 void printReconstructedExpression()
const {
9069 if( result.hasExpandedExpression() ) {
9071 Colour colour( dimColour() );
9074 stream << result.getExpandedExpression();
9078 void printMessage() {
9079 if ( itMessage != messages.end() ) {
9080 stream <<
" '" << itMessage->message <<
"'";
9085 void printRemainingMessages( Colour::Code colour = dimColour() ) {
9086 if ( itMessage == messages.end() )
9091 const std::size_t N =
static_cast<std::size_t
>( std::distance( itMessage, itEnd ) );
9094 Colour colourGuard( colour );
9095 stream <<
" with " << pluralise( N,
"message" ) <<
":";
9098 for(; itMessage != itEnd; ) {
9101 stream <<
" '" << itMessage->message <<
"'";
9102 if ( ++itMessage != itEnd ) {
9103 Colour colourGuard( dimColour() );
9111 std::ostream& stream;
9112 AssertionStats
const& stats;
9113 AssertionResult
const& result;
9116 bool printInfoMessages;
9126 std::string bothOrAll( std::size_t count )
const {
9127 return count == 1 ?
"" : count == 2 ?
"both " :
"all " ;
9130 void printTotals(
const Totals& totals )
const {
9131 if( totals.testCases.total() == 0 ) {
9132 stream <<
"No tests ran.";
9134 else if( totals.testCases.failed == totals.testCases.total() ) {
9135 Colour colour( Colour::ResultError );
9136 const std::string qualify_assertions_failed =
9137 totals.assertions.failed == totals.assertions.total() ?
9138 bothOrAll( totals.assertions.failed ) :
"";
9140 "Failed " << bothOrAll( totals.testCases.failed )
9141 << pluralise( totals.testCases.failed,
"test case" ) <<
", "
9142 "failed " << qualify_assertions_failed <<
9143 pluralise( totals.assertions.failed,
"assertion" ) <<
".";
9145 else if( totals.assertions.total() == 0 ) {
9147 "Passed " << bothOrAll( totals.testCases.total() )
9148 << pluralise( totals.testCases.total(),
"test case" )
9149 <<
" (no assertions).";
9151 else if( totals.assertions.failed ) {
9152 Colour colour( Colour::ResultError );
9154 "Failed " << pluralise( totals.testCases.failed,
"test case" ) <<
", "
9155 "failed " << pluralise( totals.assertions.failed,
"assertion" ) <<
".";
9158 Colour colour( Colour::ResultSuccess );
9160 "Passed " << bothOrAll( totals.testCases.passed )
9161 << pluralise( totals.testCases.passed,
"test case" ) <<
9162 " with " << pluralise( totals.assertions.passed,
"assertion" ) <<
".";
9167 INTERNAL_CATCH_REGISTER_REPORTER(
"compact", CompactReporter )
9183 IReporter::~IReporter() {}
9184 IReporterFactory::~IReporterFactory() {}
9185 IReporterRegistry::~IReporterRegistry() {}
9186 IStreamingReporter::~IStreamingReporter() {}
9187 AssertionStats::~AssertionStats() {}
9188 SectionStats::~SectionStats() {}
9189 TestCaseStats::~TestCaseStats() {}
9190 TestGroupStats::~TestGroupStats() {}
9191 TestRunStats::~TestRunStats() {}
9192 CumulativeReporterBase::SectionNode::~SectionNode() {}
9193 CumulativeReporterBase::~CumulativeReporterBase() {}
9195 StreamingReporterBase::~StreamingReporterBase() {}
9196 ConsoleReporter::~ConsoleReporter() {}
9197 CompactReporter::~CompactReporter() {}
9200 IConfig::~IConfig() {}
9201 XmlReporter::~XmlReporter() {}
9202 JunitReporter::~JunitReporter() {}
9203 TestRegistry::~TestRegistry() {}
9204 FreeFunctionTestCase::~FreeFunctionTestCase() {}
9207 TestSpec::Pattern::~Pattern() {}
9208 TestSpec::NamePattern::~NamePattern() {}
9209 TestSpec::TagPattern::~TagPattern() {}
9210 TestSpec::ExcludedPattern::~ExcludedPattern() {}
9217 void Config::dummy() {}
9221#pragma clang diagnostic pop
9226#ifdef CATCH_CONFIG_MAIN
9228#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
9233int main (
int argc,
char *
const argv[]) {
9234 return Catch::Session().run( argc, argv );
9240int main (
int argc,
char *
const argv[]) {
9241#if !CATCH_ARC_ENABLED
9242 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
9245 Catch::registerTestMethods();
9246 int result = Catch::Session().run( argc, (
char*
const*)argv );
9248#if !CATCH_ARC_ENABLED
9259#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
9260# undef CLARA_CONFIG_MAIN
9266#ifdef CATCH_CONFIG_PREFIX_ALL
9268#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
9269#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
9271#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
9272#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
9273#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
9275#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
9276#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
9277#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
9278#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
9279#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
9281#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
9282#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
9283#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
9285#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
9286#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
9288#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
9289#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
9290#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
9291#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
9292#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
9294#ifdef CATCH_CONFIG_VARIADIC_MACROS
9295 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
9296 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
9297 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
9298 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
9299 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
9300 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
9302 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
9303 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
9304 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
9305 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
9306 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
9307 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
9309#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
9311#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
9312#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
9314#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
9317#ifdef CATCH_CONFIG_VARIADIC_MACROS
9318#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
9319#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
9321#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
9322#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
9324#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" )
9325#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" )
9326#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" )
9327#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" )
9328#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" )
9333#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
9334#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
9336#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
9337#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
9338#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
9340#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
9341#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
9342#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
9343#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
9344#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
9346#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
9347#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
9348#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
9350#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
9351#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
9353#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
9354#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
9355#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
9356#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
9357#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
9359#ifdef CATCH_CONFIG_VARIADIC_MACROS
9360 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
9361 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
9362 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
9363 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
9364 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
9365 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
9367 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
9368 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
9369 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
9370 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
9371 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
9372 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
9374#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
9376#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
9377#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
9379#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
9383#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
9386#ifdef CATCH_CONFIG_VARIADIC_MACROS
9387#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
9388#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
9390#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
9391#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
9393#define GIVEN( desc ) SECTION( " Given: " desc, "" )
9394#define WHEN( desc ) SECTION( " When: " desc, "" )
9395#define AND_WHEN( desc ) SECTION( "And when: " desc, "" )
9396#define THEN( desc ) SECTION( " Then: " desc, "" )
9397#define AND_THEN( desc ) SECTION( " And: " desc, "" )
9403#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
9407# pragma warning(pop)
9409# pragma clang diagnostic pop
9411#elif defined __GNUC__
9412# pragma GCC diagnostic pop
#define CATCH_INTERNAL_ERROR(msg)
#define INTERNAL_CATCH_STRINGIFY(expr)
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(T value)
CompositeGenerator & setFileInfo(const char *fileInfo)
std::vector< const IGenerator< T > * > m_composed
CompositeGenerator & then(CompositeGenerator &other)
void add(const IGenerator< T > *generator)
void move(CompositeGenerator &other)
Approx & scale(double newScale)
Approx operator()(double value)
Approx(Approx const &other)
std::string toString() const
Approx & epsilon(double newEpsilon)
ExceptionTranslator(std::string(*translateFunction)(T &))
virtual std::string translate() 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
AnyOf & add(Matcher< ExpressionT > const &matcher)
virtual std::string toString() const
std::vector< Ptr< Matcher< ExpressionT > > > m_matchers
AnyOf(AnyOf const &other)
virtual bool match(ExpressionT const &expr) const
virtual void invoke() const
virtual ~MethodTestCase()
MethodTestCase(void(C::*method)())
NonCopyable(NonCopyable const &info)
NonCopyable & operator=(NonCopyable const &)
NotImplementedException(NotImplementedException const &)
virtual ~NotImplementedException() CATCH_NOEXCEPT
virtual const char * what() const CATCH_NOEXCEPT
SourceLineInfo m_lineInfo
NotImplementedException(SourceLineInfo const &lineInfo)
T const & operator*() const
T valueOr(T const &defaultValue) const
const T * operator->() const
Option(Option const &_other)
void captureResult(ResultWas::OfType resultType)
ExpressionLhs< T const & > operator<=(T const &operand)
ResultBuilder(char const *macroName, SourceLineInfo const &lineInfo, char const *capturedExpression, ResultDisposition::Flags resultDisposition)
ResultBuilder & setResultType(bool result)
AssertionResult build() const
void useActiveException(ResultDisposition::Flags resultDisposition=ResultDisposition::Normal)
AssertionResultData m_data
AssertionInfo m_assertionInfo
bool shouldDebugBreak() const
ResultBuilder & setOp(std::string const &op)
ResultBuilder & setLhs(std::string const &lhs)
ResultBuilder & setRhs(std::string const &rhs)
ResultBuilder & setResultType(ResultWas::OfType result)
std::string reconstructExpression() const
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
A simple vector class template.
T & front()
Returns a reference to the first element.
void push_back(const T &value)
Adds an element to the end of the vector.
iterator begin()
Returns an iterator to the first element.
iterator end()
Returns an iterator to the last element.
size_t size() const
Returns the number of elements in the vector.
bool empty() const
Checks if the vector is empty.
std::string rawMemoryToString(const T &object)
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 unprintableString
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)
std::string makeString(const char *str)
Impl::StdString::StartsWith StartsWith(const char *substr)
Impl::StdString::EndsWith EndsWith(std::string const &substr)
Impl::Generic::AnyOf< ExpressionT > AnyOf(Impl::Matcher< ExpressionT > const &m1, Impl::Matcher< ExpressionT > const &m2, Impl::Matcher< ExpressionT > const &m3)
Impl::StdString::Contains Contains(const char *substr)
Impl::StdString::StartsWith StartsWith(std::string const &substr)
Impl::StdString::Equals Equals(std::string const &str)
Impl::Generic::AllOf< ExpressionT > AllOf(Impl::Matcher< ExpressionT > const &m1, Impl::Matcher< ExpressionT > const &m2, Impl::Matcher< ExpressionT > const &m3)
Impl::StdString::Contains Contains(std::string const &substr)
Impl::StdString::EndsWith EndsWith(const char *substr)
Impl::StdString::Equals Equals(const char *str)
T const & operator+(T const &value, StreamEndStop)
void toLowerInPlace(std::string &s)
std::string trim(std::string const &str)
std::string(* exceptionTranslateFunction)()
IContext & getCurrentContext()
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)
bool isOk(ResultWas::OfType resultType)
bool isJustInfo(int flags)
IMutableRegistryHub & getMutableRegistryHub()
bool startsWith(std::string const &s, std::string const &prefix)
void throwLogicError(std::string const &message, SourceLineInfo const &locationInfo)
IMutableContext & getCurrentMutableContext()
IRegistryHub & getRegistryHub()
IGeneratorsForTest * createGeneratorsForTest()
bool shouldContinueOnFailure(int flags)
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
bool isFalseTest(int flags)
bool contains(std::string const &s, std::string const &infix)
void writeToDebugConsole(std::string const &text)
void deleteAll(ContainerT &container)
ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
bool shouldSuppressFailure(int flags)
std::string toLower(std::string const &s)
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
void deleteAllValues(AssociativeContainerT &container)
IResultCapture & getResultCapture()
bool replaceInPlace(std::string &str, std::string const &replaceThis, std::string const &withThis)
Vector3D operator*(const Vector3D &v1, const Vector3D &v2)
Vector3D operator/(const Vector3D &v, const double f)
bool operator!=(const Vector3D &v1, const Vector3D &v2)
Vector3D operator-(const Vector3D &v1, const Vector3D &v2)
bool operator==(const Vector3D &v1, const Vector3D &v2)
auto invoke(F &&f, Args &&... args) -> decltype(InvokeResult< F, Args... >::invoke(std::forward< F >(f), std::forward< Args >(args)...))
void swap(shared_lock< Mutex > &lhs, shared_lock< Mutex > &rhs) noexcept
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
@ object
object (unordered set of name/value pairs)
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Provides common mathematical functions and vector operations.
iostream cout
Standard output stream.
iostream cerr
Standard error stream.
iostream endl
End-of-line manipulator.
double fabs(double x)
Computes the absolute value of a floating-point number.
int main(int argc, char *argv[])
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)
void registerTestCase(ITestCase *testCase, 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 bool advanceGeneratorsForCurrentTest()=0
virtual IResultCapture * getResultCapture()=0
virtual Ptr< IConfig const > getConfig() const =0
virtual IRunner * getRunner()=0
virtual std::string translate() const =0
virtual ~IExceptionTranslator()
virtual ~IExceptionTranslatorRegistry()
virtual std::string translateActiveException() const =0
virtual std::size_t size() const =0
virtual T getValue(std::size_t index) const =0
virtual bool moveNext()=0
virtual std::size_t getCurrentIndex() const =0
virtual ~IGeneratorInfo()
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 void registerReporter(std::string const &name, IReporterFactory *factory)=0
virtual ~IMutableRegistryHub()
virtual void registerTranslator(const IExceptionTranslator *translator)=0
virtual ITestCaseRegistry const & getTestCaseRegistry() const =0
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry()=0
virtual IReporterRegistry const & getReporterRegistry() const =0
virtual void sectionEnded(SectionInfo const &name, Counts const &assertions, double _durationInSeconds)=0
virtual const AssertionResult * getLastResult() const =0
virtual ~IResultCapture()
virtual void popScopedMessage(MessageInfo const &message)=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 void assertionEnded(AssertionResult const &result)=0
virtual std::string getCurrentTestName() const =0
virtual bool aborting() const =0
virtual void release() const =0
virtual void addRef() const =0
static ITagAliasRegistry const & get()
virtual Option< TagAlias > find(std::string const &alias) const =0
virtual ~ITagAliasRegistry()
virtual std::string expandAliases(std::string const &unexpandedTestSpec) const =0
virtual void invoke() const =0
virtual std::vector< TestCase > const & getAllTests() const =0
virtual void getFilteredTests(TestSpec const &testSpec, IConfig const &config, std::vector< TestCase > &matchingTestCases, bool negated=false) const =0
virtual ~ITestCaseRegistry()
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 std::string toString() const =0
virtual Ptr< Matcher > clone() const =0
ExpressionT ExpressionType
virtual bool match(ExpressionT const &expr) const =0
virtual Ptr< Matcher< ExpressionT > > clone() const
virtual bool match(std::string const &expr) const
Contains(std::string const &substr)
Contains(Contains const &other)
virtual std::string toString() const
virtual std::string toString() const
EndsWith(std::string const &substr)
EndsWith(EndsWith const &other)
virtual bool match(std::string const &expr) const
Equals(std::string const &str)
virtual std::string toString() const
virtual bool match(std::string const &expr) const
Equals(Equals const &other)
StartsWith(std::string const &substr)
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)
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)
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)