11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 16 #define CATCH_VERSION_MAJOR 2 17 #define CATCH_VERSION_MINOR 2 18 #define CATCH_VERSION_PATCH 2 21 # pragma clang system_header 22 #elif defined __GNUC__ 23 # pragma GCC system_header 29 # ifdef __ICC // icpc defines the __clang__ macro 30 # pragma warning(push) 31 # pragma warning(disable: 161 1682) 33 # pragma clang diagnostic ignored "-Wunused-variable" 34 # pragma clang diagnostic push 35 # pragma clang diagnostic ignored "-Wpadded" 36 # pragma clang diagnostic ignored "-Wswitch-enum" 37 # pragma clang diagnostic ignored "-Wcovered-switch-default" 39 #elif defined __GNUC__ 40 # pragma GCC diagnostic ignored "-Wparentheses" 41 # pragma GCC diagnostic push 42 # pragma GCC diagnostic ignored "-Wunused-variable" 43 # pragma GCC diagnostic ignored "-Wpadded" 46 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) 48 # define CATCH_CONFIG_ALL_PARTS 53 #if defined(CATCH_CONFIG_ALL_PARTS) 54 # define CATCH_CONFIG_EXTERNAL_INTERFACES 55 # if defined(CATCH_CONFIG_DISABLE_MATCHERS) 56 # undef CATCH_CONFIG_DISABLE_MATCHERS 58 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 61 #if !defined(CATCH_CONFIG_IMPL_ONLY) 65 # include <TargetConditionals.h> 66 # if TARGET_OS_OSX == 1 67 # define CATCH_PLATFORM_MAC 68 # elif TARGET_OS_IPHONE == 1 69 # define CATCH_PLATFORM_IPHONE 72 #elif defined(linux) || defined(__linux) || defined(__linux__) 73 # define CATCH_PLATFORM_LINUX 75 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) 76 # define CATCH_PLATFORM_WINDOWS 82 # ifndef CLARA_CONFIG_MAIN 83 # define CLARA_CONFIG_MAIN_NOT_DEFINED 84 # define CLARA_CONFIG_MAIN 119 # if __cplusplus >= 201402L 120 # define CATCH_CPP14_OR_GREATER 123 # if __cplusplus >= 201703L 124 # define CATCH_CPP17_OR_GREATER 129 #if defined(CATCH_CPP17_OR_GREATER) 130 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 135 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 136 _Pragma( "clang diagnostic push" ) \ 137 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ 138 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") 139 # define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 140 _Pragma( "clang diagnostic pop" ) 142 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 143 _Pragma( "clang diagnostic push" ) \ 144 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 145 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 146 _Pragma( "clang diagnostic pop" ) 152 #if !defined(CATCH_PLATFORM_WINDOWS) 153 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS 158 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) 159 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 163 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 164 # define CATCH_CONFIG_COLOUR_NONE 181 # if _MSC_VER >= 1900 // Visual Studio 2015 or newer 182 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 187 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 188 # define CATCH_CONFIG_COLOUR_NONE 190 # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 199 # define CATCH_INTERNAL_CONFIG_NO_WCHAR 209 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) 210 #define CATCH_INTERNAL_CONFIG_COUNTER 213 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) 214 # define CATCH_CONFIG_COUNTER 216 #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) 217 # define CATCH_CONFIG_WINDOWS_SEH 220 #if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) 221 # define CATCH_CONFIG_POSIX_SIGNALS 224 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) 225 # define CATCH_CONFIG_WCHAR 228 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 229 # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 232 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) 233 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 234 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS 236 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) 237 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 238 # define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 242 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 243 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 244 #ifdef CATCH_CONFIG_COUNTER 245 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 247 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 285 bool empty()
const noexcept;
308 #define CATCH_INTERNAL_LINEINFO \ 309 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 320 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ 321 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 322 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ 323 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 338 virtual void invoke ()
const = 0;
349 virtual std::vector<TestCase>
const& getAllTests()
const = 0;
350 virtual std::vector<TestCase>
const& getAllTestsSorted( IConfig
const& config )
const = 0;
353 bool matchTest(
TestCase const& testCase, TestSpec
const& testSpec, IConfig
const& config );
354 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config );
382 friend struct StringRefTestAccess;
387 char* m_data =
nullptr;
389 void takeOwnership();
391 static constexpr
char const*
const s_empty =
"";
399 : m_start( other.m_start ),
400 m_size( other.m_size )
404 : m_start( other.m_start ),
405 m_size( other.m_size ),
406 m_data( other.m_data )
408 other.m_data =
nullptr;
411 StringRef(
char const* rawChars ) noexcept;
414 : m_start( rawChars ),
419 : m_start( stdString.c_str() ),
420 m_size( stdString.size() )
430 m_start = other.m_start;
431 m_size = other.m_size;
435 operator std::string()
const;
440 auto operator == (
StringRef const& other )
const noexcept -> bool;
441 auto operator != (
StringRef const& other )
const noexcept -> bool;
443 auto operator[] (
size_type index )
const noexcept -> char;
446 auto empty() const noexcept ->
bool {
453 auto numberOfCharacters()
const noexcept ->
size_type;
454 auto c_str()
const ->
char const*;
461 auto currentData()
const noexcept ->
char const*;
464 auto isOwned()
const noexcept -> bool;
465 auto isSubstring()
const noexcept -> bool;
475 inline auto operator "" _sr(
char const* rawChars, std::size_t
size ) noexcept ->
StringRef {
486 void (C::*m_testAsMethod)();
492 (obj.*m_testAsMethod)();
516 #if defined(CATCH_CONFIG_DISABLE) 517 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ 518 static void TestName() 519 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 521 struct TestName : ClassName { \ 525 void TestName::test() 530 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ 531 static void TestName(); \ 532 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 533 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } \ 534 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 535 static void TestName() 536 #define INTERNAL_CATCH_TESTCASE( ... ) \ 537 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) 540 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ 541 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 542 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } \ 543 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 546 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ 547 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 549 struct TestName : ClassName{ \ 552 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); \ 554 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 555 void TestName::test() 556 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ 557 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) 560 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ 561 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 562 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); \ 563 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 585 ExpressionFailed = FailureBit | 1,
586 ExplicitFailure = FailureBit | 2,
588 Exception = 0x100 | FailureBit,
590 ThrewException = Exception | 1,
591 DidntThrowException = Exception | 2,
593 FatalErrorCondition = 0x200 | FailureBit
604 ContinueOnFailure = 0x02,
641 #include <type_traits> 651 std::ostream&
cout();
652 std::ostream&
cerr();
653 std::ostream&
clog();
659 virtual std::ostream& stream()
const = 0;
671 auto str()
const -> std::string;
678 auto get() -> std::ostream& {
return *m_oss; }
680 static void cleanup();
689 #import <Foundation/Foundation.h> 692 #define CATCH_ARC_ENABLED __has_feature(objc_arc) 694 #define CATCH_ARC_ENABLED 0 697 void arcSafeRelease( NSObject* obj );
698 id performOptionalSelector(
id obj,
SEL sel );
700 #if !CATCH_ARC_ENABLED 701 inline void arcSafeRelease( NSObject* obj ) {
704 inline id performOptionalSelector(
id obj,
SEL sel ) {
705 if( [obj respondsToSelector: sel] )
706 return [obj performSelector: sel];
709 #define CATCH_UNSAFE_UNRETAINED 710 #define CATCH_ARC_STRONG 712 inline void arcSafeRelease( NSObject* ){}
713 inline id performOptionalSelector(
id obj,
SEL sel ) {
715 #pragma clang diagnostic push 716 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 718 if( [obj respondsToSelector: sel] )
719 return [obj performSelector: sel];
721 #pragma clang diagnostic pop 725 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 726 #define CATCH_ARC_STRONG __strong 733 #pragma warning(push) 734 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless 758 template<
typename SS,
typename TT>
759 static auto test(
int)
760 -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
762 template<
typename,
typename>
763 static auto test(...)->std::false_type;
766 static const bool value = decltype(test<std::ostream, const T&>(0))::value;
774 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) 778 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
786 #if defined(_MANAGED) 789 std::string clrReferenceToString( T^ ref ) {
791 return std::string(
"null");
792 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
793 cli::pin_ptr<System::Byte> p = &bytes[0];
794 return std::string(reinterpret_cast<char const *>(p), bytes->Length);
801 template <
typename T,
typename =
void>
803 template <
typename Fake = T>
805 typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>
::type 812 template <
typename Fake = T>
814 typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>
::type 824 template <
typename T>
834 #if defined(_MANAGED) 835 template <
typename T>
837 return ::Catch::StringMaker<T^>::convert(e);
847 static std::string convert(
const std::string& str);
849 #ifdef CATCH_CONFIG_WCHAR 852 static std::string convert(
const std::wstring& wstr);
858 static std::string convert(
char const * str);
862 static std::string convert(
char * str);
865 #ifdef CATCH_CONFIG_WCHAR 868 static std::string convert(
wchar_t const * str);
872 static std::string convert(
wchar_t * str);
886 static std::string
convert(
signed char const* str) {
892 static std::string
convert(
unsigned char const* str) {
899 static std::string convert(
int value);
903 static std::string convert(
long value);
907 static std::string convert(
long long value);
911 static std::string convert(
unsigned int value);
915 static std::string convert(
unsigned long value);
919 static std::string convert(
unsigned long long value);
924 static std::string convert(
bool b);
929 static std::string convert(
char c);
933 static std::string convert(
signed char c);
937 static std::string convert(
unsigned char c);
942 static std::string convert(std::nullptr_t);
947 static std::string convert(
float value);
951 static std::string convert(
double value);
954 template <
typename T>
956 template <
typename U>
966 template <
typename R,
typename C>
977 #if defined(_MANAGED) 978 template <
typename T>
980 static std::string convert( T^ ref ) {
981 return ::Catch::Detail::clrReferenceToString(ref);
987 template<
typename InputIterator>
993 for (++first; first != last; ++first)
1004 static std::string convert(NSString * nsstring) {
1007 return std::string(
"@") + [nsstring UTF8String];
1012 static std::string convert(NSObject* nsObject) {
1018 inline std::string
stringify( NSString* nsstring ) {
1031 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) 1032 # define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1033 # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1034 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1038 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) 1041 template<
typename T1,
typename T2>
1043 static std::string convert(
const std::pair<T1, T2>& pair) {
1054 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1057 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) 1064 bool = (N < std::tuple_size<Tuple>::value)
1066 struct TupleElementPrinter {
1067 static void print(
const Tuple& tuple, std::ostream& os) {
1068 os << (N ?
", " :
" ")
1070 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
1078 struct TupleElementPrinter<Tuple, N, false> {
1079 static void print(
const Tuple&, std::ostream&) {}
1084 template<
typename ...Types>
1086 static std::string convert(
const std::tuple<Types...>& tuple) {
1089 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.
get());
1095 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1107 template <
typename T>
1109 static const bool value =
1110 !std::is_same<decltype(begin(std::declval<T>())),
not_this_one>::value &&
1114 #if defined(_MANAGED) // Managed types are never ranges 1115 template <
typename T>
1117 static const bool value =
false;
1121 template<
typename Range>
1127 template<
typename Allocator>
1143 template<
typename R>
1144 struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>
::type> {
1150 template <
typename T,
int SZ>
1160 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 1167 template <
class Ratio>
1168 struct ratio_string {
1169 static std::string symbol();
1172 template <
class Ratio>
1173 std::string ratio_string<Ratio>::symbol() {
1175 rss <<
'[' << Ratio::num <<
'/' 1176 << Ratio::den <<
']';
1180 struct ratio_string<std::atto> {
1181 static std::string symbol();
1184 struct ratio_string<std::femto> {
1185 static std::string symbol();
1188 struct ratio_string<std::pico> {
1189 static std::string symbol();
1192 struct ratio_string<std::nano> {
1193 static std::string symbol();
1196 struct ratio_string<std::micro> {
1197 static std::string symbol();
1200 struct ratio_string<std::milli> {
1201 static std::string symbol();
1206 template<
typename Value,
typename Ratio>
1207 struct StringMaker<std::chrono::duration<Value, Ratio>> {
1208 static std::string convert(std::chrono::duration<Value, Ratio>
const& duration) {
1210 rss << duration.count() <<
' ' << ratio_string<Ratio>::symbol() <<
's';
1214 template<
typename Value>
1215 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
1216 static std::string convert(std::chrono::duration<
Value, std::ratio<1>>
const& duration) {
1218 rss << duration.count() <<
" s";
1222 template<
typename Value>
1223 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
1224 static std::string convert(std::chrono::duration<
Value, std::ratio<60>>
const& duration) {
1226 rss << duration.count() <<
" m";
1230 template<
typename Value>
1231 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
1232 static std::string convert(std::chrono::duration<
Value, std::ratio<3600>>
const& duration) {
1234 rss << duration.count() <<
" h";
1242 template<
typename Clock,
typename Duration>
1243 struct StringMaker<std::chrono::time_point<Clock, Duration>> {
1244 static std::string convert(std::chrono::time_point<Clock, Duration>
const& time_point) {
1249 template<
typename Duration>
1250 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
1251 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration>
const& time_point) {
1252 auto converted = std::chrono::system_clock::to_time_t(time_point);
1255 std::tm timeInfo = {};
1256 gmtime_s(&timeInfo, &converted);
1258 std::tm* timeInfo = std::gmtime(&converted);
1261 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
1262 char timeStamp[timeStampSize];
1263 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
1266 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
1268 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
1270 return std::string(timeStamp);
1274 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1277 #pragma warning(pop) 1284 #pragma warning(push) 1285 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch 1286 #pragma warning(disable:4018) // more "signed/unsigned mismatch" 1287 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 1288 #pragma warning(disable:4180) // qualifier applied to function type has no meaning 1296 virtual void streamReconstructedExpression( std::ostream &os )
const = 0;
1299 : m_isBinaryExpression( isBinaryExpression ),
1314 template<
typename LhsT,
typename RhsT>
1320 void streamReconstructedExpression( std::ostream &os )
const override {
1334 template<
typename LhsT>
1338 void streamReconstructedExpression( std::ostream &os )
const override {
1350 template<
typename LhsT,
typename RhsT>
1351 auto compareEqual( LhsT
const& lhs, RhsT
const& rhs ) ->
bool {
return static_cast<bool>(lhs == rhs); }
1352 template<
typename T>
1353 auto compareEqual( T*
const& lhs,
int rhs ) ->
bool {
return lhs ==
reinterpret_cast<void const*
>( rhs ); }
1354 template<
typename T>
1355 auto compareEqual( T*
const& lhs,
long rhs ) ->
bool {
return lhs ==
reinterpret_cast<void const*
>( rhs ); }
1356 template<
typename T>
1357 auto compareEqual(
int lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) == rhs; }
1358 template<
typename T>
1359 auto compareEqual(
long lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) == rhs; }
1361 template<
typename LhsT,
typename RhsT>
1362 auto compareNotEqual( LhsT
const& lhs, RhsT&& rhs ) ->
bool {
return static_cast<bool>(lhs != rhs); }
1363 template<
typename T>
1364 auto compareNotEqual( T*
const& lhs,
int rhs ) ->
bool {
return lhs !=
reinterpret_cast<void const*
>( rhs ); }
1365 template<
typename T>
1366 auto compareNotEqual( T*
const& lhs,
long rhs ) ->
bool {
return lhs !=
reinterpret_cast<void const*
>( rhs ); }
1367 template<
typename T>
1368 auto compareNotEqual(
int lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) != rhs; }
1369 template<
typename T>
1370 auto compareNotEqual(
long lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) != rhs; }
1372 template<
typename LhsT>
1378 template<
typename RhsT>
1380 return {
compareEqual( m_lhs, rhs ), m_lhs,
"==", rhs };
1383 return { m_lhs == rhs, m_lhs,
"==", rhs };
1386 template<
typename RhsT>
1391 return { m_lhs != rhs, m_lhs,
"!=", rhs };
1394 template<
typename RhsT>
1396 return {
static_cast<bool>(m_lhs > rhs), m_lhs,
">", rhs };
1398 template<
typename RhsT>
1400 return {
static_cast<bool>(m_lhs < rhs), m_lhs,
"<", rhs };
1402 template<
typename RhsT>
1404 return {
static_cast<bool>(m_lhs >= rhs), m_lhs,
">=", rhs };
1406 template<
typename RhsT>
1408 return {
static_cast<bool>(m_lhs <= rhs), m_lhs,
"<=", rhs };
1418 template<
typename T>
1424 template<
typename T>
1437 #pragma warning(pop) 1447 class AssertionResult;
1453 struct BenchmarkInfo;
1454 struct BenchmarkStats;
1463 virtual bool sectionStarted(
SectionInfo const& sectionInfo,
1464 Counts& assertions ) = 0;
1466 virtual void sectionEndedEarly(
SectionEndInfo const& endInfo ) = 0;
1468 virtual void benchmarkStarting( BenchmarkInfo
const& info ) = 0;
1469 virtual void benchmarkEnded( BenchmarkStats
const& stats ) = 0;
1471 virtual void pushScopedMessage(
MessageInfo const& message ) = 0;
1472 virtual void popScopedMessage(
MessageInfo const& message ) = 0;
1474 virtual void handleFatalErrorCondition(
StringRef message ) = 0;
1476 virtual void handleExpr
1480 virtual void handleMessage
1485 virtual void handleUnexpectedExceptionNotThrown
1488 virtual void handleUnexpectedInflightException
1490 std::string
const& message,
1492 virtual void handleIncomplete
1494 virtual void handleNonExpr
1499 virtual bool lastAssertionPassed() = 0;
1500 virtual void assertionPassed() = 0;
1503 virtual std::string getCurrentTestName()
const = 0;
1504 virtual const AssertionResult* getLastResult()
const = 0;
1505 virtual void exceptionEarlyReported() = 0;
1515 struct AssertionResultData;
1521 friend struct AssertionStats;
1522 friend class RunContext;
1531 explicit operator bool()
const;
1537 bool shouldDebugBreak =
false;
1538 bool shouldThrow =
false;
1544 bool m_completed =
false;
1554 if ( !m_completed ) {
1559 template<
typename T>
1567 void handleExceptionThrownAsExpected();
1568 void handleUnexpectedExceptionNotThrown();
1569 void handleExceptionNotThrownAsExpected();
1570 void handleThrowingCallSkipped();
1571 void handleUnexpectedInflightException();
1574 void setCompleted();
1577 auto allowThrows()
const -> bool;
1602 bool operator == (
MessageInfo const& other )
const;
1603 bool operator < (
MessageInfo const& other )
const;
1605 static unsigned int globalCount;
1610 template<
typename T>
1624 template<
typename T>
1644 #if !defined(CATCH_CONFIG_DISABLE) 1646 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) 1647 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ 1649 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" 1652 #if defined(CATCH_CONFIG_FAST_COMPILE) 1657 #define INTERNAL_CATCH_TRY 1658 #define INTERNAL_CATCH_CATCH( capturer ) 1660 #else // CATCH_CONFIG_FAST_COMPILE 1662 #define INTERNAL_CATCH_TRY try 1663 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); } 1667 #define INTERNAL_CATCH_REACT( handler ) handler.complete(); 1670 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ 1672 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 1673 INTERNAL_CATCH_TRY { \ 1674 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 1675 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ 1676 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 1677 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 1678 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1679 } while( (void)0, false && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look 1683 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ 1684 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 1685 if( Catch::getResultCapture().lastAssertionPassed() ) 1688 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ 1689 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 1690 if( !Catch::getResultCapture().lastAssertionPassed() ) 1693 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ 1695 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 1697 static_cast<void>(__VA_ARGS__); \ 1698 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ 1701 catchAssertionHandler.handleUnexpectedInflightException(); \ 1703 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1707 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ 1709 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ 1710 if( catchAssertionHandler.allowThrows() ) \ 1712 static_cast<void>(__VA_ARGS__); \ 1713 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 1716 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 1719 catchAssertionHandler.handleThrowingCallSkipped(); \ 1720 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1724 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 1726 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 1727 if( catchAssertionHandler.allowThrows() ) \ 1729 static_cast<void>(expr); \ 1730 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 1732 catch( exceptionType const& ) { \ 1733 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 1736 catchAssertionHandler.handleUnexpectedInflightException(); \ 1739 catchAssertionHandler.handleThrowingCallSkipped(); \ 1740 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1744 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 1746 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ 1747 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 1748 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1752 #define INTERNAL_CATCH_INFO( macroName, log ) \ 1753 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); 1757 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ 1759 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 1760 if( catchAssertionHandler.allowThrows() ) \ 1762 static_cast<void>(__VA_ARGS__); \ 1763 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 1766 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \ 1769 catchAssertionHandler.handleThrowingCallSkipped(); \ 1770 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1773 #endif // CATCH_CONFIG_DISABLE 1790 std::size_t total()
const;
1791 bool allPassed()
const;
1794 std::size_t passed = 0;
1795 std::size_t failed = 0;
1796 std::size_t failedButOk = 0;
1820 std::string
const& _name,
1821 std::string
const& _description = std::string() );
1849 uint64_t m_nanoseconds = 0;
1852 auto getElapsedNanoseconds()
const -> uint64_t;
1853 auto getElapsedMicroseconds()
const -> uint64_t;
1854 auto getElapsedMilliseconds()
const ->
unsigned int;
1855 auto getElapsedSeconds()
const -> double;
1871 explicit operator bool()
const;
1878 bool m_sectionIncluded;
1884 #define INTERNAL_CATCH_SECTION( ... ) \ 1885 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) 1898 std::size_t m_count = 0;
1899 std::size_t m_iterationsToRun = 1;
1900 uint64_t m_resolution;
1903 static auto getResolution() -> uint64_t;
1908 m_resolution( getResolution() )
1914 explicit operator bool() {
1915 if( m_count < m_iterationsToRun )
1917 return needsMoreIterations();
1925 auto needsMoreIterations() -> bool;
1930 #define BENCHMARK( name ) \ 1931 for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() ) 1944 struct ITestCaseRegistry;
1945 struct IExceptionTranslatorRegistry;
1946 struct IExceptionTranslator;
1947 struct IReporterRegistry;
1948 struct IReporterFactory;
1949 struct ITagAliasRegistry;
1950 class StartupExceptionRegistry;
1957 virtual IReporterRegistry
const& getReporterRegistry()
const = 0;
1959 virtual ITagAliasRegistry
const& getTagAliasRegistry()
const = 0;
1963 virtual StartupExceptionRegistry
const& getStartupExceptionRegistry()
const = 0;
1970 virtual void registerTest(
TestCase const& testInfo ) = 0;
1972 virtual void registerTagAlias( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo ) = 0;
1973 virtual void registerStartupException() noexcept = 0;
1984 #if defined(CATCH_CONFIG_DISABLE) 1985 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ 1986 static std::string translatorName( signature ) 1989 #include <exception> 2001 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const = 0;
2011 template<
typename T>
2015 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2016 : m_translateFunction( translateFunction )
2019 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const override {
2022 std::rethrow_exception(std::current_exception());
2024 return (*it)->translate( it+1, itEnd );
2027 return m_translateFunction( ex );
2032 std::string(*m_translateFunction)( T& );
2036 template<
typename T>
2039 (
new ExceptionTranslator<T>( translateFunction ) );
2045 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ 2046 static std::string translatorName( signature ); \ 2047 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 2048 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ 2049 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 2050 static std::string translatorName( signature ) 2052 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 2057 #include <type_traits> 2058 #include <stdexcept> 2065 bool equalityComparisonImpl(
double other)
const;
2068 explicit Approx (
double value );
2072 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2074 Approx approx( static_cast<double>(value) );
2076 approx.
margin( m_margin );
2077 approx.
scale( m_scale );
2081 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2085 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2086 friend bool operator == (
const T& lhs,
Approx const& rhs ) {
2087 auto lhs_v =
static_cast<double>(lhs);
2088 return rhs.equalityComparisonImpl(lhs_v);
2091 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2092 friend bool operator == (
Approx const& lhs,
const T& rhs ) {
2093 return operator==( rhs, lhs );
2096 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2097 friend bool operator != ( T
const& lhs,
Approx const& rhs ) {
2098 return !operator==( lhs, rhs );
2101 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2102 friend bool operator != (
Approx const& lhs, T
const& rhs ) {
2103 return !operator==( rhs, lhs );
2106 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2107 friend bool operator <= ( T
const& lhs,
Approx const& rhs ) {
2108 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
2111 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2112 friend bool operator <= (
Approx const& lhs, T
const& rhs ) {
2113 return lhs.m_value <
static_cast<double>(rhs) || lhs == rhs;
2116 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2117 friend bool operator >= ( T
const& lhs,
Approx const& rhs ) {
2118 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
2121 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2122 friend bool operator >= (
Approx const& lhs, T
const& rhs ) {
2123 return lhs.m_value >
static_cast<double>(rhs) || lhs == rhs;
2126 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2128 double epsilonAsDouble =
static_cast<double>(newEpsilon);
2129 if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) {
2130 throw std::domain_error
2131 (
"Invalid Approx::epsilon: " +
2133 ", Approx::epsilon has to be between 0 and 1" );
2135 m_epsilon = epsilonAsDouble;
2139 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2141 double marginAsDouble =
static_cast<double>(newMargin);
2142 if( marginAsDouble < 0 ) {
2143 throw std::domain_error
2144 (
"Invalid Approx::margin: " +
2146 ", Approx::Margin has to be non-negative." );
2149 m_margin = marginAsDouble;
2153 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
2155 m_scale =
static_cast<double>(newScale);
2159 std::string toString()
const;
2184 bool startsWith( std::string
const& s, std::string
const& prefix );
2185 bool startsWith( std::string
const& s,
char prefix );
2186 bool endsWith( std::string
const& s, std::string
const& suffix );
2187 bool endsWith( std::string
const& s,
char suffix );
2188 bool contains( std::string
const& s, std::string
const& infix );
2190 std::string
toLower( std::string
const& s );
2191 std::string
trim( std::string
const& str );
2192 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis );
2205 #ifndef CATCH_CONFIG_DISABLE_MATCHERS 2214 namespace Matchers {
2226 std::string toString()
const;
2230 virtual std::string describe()
const = 0;
2234 template<
typename ObjectT>
2236 virtual bool match( ObjectT
const& arg )
const = 0;
2238 template<
typename PtrT>
2240 virtual bool match( PtrT* arg )
const = 0;
2243 template<
typename T>
2251 template<
typename ArgT>
2253 bool match( ArgT
const& arg )
const override {
2254 for(
auto matcher : m_matchers ) {
2255 if (!matcher->match(arg))
2261 std::string description;
2262 description.reserve( 4 + m_matchers.size()*32 );
2263 description +=
"( ";
2265 for(
auto matcher : m_matchers ) {
2269 description +=
" and ";
2270 description += matcher->toString();
2272 description +=
" )";
2277 m_matchers.push_back( &other );
2283 template<
typename ArgT>
2286 bool match( ArgT
const& arg )
const override {
2287 for(
auto matcher : m_matchers ) {
2288 if (matcher->match(arg))
2294 std::string description;
2295 description.reserve( 4 + m_matchers.size()*32 );
2296 description +=
"( ";
2298 for(
auto matcher : m_matchers ) {
2302 description +=
" or ";
2303 description += matcher->toString();
2305 description +=
" )";
2310 m_matchers.push_back( &other );
2317 template<
typename ArgT>
2322 bool match( ArgT
const& arg )
const override {
2323 return !m_underlyingMatcher.match( arg );
2327 return "not " + m_underlyingMatcher.toString();
2332 template<
typename T>
2336 template<
typename T>
2340 template<
typename T>
2349 using namespace Matchers;
2357 #include <type_traits> 2361 namespace Matchers {
2363 namespace Floating {
2365 enum class FloatingPointKind : uint8_t;
2369 bool match(
double const& matchee)
const override;
2370 std::string describe()
const override;
2378 bool match(
double const& matchee)
const override;
2379 std::string describe()
const override;
2383 FloatingPointKind m_type;
2400 #include <functional> 2404 namespace Matchers {
2411 template <
typename T>
2413 std::function<bool(T const&)> m_predicate;
2414 std::string m_description;
2418 :m_predicate(std::move(elem)),
2422 bool match( T
const& item )
const override {
2423 return m_predicate(item);
2427 return m_description;
2437 template<
typename T>
2451 namespace Matchers {
2453 namespace StdString {
2458 std::string adjustString( std::string
const& str )
const;
2459 std::string caseSensitivitySuffix()
const;
2467 std::string describe()
const override;
2475 bool match( std::string
const& source )
const override;
2479 bool match( std::string
const& source )
const override;
2483 bool match( std::string
const& source )
const override;
2487 bool match( std::string
const& source )
const override;
2492 bool match( std::string
const& matchee )
const override;
2493 std::string describe()
const override;
2496 std::string m_regex;
2517 #include <algorithm> 2520 namespace Matchers {
2524 template <
typename InputIterator,
typename T>
2525 size_t count(InputIterator first, InputIterator last, T
const& item) {
2527 for (; first != last; ++first) {
2528 if (*first == item) {
2534 template <
typename InputIterator,
typename T>
2535 bool contains(InputIterator first, InputIterator last, T
const& item) {
2536 for (; first != last; ++first) {
2537 if (*first == item) {
2545 template<
typename T>
2550 bool match(std::vector<T>
const &v)
const override {
2551 for (
auto const& el : v) {
2552 if (el == m_comparator) {
2566 template<
typename T>
2571 bool match(std::vector<T>
const &v)
const override {
2573 if (m_comparator.size() > v.size())
2575 for (
auto const& comparator : m_comparator) {
2576 auto present =
false;
2577 for (
const auto& el : v) {
2578 if (el == comparator) {
2596 template<
typename T>
2601 bool match(std::vector<T>
const &v)
const override {
2606 if (m_comparator.size() != v.size())
2608 for (std::size_t i = 0; i < v.size(); ++i)
2609 if (m_comparator[i] != v[i])
2619 template<
typename T>
2622 bool match(std::vector<T>
const& vec)
const override {
2625 if (m_target.size() != vec.size()) {
2628 auto lfirst = m_target.begin(), llast = m_target.end();
2629 auto rfirst = vec.begin(), rlast = vec.end();
2631 while (lfirst != llast && *lfirst != *rfirst) {
2634 if (lfirst == llast) {
2638 for (
auto mid = lfirst; mid != llast; ++mid) {
2644 if (num_vec == 0 ||
Detail::count(lfirst, llast, *mid) != num_vec) {
2656 std::vector<T>
const& m_target;
2664 template<
typename T>
2669 template<
typename T>
2674 template<
typename T>
2679 template<
typename T>
2690 template<
typename ArgT,
typename MatcherT>
2699 m_matcher( matcher ),
2700 m_matcherString( matcherString )
2704 auto matcherAsString = m_matcher.toString();
2707 os << m_matcherString;
2709 os << matcherAsString;
2717 template<
typename ArgT,
typename MatcherT>
2725 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 2727 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2728 INTERNAL_CATCH_TRY { \ 2729 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ 2730 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 2731 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2735 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 2737 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2738 if( catchAssertionHandler.allowThrows() ) \ 2740 static_cast<void>(__VA_ARGS__ ); \ 2741 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2743 catch( exceptionType const& ex ) { \ 2744 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ 2747 catchAssertionHandler.handleUnexpectedInflightException(); \ 2750 catchAssertionHandler.handleThrowingCallSkipped(); \ 2751 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2766 #pragma clang diagnostic push 2767 #pragma clang diagnostic ignored "-Wpadded" 2772 struct ITestInvoker;
2778 ShouldFail = 1 << 2,
2781 NonPortable = 1 << 5,
2786 std::string
const& _className,
2787 std::string
const& _description,
2788 std::vector<std::string>
const& _tags,
2791 friend void setTags(
TestCaseInfo& testCaseInfo, std::vector<std::string> tags );
2793 bool isHidden()
const;
2794 bool throws()
const;
2795 bool okToFail()
const;
2796 bool expectedToFail()
const;
2798 std::string tagsAsString()
const;
2814 TestCase withName( std::string
const& _newName )
const;
2816 void invoke()
const;
2820 bool operator == (
TestCase const& other )
const;
2821 bool operator < (
TestCase const& other )
const;
2824 std::shared_ptr<ITestInvoker> test;
2828 std::string
const& className,
2834 #pragma clang diagnostic pop 2844 virtual bool aborting()
const = 0;
2853 #import <objc/runtime.h> 2878 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2880 virtual void invoke()
const {
2881 id obj = [[m_cls alloc] init];
2883 performOptionalSelector( obj,
@selector(setUp) );
2884 performOptionalSelector( obj, m_sel );
2885 performOptionalSelector( obj,
@selector(tearDown) );
2887 arcSafeRelease( obj );
2890 virtual ~OcMethod() {}
2898 inline std::string getAnnotation( Class cls,
2899 std::string
const& annotationName,
2900 std::string
const& testCaseName ) {
2901 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2902 SEL sel = NSSelectorFromString( selStr );
2903 arcSafeRelease( selStr );
2904 id value = performOptionalSelector( cls, sel );
2906 return [(NSString*)value UTF8String];
2911 inline std::size_t registerTestMethods() {
2912 std::size_t noTestMethods = 0;
2913 int noClasses = objc_getClassList(
nullptr, 0 );
2915 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc(
sizeof(Class) * noClasses);
2916 objc_getClassList( classes, noClasses );
2918 for(
int c = 0; c < noClasses; c++ ) {
2919 Class cls = classes[c];
2922 Method* methods = class_copyMethodList( cls, &count );
2923 for( u_int m = 0; m <
count ; m++ ) {
2924 SEL selector = method_getName(methods[m]);
2925 std::string methodName = sel_getName(selector);
2926 if(
startsWith( methodName,
"Catch_TestCase_" ) ) {
2927 std::string testCaseName = methodName.substr( 15 );
2928 std::string
name = Detail::getAnnotation( cls,
"Name", testCaseName );
2929 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
2930 const char* className = class_getName( cls );
2939 return noTestMethods;
2942 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 2944 namespace Matchers {
2946 namespace NSStringMatchers {
2948 struct StringHolder : MatcherBase<NSString*>{
2949 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2950 StringHolder( StringHolder
const& other ) : m_substr( [other.m_substr copy] ){}
2952 arcSafeRelease( m_substr );
2955 bool match( NSString* arg )
const override {
2959 NSString* CATCH_ARC_STRONG m_substr;
2962 struct Equals : StringHolder {
2963 Equals( NSString* substr ) : StringHolder( substr ){}
2965 bool match( NSString* str )
const override {
2966 return (str != nil || m_substr == nil ) &&
2967 [str isEqualToString:m_substr];
2970 std::string describe()
const override {
2976 Contains( NSString* substr ) : StringHolder( substr ){}
2978 bool match( NSString* str )
const {
2979 return (str != nil || m_substr == nil ) &&
2980 [str rangeOfString:m_substr].location != NSNotFound;
2983 std::string describe()
const override {
2989 StartsWith( NSString* substr ) : StringHolder( substr ){}
2991 bool match( NSString* str )
const override {
2992 return (str != nil || m_substr == nil ) &&
2993 [str rangeOfString:m_substr].location == 0;
2996 std::string describe()
const override {
3001 EndsWith( NSString* substr ) : StringHolder( substr ){}
3003 bool match( NSString* str )
const override {
3004 return (str != nil || m_substr == nil ) &&
3005 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
3008 std::string describe()
const override {
3030 using namespace Matchers;
3032 #endif // CATCH_CONFIG_DISABLE_MATCHERS 3037 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix 3038 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ 3039 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ 3043 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ 3047 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) 3049 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) 3054 #ifdef CATCH_CONFIG_EXTERNAL_INTERFACES 3066 #pragma clang diagnostic push 3067 #pragma clang diagnostic ignored "-Wpadded" 3073 #pragma clang diagnostic push 3074 #pragma clang diagnostic ignored "-Wpadded" 3081 class WildcardPattern {
3082 enum WildcardPosition {
3084 WildcardAtStart = 1,
3086 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3092 virtual ~WildcardPattern() =
default;
3093 virtual bool matches( std::string
const& str )
const;
3096 std::string adjustCase( std::string
const& str )
const;
3098 WildcardPosition m_wildcard = NoWildcard;
3099 std::string m_pattern;
3113 virtual bool matches(
TestCaseInfo const& testCase )
const = 0;
3115 using PatternPtr = std::shared_ptr<Pattern>;
3117 class NamePattern :
public Pattern {
3119 NamePattern( std::string
const&
name );
3120 virtual ~NamePattern();
3121 virtual bool matches(
TestCaseInfo const& testCase )
const override;
3123 WildcardPattern m_wildcardPattern;
3126 class TagPattern :
public Pattern {
3128 TagPattern( std::string
const& tag );
3129 virtual ~TagPattern();
3130 virtual bool matches(
TestCaseInfo const& testCase )
const override;
3135 class ExcludedPattern :
public Pattern {
3137 ExcludedPattern( PatternPtr
const& underlyingPattern );
3138 virtual ~ExcludedPattern();
3139 virtual bool matches(
TestCaseInfo const& testCase )
const override;
3141 PatternPtr m_underlyingPattern;
3145 std::vector<PatternPtr> m_patterns;
3151 bool hasFilters()
const;
3155 std::vector<Filter> m_filters;
3157 friend class TestSpecParser;
3162 #pragma clang diagnostic pop 3174 struct ITagAliasRegistry {
3175 virtual ~ITagAliasRegistry();
3177 virtual TagAlias
const* find( std::string
const& alias )
const = 0;
3178 virtual std::string expandAliases( std::string
const& unexpandedTestSpec )
const = 0;
3180 static ITagAliasRegistry
const&
get();
3188 class TestSpecParser {
3189 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
3191 bool m_exclusion =
false;
3192 std::size_t m_start = std::string::npos, m_pos = 0;
3194 std::vector<std::size_t> m_escapeChars;
3195 TestSpec::Filter m_currentFilter;
3196 TestSpec m_testSpec;
3197 ITagAliasRegistry
const* m_tagAliases =
nullptr;
3200 TestSpecParser( ITagAliasRegistry
const& tagAliases );
3202 TestSpecParser&
parse( std::string
const& arg );
3203 TestSpec testSpec();
3206 void visitChar(
char c );
3207 void startNewMode(
Mode mode, std::size_t start );
3209 std::string subString()
const;
3211 template<
typename T>
3213 std::string token = subString();
3214 for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
3215 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
3216 m_escapeChars.clear();
3219 token = token.substr( 8 );
3221 if( !token.empty() ) {
3222 TestSpec::PatternPtr pattern = std::make_shared<T>( token );
3224 pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
3225 m_currentFilter.m_patterns.push_back( pattern );
3227 m_exclusion =
false;
3233 TestSpec parseTestSpec( std::string
const& arg );
3238 #pragma clang diagnostic pop 3251 enum class Verbosity {
3257 struct WarnAbout {
enum What {
3259 NoAssertions = 0x01,
3263 struct ShowDurations {
enum OrNot {
3268 struct RunTests {
enum InWhatOrder {
3270 InLexicographicalOrder,
3273 struct UseColour {
enum YesOrNo {
3278 struct WaitForKeypress {
enum When {
3282 BeforeStartAndExit = BeforeStart | BeforeExit
3291 virtual bool allowThrows()
const = 0;
3292 virtual std::ostream& stream()
const = 0;
3293 virtual std::string
name()
const = 0;
3294 virtual bool includeSuccessfulResults()
const = 0;
3295 virtual bool shouldDebugBreak()
const = 0;
3296 virtual bool warnAboutMissingAssertions()
const = 0;
3297 virtual bool warnAboutNoTests()
const = 0;
3298 virtual int abortAfter()
const = 0;
3299 virtual bool showInvisibles()
const = 0;
3300 virtual ShowDurations::OrNot showDurations()
const = 0;
3301 virtual TestSpec
const& testSpec()
const = 0;
3302 virtual bool hasTestFilters()
const = 0;
3303 virtual RunTests::InWhatOrder runOrder()
const = 0;
3304 virtual unsigned int rngSeed()
const = 0;
3305 virtual int benchmarkResolutionMultiple()
const = 0;
3306 virtual UseColour::YesOrNo useColour()
const = 0;
3307 virtual std::vector<std::string>
const& getSectionsToRun()
const = 0;
3308 virtual Verbosity verbosity()
const = 0;
3311 using IConfigPtr = std::shared_ptr<IConfig const>;
3321 #ifndef CATCH_CONFIG_CONSOLE_WIDTH 3322 #define CATCH_CONFIG_CONSOLE_WIDTH 80 3330 bool listTests =
false;
3331 bool listTags =
false;
3332 bool listReporters =
false;
3333 bool listTestNamesOnly =
false;
3335 bool showSuccessfulTests =
false;
3336 bool shouldDebugBreak =
false;
3337 bool noThrow =
false;
3338 bool showHelp =
false;
3339 bool showInvisibles =
false;
3340 bool filenamesAsTags =
false;
3341 bool libIdentify =
false;
3343 int abortAfter = -1;
3345 int benchmarkResolutionMultiple = 100;
3347 Verbosity verbosity = Verbosity::Normal;
3348 WarnAbout::What warnings = WarnAbout::Nothing;
3349 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
3350 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
3351 UseColour::YesOrNo useColour = UseColour::Auto;
3352 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
3354 std::string outputFilename;
3356 std::string processName;
3358 std::vector<std::string> reporterNames;
3359 std::vector<std::string> testsOrTags;
3360 std::vector<std::string> sectionsToRun;
3363 class Config :
public IConfig {
3367 Config( ConfigData
const&
data );
3368 virtual ~Config() =
default;
3370 std::string
const& getFilename()
const;
3372 bool listTests()
const;
3373 bool listTestNamesOnly()
const;
3374 bool listTags()
const;
3375 bool listReporters()
const;
3377 std::string getProcessName()
const;
3379 std::vector<std::string>
const& getReporterNames()
const;
3380 std::vector<std::string>
const& getTestsOrTags()
const;
3381 std::vector<std::string>
const& getSectionsToRun()
const override;
3383 virtual TestSpec
const& testSpec()
const override;
3384 bool hasTestFilters()
const override;
3386 bool showHelp()
const;
3389 bool allowThrows()
const override;
3390 std::ostream& stream()
const override;
3391 std::string
name()
const override;
3392 bool includeSuccessfulResults()
const override;
3393 bool warnAboutMissingAssertions()
const override;
3394 bool warnAboutNoTests()
const override;
3395 ShowDurations::OrNot showDurations()
const override;
3396 RunTests::InWhatOrder runOrder()
const override;
3397 unsigned int rngSeed()
const override;
3398 int benchmarkResolutionMultiple()
const override;
3399 UseColour::YesOrNo useColour()
const override;
3400 bool shouldDebugBreak()
const override;
3401 int abortAfter()
const override;
3402 bool showInvisibles()
const override;
3403 Verbosity verbosity()
const override;
3410 std::unique_ptr<IStream const> m_stream;
3411 TestSpec m_testSpec;
3412 bool m_hasTestFilters =
false;
3424 struct AssertionResultData
3426 AssertionResultData() =
delete;
3430 std::string message;
3431 mutable std::string reconstructedExpression;
3435 std::string reconstructExpression()
const;
3438 class AssertionResult {
3440 AssertionResult() =
delete;
3444 bool succeeded()
const;
3446 bool hasExpression()
const;
3447 bool hasMessage()
const;
3448 std::string getExpression()
const;
3449 std::string getExpressionInMacro()
const;
3450 bool hasExpandedExpression()
const;
3451 std::string getExpandedExpression()
const;
3452 std::string getMessage()
const;
3458 AssertionResultData m_resultData;
3469 template<
typename T>
3472 Option() : nullableValue(
nullptr ) {}
3473 Option( T
const& _value )
3474 : nullableValue(
new( storage ) T( _value ) )
3476 Option( Option
const& _other )
3477 : nullableValue( _other ?
new( storage ) T( *_other ) :
nullptr )
3484 Option& operator= ( Option
const& _other ) {
3485 if( &_other !=
this ) {
3488 nullableValue =
new( storage ) T( *_other );
3492 Option& operator = ( T
const& _value ) {
3494 nullableValue =
new( storage ) T( _value );
3500 nullableValue->~T();
3501 nullableValue =
nullptr;
3504 T& operator*() {
return *nullableValue; }
3505 T
const& operator*()
const {
return *nullableValue; }
3506 T* operator->() {
return nullableValue; }
3507 const T* operator->()
const {
return nullableValue; }
3509 T valueOr( T
const& defaultValue )
const {
3510 return nullableValue ? *nullableValue : defaultValue;
3513 bool some()
const {
return nullableValue !=
nullptr; }
3514 bool none()
const {
return nullableValue ==
nullptr; }
3516 bool operator !()
const {
return nullableValue ==
nullptr; }
3517 explicit operator bool()
const {
3523 alignas(
alignof(T))
char storage[sizeof(T)];
3537 struct ReporterConfig {
3538 explicit ReporterConfig( IConfigPtr
const& _fullConfig );
3540 ReporterConfig( IConfigPtr
const& _fullConfig, std::ostream& _stream );
3542 std::ostream& stream()
const;
3543 IConfigPtr fullConfig()
const;
3546 std::ostream* m_stream;
3547 IConfigPtr m_fullConfig;
3550 struct ReporterPreferences {
3551 bool shouldRedirectStdOut =
false;
3554 template<
typename T>
3555 struct LazyStat : Option<T> {
3556 LazyStat& operator=( T
const& _value ) {
3557 Option<T>::operator=( _value );
3568 struct TestRunInfo {
3569 TestRunInfo( std::string
const& _name );
3573 GroupInfo( std::string
const& _name,
3574 std::size_t _groupIndex,
3575 std::size_t _groupsCount );
3578 std::size_t groupIndex;
3579 std::size_t groupsCounts;
3582 struct AssertionStats {
3583 AssertionStats( AssertionResult
const& _assertionResult,
3584 std::vector<MessageInfo>
const& _infoMessages,
3587 AssertionStats( AssertionStats
const& ) =
default;
3588 AssertionStats( AssertionStats && ) =
default;
3589 AssertionStats& operator = ( AssertionStats
const& ) =
default;
3590 AssertionStats& operator = ( AssertionStats && ) =
default;
3591 virtual ~AssertionStats();
3593 AssertionResult assertionResult;
3594 std::vector<MessageInfo> infoMessages;
3598 struct SectionStats {
3600 Counts const& _assertions,
3601 double _durationInSeconds,
3602 bool _missingAssertions );
3603 SectionStats( SectionStats
const& ) =
default;
3604 SectionStats( SectionStats && ) =
default;
3605 SectionStats& operator = ( SectionStats
const& ) =
default;
3606 SectionStats& operator = ( SectionStats && ) =
default;
3607 virtual ~SectionStats();
3611 double durationInSeconds;
3612 bool missingAssertions;
3615 struct TestCaseStats {
3618 std::string
const& _stdOut,
3619 std::string
const& _stdErr,
3622 TestCaseStats( TestCaseStats
const& ) =
default;
3623 TestCaseStats( TestCaseStats && ) =
default;
3624 TestCaseStats& operator = ( TestCaseStats
const& ) =
default;
3625 TestCaseStats& operator = ( TestCaseStats && ) =
default;
3626 virtual ~TestCaseStats();
3635 struct TestGroupStats {
3636 TestGroupStats( GroupInfo
const& _groupInfo,
3639 TestGroupStats( GroupInfo
const& _groupInfo );
3641 TestGroupStats( TestGroupStats
const& ) =
default;
3642 TestGroupStats( TestGroupStats && ) =
default;
3643 TestGroupStats& operator = ( TestGroupStats
const& ) =
default;
3644 TestGroupStats& operator = ( TestGroupStats && ) =
default;
3645 virtual ~TestGroupStats();
3647 GroupInfo groupInfo;
3652 struct TestRunStats {
3653 TestRunStats( TestRunInfo
const& _runInfo,
3657 TestRunStats( TestRunStats
const& ) =
default;
3658 TestRunStats( TestRunStats && ) =
default;
3659 TestRunStats& operator = ( TestRunStats
const& ) =
default;
3660 TestRunStats& operator = ( TestRunStats && ) =
default;
3661 virtual ~TestRunStats();
3663 TestRunInfo runInfo;
3668 struct BenchmarkInfo {
3671 struct BenchmarkStats {
3673 std::size_t iterations;
3674 uint64_t elapsedTimeInNanoseconds;
3677 struct IStreamingReporter {
3678 virtual ~IStreamingReporter() =
default;
3684 virtual ReporterPreferences getPreferences()
const = 0;
3686 virtual void noMatchingTestCases( std::string
const& spec ) = 0;
3688 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
3689 virtual void testGroupStarting( GroupInfo
const& groupInfo ) = 0;
3691 virtual void testCaseStarting(
TestCaseInfo const& testInfo ) = 0;
3692 virtual void sectionStarting(
SectionInfo const& sectionInfo ) = 0;
3695 virtual void benchmarkStarting( BenchmarkInfo
const& ) {}
3697 virtual void assertionStarting(
AssertionInfo const& assertionInfo ) = 0;
3700 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
3703 virtual void benchmarkEnded( BenchmarkStats
const& ) {}
3705 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
3706 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
3707 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
3708 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
3710 virtual void skipTest(
TestCaseInfo const& testInfo ) = 0;
3715 virtual bool isMulti()
const;
3717 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
3719 struct IReporterFactory {
3720 virtual ~IReporterFactory();
3721 virtual IStreamingReporterPtr create( ReporterConfig
const& config )
const = 0;
3722 virtual std::string getDescription()
const = 0;
3726 struct IReporterRegistry {
3727 using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
3728 using Listeners = std::vector<IReporterFactoryPtr>;
3730 virtual ~IReporterRegistry();
3731 virtual IStreamingReporterPtr create( std::string
const&
name, IConfigPtr
const& config )
const = 0;
3732 virtual FactoryMap
const& getFactories()
const = 0;
3733 virtual Listeners
const& getListeners()
const = 0;
3736 void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter );
3741 #include <algorithm> 3750 void prepareExpandedExpression(AssertionResult& result);
3753 std::string getFormattedDuration(
double duration );
3755 template<
typename DerivedT>
3756 struct StreamingReporterBase : IStreamingReporter {
3758 StreamingReporterBase( ReporterConfig
const& _config )
3759 : m_config( _config.fullConfig() ),
3760 stream( _config.stream() )
3762 m_reporterPrefs.shouldRedirectStdOut =
false;
3763 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
3764 throw std::domain_error(
"Verbosity level not supported by this reporter" );
3767 ReporterPreferences getPreferences()
const override {
3768 return m_reporterPrefs;
3771 static std::set<Verbosity> getSupportedVerbosities() {
3772 return { Verbosity::Normal };
3775 ~StreamingReporterBase()
override =
default;
3777 void noMatchingTestCases(std::string
const&)
override {}
3779 void testRunStarting(TestRunInfo
const& _testRunInfo)
override {
3780 currentTestRunInfo = _testRunInfo;
3782 void testGroupStarting(GroupInfo
const& _groupInfo)
override {
3783 currentGroupInfo = _groupInfo;
3786 void testCaseStarting(
TestCaseInfo const& _testInfo)
override {
3787 currentTestCaseInfo = _testInfo;
3789 void sectionStarting(
SectionInfo const& _sectionInfo)
override {
3790 m_sectionStack.push_back(_sectionInfo);
3793 void sectionEnded(SectionStats
const& )
override {
3794 m_sectionStack.pop_back();
3796 void testCaseEnded(TestCaseStats
const& )
override {
3797 currentTestCaseInfo.reset();
3799 void testGroupEnded(TestGroupStats
const& )
override {
3800 currentGroupInfo.reset();
3802 void testRunEnded(TestRunStats
const& )
override {
3803 currentTestCaseInfo.reset();
3804 currentGroupInfo.reset();
3805 currentTestRunInfo.reset();
3813 IConfigPtr m_config;
3814 std::ostream& stream;
3816 LazyStat<TestRunInfo> currentTestRunInfo;
3817 LazyStat<GroupInfo> currentGroupInfo;
3818 LazyStat<TestCaseInfo> currentTestCaseInfo;
3820 std::vector<SectionInfo> m_sectionStack;
3821 ReporterPreferences m_reporterPrefs;
3824 template<
typename DerivedT>
3825 struct CumulativeReporterBase : IStreamingReporter {
3826 template<
typename T,
typename ChildNodeT>
3828 explicit Node( T
const& _value ) : value( _value ) {}
3831 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
3833 ChildNodes children;
3835 struct SectionNode {
3836 explicit SectionNode(SectionStats
const& _stats) : stats(_stats) {}
3837 virtual ~SectionNode() =
default;
3839 bool operator == (SectionNode
const& other)
const {
3840 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
3842 bool operator == (std::shared_ptr<SectionNode>
const& other)
const {
3843 return operator==(*other);
3847 using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
3848 using Assertions = std::vector<AssertionStats>;
3849 ChildSections childSections;
3850 Assertions assertions;
3855 struct BySectionInfo {
3856 BySectionInfo(
SectionInfo const& other ) : m_other( other ) {}
3857 BySectionInfo( BySectionInfo
const& other ) : m_other( other.m_other ) {}
3858 bool operator() (std::shared_ptr<SectionNode>
const& node)
const {
3859 return ((node->stats.sectionInfo.name == m_other.name) &&
3860 (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
3862 void operator=(BySectionInfo
const&) =
delete;
3868 using TestCaseNode = Node<TestCaseStats, SectionNode>;
3869 using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
3870 using TestRunNode = Node<TestRunStats, TestGroupNode>;
3872 CumulativeReporterBase( ReporterConfig
const& _config )
3873 : m_config( _config.fullConfig() ),
3874 stream( _config.stream() )
3876 m_reporterPrefs.shouldRedirectStdOut =
false;
3877 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
3878 throw std::domain_error(
"Verbosity level not supported by this reporter" );
3880 ~CumulativeReporterBase()
override =
default;
3882 ReporterPreferences getPreferences()
const override {
3883 return m_reporterPrefs;
3886 static std::set<Verbosity> getSupportedVerbosities() {
3887 return { Verbosity::Normal };
3890 void testRunStarting( TestRunInfo
const& )
override {}
3891 void testGroupStarting( GroupInfo
const& )
override {}
3893 void testCaseStarting(
TestCaseInfo const& )
override {}
3895 void sectionStarting(
SectionInfo const& sectionInfo )
override {
3896 SectionStats incompleteStats( sectionInfo,
Counts(), 0,
false );
3897 std::shared_ptr<SectionNode> node;
3898 if( m_sectionStack.empty() ) {
3899 if( !m_rootSection )
3900 m_rootSection = std::make_shared<SectionNode>( incompleteStats );
3901 node = m_rootSection;
3904 SectionNode& parentNode = *m_sectionStack.back();
3906 std::find_if( parentNode.childSections.begin(),
3907 parentNode.childSections.end(),
3908 BySectionInfo( sectionInfo ) );
3909 if( it == parentNode.childSections.end() ) {
3910 node = std::make_shared<SectionNode>( incompleteStats );
3911 parentNode.childSections.push_back( node );
3916 m_sectionStack.push_back( node );
3917 m_deepestSection = std::move(node);
3922 bool assertionEnded(AssertionStats
const& assertionStats)
override {
3923 assert(!m_sectionStack.empty());
3929 prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );
3930 SectionNode& sectionNode = *m_sectionStack.back();
3931 sectionNode.assertions.push_back(assertionStats);
3934 void sectionEnded(SectionStats
const& sectionStats)
override {
3935 assert(!m_sectionStack.empty());
3936 SectionNode& node = *m_sectionStack.back();
3937 node.stats = sectionStats;
3938 m_sectionStack.pop_back();
3940 void testCaseEnded(TestCaseStats
const& testCaseStats)
override {
3941 auto node = std::make_shared<TestCaseNode>(testCaseStats);
3942 assert(m_sectionStack.size() == 0);
3943 node->children.push_back(m_rootSection);
3944 m_testCases.push_back(node);
3945 m_rootSection.reset();
3947 assert(m_deepestSection);
3948 m_deepestSection->stdOut = testCaseStats.stdOut;
3949 m_deepestSection->stdErr = testCaseStats.stdErr;
3951 void testGroupEnded(TestGroupStats
const& testGroupStats)
override {
3952 auto node = std::make_shared<TestGroupNode>(testGroupStats);
3953 node->children.swap(m_testCases);
3954 m_testGroups.push_back(node);
3956 void testRunEnded(TestRunStats
const& testRunStats)
override {
3957 auto node = std::make_shared<TestRunNode>(testRunStats);
3958 node->children.swap(m_testGroups);
3959 m_testRuns.push_back(node);
3960 testRunEndedCumulative();
3962 virtual void testRunEndedCumulative() = 0;
3966 IConfigPtr m_config;
3967 std::ostream& stream;
3968 std::vector<AssertionStats> m_assertions;
3969 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
3970 std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
3971 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
3973 std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
3975 std::shared_ptr<SectionNode> m_rootSection;
3976 std::shared_ptr<SectionNode> m_deepestSection;
3977 std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
3978 ReporterPreferences m_reporterPrefs;
3982 char const* getLineOfChars() {
3983 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
3985 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
3986 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
3991 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
3992 TestEventListenerBase( ReporterConfig
const& _config );
3995 bool assertionEnded(AssertionStats
const&)
override;
4019 BrightRed = Bright | Red,
4020 BrightGreen = Bright | Green,
4021 LightGrey = Bright | Grey,
4022 BrightWhite = Bright | White,
4023 BrightYellow = Bright | Yellow,
4026 FileName = LightGrey,
4027 Warning = BrightYellow,
4028 ResultError = BrightRed,
4029 ResultSuccess = BrightGreen,
4030 ResultExpectedFailure = Warning,
4035 OriginalExpression = Cyan,
4036 ReconstructedExpression = BrightYellow,
4038 SecondaryText = LightGrey,
4043 Colour( Code _colourCode );
4044 Colour( Colour&& other ) noexcept;
4045 Colour& operator=( Colour&& other ) noexcept;
4049 static void use( Code _colourCode );
4052 bool m_moved =
false;
4055 std::ostream&
operator << ( std::ostream& os, Colour
const& );
4065 template<
typename T>
4066 class ReporterRegistrar {
4068 class ReporterFactory :
public IReporterFactory {
4070 virtual IStreamingReporterPtr create( ReporterConfig
const& config )
const override {
4071 return std::unique_ptr<T>(
new T( config ) );
4074 virtual std::string getDescription()
const override {
4075 return T::getDescription();
4081 explicit ReporterRegistrar( std::string
const&
name ) {
4086 template<
typename T>
4087 class ListenerRegistrar {
4089 class ListenerFactory :
public IReporterFactory {
4091 virtual IStreamingReporterPtr create( ReporterConfig
const& config )
const override {
4092 return std::unique_ptr<T>(
new T( config ) );
4094 virtual std::string getDescription()
const override {
4095 return std::string();
4101 ListenerRegistrar() {
4107 #if !defined(CATCH_CONFIG_DISABLE) 4109 #define CATCH_REGISTER_REPORTER( name, reporterType ) \ 4110 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 4111 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ 4112 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 4114 #define CATCH_REGISTER_LISTENER( listenerType ) \ 4115 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 4116 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ 4117 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 4118 #else // CATCH_CONFIG_DISABLE 4120 #define CATCH_REGISTER_REPORTER(name, reporterType) 4121 #define CATCH_REGISTER_LISTENER(listenerType) 4123 #endif // CATCH_CONFIG_DISABLE 4131 struct CompactReporter : StreamingReporterBase<CompactReporter> {
4133 using StreamingReporterBase::StreamingReporterBase;
4135 ~CompactReporter()
override;
4137 static std::string getDescription();
4139 ReporterPreferences getPreferences()
const override;
4141 void noMatchingTestCases(std::string
const& spec)
override;
4145 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
4147 void sectionEnded(SectionStats
const& _sectionStats)
override;
4149 void testRunEnded(TestRunStats
const& _testRunStats)
override;
4158 #if defined(_MSC_VER) 4159 #pragma warning(push) 4160 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 4167 struct SummaryColumn;
4170 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
4171 std::unique_ptr<TablePrinter> m_tablePrinter;
4173 ConsoleReporter(ReporterConfig
const& config);
4174 ~ConsoleReporter()
override;
4175 static std::string getDescription();
4177 void noMatchingTestCases(std::string
const& spec)
override;
4181 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
4183 void sectionStarting(
SectionInfo const& _sectionInfo)
override;
4184 void sectionEnded(SectionStats
const& _sectionStats)
override;
4186 void benchmarkStarting(BenchmarkInfo
const& info)
override;
4187 void benchmarkEnded(BenchmarkStats
const& stats)
override;
4189 void testCaseEnded(TestCaseStats
const& _testCaseStats)
override;
4190 void testGroupEnded(TestGroupStats
const& _testGroupStats)
override;
4191 void testRunEnded(TestRunStats
const& _testRunStats)
override;
4197 void lazyPrintWithoutClosingBenchmarkTable();
4198 void lazyPrintRunInfo();
4199 void lazyPrintGroupInfo();
4200 void printTestCaseAndSectionHeader();
4202 void printClosedHeader(std::string
const& _name);
4203 void printOpenHeader(std::string
const& _name);
4207 void printHeaderString(std::string
const& _string, std::size_t indent = 0);
4209 void printTotals(
Totals const& totals);
4210 void printSummaryRow(std::string
const& label, std::vector<SummaryColumn>
const& cols, std::size_t row);
4212 void printTotalsDivider(
Totals const& totals);
4213 void printSummaryDivider();
4216 bool m_headerPrinted =
false;
4221 #if defined(_MSC_VER) 4222 #pragma warning(pop) 4236 enum ForWhat { ForTextNodes, ForAttributes };
4238 XmlEncode( std::string
const& str, ForWhat forWhat = ForTextNodes );
4240 void encodeTo( std::ostream& os )
const;
4242 friend std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode );
4252 class ScopedElement {
4254 ScopedElement( XmlWriter* writer );
4256 ScopedElement( ScopedElement&& other ) noexcept;
4257 ScopedElement& operator=( ScopedElement&& other ) noexcept;
4261 ScopedElement& writeText( std::string
const& text,
bool indent =
true );
4263 template<
typename T>
4264 ScopedElement& writeAttribute( std::string
const&
name, T
const& attribute ) {
4265 m_writer->writeAttribute( name, attribute );
4270 mutable XmlWriter* m_writer =
nullptr;
4276 XmlWriter( XmlWriter
const& ) =
delete;
4277 XmlWriter& operator=( XmlWriter
const& ) =
delete;
4279 XmlWriter& startElement( std::string
const&
name );
4281 ScopedElement scopedElement( std::string
const& name );
4283 XmlWriter& endElement();
4285 XmlWriter& writeAttribute( std::string
const& name, std::string
const& attribute );
4287 XmlWriter& writeAttribute( std::string
const& name,
bool attribute );
4289 template<
typename T>
4290 XmlWriter& writeAttribute( std::string
const& name, T
const& attribute ) {
4293 return writeAttribute( name, rss.
str() );
4296 XmlWriter& writeText( std::string
const& text,
bool indent =
true );
4298 XmlWriter& writeComment( std::string
const& text );
4300 void writeStylesheetRef( std::string
const& url );
4302 XmlWriter& writeBlankLine();
4304 void ensureTagClosed();
4308 void writeDeclaration();
4310 void newlineIfNecessary();
4312 bool m_tagIsOpen =
false;
4313 bool m_needsNewline =
false;
4314 std::vector<std::string> m_tags;
4315 std::string m_indent;
4324 class JunitReporter :
public CumulativeReporterBase<JunitReporter> {
4326 JunitReporter(ReporterConfig
const& _config);
4328 ~JunitReporter()
override;
4330 static std::string getDescription();
4332 void noMatchingTestCases(std::string
const& )
override;
4334 void testRunStarting(TestRunInfo
const& runInfo)
override;
4336 void testGroupStarting(GroupInfo
const& groupInfo)
override;
4338 void testCaseStarting(
TestCaseInfo const& testCaseInfo)
override;
4339 bool assertionEnded(AssertionStats
const& assertionStats)
override;
4341 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
4343 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
4345 void testRunEndedCumulative()
override;
4347 void writeGroup(TestGroupNode
const& groupNode,
double suiteTime);
4349 void writeTestCase(TestCaseNode
const& testCaseNode);
4351 void writeSection(std::string
const& className,
4352 std::string
const& rootName,
4353 SectionNode
const& sectionNode);
4355 void writeAssertions(SectionNode
const& sectionNode);
4356 void writeAssertion(AssertionStats
const& stats);
4360 std::string stdOutForSuite;
4361 std::string stdErrForSuite;
4362 unsigned int unexpectedExceptions = 0;
4363 bool m_okToFail =
false;
4372 class XmlReporter :
public StreamingReporterBase<XmlReporter> {
4374 XmlReporter(ReporterConfig
const& _config);
4376 ~XmlReporter()
override;
4378 static std::string getDescription();
4380 virtual std::string getStylesheetRef()
const;
4386 void noMatchingTestCases(std::string
const& s)
override;
4388 void testRunStarting(TestRunInfo
const& testInfo)
override;
4390 void testGroupStarting(GroupInfo
const& groupInfo)
override;
4392 void testCaseStarting(
TestCaseInfo const& testInfo)
override;
4394 void sectionStarting(
SectionInfo const& sectionInfo)
override;
4398 bool assertionEnded(AssertionStats
const& assertionStats)
override;
4400 void sectionEnded(SectionStats
const& sectionStats)
override;
4402 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
4404 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
4406 void testRunEnded(TestRunStats
const& testRunStats)
override;
4409 Timer m_testCaseTimer;
4411 int m_sectionDepth = 0;
4421 #endif // ! CATCH_CONFIG_IMPL_ONLY 4427 #pragma clang diagnostic push 4428 #pragma clang diagnostic ignored "-Wweak-vtables" 4439 namespace TestCaseTracking {
4441 struct NameAndLocation {
4445 NameAndLocation( std::string
const& _name,
SourceLineInfo const& _location );
4450 using ITrackerPtr = std::shared_ptr<ITracker>;
4453 virtual ~ITracker();
4456 virtual NameAndLocation
const& nameAndLocation()
const = 0;
4459 virtual bool isComplete()
const = 0;
4460 virtual bool isSuccessfullyCompleted()
const = 0;
4461 virtual bool isOpen()
const = 0;
4462 virtual bool hasChildren()
const = 0;
4464 virtual ITracker& parent() = 0;
4467 virtual void close() = 0;
4468 virtual void fail() = 0;
4469 virtual void markAsNeedingAnotherRun() = 0;
4471 virtual void addChild( ITrackerPtr
const& child ) = 0;
4472 virtual ITrackerPtr findChild( NameAndLocation
const& nameAndLocation ) = 0;
4473 virtual void openChild() = 0;
4476 virtual bool isSectionTracker()
const = 0;
4477 virtual bool isIndexTracker()
const = 0;
4480 class TrackerContext {
4488 ITrackerPtr m_rootTracker;
4489 ITracker* m_currentTracker =
nullptr;
4490 RunState m_runState = NotStarted;
4494 static TrackerContext& instance();
4496 ITracker& startRun();
4500 void completeCycle();
4502 bool completedCycle()
const;
4503 ITracker& currentTracker();
4504 void setCurrentTracker( ITracker* tracker );
4507 class TrackerBase :
public ITracker {
4514 CompletedSuccessfully,
4518 class TrackerHasName {
4519 NameAndLocation m_nameAndLocation;
4521 TrackerHasName( NameAndLocation
const& nameAndLocation );
4522 bool operator ()( ITrackerPtr
const& tracker )
const;
4525 using Children = std::vector<ITrackerPtr>;
4526 NameAndLocation m_nameAndLocation;
4527 TrackerContext& m_ctx;
4529 Children m_children;
4530 CycleState m_runState = NotStarted;
4533 TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
4535 NameAndLocation
const& nameAndLocation()
const override;
4536 bool isComplete()
const override;
4537 bool isSuccessfullyCompleted()
const override;
4538 bool isOpen()
const override;
4539 bool hasChildren()
const override;
4541 void addChild( ITrackerPtr
const& child )
override;
4543 ITrackerPtr findChild( NameAndLocation
const& nameAndLocation )
override;
4544 ITracker& parent()
override;
4546 void openChild()
override;
4548 bool isSectionTracker()
const override;
4549 bool isIndexTracker()
const override;
4553 void close()
override;
4554 void fail()
override;
4555 void markAsNeedingAnotherRun()
override;
4558 void moveToParent();
4562 class SectionTracker :
public TrackerBase {
4563 std::vector<std::string> m_filters;
4565 SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
4567 bool isSectionTracker()
const override;
4569 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation );
4573 void addInitialFilters( std::vector<std::string>
const& filters );
4574 void addNextFilters( std::vector<std::string>
const& filters );
4577 class IndexTracker :
public TrackerBase {
4581 IndexTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent,
int size );
4583 bool isIndexTracker()
const override;
4584 void close()
override;
4586 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation,
int size );
4595 using TestCaseTracking::ITracker;
4596 using TestCaseTracking::TrackerContext;
4597 using TestCaseTracking::SectionTracker;
4598 using TestCaseTracking::IndexTracker;
4608 struct LeakDetector {
4624 bool marginComparison(
double lhs,
double rhs,
double margin) {
4625 return (lhs + margin >= rhs) && (rhs + margin >= lhs);
4633 Approx::Approx (
double value )
4634 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
4640 Approx Approx::custom() {
4644 std::string Approx::toString()
const {
4650 bool Approx::equalityComparisonImpl(
const double other)
const {
4653 return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
4675 struct IMutableContext;
4677 using IConfigPtr = std::shared_ptr<IConfig const>;
4681 virtual ~IContext();
4684 virtual IRunner* getRunner() = 0;
4685 virtual IConfigPtr
const& getConfig()
const = 0;
4688 struct IMutableContext : IContext
4690 virtual ~IMutableContext();
4691 virtual void setResultCapture(
IResultCapture* resultCapture ) = 0;
4692 virtual void setRunner(
IRunner* runner ) = 0;
4693 virtual void setConfig( IConfigPtr
const& config ) = 0;
4696 static IMutableContext *currentContext;
4697 friend IMutableContext& getCurrentMutableContext();
4698 friend void cleanUpContext();
4699 static void createContext();
4702 inline IMutableContext& getCurrentMutableContext()
4704 if( !IMutableContext::currentContext )
4705 IMutableContext::createContext();
4706 return *IMutableContext::currentContext;
4709 inline IContext& getCurrentContext()
4711 return getCurrentMutableContext();
4714 void cleanUpContext();
4721 bool isDebuggerActive();
4724 #ifdef CATCH_PLATFORM_MAC 4726 #define CATCH_TRAP() __asm__("int $3\n" : : ) 4728 #elif defined(CATCH_PLATFORM_LINUX) 4732 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) 4733 #define CATCH_TRAP() asm volatile ("int $3") 4734 #else // Fall back to the generic way. 4737 #define CATCH_TRAP() raise(SIGTRAP) 4739 #elif defined(_MSC_VER) 4740 #define CATCH_TRAP() __debugbreak() 4741 #elif defined(__MINGW32__) 4742 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
4743 #define CATCH_TRAP() DebugBreak() 4747 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } 4750 inline void doNothing() {}
4752 #define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing() 4763 #if defined(CATCH_PLATFORM_WINDOWS) 4765 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) 4766 # define CATCH_DEFINED_NOMINMAX 4769 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) 4770 # define CATCH_DEFINED_WIN32_LEAN_AND_MEAN 4771 # define WIN32_LEAN_AND_MEAN 4777 #include <windows.h> 4780 #ifdef CATCH_DEFINED_NOMINMAX 4783 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN 4784 # undef WIN32_LEAN_AND_MEAN 4787 #endif // defined(CATCH_PLATFORM_WINDOWS) 4790 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 4794 struct FatalConditionHandler {
4796 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
4797 FatalConditionHandler();
4798 static void reset();
4799 ~FatalConditionHandler();
4803 static ULONG guaranteeSize;
4804 static PVOID exceptionHandlerHandle;
4809 #elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) 4815 struct FatalConditionHandler {
4818 static struct sigaction oldSigActions[];
4819 static stack_t oldSigStack;
4820 static char altStackMem[];
4822 static void handleSignal(
int sig );
4824 FatalConditionHandler();
4825 ~FatalConditionHandler();
4826 static void reset();
4834 struct FatalConditionHandler {
4846 struct IMutableContext;
4853 RunContext( RunContext
const& ) =
delete;
4854 RunContext& operator =( RunContext
const& ) =
delete;
4856 explicit RunContext( IConfigPtr
const& _config, IStreamingReporterPtr&& reporter );
4858 ~RunContext()
override;
4860 void testGroupStarting( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
4861 void testGroupEnded( std::string
const& testSpec,
Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );
4865 IConfigPtr config()
const;
4866 IStreamingReporter& reporter()
const;
4880 void handleUnexpectedExceptionNotThrown
4883 void handleUnexpectedInflightException
4885 std::string
const& message,
4887 void handleIncomplete
4894 bool sectionStarted(
SectionInfo const& sectionInfo,
Counts& assertions )
override;
4897 void sectionEndedEarly(
SectionEndInfo const& endInfo )
override;
4899 void benchmarkStarting( BenchmarkInfo
const& info )
override;
4900 void benchmarkEnded( BenchmarkStats
const& stats )
override;
4902 void pushScopedMessage(
MessageInfo const& message )
override;
4903 void popScopedMessage(
MessageInfo const& message )
override;
4905 std::string getCurrentTestName()
const override;
4907 const AssertionResult* getLastResult()
const override;
4909 void exceptionEarlyReported()
override;
4911 void handleFatalErrorCondition(
StringRef message )
override;
4913 bool lastAssertionPassed()
override;
4915 void assertionPassed()
override;
4919 bool aborting()
const final;
4923 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );
4924 void invokeActiveTestCase();
4926 void resetAssertionInfo();
4927 bool testForMissingAssertions(
Counts& assertions );
4929 void assertionEnded( AssertionResult
const& result );
4940 void handleUnfinishedSections();
4942 TestRunInfo m_runInfo;
4943 IMutableContext& m_context;
4944 TestCase const* m_activeTestCase =
nullptr;
4945 ITracker* m_testCaseTracker;
4946 Option<AssertionResult> m_lastResult;
4948 IConfigPtr m_config;
4950 IStreamingReporterPtr m_reporter;
4951 std::vector<MessageInfo> m_messages;
4953 std::vector<SectionEndInfo> m_unfinishedSections;
4954 std::vector<ITracker*> m_activeSections;
4955 TrackerContext m_trackerContext;
4956 bool m_lastAssertionPassed =
false;
4957 bool m_shouldReportUnexpected =
true;
4958 bool m_includeSuccessfulResults;
4972 : m_isNegated( isNegated )
4977 LazyExpression::operator bool()
const {
4978 return m_transientExpression !=
nullptr;
4982 if( lazyExpr.m_isNegated )
4987 os <<
"(" << *lazyExpr.m_transientExpression <<
")";
4989 os << *lazyExpr.m_transientExpression;
4992 os <<
"{** error - unchecked empty expression requested **}";
5002 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
5007 m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
5010 m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
5014 return getCurrentContext().getConfig()->allowThrows();
5019 if( m_reaction.shouldDebugBreak ) {
5025 CATCH_BREAK_INTO_DEBUGGER();
5027 if( m_reaction.shouldThrow )
5039 m_resultCapture.handleNonExpr(m_assertionInfo,
ResultWas::Ok, m_reaction);
5042 m_resultCapture.handleNonExpr(m_assertionInfo,
ResultWas::Ok, m_reaction);
5046 m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
5050 m_resultCapture.handleNonExpr(m_assertionInfo,
ResultWas::Ok, m_reaction);
5065 lazyExpression(_lazyExpression),
5066 resultType(_resultType) {}
5068 std::string AssertionResultData::reconstructExpression()
const {
5070 if( reconstructedExpression.empty() ) {
5071 if( lazyExpression ) {
5073 rss << lazyExpression;
5074 reconstructedExpression = rss.
str();
5077 return reconstructedExpression;
5080 AssertionResult::AssertionResult(
AssertionInfo const& info, AssertionResultData
const&
data )
5082 m_resultData( data )
5086 bool AssertionResult::succeeded()
const {
5096 return m_resultData.resultType;
5099 bool AssertionResult::hasExpression()
const {
5100 return m_info.capturedExpression[0] != 0;
5103 bool AssertionResult::hasMessage()
const {
5104 return !m_resultData.message.empty();
5107 std::string AssertionResult::getExpression()
const {
5109 return "!(" + m_info.capturedExpression +
")";
5111 return m_info.capturedExpression;
5114 std::string AssertionResult::getExpressionInMacro()
const {
5116 if( m_info.macroName[0] == 0 )
5117 expr = m_info.capturedExpression;
5119 expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
5120 expr += m_info.macroName;
5122 expr += m_info.capturedExpression;
5128 bool AssertionResult::hasExpandedExpression()
const {
5129 return hasExpression() && getExpandedExpression() != getExpression();
5132 std::string AssertionResult::getExpandedExpression()
const {
5133 std::string expr = m_resultData.reconstructExpression();
5139 std::string AssertionResult::getMessage()
const {
5140 return m_resultData.message;
5143 return m_info.lineInfo;
5146 StringRef AssertionResult::getTestMacroName()
const {
5147 return m_info.macroName;
5156 auto BenchmarkLooper::getResolution() -> uint64_t {
5164 auto elapsed = m_timer.getElapsedNanoseconds();
5167 if( elapsed < m_resolution ) {
5168 m_iterationsToRun *= 10;
5202 #ifdef CLARA_CONFIG_CONSOLE_WIDTH 5203 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 5204 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 5206 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 5209 #pragma clang diagnostic push 5210 #pragma clang diagnostic ignored "-Wweak-vtables" 5211 #pragma clang diagnostic ignored "-Wexit-time-destructors" 5212 #pragma clang diagnostic ignored "-Wshadow" 5226 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH 5227 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 5230 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 5231 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH 5234 #ifndef CLARA_CONFIG_OPTIONAL_TYPE 5235 #ifdef __has_include 5236 #if __has_include(<optional>) && __cplusplus >= 201703L 5238 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional 5260 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 5261 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 5264 namespace Catch {
namespace clara {
namespace TextFlow {
5266 inline auto isWhitespace(
char c ) ->
bool {
5267 static std::string chars =
" \t\n\r";
5268 return chars.find( c ) != std::string::npos;
5270 inline auto isBreakableBefore(
char c ) ->
bool {
5271 static std::string chars =
"[({<|";
5272 return chars.find( c ) != std::string::npos;
5274 inline auto isBreakableAfter(
char c ) ->
bool {
5275 static std::string chars =
"])}>.,:;*+-=&/\\";
5276 return chars.find( c ) != std::string::npos;
5282 std::vector<std::string> m_strings;
5283 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
5284 size_t m_indent = 0;
5285 size_t m_initialIndent = std::string::npos;
5291 Column
const& m_column;
5292 size_t m_stringIndex = 0;
5297 bool m_suffix =
false;
5299 iterator( Column
const& column,
size_t stringIndex )
5300 : m_column( column ),
5301 m_stringIndex( stringIndex )
5304 auto line()
const -> std::string
const& {
return m_column.m_strings[m_stringIndex]; }
5306 auto isBoundary(
size_t at )
const ->
bool {
5308 assert( at <= line().
size() );
5310 return at == line().size() ||
5311 ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) ||
5312 isBreakableBefore( line()[at] ) ||
5313 isBreakableAfter( line()[at-1] );
5317 assert( m_stringIndex < m_column.m_strings.size() );
5320 auto width = m_column.m_width-indent();
5322 while( m_end < line().
size() && line()[m_end] !=
'\n' )
5325 if( m_end < m_pos +
width ) {
5326 m_len = m_end - m_pos;
5330 while (len > 0 && !isBoundary(m_pos + len))
5332 while (len > 0 && isWhitespace( line()[m_pos + len - 1] ))
5344 auto indent()
const ->
size_t {
5345 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
5346 return initial == std::string::npos ? m_column.m_indent : initial;
5349 auto addIndentAndSuffix(std::string
const &plain)
const -> std::string {
5350 return std::string( indent(),
' ' ) + (m_suffix ? plain +
"-" : plain);
5354 explicit iterator( Column
const& column ) : m_column( column ) {
5355 assert( m_column.m_width > m_column.m_indent );
5356 assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent );
5362 auto operator *()
const -> std::string {
5363 assert( m_stringIndex < m_column.m_strings.size() );
5364 assert( m_pos <= m_end );
5365 if( m_pos + m_column.m_width < m_end )
5366 return addIndentAndSuffix(line().substr(m_pos, m_len));
5368 return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos));
5371 auto operator ++() -> iterator& {
5373 if( m_pos < line().
size() && line()[m_pos] ==
'\n' )
5376 while( m_pos < line().
size() && isWhitespace( line()[m_pos] ) )
5379 if( m_pos == line().
size() ) {
5383 if( m_stringIndex < m_column.m_strings.size() )
5387 auto operator ++(
int) -> iterator {
5388 iterator prev( *
this );
5393 auto operator ==( iterator
const& other )
const ->
bool {
5395 m_pos == other.m_pos &&
5396 m_stringIndex == other.m_stringIndex &&
5397 &m_column == &other.m_column;
5399 auto operator !=( iterator
const& other )
const ->
bool {
5400 return !operator==( other );
5403 using const_iterator = iterator;
5405 explicit Column( std::string
const& text ) { m_strings.push_back( text ); }
5407 auto width(
size_t newWidth ) -> Column& {
5408 assert( newWidth > 0 );
5412 auto indent(
size_t newIndent ) -> Column& {
5413 m_indent = newIndent;
5416 auto initialIndent(
size_t newIndent ) -> Column& {
5417 m_initialIndent = newIndent;
5421 auto width()
const ->
size_t {
return m_width; }
5422 auto begin()
const -> iterator {
return iterator( *
this ); }
5423 auto end()
const -> iterator {
return { *
this, m_strings.size() }; }
5425 inline friend std::ostream&
operator << ( std::ostream& os, Column
const& col ) {
5427 for(
auto line : col ) {
5439 auto toString()
const -> std::string {
5440 std::ostringstream oss;
5446 class Spacer :
public Column {
5449 explicit Spacer(
size_t spaceWidth ) : Column(
"" ) {
5450 width( spaceWidth );
5455 std::vector<Column> m_columns;
5463 std::vector<Column>
const& m_columns;
5464 std::vector<Column::iterator> m_iterators;
5465 size_t m_activeIterators;
5467 iterator(
Columns const& columns, EndTag )
5468 : m_columns( columns.m_columns ),
5469 m_activeIterators( 0 )
5471 m_iterators.reserve( m_columns.size() );
5473 for(
auto const& col : m_columns )
5474 m_iterators.push_back( col.end() );
5478 explicit iterator(
Columns const& columns )
5479 : m_columns( columns.m_columns ),
5480 m_activeIterators( m_columns.size() )
5482 m_iterators.reserve( m_columns.size() );
5484 for(
auto const& col : m_columns )
5485 m_iterators.push_back( col.begin() );
5488 auto operator ==( iterator
const& other )
const ->
bool {
5489 return m_iterators == other.m_iterators;
5491 auto operator !=( iterator
const& other )
const ->
bool {
5492 return m_iterators != other.m_iterators;
5494 auto operator *()
const -> std::string {
5495 std::string row, padding;
5497 for(
size_t i = 0; i < m_columns.size(); ++i ) {
5498 auto width = m_columns[i].width();
5499 if( m_iterators[i] != m_columns[i].
end() ) {
5500 std::string col = *m_iterators[i];
5501 row += padding + col;
5502 if( col.size() <
width )
5503 padding = std::string(
width - col.size(),
' ' );
5508 padding += std::string(
width,
' ' );
5513 auto operator ++() -> iterator& {
5514 for(
size_t i = 0; i < m_columns.size(); ++i ) {
5515 if (m_iterators[i] != m_columns[i].
end())
5520 auto operator ++(
int) -> iterator {
5521 iterator prev( *
this );
5526 using const_iterator = iterator;
5528 auto begin()
const -> iterator {
return iterator( *
this ); }
5529 auto end()
const -> iterator {
return { *
this, iterator::EndTag() }; }
5532 m_columns.push_back( col );
5544 for(
auto line : cols ) {
5554 auto toString()
const -> std::string {
5555 std::ostringstream oss;
5574 #include <algorithm> 5576 #if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) 5577 #define CATCH_PLATFORM_WINDOWS 5580 namespace Catch {
namespace clara {
5584 template<
typename L>
5585 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
5587 template<
typename ClassT,
typename ReturnT,
typename... Args>
5588 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
5589 static const bool isValid =
false;
5592 template<
typename ClassT,
typename ReturnT,
typename ArgT>
5593 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
5594 static const bool isValid =
true;
5596 using ReturnType = ReturnT;
5604 std::string m_exeName;
5605 std::vector<std::string> m_args;
5608 Args(
int argc,
char const*
const* argv )
5609 : m_exeName(argv[0]),
5610 m_args(argv + 1, argv + argc) {}
5612 Args( std::initializer_list<std::string> args )
5613 : m_exeName( *args.begin() ),
5614 m_args( args.begin()+1, args.end() )
5617 auto exeName()
const -> std::string {
5624 enum class TokenType {
5632 inline auto isOptPrefix(
char c ) ->
bool {
5634 #ifdef CATCH_PLATFORM_WINDOWS 5642 using Iterator = std::vector<std::string>::const_iterator;
5645 std::vector<Token> m_tokenBuffer;
5648 m_tokenBuffer.resize( 0 );
5651 while( it != itEnd && it->empty() )
5655 auto const &next = *it;
5656 if( isOptPrefix( next[0] ) ) {
5657 auto delimiterPos = next.find_first_of(
" :=" );
5658 if( delimiterPos != std::string::npos ) {
5659 m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
5660 m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
5662 if( next[1] !=
'-' && next.size() > 2 ) {
5663 std::string opt =
"- ";
5664 for(
size_t i = 1; i < next.size(); ++i ) {
5666 m_tokenBuffer.push_back( { TokenType::Option, opt } );
5669 m_tokenBuffer.push_back( { TokenType::Option, next } );
5673 m_tokenBuffer.push_back( { TokenType::Argument, next } );
5679 explicit TokenStream( Args
const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
5681 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
5685 explicit operator bool()
const {
5686 return !m_tokenBuffer.empty() || it != itEnd;
5689 auto count()
const ->
size_t {
return m_tokenBuffer.size() + (itEnd - it); }
5691 auto operator*()
const -> Token {
5692 assert( !m_tokenBuffer.empty() );
5693 return m_tokenBuffer.front();
5696 auto operator->()
const -> Token
const * {
5697 assert( !m_tokenBuffer.empty() );
5698 return &m_tokenBuffer.front();
5701 auto operator++() -> TokenStream & {
5702 if( m_tokenBuffer.size() >= 2 ) {
5703 m_tokenBuffer.erase( m_tokenBuffer.begin() );
5716 Ok, LogicError, RuntimeError
5720 ResultBase( Type
type ) : m_type( type ) {}
5721 virtual ~ResultBase() =
default;
5723 virtual void enforceOk()
const = 0;
5728 template<
typename T>
5729 class ResultValueBase :
public ResultBase {
5731 auto value()
const -> T
const & {
5737 ResultValueBase( Type
type ) : ResultBase( type ) {}
5739 ResultValueBase( ResultValueBase
const &other ) : ResultBase( other ) {
5740 if( m_type == ResultBase::Ok )
5741 new( &m_value ) T( other.m_value );
5744 ResultValueBase( Type, T
const &value ) : ResultBase( Ok ) {
5745 new( &m_value ) T( value );
5748 auto operator=( ResultValueBase
const &other ) -> ResultValueBase & {
5749 if( m_type == ResultBase::Ok )
5751 ResultBase::operator=(other);
5752 if( m_type == ResultBase::Ok )
5753 new( &m_value ) T( other.m_value );
5757 ~ResultValueBase()
override {
5768 class ResultValueBase<void> :
public ResultBase {
5770 using ResultBase::ResultBase;
5773 template<
typename T =
void>
5774 class BasicResult :
public ResultValueBase<T> {
5776 template<
typename U>
5777 explicit BasicResult( BasicResult<U>
const &other )
5778 : ResultValueBase<T>( other.type() ),
5779 m_errorMessage( other.errorMessage() )
5781 assert(
type() != ResultBase::Ok );
5784 template<
typename U>
5785 static auto ok( U
const &value ) -> BasicResult {
return { ResultBase::Ok, value }; }
5786 static auto ok() -> BasicResult {
return { ResultBase::Ok }; }
5787 static auto logicError( std::string
const &message ) -> BasicResult {
return { ResultBase::LogicError, message }; }
5788 static auto runtimeError( std::string
const &message ) -> BasicResult {
return { ResultBase::RuntimeError, message }; }
5790 explicit operator bool()
const {
return m_type == ResultBase::Ok; }
5791 auto type()
const -> ResultBase::Type {
return m_type; }
5792 auto errorMessage()
const -> std::string {
return m_errorMessage; }
5795 void enforceOk()
const override {
5799 assert( m_type != ResultBase::LogicError );
5800 assert( m_type != ResultBase::RuntimeError );
5801 if( m_type != ResultBase::Ok )
5805 std::string m_errorMessage;
5807 BasicResult( ResultBase::Type
type, std::string
const &message )
5808 : ResultValueBase<T>(
type),
5809 m_errorMessage(message)
5811 assert( m_type != ResultBase::Ok );
5814 using ResultValueBase<T>::ResultValueBase;
5815 using ResultBase::m_type;
5818 enum class ParseResultType {
5819 Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
5825 ParseState( ParseResultType
type, TokenStream
const &remainingTokens )
5827 m_remainingTokens( remainingTokens )
5830 auto type()
const -> ParseResultType {
return m_type; }
5831 auto remainingTokens()
const -> TokenStream {
return m_remainingTokens; }
5834 ParseResultType m_type;
5835 TokenStream m_remainingTokens;
5838 using Result = BasicResult<void>;
5839 using ParserResult = BasicResult<ParseResultType>;
5840 using InternalParseResult = BasicResult<ParseState>;
5842 struct HelpColumns {
5847 template<
typename T>
5848 inline auto convertInto( std::string
const &source, T& target ) -> ParserResult {
5849 std::stringstream ss;
5853 return ParserResult::runtimeError(
"Unable to convert '" + source +
"' to destination type" );
5855 return ParserResult::ok( ParseResultType::Matched );
5857 inline auto convertInto( std::string
const &source, std::string& target ) -> ParserResult {
5859 return ParserResult::ok( ParseResultType::Matched );
5861 inline auto convertInto( std::string
const &source,
bool &target ) -> ParserResult {
5862 std::string srcLC = source;
5863 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), [](
char c ) {
return static_cast<char>( ::tolower(c) ); } );
5864 if (srcLC ==
"y" || srcLC ==
"1" || srcLC ==
"true" || srcLC ==
"yes" || srcLC ==
"on")
5866 else if (srcLC ==
"n" || srcLC ==
"0" || srcLC ==
"false" || srcLC ==
"no" || srcLC ==
"off")
5869 return ParserResult::runtimeError(
"Expected a boolean value but did not recognise: '" + source +
"'" );
5870 return ParserResult::ok( ParseResultType::Matched );
5872 #ifdef CLARA_CONFIG_OPTIONAL_TYPE 5873 template<
typename T>
5874 inline auto convertInto( std::string
const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
5876 auto result = convertInto( source, temp );
5878 target = std::move(temp);
5881 #endif // CLARA_CONFIG_OPTIONAL_TYPE 5892 virtual ~BoundRef() =
default;
5893 virtual auto isContainer()
const ->
bool {
return false; }
5894 virtual auto isFlag()
const ->
bool {
return false; }
5896 struct BoundValueRefBase : BoundRef {
5897 virtual auto setValue( std::string
const &arg ) -> ParserResult = 0;
5899 struct BoundFlagRefBase : BoundRef {
5900 virtual auto setFlag(
bool flag ) -> ParserResult = 0;
5901 virtual auto isFlag()
const ->
bool {
return true; }
5904 template<
typename T>
5905 struct BoundValueRef : BoundValueRefBase {
5908 explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
5910 auto setValue( std::string
const &arg ) -> ParserResult
override {
5911 return convertInto( arg, m_ref );
5915 template<
typename T>
5916 struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
5917 std::vector<T> &m_ref;
5919 explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
5921 auto isContainer()
const ->
bool override {
return true; }
5923 auto setValue( std::string
const &arg ) -> ParserResult
override {
5925 auto result = convertInto( arg, temp );
5927 m_ref.push_back( temp );
5932 struct BoundFlagRef : BoundFlagRefBase {
5935 explicit BoundFlagRef(
bool &ref ) : m_ref( ref ) {}
5937 auto setFlag(
bool flag ) -> ParserResult
override {
5939 return ParserResult::ok( ParseResultType::Matched );
5943 template<
typename ReturnType>
5944 struct LambdaInvoker {
5945 static_assert( std::is_same<ReturnType, ParserResult>::value,
"Lambda must return void or clara::ParserResult" );
5947 template<
typename L,
typename ArgType>
5948 static auto invoke( L
const &lambda, ArgType
const &arg ) -> ParserResult {
5949 return lambda( arg );
5954 struct LambdaInvoker<void> {
5955 template<
typename L,
typename ArgType>
5956 static auto invoke( L
const &lambda, ArgType
const &arg ) -> ParserResult {
5958 return ParserResult::ok( ParseResultType::Matched );
5962 template<
typename ArgType,
typename L>
5963 inline auto invokeLambda( L
const &lambda, std::string
const &arg ) -> ParserResult {
5965 auto result = convertInto( arg, temp );
5968 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
5971 template<
typename L>
5972 struct BoundLambda : BoundValueRefBase {
5975 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
5976 explicit BoundLambda( L
const &lambda ) : m_lambda( lambda ) {}
5978 auto setValue( std::string
const &arg ) -> ParserResult
override {
5979 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
5983 template<
typename L>
5984 struct BoundFlagLambda : BoundFlagRefBase {
5987 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
5988 static_assert( std::is_same<
typename UnaryLambdaTraits<L>::ArgType,
bool>::value,
"flags must be boolean" );
5990 explicit BoundFlagLambda( L
const &lambda ) : m_lambda( lambda ) {}
5992 auto setFlag(
bool flag ) -> ParserResult
override {
5993 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
5997 enum class Optionality { Optional, Required };
6003 virtual ~ParserBase() =
default;
6004 virtual auto validate()
const -> Result {
return Result::ok(); }
6005 virtual auto parse( std::string
const& exeName, TokenStream
const &tokens)
const -> InternalParseResult = 0;
6006 virtual auto cardinality()
const ->
size_t {
return 1; }
6008 auto parse( Args
const &args )
const -> InternalParseResult {
6009 return parse( args.exeName(), TokenStream( args ) );
6013 template<
typename DerivedT>
6014 class ComposableParserImpl :
public ParserBase {
6016 template<
typename T>
6017 auto operator|( T
const &other )
const -> Parser;
6019 template<
typename T>
6020 auto operator+( T
const &other )
const -> Parser;
6024 template<
typename DerivedT>
6025 class ParserRefImpl :
public ComposableParserImpl<DerivedT> {
6027 Optionality m_optionality = Optionality::Optional;
6028 std::shared_ptr<BoundRef> m_ref;
6030 std::string m_description;
6032 explicit ParserRefImpl( std::shared_ptr<BoundRef>
const &ref ) : m_ref( ref ) {}
6035 template<
typename T>
6036 ParserRefImpl( T &ref, std::string
const &hint )
6037 : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
6041 template<
typename LambdaT>
6042 ParserRefImpl( LambdaT
const &ref, std::string
const &hint )
6043 : m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
6047 auto operator()( std::string
const &description ) -> DerivedT & {
6048 m_description = description;
6049 return static_cast<DerivedT &
>( *this );
6052 auto optional() -> DerivedT & {
6053 m_optionality = Optionality::Optional;
6054 return static_cast<DerivedT &
>( *this );
6057 auto required() -> DerivedT & {
6058 m_optionality = Optionality::Required;
6059 return static_cast<DerivedT &
>( *this );
6062 auto isOptional()
const ->
bool {
6063 return m_optionality == Optionality::Optional;
6066 auto cardinality()
const ->
size_t override {
6067 if( m_ref->isContainer() )
6073 auto hint()
const -> std::string {
return m_hint; }
6076 class ExeName :
public ComposableParserImpl<ExeName> {
6077 std::shared_ptr<std::string> m_name;
6078 std::shared_ptr<BoundValueRefBase> m_ref;
6080 template<
typename LambdaT>
6081 static auto makeRef(LambdaT
const &lambda) -> std::shared_ptr<BoundValueRefBase> {
6082 return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
6086 ExeName() : m_name( std::make_shared<std::string>(
"<executable>" ) ) {}
6088 explicit ExeName( std::string &ref ) : ExeName() {
6089 m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
6092 template<
typename LambdaT>
6093 explicit ExeName( LambdaT
const& lambda ) : ExeName() {
6094 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );
6098 auto parse( std::string
const&, TokenStream
const &tokens )
const -> InternalParseResult
override {
6099 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
6102 auto name()
const -> std::string {
return *m_name; }
6103 auto set( std::string
const& newName ) -> ParserResult {
6105 auto lastSlash = newName.find_last_of(
"\\/" );
6106 auto filename = ( lastSlash == std::string::npos )
6108 : newName.substr( lastSlash+1 );
6112 return m_ref->setValue( filename );
6114 return ParserResult::ok( ParseResultType::Matched );
6118 class Arg :
public ParserRefImpl<Arg> {
6120 using ParserRefImpl::ParserRefImpl;
6122 auto parse( std::string
const &, TokenStream
const &tokens )
const -> InternalParseResult
override {
6123 auto validationResult = validate();
6124 if( !validationResult )
6125 return InternalParseResult( validationResult );
6127 auto remainingTokens = tokens;
6128 auto const &token = *remainingTokens;
6129 if( token.type != TokenType::Argument )
6130 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
6132 assert( !m_ref->isFlag() );
6133 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.get() );
6135 auto result = valueRef->setValue( remainingTokens->token );
6137 return InternalParseResult( result );
6139 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
6143 inline auto normaliseOpt( std::string
const &optName ) -> std::string {
6144 #ifdef CATCH_PLATFORM_WINDOWS 6145 if( optName[0] ==
'/' )
6146 return "-" + optName.substr( 1 );
6152 class Opt :
public ParserRefImpl<Opt> {
6154 std::vector<std::string> m_optNames;
6157 template<
typename LambdaT>
6158 explicit Opt( LambdaT
const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
6160 explicit Opt(
bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}
6162 template<
typename LambdaT>
6163 Opt( LambdaT
const &ref, std::string
const &hint ) : ParserRefImpl( ref, hint ) {}
6165 template<
typename T>
6166 Opt( T &ref, std::string
const &hint ) : ParserRefImpl( ref, hint ) {}
6168 auto operator[]( std::string
const &optName ) -> Opt & {
6169 m_optNames.push_back( optName );
6173 auto getHelpColumns()
const -> std::vector<HelpColumns> {
6174 std::ostringstream oss;
6176 for(
auto const &opt : m_optNames ) {
6183 if( !m_hint.empty() )
6184 oss <<
" <" << m_hint <<
">";
6185 return { { oss.str(), m_description } };
6188 auto isMatch( std::string
const &optToken )
const ->
bool {
6189 auto normalisedToken = normaliseOpt( optToken );
6190 for(
auto const &
name : m_optNames ) {
6191 if( normaliseOpt(
name ) == normalisedToken )
6199 auto parse( std::string
const&, TokenStream
const &tokens )
const -> InternalParseResult
override {
6200 auto validationResult = validate();
6201 if( !validationResult )
6202 return InternalParseResult( validationResult );
6204 auto remainingTokens = tokens;
6205 if( remainingTokens && remainingTokens->type == TokenType::Option ) {
6206 auto const &token = *remainingTokens;
6207 if( isMatch(token.token ) ) {
6208 if( m_ref->isFlag() ) {
6209 auto flagRef =
static_cast<detail::BoundFlagRefBase*
>( m_ref.get() );
6210 auto result = flagRef->setFlag(
true );
6212 return InternalParseResult( result );
6213 if( result.value() == ParseResultType::ShortCircuitAll )
6214 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
6216 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.get() );
6218 if( !remainingTokens )
6219 return InternalParseResult::runtimeError(
"Expected argument following " + token.token );
6220 auto const &argToken = *remainingTokens;
6221 if( argToken.type != TokenType::Argument )
6222 return InternalParseResult::runtimeError(
"Expected argument following " + token.token );
6223 auto result = valueRef->setValue( argToken.token );
6225 return InternalParseResult( result );
6226 if( result.value() == ParseResultType::ShortCircuitAll )
6227 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
6229 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
6232 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
6235 auto validate()
const -> Result
override {
6236 if( m_optNames.empty() )
6237 return Result::logicError(
"No options supplied to Opt" );
6238 for(
auto const &
name : m_optNames ) {
6240 return Result::logicError(
"Option name cannot be empty" );
6241 #ifdef CATCH_PLATFORM_WINDOWS 6242 if(
name[0] !=
'-' &&
name[0] !=
'/' )
6243 return Result::logicError(
"Option name must begin with '-' or '/'" );
6245 if(
name[0] !=
'-' )
6246 return Result::logicError(
"Option name must begin with '-'" );
6249 return ParserRefImpl::validate();
6254 Help(
bool &showHelpFlag )
6255 : Opt([&](
bool flag ) {
6256 showHelpFlag = flag;
6257 return ParserResult::ok( ParseResultType::ShortCircuitAll );
6260 static_cast<Opt &
>( *this )
6261 (
"display usage information")
6262 [
"-?"][
"-h"][
"--help"]
6267 struct Parser : ParserBase {
6269 mutable ExeName m_exeName;
6270 std::vector<Opt> m_options;
6271 std::vector<Arg> m_args;
6273 auto operator|=( ExeName
const &exeName ) -> Parser & {
6274 m_exeName = exeName;
6278 auto operator|=( Arg
const &arg ) -> Parser & {
6279 m_args.push_back(arg);
6283 auto operator|=( Opt
const &opt ) -> Parser & {
6284 m_options.push_back(opt);
6288 auto operator|=( Parser
const &other ) -> Parser & {
6289 m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
6290 m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
6294 template<
typename T>
6295 auto operator|( T
const &other )
const -> Parser {
6296 return Parser( *
this ) |= other;
6300 template<
typename T>
6301 auto operator+=( T
const &other ) -> Parser & {
return operator|=( other ); }
6302 template<
typename T>
6305 auto getHelpColumns()
const -> std::vector<HelpColumns> {
6306 std::vector<HelpColumns> cols;
6307 for (
auto const &o : m_options) {
6308 auto childCols = o.getHelpColumns();
6309 cols.insert( cols.end(), childCols.begin(), childCols.end() );
6314 void writeToStream( std::ostream &os )
const {
6315 if (!m_exeName.name().empty()) {
6316 os <<
"usage:\n" <<
" " << m_exeName.name() <<
" ";
6317 bool required =
true, first =
true;
6318 for(
auto const &arg : m_args ) {
6323 if( arg.isOptional() && required ) {
6327 os <<
"<" << arg.hint() <<
">";
6328 if( arg.cardinality() == 0 )
6333 if( !m_options.empty() )
6335 os <<
"\n\nwhere options are:" << std::endl;
6338 auto rows = getHelpColumns();
6339 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
6340 size_t optWidth = 0;
6341 for(
auto const &cols : rows )
6342 optWidth = (std::max)(optWidth, cols.left.size() + 2);
6344 optWidth = (std::min)(optWidth, consoleWidth/2);
6346 for(
auto const &cols : rows ) {
6348 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
6349 TextFlow::Spacer(4) +
6350 TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
6351 os << row << std::endl;
6355 friend auto operator<<( std::ostream &os, Parser
const &parser ) -> std::ostream& {
6356 parser.writeToStream( os );
6360 auto validate()
const -> Result
override {
6361 for(
auto const &opt : m_options ) {
6362 auto result = opt.validate();
6366 for(
auto const &arg : m_args ) {
6367 auto result = arg.validate();
6371 return Result::ok();
6376 auto parse( std::string
const& exeName, TokenStream
const &tokens )
const -> InternalParseResult
override {
6379 ParserBase
const* parser =
nullptr;
6382 const size_t totalParsers = m_options.size() + m_args.size();
6383 assert( totalParsers < 512 );
6385 ParserInfo parseInfos[512];
6389 for (
auto const &opt : m_options) parseInfos[i++].parser = &opt;
6390 for (
auto const &arg : m_args) parseInfos[i++].parser = &arg;
6393 m_exeName.set( exeName );
6395 auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
6396 while( result.value().remainingTokens() ) {
6397 bool tokenParsed =
false;
6399 for(
size_t i = 0; i < totalParsers; ++i ) {
6400 auto& parseInfo = parseInfos[i];
6401 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
6402 result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
6405 if (result.value().type() != ParseResultType::NoMatch) {
6413 if( result.value().type() == ParseResultType::ShortCircuitAll )
6416 return InternalParseResult::runtimeError(
"Unrecognised token: " + result.value().remainingTokens()->token );
6423 template<
typename DerivedT>
6424 template<
typename T>
6426 return Parser() |
static_cast<DerivedT
const &
>( *this ) | other;
6431 using detail::Parser;
6443 using detail::ExeName;
6449 using detail::ParseResultType;
6452 using detail::ParserResult;
6458 #pragma clang diagnostic pop 6462 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 6463 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 6464 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 6470 clara::Parser makeCommandLineParser( ConfigData& config );
6480 clara::Parser makeCommandLineParser( ConfigData& config ) {
6482 using namespace clara;
6484 auto const setWarning = [&]( std::string
const& warning ) {
6485 auto warningSet = [&]() {
6486 if( warning ==
"NoAssertions" )
6487 return WarnAbout::NoAssertions;
6489 if ( warning ==
"NoTests" )
6490 return WarnAbout::NoTests;
6492 return WarnAbout::Nothing;
6495 if (warningSet == WarnAbout::Nothing)
6496 return ParserResult::runtimeError(
"Unrecognised warning: '" + warning +
"'" );
6497 config.warnings =
static_cast<WarnAbout::What
>( config.warnings | warningSet );
6498 return ParserResult::ok( ParseResultType::Matched );
6500 auto const loadTestNamesFromFile = [&]( std::string
const& filename ) {
6501 std::ifstream f( filename.c_str() );
6503 return ParserResult::runtimeError(
"Unable to load input file: '" + filename +
"'" );
6506 while( std::getline( f, line ) ) {
6508 if( !line.empty() && !
startsWith( line,
'#' ) ) {
6510 line =
'"' + line +
'"';
6511 config.testsOrTags.push_back( line +
',' );
6514 return ParserResult::ok( ParseResultType::Matched );
6516 auto const setTestOrder = [&]( std::string
const& order ) {
6518 config.runOrder = RunTests::InDeclarationOrder;
6520 config.runOrder = RunTests::InLexicographicalOrder;
6522 config.runOrder = RunTests::InRandomOrder;
6524 return clara::ParserResult::runtimeError(
"Unrecognised ordering: '" + order +
"'" );
6525 return ParserResult::ok( ParseResultType::Matched );
6527 auto const setRngSeed = [&]( std::string
const& seed ) {
6528 if( seed !=
"time" )
6529 return clara::detail::convertInto( seed, config.rngSeed );
6530 config.rngSeed =
static_cast<unsigned int>( std::time(
nullptr) );
6531 return ParserResult::ok( ParseResultType::Matched );
6533 auto const setColourUsage = [&]( std::string
const& useColour ) {
6534 auto mode =
toLower( useColour );
6537 config.useColour = UseColour::Yes;
6538 else if( mode ==
"no" )
6539 config.useColour = UseColour::No;
6540 else if( mode ==
"auto" )
6541 config.useColour = UseColour::Auto;
6543 return ParserResult::runtimeError(
"colour mode must be one of: auto, yes or no. '" + useColour +
"' not recognised" );
6544 return ParserResult::ok( ParseResultType::Matched );
6546 auto const setWaitForKeypress = [&]( std::string
const& keypress ) {
6547 auto keypressLc =
toLower( keypress );
6548 if( keypressLc ==
"start" )
6549 config.waitForKeypress = WaitForKeypress::BeforeStart;
6550 else if( keypressLc ==
"exit" )
6551 config.waitForKeypress = WaitForKeypress::BeforeExit;
6552 else if( keypressLc ==
"both" )
6553 config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
6555 return ParserResult::runtimeError(
"keypress argument must be one of: start, exit or both. '" + keypress +
"' not recognised" );
6556 return ParserResult::ok( ParseResultType::Matched );
6558 auto const setVerbosity = [&]( std::string
const& verbosity ) {
6559 auto lcVerbosity =
toLower( verbosity );
6560 if( lcVerbosity ==
"quiet" )
6561 config.verbosity = Verbosity::Quiet;
6562 else if( lcVerbosity ==
"normal" )
6563 config.verbosity = Verbosity::Normal;
6564 else if( lcVerbosity ==
"high" )
6565 config.verbosity = Verbosity::High;
6567 return ParserResult::runtimeError(
"Unrecognised verbosity, '" + verbosity +
"'" );
6568 return ParserResult::ok( ParseResultType::Matched );
6572 = ExeName( config.processName )
6573 | Help( config.showHelp )
6574 | Opt( config.listTests )
6575 ["-l"]["--list-tests"]
6576 (
"list all/matching test cases" )
6577 | Opt( config.listTags )
6578 ["-t"]["--list-tags"]
6579 (
"list all/matching tags" )
6580 | Opt( config.showSuccessfulTests )
6582 (
"include successful tests in output" )
6583 | Opt( config.shouldDebugBreak )
6585 (
"break into debugger on failure" )
6586 | Opt( config.noThrow )
6588 (
"skip exception tests" )
6589 | Opt( config.showInvisibles )
6590 ["-i"]["--invisibles"]
6591 (
"show invisibles (tabs, newlines)" )
6592 | Opt( config.outputFilename,
"filename" )
6594 (
"output filename" )
6595 | Opt( config.reporterNames,
"name" )
6596 ["-r"]["--reporter"]
6597 (
"reporter to use (defaults to console)" )
6598 | Opt( config.name,
"name" )
6601 | Opt( [&](
bool ){ config.abortAfter = 1; } )
6603 (
"abort at first failure" )
6604 | Opt( [&](
int x ){ config.abortAfter =
x; },
"no. failures" )
6606 (
"abort after x failures" )
6607 | Opt( setWarning,
"warning name" )
6609 (
"enable warnings" )
6610 | Opt( [&](
bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; },
"yes|no" )
6611 [
"-d"][
"--durations"]
6612 (
"show test durations" )
6613 | Opt( loadTestNamesFromFile,
"filename" )
6614 ["-f"]["--input-file"]
6615 (
"load test names to run from a file" )
6616 | Opt( config.filenamesAsTags )
6617 ["-#"]["--filenames-as-tags"]
6618 (
"adds a tag for the filename" )
6619 | Opt( config.sectionsToRun,
"section name" )
6621 (
"specify section to run" )
6622 | Opt( setVerbosity,
"quiet|normal|high" )
6623 ["-v"]["--verbosity"]
6624 (
"set output verbosity" )
6625 | Opt( config.listTestNamesOnly )
6626 ["--list-test-names-only"]
6627 (
"list all/matching test cases names only" )
6628 | Opt( config.listReporters )
6629 ["--list-reporters"]
6630 (
"list all reporters" )
6631 | Opt( setTestOrder,
"decl|lex|rand" )
6633 (
"test case order (defaults to decl)" )
6634 | Opt( setRngSeed,
"'time'|number" )
6636 (
"set a specific seed for random numbers" )
6637 | Opt( setColourUsage,
"yes|no" )
6639 (
"should output be colourised" )
6640 | Opt( config.libIdentify )
6642 (
"report name and version according to libidentify standard" )
6643 | Opt( setWaitForKeypress,
"start|exit|both" )
6644 ["--wait-for-keypress"]
6645 (
"waits for a keypress before exiting" )
6646 | Opt( config.benchmarkResolutionMultiple,
"multiplier" )
6647 ["--benchmark-resolution-multiple"]
6648 (
"multiple of clock resolution to run benchmarks" )
6650 | Arg( config.testsOrTags,
"test name|pattern|tags" )
6651 (
"which test or tests to use" );
6666 return file[0] ==
'\0';
6669 return line == other.
line && (file == other.
file || std::strcmp(file, other.
file) == 0);
6672 return line < other.
line || ( line == other.
line && (std::strcmp(file, other.
file) < 0));
6677 os << info.
file <<
'(' << info.
line <<
')';
6679 os << info.
file <<
':' << info.
line;
6685 return std::string();
6697 #include <stdexcept> 6699 #define CATCH_PREPARE_EXCEPTION( type, msg ) \ 6700 type( ( Catch::ReusableStringStream() << msg ).str() ) 6701 #define CATCH_INTERNAL_ERROR( msg ) \ 6702 throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); 6703 #define CATCH_ERROR( msg ) \ 6704 throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) 6705 #define CATCH_ENFORCE( condition, msg ) \ 6706 do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) 6711 Config::Config( ConfigData
const&
data )
6713 m_stream( openStream() )
6715 TestSpecParser parser(ITagAliasRegistry::get());
6716 if (data.testsOrTags.empty()) {
6717 parser.parse(
"~[.]");
6720 m_hasTestFilters =
true;
6721 for(
auto const& testOrTags : data.testsOrTags )
6722 parser.parse( testOrTags );
6724 m_testSpec = parser.testSpec();
6727 std::string
const& Config::getFilename()
const {
6728 return m_data.outputFilename ;
6731 bool Config::listTests()
const {
return m_data.listTests; }
6732 bool Config::listTestNamesOnly()
const {
return m_data.listTestNamesOnly; }
6733 bool Config::listTags()
const {
return m_data.listTags; }
6734 bool Config::listReporters()
const {
return m_data.listReporters; }
6736 std::string Config::getProcessName()
const {
return m_data.processName; }
6738 std::vector<std::string>
const& Config::getReporterNames()
const {
return m_data.reporterNames; }
6739 std::vector<std::string>
const& Config::getTestsOrTags()
const {
return m_data.testsOrTags; }
6740 std::vector<std::string>
const& Config::getSectionsToRun()
const {
return m_data.sectionsToRun; }
6742 TestSpec
const& Config::testSpec()
const {
return m_testSpec; }
6743 bool Config::hasTestFilters()
const {
return m_hasTestFilters; }
6745 bool Config::showHelp()
const {
return m_data.showHelp; }
6748 bool Config::allowThrows()
const {
return !m_data.noThrow; }
6749 std::ostream& Config::stream()
const {
return m_stream->stream(); }
6750 std::string
Config::name()
const {
return m_data.name.empty() ? m_data.processName : m_data.name; }
6751 bool Config::includeSuccessfulResults()
const {
return m_data.showSuccessfulTests; }
6752 bool Config::warnAboutMissingAssertions()
const {
return !!(m_data.warnings & WarnAbout::NoAssertions); }
6753 bool Config::warnAboutNoTests()
const {
return !!(m_data.warnings & WarnAbout::NoTests); }
6754 ShowDurations::OrNot Config::showDurations()
const {
return m_data.showDurations; }
6755 RunTests::InWhatOrder Config::runOrder()
const {
return m_data.runOrder; }
6757 int Config::benchmarkResolutionMultiple()
const {
return m_data.benchmarkResolutionMultiple; }
6758 UseColour::YesOrNo Config::useColour()
const {
return m_data.useColour; }
6759 bool Config::shouldDebugBreak()
const {
return m_data.shouldDebugBreak; }
6760 int Config::abortAfter()
const {
return m_data.abortAfter; }
6761 bool Config::showInvisibles()
const {
return m_data.showInvisibles; }
6762 Verbosity Config::verbosity()
const {
return m_data.verbosity; }
6764 IStream const* Config::openStream() {
6772 #if defined(__clang__) 6773 # pragma clang diagnostic push 6774 # pragma clang diagnostic ignored "-Wexit-time-destructors" 6797 struct IColourImpl {
6798 virtual ~IColourImpl() =
default;
6799 virtual void use( Colour::Code _colourCode ) = 0;
6802 struct NoColourImpl : IColourImpl {
6803 void use( Colour::Code ) {}
6805 static IColourImpl* instance() {
6806 static NoColourImpl s_instance;
6814 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) 6815 # ifdef CATCH_PLATFORM_WINDOWS 6816 # define CATCH_CONFIG_COLOUR_WINDOWS 6818 # define CATCH_CONFIG_COLOUR_ANSI 6822 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) 6827 class Win32ColourImpl :
public IColourImpl {
6829 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
6831 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
6832 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
6833 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
6834 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
6837 virtual void use( Colour::Code _colourCode )
override {
6838 switch( _colourCode ) {
6839 case Colour::None:
return setTextAttribute( originalForegroundAttributes );
6840 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6841 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
6842 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
6843 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
6844 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
6845 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
6846 case Colour::Grey:
return setTextAttribute( 0 );
6848 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
6849 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
6850 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
6851 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6852 case Colour::BrightYellow:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
6854 case Colour::Bright: CATCH_INTERNAL_ERROR(
"not a colour" );
6857 CATCH_ERROR(
"Unknown colour requested" );
6862 void setTextAttribute( WORD _textAttribute ) {
6863 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
6866 WORD originalForegroundAttributes;
6867 WORD originalBackgroundAttributes;
6870 IColourImpl* platformColourInstance() {
6871 static Win32ColourImpl s_instance;
6873 IConfigPtr config = getCurrentContext().getConfig();
6874 UseColour::YesOrNo colourMode = config
6875 ? config->useColour()
6877 if( colourMode == UseColour::Auto )
6878 colourMode = UseColour::Yes;
6879 return colourMode == UseColour::Yes
6881 : NoColourImpl::instance();
6887 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) 6898 class PosixColourImpl :
public IColourImpl {
6900 virtual void use( Colour::Code _colourCode )
override {
6901 switch( _colourCode ) {
6903 case Colour::White:
return setColour(
"[0m" );
6904 case Colour::Red:
return setColour(
"[0;31m" );
6905 case Colour::Green:
return setColour(
"[0;32m" );
6906 case Colour::Blue:
return setColour(
"[0;34m" );
6907 case Colour::Cyan:
return setColour(
"[0;36m" );
6908 case Colour::Yellow:
return setColour(
"[0;33m" );
6909 case Colour::Grey:
return setColour(
"[1;30m" );
6911 case Colour::LightGrey:
return setColour(
"[0;37m" );
6912 case Colour::BrightRed:
return setColour(
"[1;31m" );
6913 case Colour::BrightGreen:
return setColour(
"[1;32m" );
6914 case Colour::BrightWhite:
return setColour(
"[1;37m" );
6915 case Colour::BrightYellow:
return setColour(
"[1;33m" );
6917 case Colour::Bright: CATCH_INTERNAL_ERROR(
"not a colour" );
6918 default: CATCH_INTERNAL_ERROR(
"Unknown colour requested" );
6921 static IColourImpl* instance() {
6922 static PosixColourImpl s_instance;
6927 void setColour(
const char* _escapeCode ) {
6932 bool useColourOnPlatform() {
6934 #ifdef CATCH_PLATFORM_MAC 6935 !isDebuggerActive() &&
6937 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) 6938 isatty(STDOUT_FILENO)
6944 IColourImpl* platformColourInstance() {
6946 IConfigPtr config = getCurrentContext().getConfig();
6947 UseColour::YesOrNo colourMode = config
6948 ? config->useColour()
6950 if( colourMode == UseColour::Auto )
6951 colourMode = useColourOnPlatform()
6954 return colourMode == UseColour::Yes
6955 ? PosixColourImpl::instance()
6956 : NoColourImpl::instance();
6962 #else // not Windows or ANSI 6966 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
6970 #endif // Windows/ ANSI/ None 6974 Colour::Colour( Code _colourCode ) { use( _colourCode ); }
6975 Colour::Colour( Colour&& rhs ) noexcept {
6976 m_moved = rhs.m_moved;
6979 Colour& Colour::operator=( Colour&& rhs ) noexcept {
6980 m_moved = rhs.m_moved;
6985 Colour::~Colour(){
if( !m_moved ) use( None ); }
6987 void Colour::use( Code _colourCode ) {
6988 static IColourImpl* impl = platformColourInstance();
6989 impl->use( _colourCode );
6992 std::ostream&
operator << ( std::ostream& os, Colour
const& ) {
6998 #if defined(__clang__) 6999 # pragma clang diagnostic pop 7007 class Context :
public IMutableContext,
NonCopyable {
7011 return m_resultCapture;
7013 virtual IRunner* getRunner()
override {
7017 virtual IConfigPtr
const& getConfig()
const override {
7021 virtual ~Context()
override;
7024 virtual void setResultCapture(
IResultCapture* resultCapture )
override {
7025 m_resultCapture = resultCapture;
7027 virtual void setRunner(
IRunner* runner )
override {
7030 virtual void setConfig( IConfigPtr
const& config )
override {
7034 friend IMutableContext& getCurrentMutableContext();
7037 IConfigPtr m_config;
7042 IMutableContext *IMutableContext::currentContext =
nullptr;
7044 void IMutableContext::createContext()
7046 currentContext =
new Context();
7049 void cleanUpContext() {
7050 delete IMutableContext::currentContext;
7051 IMutableContext::currentContext =
nullptr;
7053 IContext::~IContext() =
default;
7054 IMutableContext::~IMutableContext() =
default;
7055 Context::~Context() =
default;
7065 void writeToDebugConsole( std::string
const& text );
7069 #ifdef CATCH_PLATFORM_WINDOWS 7072 void writeToDebugConsole( std::string
const& text ) {
7073 ::OutputDebugStringA( text.c_str() );
7080 void writeToDebugConsole( std::string
const& text ) {
7090 #ifdef CATCH_PLATFORM_MAC 7092 # include <assert.h> 7093 # include <stdbool.h> 7094 # include <sys/types.h> 7095 # include <unistd.h> 7096 # include <sys/sysctl.h> 7107 bool isDebuggerActive(){
7110 struct kinfo_proc info;
7116 info.kp_proc.p_flag = 0;
7123 mib[2] = KERN_PROC_PID;
7128 size =
sizeof(info);
7129 if( sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size,
nullptr, 0) != 0 ) {
7130 Catch::cerr() <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
7136 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
7140 #elif defined(CATCH_PLATFORM_LINUX) 7152 bool isDebuggerActive(){
7156 std::ifstream in(
"/proc/self/status");
7157 for( std::string line; std::getline(in, line); ) {
7158 static const int PREFIX_LEN = 11;
7159 if( line.compare(0, PREFIX_LEN,
"TracerPid:\t") == 0 ) {
7163 return line.length() > PREFIX_LEN && line[PREFIX_LEN] !=
'0';
7170 #elif defined(_MSC_VER) 7171 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7173 bool isDebuggerActive() {
7174 return IsDebuggerPresent() != 0;
7177 #elif defined(__MINGW32__) 7178 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7180 bool isDebuggerActive() {
7181 return IsDebuggerPresent() != 0;
7186 bool isDebuggerActive() {
return false; }
7197 if( lhs.size() + rhs.size() < 40 &&
7198 lhs.find(
'\n') == std::string::npos &&
7199 rhs.find(
'\n') == std::string::npos )
7200 os << lhs <<
" " << op <<
" " << rhs;
7202 os << lhs <<
"\n" << op <<
"\n" << rhs;
7211 ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
7212 ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
7227 ~ExceptionTranslatorRegistry();
7230 std::string tryTranslators()
const;
7233 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
7239 #import "Foundation/Foundation.h" 7244 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
7247 void ExceptionTranslatorRegistry::registerTranslator(
const IExceptionTranslator* translator ) {
7248 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
7256 return tryTranslators();
7258 @catch (NSException *exception) {
7270 if (std::current_exception() ==
nullptr) {
7271 return "Non C++ exception. Possibly a CLR exception.";
7273 return tryTranslators();
7277 std::rethrow_exception(std::current_exception());
7279 catch( std::exception& ex ) {
7282 catch( std::string& msg ) {
7285 catch(
const char* msg ) {
7289 return "Unknown exception";
7293 std::string ExceptionTranslatorRegistry::tryTranslators()
const {
7294 if( m_translators.empty() )
7295 std::rethrow_exception(std::current_exception());
7297 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
7303 #if defined(__GNUC__) 7304 # pragma GCC diagnostic push 7305 # pragma GCC diagnostic ignored "-Wmissing-field-initializers" 7308 #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) 7312 void reportFatal(
char const *
const message ) {
7313 Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
7317 #endif // signals/SEH handling 7319 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 7322 struct SignalDefs { DWORD id;
const char*
name; };
7327 static SignalDefs signalDefs[] = {
7328 { EXCEPTION_ILLEGAL_INSTRUCTION,
"SIGILL - Illegal instruction signal" },
7329 { EXCEPTION_STACK_OVERFLOW,
"SIGSEGV - Stack overflow" },
7330 { EXCEPTION_ACCESS_VIOLATION,
"SIGSEGV - Segmentation violation signal" },
7331 { EXCEPTION_INT_DIVIDE_BY_ZERO,
"Divide by zero error" },
7334 LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
7335 for (
auto const& def : signalDefs) {
7336 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
7337 reportFatal(def.name);
7342 return EXCEPTION_CONTINUE_SEARCH;
7345 FatalConditionHandler::FatalConditionHandler() {
7349 guaranteeSize = 32 * 1024;
7350 exceptionHandlerHandle =
nullptr;
7352 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
7354 SetThreadStackGuarantee(&guaranteeSize);
7357 void FatalConditionHandler::reset() {
7359 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
7360 SetThreadStackGuarantee(&guaranteeSize);
7361 exceptionHandlerHandle =
nullptr;
7366 FatalConditionHandler::~FatalConditionHandler() {
7370 bool FatalConditionHandler::isSet =
false;
7371 ULONG FatalConditionHandler::guaranteeSize = 0;
7372 PVOID FatalConditionHandler::exceptionHandlerHandle =
nullptr;
7376 #elif defined( CATCH_CONFIG_POSIX_SIGNALS ) 7384 static SignalDefs signalDefs[] = {
7385 { SIGINT,
"SIGINT - Terminal interrupt signal" },
7386 { SIGILL,
"SIGILL - Illegal instruction signal" },
7387 { SIGFPE,
"SIGFPE - Floating point error signal" },
7388 { SIGSEGV,
"SIGSEGV - Segmentation violation signal" },
7389 { SIGTERM,
"SIGTERM - Termination request signal" },
7390 { SIGABRT,
"SIGABRT - Abort (abnormal termination) signal" }
7393 void FatalConditionHandler::handleSignal(
int sig ) {
7394 char const *
name =
"<unknown signal>";
7395 for (
auto const& def : signalDefs) {
7396 if (sig == def.id) {
7406 FatalConditionHandler::FatalConditionHandler() {
7409 sigStack.ss_sp = altStackMem;
7410 sigStack.ss_size = SIGSTKSZ;
7411 sigStack.ss_flags = 0;
7412 sigaltstack(&sigStack, &oldSigStack);
7413 struct sigaction sa = { };
7415 sa.sa_handler = handleSignal;
7416 sa.sa_flags = SA_ONSTACK;
7417 for (std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i) {
7418 sigaction(signalDefs[i].
id, &sa, &oldSigActions[i]);
7422 FatalConditionHandler::~FatalConditionHandler() {
7426 void FatalConditionHandler::reset() {
7429 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i ) {
7430 sigaction(signalDefs[i].
id, &oldSigActions[i],
nullptr);
7433 sigaltstack(&oldSigStack,
nullptr);
7438 bool FatalConditionHandler::isSet =
false;
7439 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
7440 stack_t FatalConditionHandler::oldSigStack = {};
7441 char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
7448 void FatalConditionHandler::reset() {}
7451 #endif // signals/SEH handling 7453 #if defined(__GNUC__) 7454 # pragma GCC diagnostic pop 7466 IConfig::~IConfig() =
default;
7489 class MultipleReporters :
public IStreamingReporter {
7490 using Reporters = std::vector<IStreamingReporterPtr>;
7491 Reporters m_reporters;
7494 void add( IStreamingReporterPtr&& reporter );
7498 ReporterPreferences getPreferences()
const override;
7500 void noMatchingTestCases( std::string
const& spec )
override;
7502 static std::set<Verbosity> getSupportedVerbosities();
7504 void benchmarkStarting( BenchmarkInfo
const& benchmarkInfo )
override;
7505 void benchmarkEnded( BenchmarkStats
const& benchmarkStats )
override;
7507 void testRunStarting( TestRunInfo
const& testRunInfo )
override;
7508 void testGroupStarting( GroupInfo
const& groupInfo )
override;
7509 void testCaseStarting(
TestCaseInfo const& testInfo )
override;
7510 void sectionStarting(
SectionInfo const& sectionInfo )
override;
7511 void assertionStarting(
AssertionInfo const& assertionInfo )
override;
7514 bool assertionEnded( AssertionStats
const& assertionStats )
override;
7515 void sectionEnded( SectionStats
const& sectionStats )
override;
7516 void testCaseEnded( TestCaseStats
const& testCaseStats )
override;
7517 void testGroupEnded( TestGroupStats
const& testGroupStats )
override;
7518 void testRunEnded( TestRunStats
const& testRunStats )
override;
7520 void skipTest(
TestCaseInfo const& testInfo )
override;
7521 bool isMulti()
const override;
7530 ReporterConfig::ReporterConfig( IConfigPtr
const& _fullConfig )
7531 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
7533 ReporterConfig::ReporterConfig( IConfigPtr
const& _fullConfig, std::ostream& _stream )
7534 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
7536 std::ostream& ReporterConfig::stream()
const {
return *m_stream; }
7537 IConfigPtr ReporterConfig::fullConfig()
const {
return m_fullConfig; }
7539 TestRunInfo::TestRunInfo( std::string
const& _name ) :
name( _name ) {}
7541 GroupInfo::GroupInfo( std::string
const& _name,
7542 std::size_t _groupIndex,
7543 std::size_t _groupsCount )
7545 groupIndex( _groupIndex ),
7546 groupsCounts( _groupsCount )
7549 AssertionStats::AssertionStats( AssertionResult
const& _assertionResult,
7550 std::vector<MessageInfo>
const& _infoMessages,
7552 : assertionResult( _assertionResult ),
7553 infoMessages( _infoMessages ),
7556 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
7558 if( assertionResult.hasMessage() ) {
7561 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
7562 builder << assertionResult.getMessage();
7565 infoMessages.push_back( builder.m_info );
7569 AssertionStats::~AssertionStats() =
default;
7571 SectionStats::SectionStats(
SectionInfo const& _sectionInfo,
7572 Counts const& _assertions,
7573 double _durationInSeconds,
7574 bool _missingAssertions )
7575 : sectionInfo( _sectionInfo ),
7576 assertions( _assertions ),
7577 durationInSeconds( _durationInSeconds ),
7578 missingAssertions( _missingAssertions )
7581 SectionStats::~SectionStats() =
default;
7583 TestCaseStats::TestCaseStats(
TestCaseInfo const& _testInfo,
7585 std::string
const& _stdOut,
7586 std::string
const& _stdErr,
7588 : testInfo( _testInfo ),
7592 aborting( _aborting )
7595 TestCaseStats::~TestCaseStats() =
default;
7597 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo,
7600 : groupInfo( _groupInfo ),
7602 aborting( _aborting )
7605 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo )
7606 : groupInfo( _groupInfo ),
7610 TestGroupStats::~TestGroupStats() =
default;
7612 TestRunStats::TestRunStats( TestRunInfo
const& _runInfo,
7615 : runInfo( _runInfo ),
7617 aborting( _aborting )
7620 TestRunStats::~TestRunStats() =
default;
7622 void IStreamingReporter::fatalErrorEncountered(
StringRef ) {}
7623 bool IStreamingReporter::isMulti()
const {
return false; }
7625 IReporterFactory::~IReporterFactory() =
default;
7626 IReporterRegistry::~IReporterRegistry() =
default;
7628 void addReporter( IStreamingReporterPtr& existingReporter, IStreamingReporterPtr&& additionalReporter ) {
7630 if( !existingReporter ) {
7631 existingReporter = std::move( additionalReporter );
7635 MultipleReporters* multi =
nullptr;
7637 if( existingReporter->isMulti() ) {
7638 multi =
static_cast<MultipleReporters*
>( existingReporter.get() );
7641 auto newMulti = std::unique_ptr<MultipleReporters>(
new MultipleReporters );
7642 newMulti->add( std::move( existingReporter ) );
7643 multi = newMulti.get();
7644 existingReporter = std::move( newMulti );
7646 multi->add( std::move( additionalReporter ) );
7666 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG 7671 LeakDetector::LeakDetector() {
7672 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
7673 flag |= _CRTDBG_LEAK_CHECK_DF;
7674 flag |= _CRTDBG_ALLOC_MEM_DF;
7675 _CrtSetDbgFlag(flag);
7676 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
7677 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
7679 _CrtSetBreakAlloc(-1);
7685 Catch::LeakDetector::LeakDetector() {}
7697 std::size_t listTests( Config
const& config );
7699 std::size_t listTestsNamesOnly( Config
const& config );
7702 void add( std::string
const& spelling );
7703 std::string all()
const;
7705 std::set<std::string> spellings;
7706 std::size_t
count = 0;
7709 std::size_t listTags( Config
const& config );
7711 std::size_t listReporters( Config
const& );
7713 Option<std::size_t> list( Config
const& config );
7721 using namespace clara::TextFlow;
7726 #include <algorithm> 7731 std::size_t listTests( Config
const& config ) {
7732 TestSpec testSpec = config.testSpec();
7733 if( config.hasTestFilters() )
7740 for(
auto const& testCaseInfo : matchedTestCases ) {
7741 Colour::Code colour = testCaseInfo.isHidden()
7742 ? Colour::SecondaryText
7744 Colour colourGuard( colour );
7746 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) <<
"\n";
7747 if( config.verbosity() >= Verbosity::High ) {
7749 std::string description = testCaseInfo.description;
7750 if( description.empty() )
7751 description =
"(NO DESCRIPTION)";
7752 Catch::cout() << Column( description ).indent(4) << std::endl;
7754 if( !testCaseInfo.tags.empty() )
7755 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) <<
"\n";
7758 if( !config.hasTestFilters() )
7761 Catch::cout() <<
pluralise( matchedTestCases.size(),
"matching test case" ) <<
'\n' << std::endl;
7762 return matchedTestCases.size();
7765 std::size_t listTestsNamesOnly( Config
const& config ) {
7766 TestSpec testSpec = config.testSpec();
7767 std::size_t matchedTests = 0;
7769 for(
auto const& testCaseInfo : matchedTestCases ) {
7775 if ( config.verbosity() >= Verbosity::High )
7779 return matchedTests;
7782 void TagInfo::add( std::string
const& spelling ) {
7784 spellings.insert( spelling );
7787 std::string TagInfo::all()
const {
7789 for(
auto const& spelling : spellings )
7790 out +=
"[" + spelling +
"]";
7794 std::size_t listTags( Config
const& config ) {
7795 TestSpec testSpec = config.testSpec();
7796 if( config.hasTestFilters() )
7797 Catch::cout() <<
"Tags for matching test cases:\n";
7802 std::map<std::string, TagInfo> tagCounts;
7805 for(
auto const& testCase : matchedTestCases ) {
7806 for(
auto const& tagName : testCase.getTestCaseInfo().tags ) {
7807 std::string lcaseTagName =
toLower( tagName );
7808 auto countIt = tagCounts.find( lcaseTagName );
7809 if( countIt == tagCounts.end() )
7810 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
7811 countIt->second.add( tagName );
7815 for(
auto const& tagCount : tagCounts ) {
7817 rss <<
" " << std::setw(2) << tagCount.second.count <<
" ";
7818 auto str = rss.
str();
7819 auto wrapper = Column( tagCount.second.all() )
7821 .indent( str.size() )
7822 .
width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
7826 return tagCounts.size();
7829 std::size_t listReporters( Config
const& ) {
7832 std::size_t maxNameLen = 0;
7833 for(
auto const& factoryKvp : factories )
7834 maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );
7836 for(
auto const& factoryKvp : factories ) {
7838 << Column( factoryKvp.first +
":" )
7840 .width( 5+maxNameLen )
7841 + Column( factoryKvp.second->getDescription() )
7844 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
7848 return factories.size();
7851 Option<std::size_t> list( Config
const& config ) {
7852 Option<std::size_t> listedCount;
7853 if( config.listTests() )
7854 listedCount = listedCount.valueOr(0) + listTests( config );
7855 if( config.listTestNamesOnly() )
7856 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
7857 if( config.listTags() )
7858 listedCount = listedCount.valueOr(0) + listTags( config );
7859 if( config.listReporters() )
7860 listedCount = listedCount.valueOr(0) + listReporters( config );
7869 namespace Matchers {
7872 std::string MatcherUntypedBase::toString()
const {
7873 if( m_cachedToString.empty() )
7874 m_cachedToString = describe();
7875 return m_cachedToString;
7878 MatcherUntypedBase::~MatcherUntypedBase() =
default;
7883 using namespace Matchers;
7893 #include <stdexcept> 7896 namespace Matchers {
7897 namespace Floating {
7898 enum class FloatingPointKind : uint8_t {
7908 template <
typename T>
7912 struct Converter<float> {
7913 static_assert(
sizeof(
float) ==
sizeof(int32_t),
"Important ULP matcher assumption violated");
7914 Converter(
float f) {
7915 std::memcpy(&i, &f,
sizeof(f));
7921 struct Converter<double> {
7922 static_assert(
sizeof(
double) ==
sizeof(int64_t),
"Important ULP matcher assumption violated");
7923 Converter(
double d) {
7924 std::memcpy(&i, &d,
sizeof(d));
7929 template <
typename T>
7930 auto convert(T t) -> Converter<T> {
7931 return Converter<T>(t);
7934 template <
typename FP>
7935 bool almostEqualUlps(FP lhs, FP rhs,
int maxUlpDiff) {
7938 if (std::isnan(lhs) || std::isnan(rhs)) {
7942 auto lc = convert(lhs);
7943 auto rc = convert(rhs);
7945 if ((lc.i < 0) != (rc.i < 0)) {
7950 auto ulpDiff = std::abs(lc.i - rc.i);
7951 return ulpDiff <= maxUlpDiff;
7957 namespace Matchers {
7958 namespace Floating {
7959 WithinAbsMatcher::WithinAbsMatcher(
double target,
double margin)
7960 :m_target{ target }, m_margin{ margin } {
7962 throw std::domain_error(
"Allowed margin difference has to be >= 0");
7968 bool WithinAbsMatcher::match(
double const& matchee)
const {
7969 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
7972 std::string WithinAbsMatcher::describe()
const {
7976 WithinUlpsMatcher::WithinUlpsMatcher(
double target,
int ulps, FloatingPointKind baseType)
7977 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
7979 throw std::domain_error(
"Allowed ulp difference has to be >= 0");
7983 bool WithinUlpsMatcher::match(
double const& matchee)
const {
7985 case FloatingPointKind::Float:
7986 return almostEqualUlps<float>(
static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
7987 case FloatingPointKind::Double:
7988 return almostEqualUlps<double>(matchee, m_target, m_ulps);
7990 throw std::domain_error(
"Unknown FloatingPointKind value");
7994 std::string WithinUlpsMatcher::describe()
const {
7995 return "is within " + std::to_string(m_ulps) +
" ULPs of " +
::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)?
"f" :
"");
8020 return "matches undescribed predicate";
8022 return "matches predicate: \"" + desc +
'"';
8031 namespace Matchers {
8033 namespace StdString {
8036 : m_caseSensitivity( caseSensitivity ),
8037 m_str( adjustString( str ) )
8039 std::string CasedString::adjustString( std::string
const& str )
const {
8044 std::string CasedString::caseSensitivitySuffix()
const {
8046 ?
" (case insensitive)" 8050 StringMatcherBase::StringMatcherBase( std::string
const& operation, CasedString
const& comparator )
8051 : m_comparator( comparator ),
8052 m_operation( operation ) {
8055 std::string StringMatcherBase::describe()
const {
8056 std::string description;
8057 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
8058 m_comparator.caseSensitivitySuffix().size());
8059 description += m_operation;
8060 description +=
": \"";
8061 description += m_comparator.m_str;
8062 description +=
"\"";
8063 description += m_comparator.caseSensitivitySuffix();
8067 EqualsMatcher::EqualsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"equals", comparator ) {}
8069 bool EqualsMatcher::match( std::string
const& source )
const {
8070 return m_comparator.adjustString( source ) == m_comparator.m_str;
8073 ContainsMatcher::ContainsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"contains", comparator ) {}
8075 bool ContainsMatcher::match( std::string
const& source )
const {
8076 return contains( m_comparator.adjustString( source ), m_comparator.m_str );
8079 StartsWithMatcher::StartsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"starts with", comparator ) {}
8081 bool StartsWithMatcher::match( std::string
const& source )
const {
8082 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8085 EndsWithMatcher::EndsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"ends with", comparator ) {}
8087 bool EndsWithMatcher::match( std::string
const& source )
const {
8088 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8091 RegexMatcher::RegexMatcher(std::string regex,
CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}
8093 bool RegexMatcher::match(std::string
const& matchee)
const {
8094 auto flags = std::regex::ECMAScript;
8095 if (m_caseSensitivity == CaseSensitive::Choice::No) {
8096 flags |= std::regex::icase;
8098 auto reg = std::regex(m_regex, flags);
8099 return std::regex_match(matchee, reg);
8102 std::string RegexMatcher::describe()
const {
8103 return "matches " +
::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)?
" case sensitively" :
" case insensitively");
8133 bool uncaught_exceptions();
8142 : macroName( _macroName ),
8143 lineInfo( _lineInfo ),
8145 sequence( ++globalCount )
8157 unsigned int MessageInfo::globalCount = 0;
8164 :m_info(macroName, lineInfo, type) {}
8169 : m_info( builder.
m_info )
8176 if ( !uncaught_exceptions() ){
8186 #include <algorithm> 8192 void seedRng( IConfig
const& config );
8196 struct RandomNumberGenerator {
8197 using result_type =
unsigned int;
8199 static constexpr result_type (min)() {
return 0; }
8200 static constexpr result_type (max)() {
return 1000000; }
8202 result_type operator()( result_type n )
const;
8203 result_type operator()()
const;
8205 template<
typename V>
8206 static void shuffle( V& vector ) {
8207 RandomNumberGenerator rng;
8208 std::shuffle( vector.begin(), vector.end(), rng );
8219 void seedRng( IConfig
const& config ) {
8220 if( config.rngSeed() != 0 )
8221 std::srand( config.rngSeed() );
8224 return getCurrentContext().getConfig()->rngSeed();
8227 RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n )
const {
8228 return std::rand() % n;
8230 RandomNumberGenerator::result_type RandomNumberGenerator::operator()()
const {
8231 return std::rand() % (max)();
8242 #include <algorithm> 8250 std::vector<TestCase> sortTests( IConfig
const& config, std::vector<TestCase>
const& unsortedTestCases );
8251 bool matchTest(
TestCase const& testCase, TestSpec
const& testSpec, IConfig
const& config );
8253 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions );
8255 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config );
8260 virtual ~TestRegistry() =
default;
8262 virtual void registerTest(
TestCase const& testCase );
8264 std::vector<TestCase>
const& getAllTests()
const override;
8265 std::vector<TestCase>
const& getAllTestsSorted( IConfig
const& config )
const override;
8268 std::vector<TestCase> m_functions;
8269 mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
8270 mutable std::vector<TestCase> m_sortedFunctions;
8271 std::size_t m_unnamedCount = 0;
8278 void(*m_testAsFunction)();
8280 TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept;
8282 void invoke()
const override;
8285 std::string extractClassName(
StringRef const& classOrQualifiedMethodName );
8298 class ReporterRegistry :
public IReporterRegistry {
8302 ~ReporterRegistry()
override;
8304 IStreamingReporterPtr create( std::string
const&
name, IConfigPtr
const& config )
const override;
8309 FactoryMap
const& getFactories()
const override;
8310 Listeners
const& getListeners()
const override;
8313 FactoryMap m_factories;
8314 Listeners m_listeners;
8341 class TagAliasRegistry :
public ITagAliasRegistry {
8343 ~TagAliasRegistry()
override;
8344 TagAlias
const* find( std::string
const& alias )
const override;
8345 std::string expandAliases( std::string
const& unexpandedTestSpec )
const override;
8346 void add( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo );
8349 std::map<std::string, TagAlias> m_registry;
8358 #include <exception> 8362 class StartupExceptionRegistry {
8364 void add(std::exception_ptr
const& exception) noexcept;
8365 std::vector<std::exception_ptr>
const& getExceptions()
const noexcept;
8367 std::vector<std::exception_ptr> m_exceptions;
8381 RegistryHub() =
default;
8382 IReporterRegistry
const& getReporterRegistry()
const override {
8383 return m_reporterRegistry;
8386 return m_testCaseRegistry;
8389 return m_exceptionTranslatorRegistry;
8391 ITagAliasRegistry
const& getTagAliasRegistry()
const override {
8392 return m_tagAliasRegistry;
8394 StartupExceptionRegistry
const& getStartupExceptionRegistry()
const override {
8395 return m_exceptionRegistry;
8400 m_reporterRegistry.registerReporter( name, factory );
8403 m_reporterRegistry.registerListener( factory );
8405 void registerTest(
TestCase const& testInfo )
override {
8406 m_testCaseRegistry.registerTest( testInfo );
8409 m_exceptionTranslatorRegistry.registerTranslator( translator );
8411 void registerTagAlias( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo )
override {
8412 m_tagAliasRegistry.add( alias, tag, lineInfo );
8414 void registerStartupException() noexcept
override {
8415 m_exceptionRegistry.add(std::current_exception());
8419 TestRegistry m_testCaseRegistry;
8420 ReporterRegistry m_reporterRegistry;
8421 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
8422 TagAliasRegistry m_tagAliasRegistry;
8423 StartupExceptionRegistry m_exceptionRegistry;
8427 RegistryHub*& getTheRegistryHub() {
8428 static RegistryHub* theRegistryHub =
nullptr;
8429 if( !theRegistryHub )
8430 theRegistryHub =
new RegistryHub();
8431 return theRegistryHub;
8436 return *getTheRegistryHub();
8439 return *getTheRegistryHub();
8442 delete getTheRegistryHub();
8443 getTheRegistryHub() =
nullptr;
8457 ReporterRegistry::~ReporterRegistry() =
default;
8459 IStreamingReporterPtr ReporterRegistry::create( std::string
const&
name, IConfigPtr
const& config )
const {
8460 auto it = m_factories.find( name );
8461 if( it == m_factories.end() )
8463 return it->second->create( ReporterConfig( config ) );
8466 void ReporterRegistry::registerReporter( std::string
const& name,
IReporterFactoryPtr const& factory ) {
8467 m_factories.emplace(name, factory);
8470 m_listeners.push_back( factory );
8473 IReporterRegistry::FactoryMap
const& ReporterRegistry::getFactories()
const {
8476 IReporterRegistry::Listeners
const& ReporterRegistry::getListeners()
const {
8505 #include <algorithm> 8510 class RedirectedStream {
8511 std::ostream& m_originalStream;
8512 std::ostream& m_redirectionStream;
8513 std::streambuf* m_prevBuf;
8516 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
8517 : m_originalStream( originalStream ),
8518 m_redirectionStream( redirectionStream ),
8519 m_prevBuf( m_originalStream.rdbuf() )
8521 m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
8523 ~RedirectedStream() {
8524 m_originalStream.rdbuf( m_prevBuf );
8528 class RedirectedStdOut {
8530 RedirectedStream m_cout;
8533 auto str()
const -> std::string {
return m_rss.
str(); }
8539 class RedirectedStdErr {
8541 RedirectedStream m_cerr;
8542 RedirectedStream m_clog;
8548 auto str()
const -> std::string {
return m_rss.
str(); }
8551 RunContext::RunContext(IConfigPtr
const& _config, IStreamingReporterPtr&& reporter)
8552 : m_runInfo(_config->name()),
8553 m_context(getCurrentMutableContext()),
8555 m_reporter(std::move(reporter)),
8557 m_includeSuccessfulResults( m_config->includeSuccessfulResults() )
8559 m_context.setRunner(
this);
8560 m_context.setConfig(m_config);
8561 m_context.setResultCapture(
this);
8562 m_reporter->testRunStarting(m_runInfo);
8565 RunContext::~RunContext() {
8566 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
8569 void RunContext::testGroupStarting(std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
8570 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
8573 void RunContext::testGroupEnded(std::string
const& testSpec,
Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {
8574 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
8578 Totals prevTotals = m_totals;
8580 std::string redirectedCout;
8581 std::string redirectedCerr;
8585 m_reporter->testCaseStarting(testInfo);
8587 m_activeTestCase = &testCase;
8589 ITracker& rootTracker = m_trackerContext.startRun();
8590 assert(rootTracker.isSectionTracker());
8591 static_cast<SectionTracker&
>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
8593 m_trackerContext.startCycle();
8594 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
8595 runCurrentTest(redirectedCout, redirectedCerr);
8596 }
while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
8604 m_totals.testCases += deltaTotals.
testCases;
8605 m_reporter->testCaseEnded(TestCaseStats(testInfo,
8611 m_activeTestCase =
nullptr;
8612 m_testCaseTracker =
nullptr;
8617 IConfigPtr RunContext::config()
const {
8621 IStreamingReporter& RunContext::reporter()
const {
8625 void RunContext::assertionEnded(AssertionResult
const & result) {
8628 m_lastAssertionPassed =
true;
8629 }
else if (!result.isOk()) {
8630 m_lastAssertionPassed =
false;
8631 if( m_activeTestCase->getTestCaseInfo().okToFail() )
8632 m_totals.assertions.failedButOk++;
8634 m_totals.assertions.failed++;
8637 m_lastAssertionPassed =
true;
8642 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
8645 resetAssertionInfo();
8646 m_lastResult = result;
8648 void RunContext::resetAssertionInfo() {
8649 m_lastAssertionInfo.macroName =
StringRef();
8650 m_lastAssertionInfo.capturedExpression =
"{Unknown expression after the reported line}"_sr;
8653 bool RunContext::sectionStarted(
SectionInfo const & sectionInfo,
Counts & assertions) {
8654 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.
name, sectionInfo.
lineInfo));
8655 if (!sectionTracker.isOpen())
8657 m_activeSections.push_back(§ionTracker);
8659 m_lastAssertionInfo.lineInfo = sectionInfo.
lineInfo;
8661 m_reporter->sectionStarting(sectionInfo);
8663 assertions = m_totals.assertions;
8668 bool RunContext::testForMissingAssertions(
Counts& assertions) {
8669 if (assertions.
total() != 0)
8671 if (!m_config->warnAboutMissingAssertions())
8673 if (m_trackerContext.currentTracker().hasChildren())
8675 m_totals.assertions.
failed++;
8682 bool missingAssertions = testForMissingAssertions(assertions);
8684 if (!m_activeSections.empty()) {
8685 m_activeSections.back()->close();
8686 m_activeSections.pop_back();
8693 void RunContext::sectionEndedEarly(
SectionEndInfo const & endInfo) {
8694 if (m_unfinishedSections.empty())
8695 m_activeSections.back()->fail();
8697 m_activeSections.back()->close();
8698 m_activeSections.pop_back();
8700 m_unfinishedSections.push_back(endInfo);
8702 void RunContext::benchmarkStarting( BenchmarkInfo
const& info ) {
8703 m_reporter->benchmarkStarting( info );
8705 void RunContext::benchmarkEnded( BenchmarkStats
const& stats ) {
8706 m_reporter->benchmarkEnded( stats );
8709 void RunContext::pushScopedMessage(
MessageInfo const & message) {
8710 m_messages.push_back(message);
8713 void RunContext::popScopedMessage(
MessageInfo const & message) {
8714 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
8717 std::string RunContext::getCurrentTestName()
const {
8718 return m_activeTestCase
8719 ? m_activeTestCase->getTestCaseInfo().name
8723 const AssertionResult * RunContext::getLastResult()
const {
8724 return &(*m_lastResult);
8727 void RunContext::exceptionEarlyReported() {
8728 m_shouldReportUnexpected =
false;
8731 void RunContext::handleFatalErrorCondition(
StringRef message ) {
8733 m_reporter->fatalErrorEncountered(message);
8738 tempResult.message = message;
8739 AssertionResult result(m_lastAssertionInfo, tempResult);
8741 assertionEnded(result);
8743 handleUnfinishedSections();
8746 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
8747 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
8751 SectionStats testCaseSectionStats(testCaseSection, assertions, 0,
false);
8752 m_reporter->sectionEnded(testCaseSectionStats);
8754 auto const& testInfo = m_activeTestCase->getTestCaseInfo();
8759 m_reporter->testCaseEnded(TestCaseStats(testInfo,
8764 m_totals.testCases.failed++;
8765 testGroupEnded(std::string(), m_totals, 1, 1);
8766 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals,
false));
8769 bool RunContext::lastAssertionPassed() {
8770 return m_lastAssertionPassed;
8773 void RunContext::assertionPassed() {
8774 m_lastAssertionPassed =
true;
8775 ++m_totals.assertions.passed;
8776 resetAssertionInfo();
8779 bool RunContext::aborting()
const {
8780 return m_totals.assertions.failed ==
static_cast<std::size_t
>(m_config->abortAfter());
8783 void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
8784 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
8785 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
8786 m_reporter->sectionStarting(testCaseSection);
8787 Counts prevAssertions = m_totals.assertions;
8788 double duration = 0;
8789 m_shouldReportUnexpected =
true;
8796 if (m_reporter->getPreferences().shouldRedirectStdOut) {
8797 RedirectedStdOut redirectedStdOut;
8798 RedirectedStdErr redirectedStdErr;
8800 invokeActiveTestCase();
8801 redirectedCout += redirectedStdOut.str();
8802 redirectedCerr += redirectedStdErr.str();
8806 invokeActiveTestCase();
8814 if( m_shouldReportUnexpected ) {
8819 Counts assertions = m_totals.assertions - prevAssertions;
8820 bool missingAssertions = testForMissingAssertions(assertions);
8822 m_testCaseTracker->close();
8823 handleUnfinishedSections();
8826 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
8827 m_reporter->sectionEnded(testCaseSectionStats);
8830 void RunContext::invokeActiveTestCase() {
8831 FatalConditionHandler fatalConditionHandler;
8832 m_activeTestCase->invoke();
8833 fatalConditionHandler.reset();
8836 void RunContext::handleUnfinishedSections() {
8839 for (
auto it = m_unfinishedSections.rbegin(),
8840 itEnd = m_unfinishedSections.rend();
8844 m_unfinishedSections.clear();
8847 void RunContext::handleExpr(
8852 m_reporter->assertionStarting( info );
8855 bool result = expr.
getResult() != negated;
8858 if (!m_includeSuccessfulResults) {
8867 populateReaction( reaction );
8870 void RunContext::reportExpr(
8876 m_lastAssertionInfo = info;
8879 AssertionResult assertionResult{ info, data };
8880 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
8882 assertionEnded( assertionResult );
8885 void RunContext::handleMessage(
8891 m_reporter->assertionStarting( info );
8893 m_lastAssertionInfo = info;
8896 data.message = message;
8897 AssertionResult assertionResult{ m_lastAssertionInfo, data };
8898 assertionEnded( assertionResult );
8899 if( !assertionResult.isOk() )
8900 populateReaction( reaction );
8902 void RunContext::handleUnexpectedExceptionNotThrown(
8909 void RunContext::handleUnexpectedInflightException(
8911 std::string
const& message,
8914 m_lastAssertionInfo = info;
8917 data.message = message;
8918 AssertionResult assertionResult{ info, data };
8919 assertionEnded( assertionResult );
8920 populateReaction( reaction );
8928 void RunContext::handleIncomplete(
8931 m_lastAssertionInfo = info;
8934 data.message =
"Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
8935 AssertionResult assertionResult{ info, data };
8936 assertionEnded( assertionResult );
8938 void RunContext::handleNonExpr(
8943 m_lastAssertionInfo = info;
8946 AssertionResult assertionResult{ info, data };
8947 assertionEnded( assertionResult );
8949 if( !assertionResult.isOk() )
8950 populateReaction( reaction );
8957 CATCH_INTERNAL_ERROR(
"No result capture instance");
8967 m_sectionIncluded(
getResultCapture().sectionStarted( m_info, m_assertions ) )
8973 if( m_sectionIncluded ) {
8974 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
8975 if( uncaught_exceptions() )
8983 Section::operator bool()
const {
8984 return m_sectionIncluded;
8995 std::string
const& _name,
8996 std::string
const& _description )
8998 description( _description ),
8999 lineInfo( _lineInfo )
9003 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
9020 ~Session()
override;
9022 void showHelp()
const;
9025 int applyCommandLine(
int argc,
char const *
const * argv );
9027 void useConfigData( ConfigData
const& configData );
9029 int run(
int argc,
char* argv[] );
9030 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) 9031 int run(
int argc,
wchar_t*
const argv[] );
9035 clara::Parser
const& cli()
const;
9036 void cli( clara::Parser
const& newParser );
9037 ConfigData& configData();
9042 clara::Parser m_cli;
9043 ConfigData m_configData;
9044 std::shared_ptr<Config> m_config;
9045 bool m_startupExceptions =
false;
9059 Version( Version
const& ) =
delete;
9060 Version& operator=( Version
const& ) =
delete;
9061 Version(
unsigned int _majorVersion,
9062 unsigned int _minorVersion,
9063 unsigned int _patchNumber,
9064 char const *
const _branchName,
9065 unsigned int _buildNumber );
9067 unsigned int const majorVersion;
9068 unsigned int const minorVersion;
9069 unsigned int const patchNumber;
9072 char const *
const branchName;
9073 unsigned int const buildNumber;
9075 friend std::ostream&
operator << ( std::ostream& os, Version
const& version );
9078 Version
const& libraryVersion();
9088 const int MaxExitCode = 255;
9090 IStreamingReporterPtr createReporter(std::string
const& reporterName, IConfigPtr
const& config) {
9092 CATCH_ENFORCE(reporter,
"No reporter registered with name: '" << reporterName <<
"'");
9097 #ifndef CATCH_CONFIG_DEFAULT_REPORTER 9098 #define CATCH_CONFIG_DEFAULT_REPORTER "console" 9101 IStreamingReporterPtr makeReporter(std::shared_ptr<Config>
const& config) {
9102 auto const& reporterNames = config->getReporterNames();
9103 if (reporterNames.empty())
9104 return createReporter(CATCH_CONFIG_DEFAULT_REPORTER, config);
9106 IStreamingReporterPtr reporter;
9107 for (
auto const&
name : reporterNames)
9108 addReporter(reporter, createReporter(
name, config));
9112 #undef CATCH_CONFIG_DEFAULT_REPORTER 9114 void addListeners(IStreamingReporterPtr& reporters, IConfigPtr
const& config) {
9116 for (
auto const& listener : listeners)
9117 addReporter(reporters, listener->create(Catch::ReporterConfig(config)));
9120 Catch::Totals runTests(std::shared_ptr<Config>
const& config) {
9121 IStreamingReporterPtr reporter = makeReporter(config);
9122 addListeners(reporter, config);
9124 RunContext context(config, std::move(reporter));
9128 context.testGroupStarting(config->name(), 1, 1);
9130 TestSpec testSpec = config->testSpec();
9133 for (
auto const& testCase : allTestCases) {
9134 if (!context.aborting() &&
matchTest(testCase, testSpec, *config))
9135 totals += context.runTest(testCase);
9137 context.reporter().skipTest(testCase);
9140 if (config->warnAboutNoTests() && totals.
testCases.
total() == 0) {
9144 for (
const auto& input : config->getTestsOrTags()) {
9145 if (!first) { testConfig <<
' '; }
9147 testConfig << input;
9150 context.reporter().noMatchingTestCases(testConfig.
str());
9154 context.testGroupEnded(config->name(), totals, 1, 1);
9158 void applyFilenamesAsTags(Catch::IConfig
const& config) {
9160 for (
auto& testCase : tests) {
9161 auto tags = testCase.tags;
9163 std::string filename = testCase.lineInfo.file;
9164 auto lastSlash = filename.find_last_of(
"\\/");
9165 if (lastSlash != std::string::npos) {
9166 filename.erase(0, lastSlash);
9170 auto lastDot = filename.find_last_of(
'.');
9171 if (lastDot != std::string::npos) {
9172 filename.erase(lastDot);
9175 tags.push_back(std::move(filename));
9176 setTags(testCase, tags);
9182 Session::Session() {
9183 static bool alreadyInstantiated =
false;
9184 if( alreadyInstantiated ) {
9185 try { CATCH_INTERNAL_ERROR(
"Only one instance of Catch::Session can ever be used" ); }
9190 if ( !exceptions.empty() ) {
9191 m_startupExceptions =
true;
9192 Colour colourGuard( Colour::Red );
9193 Catch::cerr() <<
"Errors occurred during startup!" <<
'\n';
9195 for (
const auto& ex_ptr : exceptions ) {
9197 std::rethrow_exception(ex_ptr);
9198 }
catch ( std::exception
const& ex ) {
9199 Catch::cerr() << Column( ex.what() ).indent(2) <<
'\n';
9204 alreadyInstantiated =
true;
9205 m_cli = makeCommandLineParser( m_configData );
9207 Session::~Session() {
9211 void Session::showHelp()
const {
9213 <<
"\nCatch v" << libraryVersion() <<
"\n" 9214 << m_cli << std::endl
9215 <<
"For more detailed usage please see the project docs\n" << std::endl;
9217 void Session::libIdentify() {
9219 << std::left << std::setw(16) <<
"description: " <<
"A Catch test executable\n" 9220 << std::left << std::setw(16) <<
"category: " <<
"testframework\n" 9221 << std::left << std::setw(16) <<
"framework: " <<
"Catch Test\n" 9222 << std::left << std::setw(16) <<
"version: " << libraryVersion() << std::endl;
9225 int Session::applyCommandLine(
int argc,
char const *
const * argv ) {
9226 if( m_startupExceptions )
9229 auto result = m_cli.parse( clara::Args( argc, argv ) );
9232 << Colour( Colour::Red )
9233 <<
"\nError(s) in input:\n" 9234 << Column( result.errorMessage() ).indent( 2 )
9236 Catch::cerr() <<
"Run with -? for usage\n" << std::endl;
9240 if( m_configData.showHelp )
9242 if( m_configData.libIdentify )
9248 void Session::useConfigData( ConfigData
const& configData ) {
9249 m_configData = configData;
9253 int Session::run(
int argc,
char* argv[] ) {
9254 if( m_startupExceptions )
9256 int returnCode = applyCommandLine( argc, argv );
9257 if( returnCode == 0 )
9262 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) 9263 int Session::run(
int argc,
wchar_t*
const argv[] ) {
9265 char **utf8Argv =
new char *[ argc ];
9267 for (
int i = 0; i < argc; ++i ) {
9268 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
9270 utf8Argv[ i ] =
new char[ bufSize ];
9272 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
9275 int returnCode = run( argc, utf8Argv );
9277 for (
int i = 0; i < argc; ++i )
9278 delete [] utf8Argv[ i ];
9285 int Session::run() {
9286 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
9287 Catch::cout() <<
"...waiting for enter/ return before starting" << std::endl;
9288 static_cast<void>(std::getchar());
9290 int exitCode = runInternal();
9291 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
9292 Catch::cout() <<
"...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
9293 static_cast<void>(std::getchar());
9298 clara::Parser
const& Session::cli()
const {
9301 void Session::cli( clara::Parser
const& newParser ) {
9304 ConfigData& Session::configData() {
9305 return m_configData;
9307 Config& Session::config() {
9309 m_config = std::make_shared<Config>( m_configData );
9313 int Session::runInternal() {
9314 if( m_startupExceptions )
9317 if( m_configData.showHelp || m_configData.libIdentify )
9324 seedRng( *m_config );
9326 if( m_configData.filenamesAsTags )
9327 applyFilenamesAsTags( *m_config );
9330 if( Option<std::size_t> listed = list( config() ) )
9331 return static_cast<int>( *listed );
9333 auto totals = runTests( m_config );
9337 return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
9339 catch( std::exception& ex ) {
9350 void StartupExceptionRegistry::add( std::exception_ptr
const& exception ) noexcept {
9352 m_exceptions.push_back(exception);
9360 std::vector<std::exception_ptr>
const& StartupExceptionRegistry::getExceptions()
const noexcept {
9361 return m_exceptions;
9375 #if defined(__clang__) 9376 # pragma clang diagnostic push 9377 # pragma clang diagnostic ignored "-Wexit-time-destructors" 9384 namespace detail {
namespace {
9385 template<
typename WriterF, std::
size_t bufferSize=256>
9386 class StreamBufImpl :
public std::streambuf {
9387 char data[bufferSize];
9392 setp( data, data +
sizeof(data) );
9395 ~StreamBufImpl() noexcept {
9396 StreamBufImpl::sync();
9400 int overflow(
int c )
override {
9404 if( pbase() == epptr() )
9405 m_writer( std::string( 1, static_cast<char>( c ) ) );
9407 sputc( static_cast<char>( c ) );
9412 int sync()
override {
9413 if( pbase() != pptr() ) {
9414 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
9415 setp( pbase(), epptr() );
9423 struct OutputDebugWriter {
9425 void operator()( std::string
const&str ) {
9426 writeToDebugConsole( str );
9432 class FileStream :
public IStream {
9433 mutable std::ofstream m_ofs;
9436 m_ofs.open( filename.
c_str() );
9437 CATCH_ENFORCE( !m_ofs.fail(),
"Unable to open file: '" << filename <<
"'" );
9439 ~FileStream()
override =
default;
9441 std::ostream& stream()
const override {
9448 class CoutStream :
public IStream {
9449 mutable std::ostream m_os;
9454 ~CoutStream()
override =
default;
9457 std::ostream& stream()
const override {
return m_os; }
9462 class DebugOutStream :
public IStream {
9463 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
9464 mutable std::ostream m_os;
9467 : m_streamBuf(
new StreamBufImpl<OutputDebugWriter>() ),
9468 m_os( m_streamBuf.get() )
9471 ~DebugOutStream()
override =
default;
9474 std::ostream& stream()
const override {
return m_os; }
9482 if( filename.
empty() )
9483 return new detail::CoutStream();
9484 else if( filename[0] ==
'%' ) {
9485 if( filename ==
"%debug" )
9486 return new detail::DebugOutStream();
9488 CATCH_ERROR(
"Unrecognised stream: '" << filename <<
"'" );
9491 return new detail::FileStream( filename );
9495 struct StringStreams {
9496 std::vector<std::unique_ptr<std::ostringstream>> m_streams;
9497 std::vector<std::size_t> m_unused;
9498 std::ostringstream m_referenceStream;
9499 static StringStreams* s_instance;
9501 auto add() -> std::size_t {
9502 if( m_unused.empty() ) {
9503 m_streams.push_back( std::unique_ptr<std::ostringstream>(
new std::ostringstream ) );
9504 return m_streams.size()-1;
9507 auto index = m_unused.back();
9508 m_unused.pop_back();
9513 void release( std::size_t index ) {
9514 m_streams[index]->copyfmt( m_referenceStream );
9515 m_unused.push_back(index);
9519 static auto instance() -> StringStreams& {
9521 s_instance =
new StringStreams();
9524 static void cleanup() {
9526 s_instance =
nullptr;
9530 StringStreams* StringStreams::s_instance =
nullptr;
9533 StringStreams::cleanup();
9537 : m_index( StringStreams::instance().add() ),
9538 m_oss( StringStreams::instance().m_streams[m_index].
get() )
9542 static_cast<std::ostringstream*
>( m_oss )->str(
"");
9544 StringStreams::instance().release( m_index );
9548 return static_cast<std::ostringstream*
>( m_oss )->str();
9553 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions 9560 #if defined(__clang__) 9561 # pragma clang diagnostic pop 9566 #include <algorithm> 9573 bool startsWith( std::string
const& s, std::string
const& prefix ) {
9574 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
9576 bool startsWith( std::string
const& s,
char prefix ) {
9577 return !s.empty() && s[0] == prefix;
9579 bool endsWith( std::string
const& s, std::string
const& suffix ) {
9580 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
9582 bool endsWith( std::string
const& s,
char suffix ) {
9583 return !s.empty() && s[s.size()-1] == suffix;
9585 bool contains( std::string
const& s, std::string
const& infix ) {
9586 return s.find( infix ) != std::string::npos;
9588 char toLowerCh(
char c) {
9589 return static_cast<char>( std::tolower( c ) );
9592 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
9594 std::string
toLower( std::string
const& s ) {
9599 std::string
trim( std::string
const& str ) {
9600 static char const* whitespaceChars =
"\n\r\t ";
9601 std::string::size_type start = str.find_first_not_of( whitespaceChars );
9602 std::string::size_type end = str.find_last_not_of( whitespaceChars );
9604 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
9607 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis ) {
9608 bool replaced =
false;
9609 std::size_t i = str.find( replaceThis );
9610 while( i != std::string::npos ) {
9612 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
9613 if( i < str.size()-withThis.size() )
9614 i = str.find( replaceThis, i+withThis.size() );
9616 i = std::string::npos;
9637 #if defined(__clang__) 9638 # pragma clang diagnostic push 9639 # pragma clang diagnostic ignored "-Wexit-time-destructors" 9647 const uint32_t byte_2_lead = 0xC0;
9648 const uint32_t byte_3_lead = 0xE0;
9649 const uint32_t byte_4_lead = 0xF0;
9654 :
StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
9657 StringRef::operator std::string()
const {
9658 return std::string( m_start, m_size );
9662 std::swap( m_start, other.m_start );
9663 std::swap( m_size, other.m_size );
9664 std::swap( m_data, other.m_data );
9669 const_cast<StringRef*
>( this )->takeOwnership();
9676 auto StringRef::isOwned()
const noexcept ->
bool {
9677 return m_data !=
nullptr;
9679 auto StringRef::isSubstring()
const noexcept ->
bool {
9680 return m_start[m_size] !=
'\0';
9683 void StringRef::takeOwnership() {
9685 m_data =
new char[m_size+1];
9686 memcpy( m_data, m_start, m_size );
9687 m_data[m_size] =
'\0';
9692 if( start < m_size )
9693 return StringRef( m_start+start, size );
9700 (std::strncmp( m_start, other.m_start, size() ) == 0);
9703 return !operator==( other );
9707 return m_start[index];
9711 size_type noChars = m_size;
9713 for( size_type i=0; i < m_size; ++i ) {
9714 char c = m_start[i];
9715 if( ( c & byte_2_lead ) == byte_2_lead ) {
9717 if (( c & byte_3_lead ) == byte_3_lead )
9719 if( ( c & byte_4_lead ) == byte_4_lead )
9728 str.reserve( lhs.
size() + rhs.
size() );
9734 return std::string( lhs ) + std::string( rhs );
9737 return std::string( lhs ) + std::string( rhs );
9751 #if defined(__clang__) 9752 # pragma clang diagnostic pop 9758 TagAlias::TagAlias(std::string
const & _tag,
SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
9782 TagAliasRegistry::~TagAliasRegistry() {}
9784 TagAlias
const* TagAliasRegistry::find( std::string
const& alias )
const {
9785 auto it = m_registry.find( alias );
9786 if( it != m_registry.end() )
9787 return &(it->second);
9792 std::string TagAliasRegistry::expandAliases( std::string
const& unexpandedTestSpec )
const {
9793 std::string expandedTestSpec = unexpandedTestSpec;
9794 for(
auto const& registryKvp : m_registry ) {
9795 std::size_t pos = expandedTestSpec.find( registryKvp.first );
9796 if( pos != std::string::npos ) {
9797 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
9798 registryKvp.second.tag +
9799 expandedTestSpec.substr( pos + registryKvp.first.size() );
9802 return expandedTestSpec;
9805 void TagAliasRegistry::add( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo ) {
9807 "error: tag alias, '" << alias <<
"' is not of the form [@alias name].\n" << lineInfo );
9809 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
9810 "error: tag alias, '" << alias <<
"' already registered.\n" 9811 <<
"\tFirst seen at: " << find(alias)->lineInfo <<
"\n" 9812 <<
"\tRedefined at: " << lineInfo );
9815 ITagAliasRegistry::~ITagAliasRegistry() {}
9817 ITagAliasRegistry
const& ITagAliasRegistry::get() {
9826 #include <exception> 9827 #include <algorithm> 9836 else if( tag ==
"!throws" )
9838 else if( tag ==
"!shouldfail" )
9840 else if( tag ==
"!mayfail" )
9842 else if( tag ==
"!nonportable" )
9844 else if( tag ==
"!benchmark" )
9849 bool isReservedTag( std::string
const& tag ) {
9850 return parseSpecialTag( tag ) ==
TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
9852 void enforceNotReservedTag( std::string
const& tag,
SourceLineInfo const& _lineInfo ) {
9853 CATCH_ENFORCE( !isReservedTag(tag),
9854 "Tag name: [" << tag <<
"] is not allowed.\n" 9855 <<
"Tag names starting with non alpha-numeric characters are reserved\n" 9860 std::string
const& _className,
9864 bool isHidden =
false;
9867 std::vector<std::string> tags;
9868 std::string desc, tag;
9870 std::string _descOrTags = nameAndTags.
tags;
9871 for (
char c : _descOrTags) {
9884 enforceNotReservedTag( tag, _lineInfo );
9886 tags.push_back( tag );
9895 tags.push_back(
"." );
9899 return TestCase( _testCase, std::move(info) );
9902 void setTags(
TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
9904 tags.erase(std::unique(
begin(tags),
end(tags)),
end(tags));
9907 for(
auto const& tag : tags ) {
9908 std::string lcaseTag =
toLower( tag );
9910 testCaseInfo.
lcaseTags.push_back( lcaseTag );
9912 testCaseInfo.
tags = std::move(tags);
9916 std::string
const& _className,
9917 std::string
const& _description,
9918 std::vector<std::string>
const& _tags,
9921 className( _className ),
9922 description( _description ),
9923 lineInfo( _lineInfo ),
9926 setTags( *
this, _tags );
9930 return ( properties & IsHidden ) != 0;
9933 return ( properties & Throws ) != 0;
9936 return ( properties & (ShouldFail | MayFail ) ) != 0;
9939 return ( properties & (ShouldFail ) ) != 0;
9945 std::size_t full_size = 2 * tags.size();
9946 for (
const auto& tag : tags) {
9947 full_size += tag.size();
9949 ret.reserve(full_size);
9950 for (
const auto& tag : tags) {
9963 other.
name = _newName;
9972 return test.get() == other.test.get() &&
9994 std::vector<TestCase> sortTests( IConfig
const& config, std::vector<TestCase>
const& unsortedTestCases ) {
9996 std::vector<TestCase> sorted = unsortedTestCases;
9998 switch( config.runOrder() ) {
9999 case RunTests::InLexicographicalOrder:
10000 std::sort( sorted.begin(), sorted.end() );
10002 case RunTests::InRandomOrder:
10004 RandomNumberGenerator::shuffle( sorted );
10006 case RunTests::InDeclarationOrder:
10012 bool matchTest(
TestCase const& testCase, TestSpec
const& testSpec, IConfig
const& config ) {
10013 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.
throws() );
10016 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions ) {
10017 std::set<TestCase> seenFunctions;
10018 for(
auto const&
function : functions ) {
10019 auto prev = seenFunctions.insert(
function );
10020 CATCH_ENFORCE( prev.second,
10021 "error: TEST_CASE( \"" <<
function.name <<
"\" ) already defined.\n" 10022 <<
"\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo <<
"\n" 10023 <<
"\tRedefined at " <<
function.getTestCaseInfo().lineInfo );
10027 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config ) {
10028 std::vector<TestCase> filtered;
10029 filtered.reserve( testCases.size() );
10030 for(
auto const& testCase : testCases )
10031 if(
matchTest( testCase, testSpec, config ) )
10032 filtered.push_back( testCase );
10039 void TestRegistry::registerTest(
TestCase const& testCase ) {
10041 if( name.empty() ) {
10043 rss <<
"Anonymous test case " << ++m_unnamedCount;
10044 return registerTest( testCase.
withName( rss.
str() ) );
10046 m_functions.push_back( testCase );
10049 std::vector<TestCase>
const& TestRegistry::getAllTests()
const {
10050 return m_functions;
10052 std::vector<TestCase>
const& TestRegistry::getAllTestsSorted( IConfig
const& config )
const {
10053 if( m_sortedFunctions.empty() )
10054 enforceNoDuplicateTestCases( m_functions );
10056 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
10057 m_sortedFunctions = sortTests( config, m_functions );
10058 m_currentSortOrder = config.runOrder();
10060 return m_sortedFunctions;
10064 TestInvokerAsFunction::TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
10066 void TestInvokerAsFunction::invoke()
const {
10067 m_testAsFunction();
10070 std::string extractClassName(
StringRef const& classOrQualifiedMethodName ) {
10071 std::string className = classOrQualifiedMethodName;
10074 std::size_t lastColons = className.rfind(
"::" );
10075 std::size_t penultimateColons = className.rfind(
"::", lastColons-1 );
10076 if( penultimateColons == std::string::npos )
10077 penultimateColons = 1;
10078 className = className.
substr( penultimateColons, lastColons-penultimateColons );
10087 #include <algorithm> 10088 #include <assert.h> 10089 #include <stdexcept> 10093 #if defined(__clang__) 10094 # pragma clang diagnostic push 10095 # pragma clang diagnostic ignored "-Wexit-time-destructors" 10099 namespace TestCaseTracking {
10101 NameAndLocation::NameAndLocation( std::string
const& _name,
SourceLineInfo const& _location )
10103 location( _location )
10106 ITracker::~ITracker() =
default;
10108 TrackerContext& TrackerContext::instance() {
10109 static TrackerContext s_instance;
10113 ITracker& TrackerContext::startRun() {
10114 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation(
"{root}",
CATCH_INTERNAL_LINEINFO ), *
this, nullptr );
10115 m_currentTracker =
nullptr;
10116 m_runState = Executing;
10117 return *m_rootTracker;
10120 void TrackerContext::endRun() {
10121 m_rootTracker.reset();
10122 m_currentTracker =
nullptr;
10123 m_runState = NotStarted;
10126 void TrackerContext::startCycle() {
10127 m_currentTracker = m_rootTracker.get();
10128 m_runState = Executing;
10130 void TrackerContext::completeCycle() {
10131 m_runState = CompletedCycle;
10134 bool TrackerContext::completedCycle()
const {
10135 return m_runState == CompletedCycle;
10137 ITracker& TrackerContext::currentTracker() {
10138 return *m_currentTracker;
10140 void TrackerContext::setCurrentTracker( ITracker* tracker ) {
10141 m_currentTracker = tracker;
10144 TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation
const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
10145 bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr
const& tracker )
const {
10147 tracker->nameAndLocation().name == m_nameAndLocation.name &&
10148 tracker->nameAndLocation().location == m_nameAndLocation.location;
10151 TrackerBase::TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
10152 : m_nameAndLocation( nameAndLocation ),
10157 NameAndLocation
const& TrackerBase::nameAndLocation()
const {
10158 return m_nameAndLocation;
10160 bool TrackerBase::isComplete()
const {
10161 return m_runState == CompletedSuccessfully || m_runState == Failed;
10163 bool TrackerBase::isSuccessfullyCompleted()
const {
10164 return m_runState == CompletedSuccessfully;
10166 bool TrackerBase::isOpen()
const {
10167 return m_runState != NotStarted && !isComplete();
10169 bool TrackerBase::hasChildren()
const {
10170 return !m_children.empty();
10173 void TrackerBase::addChild( ITrackerPtr
const& child ) {
10174 m_children.push_back( child );
10177 ITrackerPtr TrackerBase::findChild( NameAndLocation
const& nameAndLocation ) {
10178 auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
10179 return( it != m_children.end() )
10183 ITracker& TrackerBase::parent() {
10184 assert( m_parent );
10188 void TrackerBase::openChild() {
10189 if( m_runState != ExecutingChildren ) {
10190 m_runState = ExecutingChildren;
10192 m_parent->openChild();
10196 bool TrackerBase::isSectionTracker()
const {
return false; }
10197 bool TrackerBase::isIndexTracker()
const {
return false; }
10199 void TrackerBase::open() {
10200 m_runState = Executing;
10203 m_parent->openChild();
10206 void TrackerBase::close() {
10209 while( &m_ctx.currentTracker() != this )
10210 m_ctx.currentTracker().close();
10212 switch( m_runState ) {
10213 case NeedsAnotherRun:
10217 m_runState = CompletedSuccessfully;
10219 case ExecutingChildren:
10220 if( m_children.empty() || m_children.back()->isComplete() )
10221 m_runState = CompletedSuccessfully;
10225 case CompletedSuccessfully:
10227 CATCH_INTERNAL_ERROR(
"Illogical state: " << m_runState );
10230 CATCH_INTERNAL_ERROR(
"Unknown state: " << m_runState );
10233 m_ctx.completeCycle();
10235 void TrackerBase::fail() {
10236 m_runState = Failed;
10238 m_parent->markAsNeedingAnotherRun();
10240 m_ctx.completeCycle();
10242 void TrackerBase::markAsNeedingAnotherRun() {
10243 m_runState = NeedsAnotherRun;
10246 void TrackerBase::moveToParent() {
10247 assert( m_parent );
10248 m_ctx.setCurrentTracker( m_parent );
10250 void TrackerBase::moveToThis() {
10251 m_ctx.setCurrentTracker(
this );
10254 SectionTracker::SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
10255 : TrackerBase( nameAndLocation, ctx, parent )
10258 while( !parent->isSectionTracker() )
10259 parent = &parent->parent();
10261 SectionTracker& parentSection =
static_cast<SectionTracker&
>( *parent );
10262 addNextFilters( parentSection.m_filters );
10266 bool SectionTracker::isSectionTracker()
const {
return true; }
10268 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation ) {
10269 std::shared_ptr<SectionTracker> section;
10271 ITracker& currentTracker = ctx.currentTracker();
10272 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
10273 assert( childTracker );
10274 assert( childTracker->isSectionTracker() );
10275 section = std::static_pointer_cast<SectionTracker>( childTracker );
10278 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker );
10279 currentTracker.addChild( section );
10281 if( !ctx.completedCycle() )
10282 section->tryOpen();
10286 void SectionTracker::tryOpen() {
10287 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
10291 void SectionTracker::addInitialFilters( std::vector<std::string>
const& filters ) {
10292 if( !filters.empty() ) {
10293 m_filters.push_back(
"");
10294 m_filters.push_back(
"");
10295 m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
10298 void SectionTracker::addNextFilters( std::vector<std::string>
const& filters ) {
10299 if( filters.size() > 1 )
10300 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
10303 IndexTracker::IndexTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent,
int size )
10304 : TrackerBase( nameAndLocation, ctx, parent ),
10308 bool IndexTracker::isIndexTracker()
const {
return true; }
10310 IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation,
int size ) {
10311 std::shared_ptr<IndexTracker> tracker;
10313 ITracker& currentTracker = ctx.currentTracker();
10314 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
10315 assert( childTracker );
10316 assert( childTracker->isIndexTracker() );
10317 tracker = std::static_pointer_cast<IndexTracker>( childTracker );
10320 tracker = std::make_shared<IndexTracker>( nameAndLocation, ctx, ¤tTracker,
size );
10321 currentTracker.addChild( tracker );
10324 if( !ctx.completedCycle() && !tracker->isComplete() ) {
10325 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
10326 tracker->moveNext();
10333 int IndexTracker::index()
const {
return m_index; }
10335 void IndexTracker::moveNext() {
10337 m_children.clear();
10340 void IndexTracker::close() {
10341 TrackerBase::close();
10342 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
10343 m_runState = Executing;
10348 using TestCaseTracking::ITracker;
10349 using TestCaseTracking::TrackerContext;
10350 using TestCaseTracking::SectionTracker;
10351 using TestCaseTracking::IndexTracker;
10355 #if defined(__clang__) 10356 # pragma clang diagnostic pop 10364 return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
10375 extractClassName( classOrMethod ),
10389 #include <algorithm> 10396 TestSpec::Pattern::~Pattern() =
default;
10397 TestSpec::NamePattern::~NamePattern() =
default;
10398 TestSpec::TagPattern::~TagPattern() =
default;
10399 TestSpec::ExcludedPattern::~ExcludedPattern() =
default;
10401 TestSpec::NamePattern::NamePattern( std::string
const&
name )
10404 bool TestSpec::NamePattern::matches(
TestCaseInfo const& testCase )
const {
10405 return m_wildcardPattern.matches(
toLower( testCase.
name ) );
10408 TestSpec::TagPattern::TagPattern( std::string
const& tag ) : m_tag(
toLower( tag ) ) {}
10409 bool TestSpec::TagPattern::matches(
TestCaseInfo const& testCase )
const {
10415 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr
const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
10416 bool TestSpec::ExcludedPattern::matches(
TestCaseInfo const& testCase )
const {
return !m_underlyingPattern->matches( testCase ); }
10418 bool TestSpec::Filter::matches(
TestCaseInfo const& testCase )
const {
10420 for(
auto const& pattern : m_patterns ) {
10421 if( !pattern->matches( testCase ) )
10427 bool TestSpec::hasFilters()
const {
10428 return !m_filters.empty();
10430 bool TestSpec::matches(
TestCaseInfo const& testCase )
const {
10432 for(
auto const&
filter : m_filters )
10433 if(
filter.matches( testCase ) )
10443 TestSpecParser::TestSpecParser( ITagAliasRegistry
const& tagAliases ) : m_tagAliases( &tagAliases ) {}
10447 m_exclusion =
false;
10448 m_start = std::string::npos;
10449 m_arg = m_tagAliases->expandAliases( arg );
10450 m_escapeChars.clear();
10451 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
10452 visitChar( m_arg[m_pos] );
10453 if( m_mode == Name )
10454 addPattern<TestSpec::NamePattern>();
10457 TestSpec TestSpecParser::testSpec() {
10462 void TestSpecParser::visitChar(
char c ) {
10463 if( m_mode == None ) {
10466 case '~': m_exclusion =
true;
return;
10467 case '[':
return startNewMode( Tag, ++m_pos );
10468 case '"':
return startNewMode( QuotedName, ++m_pos );
10469 case '\\':
return escape();
10470 default: startNewMode( Name, m_pos );
break;
10473 if( m_mode == Name ) {
10475 addPattern<TestSpec::NamePattern>();
10478 else if( c ==
'[' ) {
10479 if( subString() ==
"exclude:" )
10480 m_exclusion =
true;
10482 addPattern<TestSpec::NamePattern>();
10483 startNewMode( Tag, ++m_pos );
10485 else if( c ==
'\\' )
10488 else if( m_mode == EscapedName )
10490 else if( m_mode == QuotedName && c ==
'"' )
10491 addPattern<TestSpec::NamePattern>();
10492 else if( m_mode == Tag && c ==
']' )
10493 addPattern<TestSpec::TagPattern>();
10495 void TestSpecParser::startNewMode(
Mode mode, std::size_t start ) {
10499 void TestSpecParser::escape() {
10500 if( m_mode == None )
10502 m_mode = EscapedName;
10503 m_escapeChars.push_back( m_pos );
10505 std::string TestSpecParser::subString()
const {
return m_arg.substr( m_start, m_pos - m_start ); }
10507 void TestSpecParser::addFilter() {
10508 if( !m_currentFilter.m_patterns.empty() ) {
10509 m_testSpec.m_filters.push_back( m_currentFilter );
10510 m_currentFilter = TestSpec::Filter();
10514 TestSpec parseTestSpec( std::string
const& arg ) {
10515 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
10524 static const uint64_t nanosecondsInSecond = 1000000000;
10529 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).
count();
10532 auto estimateClockResolution() -> uint64_t {
10534 static const uint64_t iterations = 1000000;
10538 for( std::size_t i = 0; i < iterations; ++i ) {
10544 }
while( ticks == baseTicks );
10546 auto delta = ticks - baseTicks;
10552 if (ticks > startTime + 3 * nanosecondsInSecond) {
10559 return sum/iterations;
10562 static auto s_resolution = estimateClockResolution();
10563 return s_resolution;
10573 return getElapsedNanoseconds()/1000;
10576 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
10579 return getElapsedMicroseconds()/1000000.0;
10586 #if defined(__clang__) 10587 # pragma clang diagnostic push 10588 # pragma clang diagnostic ignored "-Wexit-time-destructors" 10589 # pragma clang diagnostic ignored "-Wglobal-constructors" 10593 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 10594 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 10604 const std::string unprintableString =
"{?}";
10607 const int hexThreshold = 255;
10609 struct Endianness {
10610 enum Arch { Big, Little };
10612 static Arch which() {
10615 char asChar[sizeof (int)];
10619 return ( u.asChar[
sizeof(
int)-1] == 1 ) ? Big : Little;
10626 int i = 0, end =
static_cast<int>(
size ), inc = 1;
10627 if( Endianness::which() == Endianness::Little ) {
10632 unsigned char const *bytes =
static_cast<unsigned char const *
>(object);
10634 rss <<
"0x" << std::setfill(
'0') << std::hex;
10635 for( ; i !=
end; i += inc )
10636 rss << std::setw(2) <<
static_cast<unsigned>(bytes[i]);
10641 template<
typename T>
10642 std::string fpToString( T value,
int precision ) {
10643 if (std::isnan(value)) {
10648 rss << std::setprecision( precision )
10651 std::string d = rss.
str();
10652 std::size_t i = d.find_last_not_of(
'0' );
10653 if( i != std::string::npos && i != d.size()-1 ) {
10656 d = d.substr( 0, i+1 );
10668 if (!getCurrentContext().getConfig()->showInvisibles()) {
10669 return '"' + str +
'"';
10672 std::string s(
"\"");
10673 for (
char c : str) {
10690 #ifdef CATCH_CONFIG_WCHAR 10693 s.reserve(wstr.size());
10694 for (
auto c : wstr) {
10695 s += (c <= 0xff) ? static_cast<char>(c) :
'?';
10705 return{
"{null string}" };
10712 return{
"{null string}" };
10715 #ifdef CATCH_CONFIG_WCHAR 10720 return{
"{null string}" };
10727 return{
"{null string}" };
10741 if (value > Detail::hexThreshold) {
10742 rss <<
" (0x" << std::hex << value <<
')';
10756 if (value > Detail::hexThreshold) {
10757 rss <<
" (0x" << std::hex << value <<
')';
10763 return b ?
"true" :
"false";
10767 if (value ==
'\r') {
10769 }
else if (value ==
'\f') {
10771 }
else if (value ==
'\n') {
10773 }
else if (value ==
'\t') {
10775 }
else if (
'\0' <= value && value <
' ') {
10778 char chstr[] =
"' '";
10795 return fpToString(value, 5) +
'f';
10798 return fpToString(value, 10);
10801 std::string ratio_string<std::atto>::symbol() {
return "a"; }
10802 std::string ratio_string<std::femto>::symbol() {
return "f"; }
10803 std::string ratio_string<std::pico>::symbol() {
return "p"; }
10804 std::string ratio_string<std::nano>::symbol() {
return "n"; }
10805 std::string ratio_string<std::micro>::symbol() {
return "u"; }
10806 std::string ratio_string<std::milli>::symbol() {
return "m"; }
10810 #if defined(__clang__) 10811 # pragma clang diagnostic pop 10835 return passed + failed + failedButOk;
10838 return failed == 0 && failedButOk == 0;
10841 return failed == 0;
10858 Totals diff = *
this - prevTotals;
10872 #include <exception> 10875 bool uncaught_exceptions() {
10876 #if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 10877 return std::uncaught_exception();
10880 return std::uncaught_exception();
10892 (
unsigned int _majorVersion,
10893 unsigned int _minorVersion,
10894 unsigned int _patchNumber,
10895 char const *
const _branchName,
10896 unsigned int _buildNumber )
10897 : majorVersion( _majorVersion ),
10898 minorVersion( _minorVersion ),
10899 patchNumber( _patchNumber ),
10900 branchName( _branchName ),
10901 buildNumber( _buildNumber )
10904 std::ostream&
operator << ( std::ostream& os, Version
const& version ) {
10905 os << version.majorVersion <<
'.' 10906 << version.minorVersion <<
'.' 10907 << version.patchNumber;
10909 if (version.branchName[0]) {
10910 os <<
'-' << version.branchName
10911 <<
'.' << version.buildNumber;
10916 Version
const& libraryVersion() {
10917 static Version version( 2, 2, 2,
"", 0 );
10929 WildcardPattern::WildcardPattern( std::string
const& pattern,
10931 : m_caseSensitivity( caseSensitivity ),
10932 m_pattern( adjustCase( pattern ) )
10935 m_pattern = m_pattern.substr( 1 );
10936 m_wildcard = WildcardAtStart;
10938 if(
endsWith( m_pattern,
'*' ) ) {
10939 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
10940 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
10944 bool WildcardPattern::matches( std::string
const& str )
const {
10945 switch( m_wildcard ) {
10947 return m_pattern == adjustCase( str );
10948 case WildcardAtStart:
10949 return endsWith( adjustCase( str ), m_pattern );
10950 case WildcardAtEnd:
10951 return startsWith( adjustCase( str ), m_pattern );
10952 case WildcardAtBothEnds:
10953 return contains( adjustCase( str ), m_pattern );
10955 CATCH_INTERNAL_ERROR(
"Unknown enum" );
10959 std::string WildcardPattern::adjustCase( std::string
const& str )
const {
10968 using uchar =
unsigned char;
10974 size_t trailingBytes(
unsigned char c) {
10975 if ((c & 0xE0) == 0xC0) {
10978 if ((c & 0xF0) == 0xE0) {
10981 if ((c & 0xF8) == 0xF0) {
10984 CATCH_INTERNAL_ERROR(
"Invalid multibyte utf-8 start byte encountered");
10987 uint32_t headerValue(
unsigned char c) {
10988 if ((c & 0xE0) == 0xC0) {
10991 if ((c & 0xF0) == 0xE0) {
10994 if ((c & 0xF8) == 0xF0) {
10997 CATCH_INTERNAL_ERROR(
"Invalid multibyte utf-8 start byte encountered");
11000 void hexEscapeChar(std::ostream& os,
unsigned char c) {
11002 << std::uppercase << std::hex << std::setfill(
'0') << std::setw(2)
11003 <<
static_cast<int>(c);
11008 XmlEncode::XmlEncode( std::string
const& str, ForWhat forWhat )
11010 m_forWhat( forWhat )
11013 void XmlEncode::encodeTo( std::ostream& os )
const {
11017 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
11018 uchar c = m_str[idx];
11020 case '<': os <<
"<";
break;
11021 case '&': os <<
"&";
break;
11025 if (idx > 2 && m_str[idx - 1] ==
']' && m_str[idx - 2] ==
']')
11032 if (m_forWhat == ForAttributes)
11043 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
11044 hexEscapeChar(os, c);
11062 hexEscapeChar(os, c);
11066 auto encBytes = trailingBytes(c);
11068 if (idx + encBytes - 1 >= m_str.size()) {
11069 hexEscapeChar(os, c);
11076 uint32_t value = headerValue(c);
11077 for (std::size_t n = 1; n < encBytes; ++n) {
11078 uchar nc = m_str[idx + n];
11079 valid &= ((nc & 0xC0) == 0x80);
11080 value = (value << 6) | (nc & 0x3F);
11088 (0x80 <= value && value < 0x800 && encBytes > 2) ||
11089 (0x800 < value && value < 0x10000 && encBytes > 3) ||
11091 (value >= 0x110000)
11093 hexEscapeChar(os, c);
11098 for (std::size_t n = 0; n < encBytes; ++n) {
11099 os << m_str[idx + n];
11101 idx += encBytes - 1;
11107 std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode ) {
11108 xmlEncode.encodeTo( os );
11112 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
11113 : m_writer( writer )
11116 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
11117 : m_writer( other.m_writer ){
11118 other.m_writer =
nullptr;
11120 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
11122 m_writer->endElement();
11124 m_writer = other.m_writer;
11125 other.m_writer =
nullptr;
11129 XmlWriter::ScopedElement::~ScopedElement() {
11131 m_writer->endElement();
11134 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string
const& text,
bool indent ) {
11135 m_writer->writeText( text, indent );
11139 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
11141 writeDeclaration();
11144 XmlWriter::~XmlWriter() {
11145 while( !m_tags.empty() )
11149 XmlWriter& XmlWriter::startElement( std::string
const&
name ) {
11151 newlineIfNecessary();
11152 m_os << m_indent <<
'<' <<
name;
11153 m_tags.push_back( name );
11155 m_tagIsOpen =
true;
11159 XmlWriter::ScopedElement XmlWriter::scopedElement( std::string
const& name ) {
11160 ScopedElement scoped(
this );
11161 startElement( name );
11165 XmlWriter& XmlWriter::endElement() {
11166 newlineIfNecessary();
11167 m_indent = m_indent.substr( 0, m_indent.size()-2 );
11168 if( m_tagIsOpen ) {
11170 m_tagIsOpen =
false;
11173 m_os << m_indent <<
"</" << m_tags.back() <<
">";
11180 XmlWriter& XmlWriter::writeAttribute( std::string
const& name, std::string
const& attribute ) {
11181 if( !name.empty() && !attribute.empty() )
11182 m_os <<
' ' << name <<
"=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) <<
'"';
11186 XmlWriter& XmlWriter::writeAttribute( std::string
const& name,
bool attribute ) {
11187 m_os <<
' ' << name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
'"';
11191 XmlWriter& XmlWriter::writeText( std::string
const& text,
bool indent ) {
11192 if( !text.empty() ){
11193 bool tagWasOpen = m_tagIsOpen;
11195 if( tagWasOpen && indent )
11197 m_os << XmlEncode( text );
11198 m_needsNewline =
true;
11203 XmlWriter& XmlWriter::writeComment( std::string
const& text ) {
11205 m_os << m_indent <<
"<!--" << text <<
"-->";
11206 m_needsNewline =
true;
11210 void XmlWriter::writeStylesheetRef( std::string
const& url ) {
11211 m_os <<
"<?xml-stylesheet type=\"text/xsl\" href=\"" << url <<
"\"?>\n";
11214 XmlWriter& XmlWriter::writeBlankLine() {
11220 void XmlWriter::ensureTagClosed() {
11221 if( m_tagIsOpen ) {
11222 m_os <<
">" << std::endl;
11223 m_tagIsOpen =
false;
11227 void XmlWriter::writeDeclaration() {
11228 m_os <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
11231 void XmlWriter::newlineIfNecessary() {
11232 if( m_needsNewline ) {
11234 m_needsNewline =
false;
11244 #include <assert.h> 11248 void prepareExpandedExpression(AssertionResult& result) {
11249 result.getExpandedExpression();
11254 std::string getFormattedDuration(
double duration ) {
11259 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
11260 char buffer[maxDoubleSize];
11265 sprintf_s(buffer,
"%.3f", duration);
11267 sprintf(buffer,
"%.3f", duration);
11269 return std::string(buffer);
11272 TestEventListenerBase::TestEventListenerBase(ReporterConfig
const & _config)
11273 :StreamingReporterBase(_config) {}
11275 void TestEventListenerBase::assertionStarting(
AssertionInfo const &) {}
11277 bool TestEventListenerBase::assertionEnded(AssertionStats
const &) {
11287 #ifdef CATCH_PLATFORM_MAC 11288 const char* failedString() {
return "FAILED"; }
11289 const char* passedString() {
return "PASSED"; }
11291 const char* failedString() {
return "failed"; }
11292 const char* passedString() {
return "passed"; }
11296 Catch::Colour::Code dimColour() {
return Catch::Colour::FileName; }
11298 std::string bothOrAll( std::size_t
count ) {
11299 return count == 1 ? std::string() :
11300 count == 2 ?
"both " :
"all " ;
11313 void printTotals(std::ostream& out,
const Totals& totals) {
11315 out <<
"No tests ran.";
11317 Colour colour(Colour::ResultError);
11318 const std::string qualify_assertions_failed =
11324 "failed " << qualify_assertions_failed <<
11330 <<
" (no assertions).";
11332 Colour colour(Colour::ResultError);
11337 Colour colour(Colour::ResultSuccess);
11346 class AssertionPrinter {
11348 AssertionPrinter& operator= (AssertionPrinter
const&) =
delete;
11349 AssertionPrinter(AssertionPrinter
const&) =
delete;
11350 AssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
11352 , result(_stats.assertionResult)
11353 , messages(_stats.infoMessages)
11354 , itMessage(_stats.infoMessages.begin())
11355 , printInfoMessages(_printInfoMessages) {}
11360 itMessage = messages.begin();
11362 switch (result.getResultType()) {
11364 printResultType(Colour::ResultSuccess, passedString());
11365 printOriginalExpression();
11366 printReconstructedExpression();
11367 if (!result.hasExpression())
11368 printRemainingMessages(Colour::None);
11370 printRemainingMessages();
11374 printResultType(Colour::ResultSuccess, failedString() + std::string(
" - but was ok"));
11376 printResultType(Colour::Error, failedString());
11377 printOriginalExpression();
11378 printReconstructedExpression();
11379 printRemainingMessages();
11382 printResultType(Colour::Error, failedString());
11383 printIssue(
"unexpected exception with message:");
11385 printExpressionWas();
11386 printRemainingMessages();
11389 printResultType(Colour::Error, failedString());
11390 printIssue(
"fatal error condition with message:");
11392 printExpressionWas();
11393 printRemainingMessages();
11396 printResultType(Colour::Error, failedString());
11397 printIssue(
"expected exception, got none");
11398 printExpressionWas();
11399 printRemainingMessages();
11402 printResultType(Colour::None,
"info");
11404 printRemainingMessages();
11407 printResultType(Colour::None,
"warning");
11409 printRemainingMessages();
11412 printResultType(Colour::Error, failedString());
11413 printIssue(
"explicitly");
11414 printRemainingMessages(Colour::None);
11420 printResultType(Colour::Error,
"** internal error **");
11426 void printSourceInfo()
const {
11427 Colour colourGuard(Colour::FileName);
11428 stream << result.getSourceInfo() <<
':';
11431 void printResultType(Colour::Code colour, std::string
const& passOrFail)
const {
11432 if (!passOrFail.empty()) {
11434 Colour colourGuard(colour);
11435 stream <<
' ' << passOrFail;
11441 void printIssue(std::string
const& issue)
const {
11442 stream <<
' ' << issue;
11445 void printExpressionWas() {
11446 if (result.hasExpression()) {
11449 Colour colour(dimColour());
11450 stream <<
" expression was:";
11452 printOriginalExpression();
11456 void printOriginalExpression()
const {
11457 if (result.hasExpression()) {
11458 stream <<
' ' << result.getExpression();
11462 void printReconstructedExpression()
const {
11463 if (result.hasExpandedExpression()) {
11465 Colour colour(dimColour());
11466 stream <<
" for: ";
11468 stream << result.getExpandedExpression();
11472 void printMessage() {
11473 if (itMessage != messages.end()) {
11474 stream <<
" '" << itMessage->message <<
'\'';
11479 void printRemainingMessages(Colour::Code colour = dimColour()) {
11480 if (itMessage == messages.end())
11484 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
11485 const std::size_t N =
static_cast<std::size_t
>(std::distance(itMessage, itEnd));
11488 Colour colourGuard(colour);
11489 stream <<
" with " <<
pluralise(N,
"message") <<
':';
11492 for (; itMessage != itEnd; ) {
11495 stream <<
" '" << itMessage->message <<
'\'';
11496 if (++itMessage != itEnd) {
11497 Colour colourGuard(dimColour());
11505 std::ostream& stream;
11506 AssertionResult
const& result;
11507 std::vector<MessageInfo> messages;
11508 std::vector<MessageInfo>::const_iterator itMessage;
11509 bool printInfoMessages;
11514 std::string CompactReporter::getDescription() {
11515 return "Reports test results on a single line, suitable for IDEs";
11518 ReporterPreferences CompactReporter::getPreferences()
const {
11519 ReporterPreferences prefs;
11520 prefs.shouldRedirectStdOut =
false;
11524 void CompactReporter::noMatchingTestCases( std::string
const& spec ) {
11525 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
11528 void CompactReporter::assertionStarting(
AssertionInfo const& ) {}
11530 bool CompactReporter::assertionEnded( AssertionStats
const& _assertionStats ) {
11531 AssertionResult
const& result = _assertionStats.assertionResult;
11533 bool printInfoMessages =
true;
11536 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
11539 printInfoMessages =
false;
11542 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
11545 stream << std::endl;
11549 void CompactReporter::sectionEnded(SectionStats
const& _sectionStats) {
11550 if (m_config->showDurations() == ShowDurations::Always) {
11551 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name << std::endl;
11555 void CompactReporter::testRunEnded( TestRunStats
const& _testRunStats ) {
11556 printTotals( stream, _testRunStats.totals );
11557 stream <<
'\n' << std::endl;
11558 StreamingReporterBase::testRunEnded( _testRunStats );
11561 CompactReporter::~CompactReporter() {}
11563 CATCH_REGISTER_REPORTER(
"compact", CompactReporter )
11572 #if defined(_MSC_VER) 11573 #pragma warning(push) 11574 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 11584 class ConsoleAssertionPrinter {
11586 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter
const&) =
delete;
11587 ConsoleAssertionPrinter(ConsoleAssertionPrinter
const&) =
delete;
11588 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
11591 result(_stats.assertionResult),
11592 colour(Colour::None),
11593 message(result.getMessage()),
11594 messages(_stats.infoMessages),
11595 printInfoMessages(_printInfoMessages) {
11596 switch (result.getResultType()) {
11598 colour = Colour::Success;
11599 passOrFail =
"PASSED";
11601 if (_stats.infoMessages.size() == 1)
11602 messageLabel =
"with message";
11603 if (_stats.infoMessages.size() > 1)
11604 messageLabel =
"with messages";
11607 if (result.isOk()) {
11608 colour = Colour::Success;
11609 passOrFail =
"FAILED - but was ok";
11611 colour = Colour::Error;
11612 passOrFail =
"FAILED";
11614 if (_stats.infoMessages.size() == 1)
11615 messageLabel =
"with message";
11616 if (_stats.infoMessages.size() > 1)
11617 messageLabel =
"with messages";
11620 colour = Colour::Error;
11621 passOrFail =
"FAILED";
11622 messageLabel =
"due to unexpected exception with ";
11623 if (_stats.infoMessages.size() == 1)
11624 messageLabel +=
"message";
11625 if (_stats.infoMessages.size() > 1)
11626 messageLabel +=
"messages";
11629 colour = Colour::Error;
11630 passOrFail =
"FAILED";
11631 messageLabel =
"due to a fatal error condition";
11634 colour = Colour::Error;
11635 passOrFail =
"FAILED";
11636 messageLabel =
"because no exception was thrown where one was expected";
11639 messageLabel =
"info";
11642 messageLabel =
"warning";
11645 passOrFail =
"FAILED";
11646 colour = Colour::Error;
11647 if (_stats.infoMessages.size() == 1)
11648 messageLabel =
"explicitly with message";
11649 if (_stats.infoMessages.size() > 1)
11650 messageLabel =
"explicitly with messages";
11656 passOrFail =
"** internal error **";
11657 colour = Colour::Error;
11662 void print()
const {
11664 if (stats.totals.assertions.total() > 0) {
11668 printOriginalExpression();
11669 printReconstructedExpression();
11677 void printResultType()
const {
11678 if (!passOrFail.empty()) {
11679 Colour colourGuard(colour);
11680 stream << passOrFail <<
":\n";
11683 void printOriginalExpression()
const {
11684 if (result.hasExpression()) {
11685 Colour colourGuard(Colour::OriginalExpression);
11687 stream << result.getExpressionInMacro();
11691 void printReconstructedExpression()
const {
11692 if (result.hasExpandedExpression()) {
11693 stream <<
"with expansion:\n";
11694 Colour colourGuard(Colour::ReconstructedExpression);
11695 stream << Column(result.getExpandedExpression()).indent(2) <<
'\n';
11698 void printMessage()
const {
11699 if (!messageLabel.empty())
11700 stream << messageLabel <<
':' <<
'\n';
11701 for (
auto const& msg : messages) {
11704 stream << Column(msg.message).indent(2) <<
'\n';
11707 void printSourceInfo()
const {
11708 Colour colourGuard(Colour::FileName);
11709 stream << result.getSourceInfo() <<
": ";
11712 std::ostream& stream;
11713 AssertionStats
const& stats;
11714 AssertionResult
const& result;
11715 Colour::Code colour;
11716 std::string passOrFail;
11717 std::string messageLabel;
11718 std::string message;
11719 std::vector<MessageInfo> messages;
11720 bool printInfoMessages;
11723 std::size_t makeRatio(std::size_t number, std::size_t total) {
11724 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
11725 return (ratio == 0 && number > 0) ? 1 : ratio;
11728 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {
11729 if (i > j && i > k)
11737 struct ColumnInfo {
11738 enum Justification { Left, Right };
11741 Justification justification;
11743 struct ColumnBreak {};
11744 struct RowBreak {};
11755 static const uint64_t s_nanosecondsInAMicrosecond = 1000;
11756 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
11757 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
11758 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
11760 uint64_t m_inNanoseconds;
11764 explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
11765 : m_inNanoseconds(inNanoseconds),
11767 if (m_units == Unit::Auto) {
11768 if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
11769 m_units = Unit::Nanoseconds;
11770 else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
11771 m_units = Unit::Microseconds;
11772 else if (m_inNanoseconds < s_nanosecondsInASecond)
11773 m_units = Unit::Milliseconds;
11774 else if (m_inNanoseconds < s_nanosecondsInAMinute)
11775 m_units = Unit::Seconds;
11777 m_units = Unit::Minutes;
11782 auto value()
const ->
double {
11784 case Unit::Microseconds:
11785 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMicrosecond);
11786 case Unit::Milliseconds:
11787 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMillisecond);
11788 case Unit::Seconds:
11789 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInASecond);
11790 case Unit::Minutes:
11791 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMinute);
11793 return static_cast<double>(m_inNanoseconds);
11796 auto unitsAsString()
const -> std::string {
11798 case Unit::Nanoseconds:
11800 case Unit::Microseconds:
11802 case Unit::Milliseconds:
11804 case Unit::Seconds:
11806 case Unit::Minutes:
11809 return "** internal error **";
11813 friend auto operator << (std::ostream& os, Duration
const& duration) -> std::ostream& {
11814 return os << duration.value() <<
" " << duration.unitsAsString();
11819 class TablePrinter {
11820 std::ostream& m_os;
11821 std::vector<ColumnInfo> m_columnInfos;
11822 std::ostringstream m_oss;
11823 int m_currentColumn = -1;
11824 bool m_isOpen =
false;
11827 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
11829 m_columnInfos( std::move( columnInfos ) ) {}
11831 auto columnInfos()
const -> std::vector<ColumnInfo>
const& {
11832 return m_columnInfos;
11838 *
this << RowBreak();
11839 for (
auto const& info : m_columnInfos)
11840 *
this << info.name << ColumnBreak();
11841 *
this << RowBreak();
11842 m_os << Catch::getLineOfChars<
'-'>() <<
"\n";
11847 *
this << RowBreak();
11853 template<
typename T>
11854 friend TablePrinter&
operator << (TablePrinter& tp, T
const& value) {
11859 friend TablePrinter&
operator << (TablePrinter& tp, ColumnBreak) {
11860 auto colStr = tp.m_oss.str();
11865 if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
11866 tp.m_currentColumn = -1;
11869 tp.m_currentColumn++;
11871 auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
11872 auto padding = (strSize + 2 <
static_cast<std::size_t
>(colInfo.width))
11873 ? std::string(colInfo.width - (strSize + 2),
' ')
11875 if (colInfo.justification == ColumnInfo::Left)
11876 tp.m_os << colStr << padding <<
" ";
11878 tp.m_os << padding << colStr <<
" ";
11882 friend TablePrinter&
operator << (TablePrinter& tp, RowBreak) {
11883 if (tp.m_currentColumn > 0) {
11885 tp.m_currentColumn = -1;
11891 ConsoleReporter::ConsoleReporter(ReporterConfig
const& config)
11892 : StreamingReporterBase(config),
11893 m_tablePrinter(
new TablePrinter(config.stream(),
11895 {
"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
11896 {
"iters", 8, ColumnInfo::Right },
11897 {
"elapsed ns", 14, ColumnInfo::Right },
11898 {
"average", 14, ColumnInfo::Right }
11900 ConsoleReporter::~ConsoleReporter() =
default;
11902 std::string ConsoleReporter::getDescription() {
11903 return "Reports test results as plain lines of text";
11906 void ConsoleReporter::noMatchingTestCases(std::string
const& spec) {
11907 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
11910 void ConsoleReporter::assertionStarting(
AssertionInfo const&) {}
11912 bool ConsoleReporter::assertionEnded(AssertionStats
const& _assertionStats) {
11913 AssertionResult
const& result = _assertionStats.assertionResult;
11915 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
11923 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
11925 stream << std::endl;
11929 void ConsoleReporter::sectionStarting(
SectionInfo const& _sectionInfo) {
11930 m_headerPrinted =
false;
11931 StreamingReporterBase::sectionStarting(_sectionInfo);
11933 void ConsoleReporter::sectionEnded(SectionStats
const& _sectionStats) {
11934 m_tablePrinter->close();
11935 if (_sectionStats.missingAssertions) {
11937 Colour colour(Colour::ResultError);
11938 if (m_sectionStack.size() > 1)
11939 stream <<
"\nNo assertions in section";
11941 stream <<
"\nNo assertions in test case";
11942 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" << std::endl;
11944 if (m_config->showDurations() == ShowDurations::Always) {
11945 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name << std::endl;
11947 if (m_headerPrinted) {
11948 m_headerPrinted =
false;
11950 StreamingReporterBase::sectionEnded(_sectionStats);
11953 void ConsoleReporter::benchmarkStarting(BenchmarkInfo
const& info) {
11954 lazyPrintWithoutClosingBenchmarkTable();
11956 auto nameCol = Column( info.name ).width( static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) );
11958 bool firstLine =
true;
11959 for (
auto line : nameCol) {
11961 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
11965 (*m_tablePrinter) << line << ColumnBreak();
11968 void ConsoleReporter::benchmarkEnded(BenchmarkStats
const& stats) {
11969 Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
11971 << stats.iterations << ColumnBreak()
11972 << stats.elapsedTimeInNanoseconds << ColumnBreak()
11973 << average << ColumnBreak();
11976 void ConsoleReporter::testCaseEnded(TestCaseStats
const& _testCaseStats) {
11977 m_tablePrinter->close();
11978 StreamingReporterBase::testCaseEnded(_testCaseStats);
11979 m_headerPrinted =
false;
11981 void ConsoleReporter::testGroupEnded(TestGroupStats
const& _testGroupStats) {
11982 if (currentGroupInfo.used) {
11983 printSummaryDivider();
11984 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
11985 printTotals(_testGroupStats.totals);
11986 stream <<
'\n' << std::endl;
11988 StreamingReporterBase::testGroupEnded(_testGroupStats);
11990 void ConsoleReporter::testRunEnded(TestRunStats
const& _testRunStats) {
11991 printTotalsDivider(_testRunStats.totals);
11992 printTotals(_testRunStats.totals);
11993 stream << std::endl;
11994 StreamingReporterBase::testRunEnded(_testRunStats);
11997 void ConsoleReporter::lazyPrint() {
11999 m_tablePrinter->close();
12000 lazyPrintWithoutClosingBenchmarkTable();
12003 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
12005 if (!currentTestRunInfo.used)
12006 lazyPrintRunInfo();
12007 if (!currentGroupInfo.used)
12008 lazyPrintGroupInfo();
12010 if (!m_headerPrinted) {
12011 printTestCaseAndSectionHeader();
12012 m_headerPrinted =
true;
12015 void ConsoleReporter::lazyPrintRunInfo() {
12016 stream << '\n' << getLineOfChars<'~'>() <<
'\n';
12017 Colour colour(Colour::SecondaryText);
12018 stream << currentTestRunInfo->name
12019 <<
" is a Catch v" << libraryVersion() <<
" host application.\n" 12020 <<
"Run with -? for options\n\n";
12022 if (m_config->rngSeed() != 0)
12023 stream <<
"Randomness seeded to: " << m_config->rngSeed() <<
"\n\n";
12025 currentTestRunInfo.used =
true;
12027 void ConsoleReporter::lazyPrintGroupInfo() {
12028 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
12029 printClosedHeader(
"Group: " + currentGroupInfo->name);
12030 currentGroupInfo.used =
true;
12033 void ConsoleReporter::printTestCaseAndSectionHeader() {
12034 assert(!m_sectionStack.empty());
12035 printOpenHeader(currentTestCaseInfo->name);
12037 if (m_sectionStack.size() > 1) {
12038 Colour colourGuard(Colour::Headers);
12041 it = m_sectionStack.begin() + 1,
12042 itEnd = m_sectionStack.end();
12043 for (; it != itEnd; ++it)
12044 printHeaderString(it->name, 2);
12049 if (!lineInfo.
empty()) {
12050 stream << getLineOfChars<
'-'>() <<
'\n';
12051 Colour colourGuard(Colour::FileName);
12052 stream << lineInfo <<
'\n';
12054 stream << getLineOfChars<
'.'>() <<
'\n' << std::endl;
12057 void ConsoleReporter::printClosedHeader(std::string
const& _name) {
12058 printOpenHeader(_name);
12059 stream << getLineOfChars<
'.'>() <<
'\n';
12061 void ConsoleReporter::printOpenHeader(std::string
const& _name) {
12062 stream << getLineOfChars<
'-'>() <<
'\n';
12064 Colour colourGuard(Colour::Headers);
12065 printHeaderString(_name);
12071 void ConsoleReporter::printHeaderString(std::string
const& _string, std::size_t indent) {
12072 std::size_t i = _string.find(
": ");
12073 if (i != std::string::npos)
12077 stream << Column(_string).indent(indent + i).initialIndent(indent) <<
'\n';
12080 struct SummaryColumn {
12082 SummaryColumn( std::string _label, Colour::Code _colour )
12083 : label( std::move( _label ) ),
12084 colour( _colour ) {}
12085 SummaryColumn addRow( std::size_t
count ) {
12088 std::string row = rss.
str();
12089 for (
auto& oldRow : rows) {
12090 while (oldRow.size() < row.size())
12091 oldRow =
' ' + oldRow;
12092 while (oldRow.size() > row.size())
12095 rows.push_back(row);
12100 Colour::Code colour;
12101 std::vector<std::string> rows;
12105 void ConsoleReporter::printTotals(
Totals const& totals ) {
12107 stream << Colour(Colour::Warning) <<
"No tests ran\n";
12109 stream << Colour(Colour::ResultSuccess) <<
"All tests passed";
12116 std::vector<SummaryColumn> columns;
12117 columns.push_back(SummaryColumn(
"", Colour::None)
12120 columns.push_back(SummaryColumn(
"passed", Colour::Success)
12123 columns.push_back(SummaryColumn(
"failed", Colour::ResultError)
12126 columns.push_back(SummaryColumn(
"failed as expected", Colour::ResultExpectedFailure)
12130 printSummaryRow(
"test cases", columns, 0);
12131 printSummaryRow(
"assertions", columns, 1);
12134 void ConsoleReporter::printSummaryRow(std::string
const& label, std::vector<SummaryColumn>
const& cols, std::size_t row) {
12135 for (
auto col : cols) {
12136 std::string value = col.rows[row];
12137 if (col.label.empty()) {
12138 stream << label <<
": ";
12142 stream << Colour(Colour::Warning) <<
"- none -";
12143 }
else if (value !=
"0") {
12144 stream << Colour(Colour::LightGrey) <<
" | ";
12145 stream << Colour(col.colour)
12146 << value <<
' ' << col.label;
12152 void ConsoleReporter::printTotalsDivider(
Totals const& totals) {
12157 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
12158 findMax(failedRatio, failedButOkRatio, passedRatio)++;
12159 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
12160 findMax(failedRatio, failedButOkRatio, passedRatio)--;
12162 stream << Colour(Colour::Error) << std::string(failedRatio,
'=');
12163 stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio,
'=');
12165 stream << Colour(Colour::ResultSuccess) << std::string(passedRatio,
'=');
12167 stream << Colour(Colour::Success) << std::string(passedRatio,
'=');
12169 stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1,
'=');
12173 void ConsoleReporter::printSummaryDivider() {
12174 stream << getLineOfChars<
'-'>() <<
'\n';
12177 CATCH_REGISTER_REPORTER(
"console", ConsoleReporter)
12181 #if defined(_MSC_VER) 12182 #pragma warning(pop) 12187 #include <assert.h> 12190 #include <algorithm> 12195 std::string getCurrentTimestamp() {
12199 std::time(&rawtime);
12200 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
12203 std::tm timeInfo = {};
12204 gmtime_s(&timeInfo, &rawtime);
12207 timeInfo = std::gmtime(&rawtime);
12210 char timeStamp[timeStampSize];
12211 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
12214 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
12216 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
12218 return std::string(timeStamp);
12221 std::string fileNameTag(
const std::vector<std::string> &tags) {
12222 auto it = std::find_if(
begin(tags),
12224 [] (std::string
const& tag) {
return tag.front() ==
'#'; });
12225 if (it != tags.end())
12226 return it->substr(1);
12227 return std::string();
12231 JunitReporter::JunitReporter( ReporterConfig
const& _config )
12232 : CumulativeReporterBase( _config ),
12233 xml( _config.stream() )
12235 m_reporterPrefs.shouldRedirectStdOut =
true;
12238 JunitReporter::~JunitReporter() {}
12240 std::string JunitReporter::getDescription() {
12241 return "Reports test results in an XML format that looks like Ant's junitreport target";
12244 void JunitReporter::noMatchingTestCases( std::string
const& ) {}
12246 void JunitReporter::testRunStarting( TestRunInfo
const& runInfo ) {
12247 CumulativeReporterBase::testRunStarting( runInfo );
12248 xml.startElement(
"testsuites" );
12251 void JunitReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
12252 suiteTimer.start();
12253 stdOutForSuite.clear();
12254 stdErrForSuite.clear();
12255 unexpectedExceptions = 0;
12256 CumulativeReporterBase::testGroupStarting( groupInfo );
12259 void JunitReporter::testCaseStarting(
TestCaseInfo const& testCaseInfo ) {
12260 m_okToFail = testCaseInfo.
okToFail();
12263 bool JunitReporter::assertionEnded( AssertionStats
const& assertionStats ) {
12265 unexpectedExceptions++;
12266 return CumulativeReporterBase::assertionEnded( assertionStats );
12269 void JunitReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
12270 stdOutForSuite += testCaseStats.stdOut;
12271 stdErrForSuite += testCaseStats.stdErr;
12272 CumulativeReporterBase::testCaseEnded( testCaseStats );
12275 void JunitReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
12276 double suiteTime = suiteTimer.getElapsedSeconds();
12277 CumulativeReporterBase::testGroupEnded( testGroupStats );
12278 writeGroup( *m_testGroups.back(), suiteTime );
12281 void JunitReporter::testRunEndedCumulative() {
12285 void JunitReporter::writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
12286 XmlWriter::ScopedElement e = xml.scopedElement(
"testsuite" );
12287 TestGroupStats
const& stats = groupNode.value;
12288 xml.writeAttribute(
"name", stats.groupInfo.name );
12289 xml.writeAttribute(
"errors", unexpectedExceptions );
12290 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
12291 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
12292 xml.writeAttribute(
"hostname",
"tbd" );
12293 if( m_config->showDurations() == ShowDurations::Never )
12294 xml.writeAttribute(
"time",
"" );
12296 xml.writeAttribute(
"time", suiteTime );
12297 xml.writeAttribute(
"timestamp", getCurrentTimestamp() );
12300 for(
auto const& child : groupNode.children )
12301 writeTestCase( *child );
12303 xml.scopedElement(
"system-out" ).writeText(
trim( stdOutForSuite ),
false );
12304 xml.scopedElement(
"system-err" ).writeText(
trim( stdErrForSuite ),
false );
12307 void JunitReporter::writeTestCase( TestCaseNode
const& testCaseNode ) {
12308 TestCaseStats
const& stats = testCaseNode.value;
12312 assert( testCaseNode.children.size() == 1 );
12313 SectionNode
const& rootSection = *testCaseNode.children.front();
12315 std::string className = stats.testInfo.className;
12317 if( className.empty() ) {
12318 className = fileNameTag(stats.testInfo.tags);
12319 if ( className.empty() )
12320 className =
"global";
12323 if ( !m_config->name().empty() )
12324 className = m_config->name() +
"." + className;
12326 writeSection( className,
"", rootSection );
12329 void JunitReporter::writeSection( std::string
const& className,
12330 std::string
const& rootName,
12331 SectionNode
const& sectionNode ) {
12332 std::string
name =
trim( sectionNode.stats.sectionInfo.name );
12333 if( !rootName.empty() )
12334 name = rootName +
'/' + name;
12336 if( !sectionNode.assertions.empty() ||
12337 !sectionNode.stdOut.empty() ||
12338 !sectionNode.stdErr.empty() ) {
12339 XmlWriter::ScopedElement e = xml.scopedElement(
"testcase" );
12340 if( className.empty() ) {
12341 xml.writeAttribute(
"classname", name );
12342 xml.writeAttribute(
"name",
"root" );
12345 xml.writeAttribute(
"classname", className );
12346 xml.writeAttribute(
"name", name );
12350 writeAssertions( sectionNode );
12352 if( !sectionNode.stdOut.empty() )
12353 xml.scopedElement(
"system-out" ).writeText(
trim( sectionNode.stdOut ),
false );
12354 if( !sectionNode.stdErr.empty() )
12355 xml.scopedElement(
"system-err" ).writeText(
trim( sectionNode.stdErr ),
false );
12357 for(
auto const& childNode : sectionNode.childSections )
12358 if( className.empty() )
12359 writeSection( name,
"", *childNode );
12361 writeSection( className, name, *childNode );
12364 void JunitReporter::writeAssertions( SectionNode
const& sectionNode ) {
12365 for(
auto const& assertion : sectionNode.assertions )
12366 writeAssertion( assertion );
12369 void JunitReporter::writeAssertion( AssertionStats
const& stats ) {
12370 AssertionResult
const& result = stats.assertionResult;
12371 if( !result.isOk() ) {
12372 std::string elementName;
12373 switch( result.getResultType() ) {
12376 elementName =
"error";
12379 elementName =
"failure";
12382 elementName =
"failure";
12385 elementName =
"failure";
12395 elementName =
"internalError";
12399 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
12401 xml.writeAttribute(
"message", result.getExpandedExpression() );
12402 xml.writeAttribute(
"type", result.getTestMacroName() );
12405 if( !result.getMessage().empty() )
12406 rss << result.getMessage() <<
'\n';
12407 for(
auto const& msg : stats.infoMessages )
12409 rss << msg.message <<
'\n';
12411 rss <<
"at " << result.getSourceInfo();
12412 xml.writeText( rss.
str(), false );
12416 CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
12424 void MultipleReporters::add( IStreamingReporterPtr&& reporter ) {
12425 m_reporters.push_back( std::move( reporter ) );
12428 ReporterPreferences MultipleReporters::getPreferences()
const {
12429 return m_reporters[0]->getPreferences();
12432 std::set<Verbosity> MultipleReporters::getSupportedVerbosities() {
12433 return std::set<Verbosity>{ };
12436 void MultipleReporters::noMatchingTestCases( std::string
const& spec ) {
12437 for(
auto const& reporter : m_reporters )
12438 reporter->noMatchingTestCases( spec );
12441 void MultipleReporters::benchmarkStarting( BenchmarkInfo
const& benchmarkInfo ) {
12442 for(
auto const& reporter : m_reporters )
12443 reporter->benchmarkStarting( benchmarkInfo );
12445 void MultipleReporters::benchmarkEnded( BenchmarkStats
const& benchmarkStats ) {
12446 for(
auto const& reporter : m_reporters )
12447 reporter->benchmarkEnded( benchmarkStats );
12450 void MultipleReporters::testRunStarting( TestRunInfo
const& testRunInfo ) {
12451 for(
auto const& reporter : m_reporters )
12452 reporter->testRunStarting( testRunInfo );
12455 void MultipleReporters::testGroupStarting( GroupInfo
const& groupInfo ) {
12456 for(
auto const& reporter : m_reporters )
12457 reporter->testGroupStarting( groupInfo );
12460 void MultipleReporters::testCaseStarting(
TestCaseInfo const& testInfo ) {
12461 for(
auto const& reporter : m_reporters )
12462 reporter->testCaseStarting( testInfo );
12465 void MultipleReporters::sectionStarting(
SectionInfo const& sectionInfo ) {
12466 for(
auto const& reporter : m_reporters )
12467 reporter->sectionStarting( sectionInfo );
12470 void MultipleReporters::assertionStarting(
AssertionInfo const& assertionInfo ) {
12471 for(
auto const& reporter : m_reporters )
12472 reporter->assertionStarting( assertionInfo );
12476 bool MultipleReporters::assertionEnded( AssertionStats
const& assertionStats ) {
12477 bool clearBuffer =
false;
12478 for(
auto const& reporter : m_reporters )
12479 clearBuffer |= reporter->assertionEnded( assertionStats );
12480 return clearBuffer;
12483 void MultipleReporters::sectionEnded( SectionStats
const& sectionStats ) {
12484 for(
auto const& reporter : m_reporters )
12485 reporter->sectionEnded( sectionStats );
12488 void MultipleReporters::testCaseEnded( TestCaseStats
const& testCaseStats ) {
12489 for(
auto const& reporter : m_reporters )
12490 reporter->testCaseEnded( testCaseStats );
12493 void MultipleReporters::testGroupEnded( TestGroupStats
const& testGroupStats ) {
12494 for(
auto const& reporter : m_reporters )
12495 reporter->testGroupEnded( testGroupStats );
12498 void MultipleReporters::testRunEnded( TestRunStats
const& testRunStats ) {
12499 for(
auto const& reporter : m_reporters )
12500 reporter->testRunEnded( testRunStats );
12503 void MultipleReporters::skipTest(
TestCaseInfo const& testInfo ) {
12504 for(
auto const& reporter : m_reporters )
12505 reporter->skipTest( testInfo );
12508 bool MultipleReporters::isMulti()
const {
12516 #if defined(_MSC_VER) 12517 #pragma warning(push) 12518 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 12524 XmlReporter::XmlReporter( ReporterConfig
const& _config )
12525 : StreamingReporterBase( _config ),
12526 m_xml(_config.stream())
12528 m_reporterPrefs.shouldRedirectStdOut =
true;
12531 XmlReporter::~XmlReporter() =
default;
12533 std::string XmlReporter::getDescription() {
12534 return "Reports test results as an XML document";
12537 std::string XmlReporter::getStylesheetRef()
const {
12538 return std::string();
12541 void XmlReporter::writeSourceInfo(
SourceLineInfo const& sourceInfo ) {
12543 .writeAttribute(
"filename", sourceInfo.
file )
12544 .writeAttribute(
"line", sourceInfo.
line );
12547 void XmlReporter::noMatchingTestCases( std::string
const& s ) {
12548 StreamingReporterBase::noMatchingTestCases( s );
12551 void XmlReporter::testRunStarting( TestRunInfo
const& testInfo ) {
12552 StreamingReporterBase::testRunStarting( testInfo );
12553 std::string stylesheetRef = getStylesheetRef();
12554 if( !stylesheetRef.empty() )
12555 m_xml.writeStylesheetRef( stylesheetRef );
12556 m_xml.startElement(
"Catch" );
12557 if( !m_config->name().empty() )
12558 m_xml.writeAttribute(
"name", m_config->name() );
12561 void XmlReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
12562 StreamingReporterBase::testGroupStarting( groupInfo );
12563 m_xml.startElement(
"Group" )
12564 .writeAttribute(
"name", groupInfo.name );
12567 void XmlReporter::testCaseStarting(
TestCaseInfo const& testInfo ) {
12568 StreamingReporterBase::testCaseStarting(testInfo);
12569 m_xml.startElement(
"TestCase" )
12570 .writeAttribute(
"name",
trim( testInfo.
name ) )
12571 .writeAttribute(
"description", testInfo.
description )
12574 writeSourceInfo( testInfo.
lineInfo );
12576 if ( m_config->showDurations() == ShowDurations::Always )
12577 m_testCaseTimer.start();
12578 m_xml.ensureTagClosed();
12581 void XmlReporter::sectionStarting(
SectionInfo const& sectionInfo ) {
12582 StreamingReporterBase::sectionStarting( sectionInfo );
12583 if( m_sectionDepth++ > 0 ) {
12584 m_xml.startElement(
"Section" )
12585 .writeAttribute(
"name",
trim( sectionInfo.
name ) )
12586 .writeAttribute(
"description", sectionInfo.
description );
12587 writeSourceInfo( sectionInfo.
lineInfo );
12588 m_xml.ensureTagClosed();
12592 void XmlReporter::assertionStarting(
AssertionInfo const& ) { }
12594 bool XmlReporter::assertionEnded( AssertionStats
const& assertionStats ) {
12596 AssertionResult
const& result = assertionStats.assertionResult;
12598 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
12602 for(
auto const& msg : assertionStats.infoMessages ) {
12604 m_xml.scopedElement(
"Info" )
12605 .writeText( msg.message );
12607 m_xml.scopedElement(
"Warning" )
12608 .writeText( msg.message );
12618 if( result.hasExpression() ) {
12619 m_xml.startElement(
"Expression" )
12620 .writeAttribute(
"success", result.succeeded() )
12621 .writeAttribute(
"type", result.getTestMacroName() );
12623 writeSourceInfo( result.getSourceInfo() );
12625 m_xml.scopedElement(
"Original" )
12626 .writeText( result.getExpression() );
12627 m_xml.scopedElement(
"Expanded" )
12628 .writeText( result.getExpandedExpression() );
12632 switch( result.getResultType() ) {
12634 m_xml.startElement(
"Exception" );
12635 writeSourceInfo( result.getSourceInfo() );
12636 m_xml.writeText( result.getMessage() );
12637 m_xml.endElement();
12640 m_xml.startElement(
"FatalErrorCondition" );
12641 writeSourceInfo( result.getSourceInfo() );
12642 m_xml.writeText( result.getMessage() );
12643 m_xml.endElement();
12646 m_xml.scopedElement(
"Info" )
12647 .writeText( result.getMessage() );
12653 m_xml.startElement(
"Failure" );
12654 writeSourceInfo( result.getSourceInfo() );
12655 m_xml.writeText( result.getMessage() );
12656 m_xml.endElement();
12662 if( result.hasExpression() )
12663 m_xml.endElement();
12668 void XmlReporter::sectionEnded( SectionStats
const& sectionStats ) {
12669 StreamingReporterBase::sectionEnded( sectionStats );
12670 if( --m_sectionDepth > 0 ) {
12671 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResults" );
12672 e.writeAttribute(
"successes", sectionStats.assertions.passed );
12673 e.writeAttribute(
"failures", sectionStats.assertions.failed );
12674 e.writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
12676 if ( m_config->showDurations() == ShowDurations::Always )
12677 e.writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
12679 m_xml.endElement();
12683 void XmlReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
12684 StreamingReporterBase::testCaseEnded( testCaseStats );
12685 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResult" );
12686 e.writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
12688 if ( m_config->showDurations() == ShowDurations::Always )
12689 e.writeAttribute(
"durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
12691 if( !testCaseStats.stdOut.empty() )
12692 m_xml.scopedElement(
"StdOut" ).writeText(
trim( testCaseStats.stdOut ),
false );
12693 if( !testCaseStats.stdErr.empty() )
12694 m_xml.scopedElement(
"StdErr" ).writeText(
trim( testCaseStats.stdErr ),
false );
12696 m_xml.endElement();
12699 void XmlReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
12700 StreamingReporterBase::testGroupEnded( testGroupStats );
12702 m_xml.scopedElement(
"OverallResults" )
12703 .writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
12704 .writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
12705 .writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
12706 m_xml.endElement();
12709 void XmlReporter::testRunEnded( TestRunStats
const& testRunStats ) {
12710 StreamingReporterBase::testRunEnded( testRunStats );
12711 m_xml.scopedElement(
"OverallResults" )
12712 .writeAttribute(
"successes", testRunStats.totals.assertions.passed )
12713 .writeAttribute(
"failures", testRunStats.totals.assertions.failed )
12714 .writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
12715 m_xml.endElement();
12718 CATCH_REGISTER_REPORTER(
"xml", XmlReporter )
12722 #if defined(_MSC_VER) 12723 #pragma warning(pop) 12728 LeakDetector leakDetector;
12732 #pragma clang diagnostic pop 12738 #ifdef CATCH_CONFIG_MAIN 12743 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) 12745 extern "C" int wmain (
int argc,
wchar_t * argv[],
wchar_t * []) {
12748 int main (
int argc,
char * argv[]) {
12751 return Catch::Session().run( argc, argv );
12757 int main (
int argc,
char *
const argv[]) {
12758 #if !CATCH_ARC_ENABLED 12759 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
12762 Catch::registerTestMethods();
12763 int result = Catch::Session().run( argc, (
char**)argv );
12765 #if !CATCH_ARC_ENABLED 12777 #if !defined(CATCH_CONFIG_IMPL_ONLY) 12779 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED 12780 # undef CLARA_CONFIG_MAIN 12783 #if !defined(CATCH_CONFIG_DISABLE) 12786 #ifdef CATCH_CONFIG_PREFIX_ALL 12788 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 12789 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 12791 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) 12792 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 12793 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 12794 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12795 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 12796 #endif// CATCH_CONFIG_DISABLE_MATCHERS 12797 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 12799 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12800 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 12801 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12802 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12803 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 12805 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) 12806 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 12807 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 12808 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12809 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 12810 #endif // CATCH_CONFIG_DISABLE_MATCHERS 12811 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12813 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12814 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 12816 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 12817 #endif // CATCH_CONFIG_DISABLE_MATCHERS 12819 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 12820 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 12821 #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) 12823 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 12824 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 12825 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 12826 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 12827 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 12828 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 12829 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12830 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12832 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 12835 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 12836 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 12837 #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc ) 12838 #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc ) 12839 #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) 12840 #define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc ) 12841 #define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) 12846 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 12847 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 12849 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 12850 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 12851 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 12852 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12853 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 12854 #endif // CATCH_CONFIG_DISABLE_MATCHERS 12855 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 12857 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12858 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 12859 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12860 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12861 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 12863 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12864 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 12865 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 12866 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12867 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 12868 #endif // CATCH_CONFIG_DISABLE_MATCHERS 12869 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12871 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12872 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 12874 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 12875 #endif // CATCH_CONFIG_DISABLE_MATCHERS 12877 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 12878 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 12879 #define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) 12881 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 12882 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 12883 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 12884 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 12885 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 12886 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 12887 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12888 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 12889 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 12893 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 12896 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 12897 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 12899 #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc ) 12900 #define WHEN( desc ) SECTION( std::string(" When: ") + desc ) 12901 #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc ) 12902 #define THEN( desc ) SECTION( std::string(" Then: ") + desc ) 12903 #define AND_THEN( desc ) SECTION( std::string(" And: ") + desc ) 12910 #ifdef CATCH_CONFIG_PREFIX_ALL 12912 #define CATCH_REQUIRE( ... ) (void)(0) 12913 #define CATCH_REQUIRE_FALSE( ... ) (void)(0) 12915 #define CATCH_REQUIRE_THROWS( ... ) (void)(0) 12916 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 12917 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 12918 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12919 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 12920 #endif// CATCH_CONFIG_DISABLE_MATCHERS 12921 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) 12923 #define CATCH_CHECK( ... ) (void)(0) 12924 #define CATCH_CHECK_FALSE( ... ) (void)(0) 12925 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) 12926 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 12927 #define CATCH_CHECK_NOFAIL( ... ) (void)(0) 12929 #define CATCH_CHECK_THROWS( ... ) (void)(0) 12930 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 12931 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) 12932 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12933 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 12934 #endif // CATCH_CONFIG_DISABLE_MATCHERS 12935 #define CATCH_CHECK_NOTHROW( ... ) (void)(0) 12937 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12938 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0) 12940 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) 12941 #endif // CATCH_CONFIG_DISABLE_MATCHERS 12943 #define CATCH_INFO( msg ) (void)(0) 12944 #define CATCH_WARN( msg ) (void)(0) 12945 #define CATCH_CAPTURE( msg ) (void)(0) 12947 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 12948 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 12949 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) 12950 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) 12951 #define CATCH_SECTION( ... ) 12952 #define CATCH_FAIL( ... ) (void)(0) 12953 #define CATCH_FAIL_CHECK( ... ) (void)(0) 12954 #define CATCH_SUCCEED( ... ) (void)(0) 12956 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 12959 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 12960 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) 12961 #define CATCH_GIVEN( desc ) 12962 #define CATCH_WHEN( desc ) 12963 #define CATCH_AND_WHEN( desc ) 12964 #define CATCH_THEN( desc ) 12965 #define CATCH_AND_THEN( desc ) 12970 #define REQUIRE( ... ) (void)(0) 12971 #define REQUIRE_FALSE( ... ) (void)(0) 12973 #define REQUIRE_THROWS( ... ) (void)(0) 12974 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 12975 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 12976 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12977 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 12978 #endif // CATCH_CONFIG_DISABLE_MATCHERS 12979 #define REQUIRE_NOTHROW( ... ) (void)(0) 12981 #define CHECK( ... ) (void)(0) 12982 #define CHECK_FALSE( ... ) (void)(0) 12983 #define CHECKED_IF( ... ) if (__VA_ARGS__) 12984 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 12985 #define CHECK_NOFAIL( ... ) (void)(0) 12987 #define CHECK_THROWS( ... ) (void)(0) 12988 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 12989 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0) 12990 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12991 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 12992 #endif // CATCH_CONFIG_DISABLE_MATCHERS 12993 #define CHECK_NOTHROW( ... ) (void)(0) 12995 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 12996 #define CHECK_THAT( arg, matcher ) (void)(0) 12998 #define REQUIRE_THAT( arg, matcher ) (void)(0) 12999 #endif // CATCH_CONFIG_DISABLE_MATCHERS 13001 #define INFO( msg ) (void)(0) 13002 #define WARN( msg ) (void)(0) 13003 #define CAPTURE( msg ) (void)(0) 13005 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 13006 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 13007 #define METHOD_AS_TEST_CASE( method, ... ) 13008 #define REGISTER_TEST_CASE( Function, ... ) (void)(0) 13009 #define SECTION( ... ) 13010 #define FAIL( ... ) (void)(0) 13011 #define FAIL_CHECK( ... ) (void)(0) 13012 #define SUCCEED( ... ) (void)(0) 13013 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 13017 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 13020 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) 13021 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) 13023 #define GIVEN( desc ) 13024 #define WHEN( desc ) 13025 #define AND_WHEN( desc ) 13026 #define THEN( desc ) 13027 #define AND_THEN( desc ) 13033 #endif // ! CATCH_CONFIG_IMPL_ONLY 13039 # ifdef __ICC // icpc defines the __clang__ macro 13040 # pragma warning(pop) 13042 # pragma clang diagnostic pop 13044 #elif defined __GNUC__ 13045 # pragma GCC diagnostic pop 13050 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED EqualsMatcher(std::vector< T > const &comparator)
Definition: catch.hpp:2599
Definition: catch.hpp:2235
static std::string convert(T const (&arr)[SZ])
Definition: catch.hpp:1152
Definition: catch.hpp:258
Definition: catch.hpp:1335
std::string macroName
Definition: catch.hpp:1596
Definition: catch.hpp:2481
Definition: catch.hpp:593
void handleExpression(ITransientExpression const &expr)
bool matchTest(TestCase const &testCase, TestSpec const &testSpec, IConfig const &config)
virtual void benchmarkEnded(BenchmarkStats const &stats)=0
SourceLineInfo lineInfo
Definition: catch.hpp:1598
std::size_t m_count
Definition: catch.hpp:2199
auto getResult() const -> bool
Definition: catch.hpp:1295
unsigned int sequence
Definition: catch.hpp:1600
Totals & operator+=(Totals const &other)
std::vector< MatcherBase< ArgT > const * > m_matchers
Definition: catch.hpp:2281
std::string rawMemoryToString(const T &object)
Definition: catch.hpp:752
MessageInfo m_info
Definition: catch.hpp:1630
bool isFalseTest(int flags)
Definition: catch.hpp:612
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
Definition: catch.hpp:2037
TestCase(ITestInvoker *testCase, TestCaseInfo &&info)
bool match(std::vector< T > const &v) const override
Definition: catch.hpp:2550
Counts testCases
Definition: catch.hpp:1808
auto empty() const noexcept-> bool
Definition: catch.hpp:446
bool operator<(TestCase const &other) const
Counts assertions
Definition: catch.hpp:1807
static std::enable_if<!::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
Definition: catch.hpp:815
virtual void registerTest(TestCase const &testInfo)=0
Definition: catch.hpp:620
Definition: catch.hpp:583
std::string toString() const
auto operator[](size_type index) const noexcept-> char
void toLowerInPlace(std::string &s)
virtual StartupExceptionRegistry const & getStartupExceptionRegistry() const =0
void handleMessage(ResultWas::OfType resultType, StringRef const &message)
std::string name
Definition: catch.hpp:2800
void handleExceptionNotThrownAsExpected()
LazyExpression(bool isNegated)
auto c_str() const -> char const *
ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
TestCase makeTestCase(ITestInvoker *testCase, std::string const &className, NameAndTags const &nameAndTags, SourceLineInfo const &lineInfo)
Definition: catch.hpp:1519
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
virtual void registerTagAlias(std::string const &alias, std::string const &tag, SourceLineInfo const &lineInfo)=0
bool contains(std::string const &s, std::string const &infix)
StringRef(char const *rawChars, size_type size) noexcept
Definition: catch.hpp:413
bool match(T const &item) const override
Definition: catch.hpp:2422
void handleExceptionMatchExpr(AssertionHandler &handler, std::string const &str, StringRef matcherString)
CaseSensitive::Choice m_caseSensitivity
Definition: catch.hpp:2461
Definition: catch.hpp:1514
Definition: catch.hpp:256
int error
Definition: catch.hpp:1806
PredicateMatcher(std::function< bool(T const &)> const &elem, std::string const &descr)
Definition: catch.hpp:2417
auto makeUnaryExpr() const -> UnaryExpr< LhsT >
Definition: catch.hpp:1411
Definition: catch.hpp:1315
bool expectedToFail() const
Definition: catch.hpp:1966
virtual void registerReporter(std::string const &name, IReporterFactoryPtr const &factory)=0
auto compareNotEqual(LhsT const &lhs, RhsT &&rhs) -> bool
Definition: catch.hpp:1362
auto getCurrentNanosecondsSinceEpoch() -> uint64_t
T const & operator+(T const &value, StreamEndStop)
Definition: catch.hpp:303
auto getEstimatedClockResolution() -> uint64_t
Definition: catch.hpp:1608
SpecialProperties properties
Definition: catch.hpp:2806
bool match(ArgT const &arg) const override
Definition: catch.hpp:2253
Definition: catch.hpp:314
std::size_t failedButOk
Definition: catch.hpp:1796
bool shouldDebugBreak
Definition: catch.hpp:1537
ContainsMatcher(std::vector< T > const &comparator)
Definition: catch.hpp:2569
TestInvokerAsMethod(void(C::*testAsMethod)()) noexcept
Definition: catch.hpp:488
Definition: catch.hpp:2776
bool match(std::vector< T > const &vec) const override
Definition: catch.hpp:2622
SourceLineInfo(char const *_file, std::size_t _line) noexcept
Definition: catch.hpp:275
Definition: catch.hpp:1541
virtual void popScopedMessage(MessageInfo const &message)=0
Definition: catch.hpp:802
typedef HANDLE(WINAPI *PFNWGLCREATEBUFFERREGIONARBPROC)(HDC hDC
IResultCapture & getResultCapture()
std::string tagsAsString() const
Approx & epsilon(T const &newEpsilon)
Definition: catch.hpp:2127
Definition: catch.hpp:2546
std::shared_ptr< ITestInvoker > ITestCasePtr
Definition: catch.hpp:342
std::vector< std::string > lcaseTags
Definition: catch.hpp:2804
Definition: catch.hpp:591
std::enable_if<!std::is_enum< T >::value, std::string >::type convertUnstreamable(T const &value)
Definition: catch.hpp:773
Definition: catch.hpp:2780
StdString::RegexMatcher Matches(std::string const ®ex, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
int int int width
Definition: wglext.h:61
double durationInSeconds
Definition: catch.hpp:1833
bool replaceInPlace(std::string &str, std::string const &replaceThis, std::string const &withThis)
Definition: catch.hpp:1459
Definition: catch.hpp:2412
StringRef(StringRef const &other) noexcept
Definition: catch.hpp:398
virtual std::vector< TestCase > const & getAllTestsSorted(IConfig const &config) const =0
bool shouldThrow
Definition: catch.hpp:1538
std::string finalizeDescription(const std::string &desc)
bool operator==(SourceLineInfo const &other) const noexcept
Definition: catch.hpp:2219
Approx operator()(T const &value)
Definition: catch.hpp:2073
SectionInfo sectionInfo
Definition: catch.hpp:1831
Definition: catch.hpp:377
Definition: catch.hpp:601
Flags
Definition: catch.hpp:601
UnaryExpr(LhsT lhs)
Definition: catch.hpp:1343
std::vector< std::unique_ptr< IExceptionTranslator const >> ExceptionTranslators
Definition: catch.hpp:1997
StringRef(std::string const &stdString) noexcept
Definition: catch.hpp:418
Definition: catch.hpp:585
Definition: catch.hpp:509
std::vector< std::string > tags
Definition: catch.hpp:2803
ExprLhs(LhsT lhs)
Definition: catch.hpp:1376
static std::string convert(signed char const *str)
Definition: catch.hpp:886
IMutableRegistryHub & getMutableRegistryHub()
Counts & operator+=(Counts const &other)
std::string(*)( exceptionTranslateFunction)
Definition: catch.hpp:1994
Vector::ContainsMatcher< T > Contains(std::vector< T > const &comparator)
Definition: catch.hpp:2665
void formatReconstructedExpression(std::ostream &os, std::string const &lhs, StringRef op, std::string const &rhs)
bool empty() const noexcept
Definition: catch.hpp:2004
ITransientExpression(bool isBinaryExpression, bool result)
Definition: catch.hpp:1298
ScopedMessage(MessageBuilder const &builder)
std::string stringify(const T &e)
Definition: catch.hpp:825
auto makeMatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef matcherString) -> MatchExpr< ArgT, MatcherT >
Definition: catch.hpp:2718
Definition: catch.hpp:2218
StdString::EqualsMatcher Equals(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
std::vector< T > const & m_comparator
Definition: catch.hpp:2593
Definition: catch.hpp:2782
bool operator==(TestCase const &other) const
static std::string convert(U *p)
Definition: catch.hpp:957
virtual void registerStartupException() noexcept=0
Definition: catch.hpp:1848
virtual void pushScopedMessage(MessageInfo const &message)=0
virtual ~ITestCaseRegistry()
Definition: catch.hpp:1536
Definition: catch.hpp:485
auto getElapsedSeconds() const -> double
auto operator+(char const *lhs, StringRef const &rhs) -> std::string
std::string describe() const override
Definition: catch.hpp:2589
ResultDisposition::Flags resultDisposition
Definition: catch.hpp:625
std::vector< TestCase > const & getAllTestCasesSorted(IConfig const &config)
Definition: catch.hpp:2473
typedef void(WINAPI *PFNWGLFREEMEMORYNVPROC)(void *pointer)
IRegistryHub & getRegistryHub()
std::string m_operation
Definition: catch.hpp:2470
bool shouldContinueOnFailure(int flags)
Definition: catch.hpp:578
int GLenum UINT size
Definition: wglext.h:321
auto str() const -> std::string
void Init(sf::RenderWindow &window, bool loadDefaultFont)
Definition: imgui-SFML.cpp:171
std::string operator+() const
bool isJustInfo(int flags)
Definition: catch.hpp:299
AutoReg(ITestInvoker *invoker, SourceLineInfo const &lineInfo, StringRef const &classOrMethod, NameAndTags const &nameAndTags) noexcept
Definition: catch.hpp:257
Definition: catch.hpp:1828
static std::string convert(R const &range)
Definition: catch.hpp:1145
std::vector< TestCase > filterTests(std::vector< TestCase > const &testCases, TestSpec const &testSpec, IConfig const &config)
Definition: catch.hpp:2217
Approx(T const &value)
Definition: catch.hpp:2082
std::string description
Definition: catch.hpp:1824
void handleUnexpectedInflightException()
Floating::WithinAbsMatcher WithinAbs(double target, double margin)
Approx & scale(T const &newScale)
Definition: catch.hpp:2154
Definition: catch.hpp:581
Totals delta(Totals const &prevTotals) const
Definition: catch.hpp:580
static std::string convert(R C::*p)
Definition: catch.hpp:968
Definition: catch.hpp:1373
Definition: catch.hpp:347
std::size_t failed
Definition: catch.hpp:1795
BinaryExpr(bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs)
Definition: catch.hpp:1326
auto operator!=(StringRef const &other) const noexcept-> bool
Definition: catch.hpp:1799
StringRef capturedExpression
Definition: catch.hpp:624
Definition: catch.hpp:2485
Definition: catch.hpp:2781
bool shouldSuppressFailure(int flags)
std::shared_ptr< IReporterFactory > IReporterFactoryPtr
Definition: catch.hpp:1952
StdString::EndsWithMatcher EndsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
std::string describe() const override
Definition: catch.hpp:2426
MatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef matcherString)
Definition: catch.hpp:2696
Definition: catch.hpp:2376
UnorderedEqualsMatcher(std::vector< T > const &target)
Definition: catch.hpp:2621
Definition: catch.hpp:2777
virtual ~IExceptionTranslatorRegistry()
auto makeTestInvoker(void(*testAsFunction)()) noexcept-> ITestInvoker *
bool isOk(ResultWas::OfType resultType)
ResultWas::OfType type
Definition: catch.hpp:1599
virtual void registerTranslator(const IExceptionTranslator *translator)=0
void increment()
Definition: catch.hpp:1920
ReusableStringStream m_stream
Definition: catch.hpp:1616
Definition: catch.hpp:2779
virtual ~ITransientExpression()
Definition: catch.hpp:586
SourceLineInfo lineInfo
Definition: catch.hpp:2805
Definition: catch.hpp:2778
int GLenum UINT void * data
Definition: wglext.h:321
bool operator<(SourceLineInfo const &other) const noexcept
auto size() const noexcept-> size_type
Definition: catch.hpp:449
void handleThrowingCallSkipped()
void handleExceptionThrownAsExpected()
Definition: catch.hpp:1954
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff)
Definition: catch.hpp:272
MessageInfo(std::string const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
virtual std::string translateActiveException() const =0
auto needsMoreIterations() -> bool
std::string className
Definition: catch.hpp:2801
std::string m_label
Definition: catch.hpp:2200
Definition: catch.hpp:2597
Definition: catch.hpp:602
std::string trim(std::string const &str)
bool endsWith(std::string const &s, std::string const &suffix)
#define CATCH_INTERNAL_LINEINFO
Definition: catch.hpp:308
Definition: catch.hpp:657
static std::string convert(char const *str)
Definition: catch.hpp:880
Definition: catch.hpp:2465
StringRef macroName
Definition: catch.hpp:622
std::string describe() const override
Definition: catch.hpp:2652
Definition: catch.hpp:1999
std::string toLower(std::string const &s)
~AssertionHandler()
Definition: catch.hpp:1553
Definition: catch.hpp:261
char const * file
Definition: catch.hpp:289
SpecialProperties
Definition: catch.hpp:2775
void Value(const char *prefix, bool b)
Definition: imgui.cpp:13087
std::string translateActiveException()
virtual void benchmarkStarting(BenchmarkInfo const &info)=0
MessageBuilder(std::string const ¯oName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
Definition: catch.hpp:664
Vector::EqualsMatcher< T > Equals(std::vector< T > const &comparator)
Definition: catch.hpp:2675
virtual void streamReconstructedExpression(std::ostream &os) const =0
TestCase withName(std::string const &_newName) const
std::string describe() const override
Definition: catch.hpp:2613
ContainsElementMatcher(T const &comparator)
Definition: catch.hpp:2548
Definition: catch.hpp:1865
virtual ITestCaseRegistry const & getTestCaseRegistry() const =0
void handleExpr(ExprLhs< T > const &expr)
Definition: catch.hpp:1560
Definition: catch.hpp:590
bool match(ArgT const &arg) const override
Definition: catch.hpp:2322
std::string name
Definition: catch.hpp:1823
Definition: catch.hpp:1895
std::size_t total() const
Definition: catch.hpp:2842
Definition: catch.hpp:2244
StringRef(StringRef &&other) noexcept
Definition: catch.hpp:403
Definition: catch.hpp:2455
bool match(ArgT const &arg) const override
Definition: catch.hpp:2286
auto operator+=(std::string &lhs, StringRef const &sr) -> std::string &
RegistrarForTagAliases(char const *alias, char const *tag, SourceLineInfo const &lineInfo)
int x
Definition: wglext.h:61
std::string m_str
Definition: catch.hpp:2462
BenchmarkLooper(StringRef name)
Definition: catch.hpp:1906
virtual ~IMutableRegistryHub()
Definition: catch.hpp:605
void GLuint GLenum type
Definition: wglext.h:636
AssertionHandler(StringRef macroName, SourceLineInfo const &lineInfo, StringRef capturedExpression, ResultDisposition::Flags resultDisposition)
Definition: catch.hpp:2691
Definition: catch.hpp:577
StringRef() noexcept
Definition: catch.hpp:394
Definition: catch.hpp:2567
auto getElapsedNanoseconds() const -> uint64_t
virtual void registerListener(IReporterFactoryPtr const &factory)=0
void streamReconstructedExpression(std::ostream &os) const override
Definition: catch.hpp:2703
TestCaseInfo const & getTestCaseInfo() const
auto getElapsedMicroseconds() const -> uint64_t
SourceLineInfo lineInfo
Definition: catch.hpp:623
const std::string unprintableString
Definition: catch.hpp:2774
SectionEndInfo(SectionInfo const &_sectionInfo, Counts const &_prevAssertions, double _durationInSeconds)
static std::enable_if<::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
Definition: catch.hpp:806
GLint GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: wglext.h:328
virtual void handleIncomplete(AssertionInfo const &info)=0
std::string rangeToString(std::vector< bool, Allocator > const &v)
Definition: catch.hpp:1128
auto isBinaryExpression() const -> bool
Definition: catch.hpp:1294
Definition: catch.hpp:337
std::string m_cachedToString
Definition: catch.hpp:2231
Section(SectionInfo const &info)
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name, std::string const &_description=std::string())
auto substr(size_type start, size_type size) const noexcept-> StringRef
Definition: catch.hpp:2221
virtual IReporterRegistry const & getReporterRegistry() const =0
Definition: catch.hpp:1293
Definition: catch.hpp:2490
Definition: catch.hpp:1098
std::vector< MatcherBase< ArgT > const * > m_matchers
Definition: catch.hpp:2314
Counts prevAssertions
Definition: catch.hpp:1832
auto operator==(StringRef const &other) const noexcept-> bool
Definition: catch.hpp:2809
Definition: catch.hpp:2620
MessageInfo m_info
Definition: catch.hpp:1638
Mode
Definition: main.cpp:109
std::size_t passed
Definition: catch.hpp:1794
StdString::StartsWithMatcher StartsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
std::size_t line
Definition: catch.hpp:290
Approx & margin(T const &newMargin)
Definition: catch.hpp:2140
std::string convertUnknownEnumToString(E e)
Definition: catch.hpp:830
Definition: catch.hpp:606
bool operator==(MessageInfo const &other) const
std::string describe() const override
Definition: catch.hpp:2293
std::string describe() const override
Definition: catch.hpp:2559
Definition: catch.hpp:1817
auto numberOfCharacters() const noexcept-> size_type
bool operator<(MessageInfo const &other) const
virtual void sectionEnded(SectionEndInfo const &endInfo)=0
Definition: catch.hpp:1591
Definition: catch.hpp:1108
Totals operator-(Totals const &other) const
MatcherBase< ArgT > const & m_underlyingMatcher
Definition: catch.hpp:2329
bool match(std::vector< T > const &v) const override
Definition: catch.hpp:2571
std::vector< T > const & m_comparator
Definition: catch.hpp:2616
Definition: catch.hpp:2063
Definition: catch.hpp:2194
Counts operator-(Counts const &other) const
void swap(StringRef &other) noexcept
bool contains(InputIterator first, InputIterator last, T const &item)
Definition: catch.hpp:2535
Vector::UnorderedEqualsMatcher< T > UnorderedEquals(std::vector< T > const &target)
Definition: catch.hpp:2680
virtual ~IExceptionTranslator()
std::size_t size_type
Definition: catch.hpp:379
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
Definition: catch.hpp:2438
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry()=0
void handleUnexpectedExceptionNotThrown()
Definition: catch.hpp:1619
Definition: catch.hpp:757
std::string description
Definition: catch.hpp:2802
auto compareEqual(LhsT const &lhs, RhsT const &rhs) -> bool
Definition: catch.hpp:1351
Definition: catch.hpp:2477
SourceLineInfo lineInfo
Definition: catch.hpp:1825
int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
Definition: main.cpp:458
T const & m_comparator
Definition: catch.hpp:2563
MatchNotOf(MatcherBase< ArgT > const &underlyingMatcher)
Definition: catch.hpp:2320
virtual void sectionEndedEarly(SectionEndInfo const &endInfo)=0
std::string message
Definition: catch.hpp:1597
std::string describe() const override
Definition: catch.hpp:2326
Definition: catch.hpp:738
Choice
Definition: catch.hpp:256
Definition: catch.hpp:2367
virtual ~IResultCapture()
OfType
Definition: catch.hpp:577
void GLuint name
Definition: wglext.h:636
CasedString m_comparator
Definition: catch.hpp:2469
std::string describe() const override
Definition: catch.hpp:2260
bool match(std::vector< T > const &v) const override
Definition: catch.hpp:2601
void Columns(int count=1, const char *id=NULL, bool border=true)
Definition: imgui.cpp:13012
std::string rangeToString(Range const &range)
Definition: catch.hpp:1122
void invoke() const override
Definition: catch.hpp:490
bool m_result
Definition: catch.hpp:1308
auto makeStream(StringRef const &filename) -> IStream const *
static std::string convert(unsigned char const *str)
Definition: catch.hpp:892
Definition: catch.hpp:1423
Definition: catch.hpp:2010
auto currentData() const noexcept-> char const *
auto allowThrows() const -> bool
TestCaseInfo(std::string const &_name, std::string const &_className, std::string const &_description, std::vector< std::string > const &_tags, SourceLineInfo const &_lineInfo)
Definition: catch.hpp:1786
virtual ITagAliasRegistry const & getTagAliasRegistry() const =0
Definition: catch.hpp:604
const HANDLE const LPVOID const DWORD UINT count
Definition: wglext.h:590
std::enable_if< std::is_enum< T >::value, std::string >::type convertUnstreamable(T const &value)
Definition: catch.hpp:782
~StringRef() noexcept
Definition: catch.hpp:423
pluralise(std::size_t count, std::string const &label)
bool m_isBinaryExpression
Definition: catch.hpp:1307
auto get() -> std::ostream &
Definition: catch.hpp:678
Definition: catch.hpp:588
Definition: catch.hpp:1633
Definition: catch.hpp:579
bool startsWith(std::string const &s, std::string const &prefix)
Vector::ContainsElementMatcher< T > VectorContains(T const &comparator)
Definition: catch.hpp:2670
auto getElapsedMilliseconds() const -> unsigned int