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
23# pragma GCC system_header
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"
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
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__ )
264 NonCopyable& operator = ( NonCopyable
const& ) =
delete;
265 NonCopyable& operator = ( NonCopyable && ) =
delete;
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
354 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config );
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;
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;
446 auto empty() const noexcept ->
bool {
464 auto isOwned() const noexcept ->
bool;
465 auto isSubstring() const noexcept ->
bool;
469 auto operator + (
StringRef const& lhs,
char const* rhs ) ->
std::
string;
470 auto operator + (
char const* lhs,
StringRef const& rhs ) ->
std::
string;
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
641#include <type_traits>
659 virtual std::ostream&
stream()
const = 0;
678 auto get() -> std::ostream& {
return *m_oss; }
689#import <Foundation/Foundation.h>
692#define CATCH_ARC_ENABLED __has_feature(objc_arc)
694#define CATCH_ARC_ENABLED 0
697void arcSafeRelease( NSObject* obj );
698id performOptionalSelector(
id obj,
SEL sel );
700#if !CATCH_ARC_ENABLED
701inline void arcSafeRelease( NSObject* obj ) {
704inline 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
712inline void arcSafeRelease( NSObject* ){}
713inline 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
734#pragma warning(disable:4180)
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);
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>
826 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
::convert(
e);
831 return ::Catch::Detail::stringify(
static_cast<typename std::underlying_type<E>::type
>(
e));
835 template <
typename T>
837 return ::Catch::StringMaker<T^>::convert(
e);
849#ifdef CATCH_CONFIG_WCHAR
852 static std::string
convert(
const std::wstring& wstr);
865#ifdef CATCH_CONFIG_WCHAR
881 return ::Catch::Detail::stringify(std::string{
str });
887 return ::Catch::Detail::stringify(std::string{
reinterpret_cast<char const *
>(
str) });
893 return ::Catch::Detail::stringify(std::string{
reinterpret_cast<char const *
>(
str) });
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);
954 template <
typename T>
956 template <
typename U>
959 return ::Catch::Detail::rawMemoryToString(p);
966 template <
typename R,
typename C>
970 return ::Catch::Detail::rawMemoryToString(p);
978 template <
typename T>
979 struct StringMaker<
T^> {
980 static std::string
convert(
T^ ref ) {
981 return ::Catch::Detail::clrReferenceToString(ref);
987 template<
typename InputIterator>
993 for (++first; first != last; ++first)
1003 struct StringMaker<NSString*> {
1004 static std::string
convert(NSString * nsstring) {
1007 return std::string(
"@") + [nsstring UTF8String];
1012 static std::string
convert(NSObject* nsObject) {
1013 return ::Catch::Detail::stringify([nsObject description]);
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) {
1044 ReusableStringStream rss;
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) {
1087 ReusableStringStream rss;
1089 Detail::TupleElementPrinter<std::tuple<Types...>>
::print(tuple, rss.get());
1107 template <
typename T>
1114#if defined(_MANAGED)
1115 template <
typename T>
1117 static const bool value =
false;
1121 template<
typename Range>
1123 return ::Catch::Detail::rangeToString(
begin( range ),
end( 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)
1167template <
class Ratio>
1168struct ratio_string {
1169 static std::string symbol();
1172template <
class Ratio>
1173std::string ratio_string<Ratio>::symbol() {
1174 Catch::ReusableStringStream rss;
1175 rss <<
'[' << Ratio::num <<
'/'
1176 << Ratio::den <<
']';
1180struct ratio_string<std::atto> {
1181 static std::string symbol();
1184struct ratio_string<std::femto> {
1185 static std::string symbol();
1188struct ratio_string<std::pico> {
1189 static std::string symbol();
1192struct ratio_string<std::nano> {
1193 static std::string symbol();
1196struct ratio_string<std::micro> {
1197 static std::string symbol();
1200struct 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) {
1209 ReusableStringStream rss;
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) {
1217 ReusableStringStream rss;
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) {
1225 ReusableStringStream rss;
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) {
1233 ReusableStringStream rss;
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) {
1245 return ::Catch::Detail::stringify(time_point.time_since_epoch()) +
" since epoch";
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);
1284#pragma warning(push)
1285#pragma warning(disable:4389)
1286#pragma warning(disable:4018)
1287#pragma warning(disable:4312)
1288#pragma warning(disable:4180)
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>
1447 class AssertionResult;
1453 struct BenchmarkInfo;
1454 struct BenchmarkStats;
1464 Counts& assertions ) = 0;
1490 std::string
const& message,
1515 struct AssertionResultData;
1531 explicit operator bool()
const;
1544 bool m_completed =
false;
1554 if ( !m_completed ) {
1555 m_resultCapture.handleIncomplete( m_assertionInfo );
1559 template<
typename T>
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 )
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__) ) )
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 ) \
1820 std::string
const& _name,
1821 std::string
const& _description = std::string() );
1849 uint64_t m_nanoseconds = 0;
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 )
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;
1984#if defined(CATCH_CONFIG_DISABLE)
1985 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
1986 static std::string translatorName( signature )
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>
2065 bool equalityComparisonImpl(
double other)
const;
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>
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>
2096 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2101 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
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);
2184 bool startsWith( std::string
const& s, std::string
const& prefix );
2186 bool endsWith( std::string
const& s, std::string
const& suffix );
2188 bool contains( std::string
const& s, std::string
const& infix );
2192 bool replaceInPlace( std::string&
str, std::string
const& replaceThis, std::string
const& withThis );
2205#ifndef CATCH_CONFIG_DISABLE_MATCHERS
2234 template<
typename ObjectT>
2238 template<
typename PtrT>
2243 template<
typename T>
2251 template<
typename ArgT>
2255 if (!matcher->match(
arg))
2261 std::string description;
2262 description.reserve( 4 +
m_matchers.size()*32 );
2263 description +=
"( ";
2269 description +=
" and ";
2270 description += matcher->toString();
2272 description +=
" )";
2283 template<
typename ArgT>
2288 if (matcher->match(
arg))
2294 std::string description;
2295 description.reserve( 4 +
m_matchers.size()*32 );
2296 description +=
"( ";
2302 description +=
" or ";
2303 description += matcher->toString();
2305 description +=
" )";
2317 template<
typename ArgT>
2332 template<
typename T>
2336 template<
typename T>
2340 template<
typename T>
2357#include <type_traits>
2365 enum class FloatingPointKind : uint8_t;
2369 bool match(
double const& matchee)
const override;
2378 bool match(
double const& matchee)
const override;
2383 FloatingPointKind m_type;
2400#include <functional>
2411template <
typename T>
2413 std::function<bool(
T const&)> m_predicate;
2414 std::string m_description;
2418 :m_predicate(
std::move(elem)),
2419 m_description(
Detail::finalizeDescription(descr))
2423 return m_predicate(item);
2427 return m_description;
2437 template<
typename T>
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;
2496 std::string m_regex;
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) {
2566 template<
typename T>
2571 bool match(std::vector<T>
const &v)
const override {
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 {
2608 for (std::size_t i = 0; i < v.size(); ++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;
2786 std::string
const& _className,
2787 std::string
const& _description,
2788 std::vector<std::string>
const& _tags,
2794 bool throws()
const;
2824 std::shared_ptr<ITestInvoker> test;
2828 std::string
const& className,
2834#pragma clang diagnostic pop
2853#import <objc/runtime.h>
2875 class OcMethod :
public ITestInvoker {
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 {
2971 return "equals string: " +
Catch::Detail::stringify( m_substr );
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 {
2984 return "contains string: " +
Catch::Detail::stringify( m_substr );
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 {
2997 return "starts with: " +
Catch::Detail::stringify( m_substr );
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 {
3009 return "ends with: " +
Catch::Detail::stringify( m_substr );
3016 inline Impl::NSStringMatchers::Equals
3017 Equals( NSString* substr ){
return Impl::NSStringMatchers::Equals( substr ); }
3019 inline Impl::NSStringMatchers::Contains
3020 Contains( NSString* substr ){
return Impl::NSStringMatchers::Contains( substr ); }
3022 inline Impl::NSStringMatchers::StartsWith
3023 StartsWith( NSString* substr ){
return Impl::NSStringMatchers::StartsWith( substr ); }
3025 inline Impl::NSStringMatchers::EndsWith
3026 EndsWith( NSString* substr ){
return Impl::NSStringMatchers::EndsWith( substr ); }
3030 using namespace 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
3091 WildcardPattern( std::string
const& pattern, CaseSensitive::Choice caseSensitivity );
3092 virtual ~WildcardPattern() =
default;
3093 virtual bool matches( std::string
const&
str )
const;
3096 std::string adjustCase( std::string
const&
str )
const;
3097 CaseSensitive::Choice m_caseSensitivity;
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;
3147 bool matches( TestCaseInfo
const& testCase )
const;
3151 bool hasFilters()
const;
3152 bool matches( TestCaseInfo
const& testCase )
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
3287 struct IConfig : NonCopyable {
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;
3407 IStream
const* openStream();
3410 std::unique_ptr<IStream const> m_stream;
3411 TestSpec m_testSpec;
3412 bool m_hasTestFilters =
false;
3424 struct AssertionResultData
3426 AssertionResultData() =
delete;
3428 AssertionResultData( ResultWas::OfType _resultType, LazyExpression
const& _lazyExpression );
3430 std::string message;
3431 mutable std::string reconstructedExpression;
3432 LazyExpression lazyExpression;
3433 ResultWas::OfType resultType;
3435 std::string reconstructExpression()
const;
3438 class AssertionResult {
3440 AssertionResult() =
delete;
3441 AssertionResult( AssertionInfo
const&
info, AssertionResultData
const&
data );
3444 bool succeeded()
const;
3445 ResultWas::OfType getResultType()
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;
3453 SourceLineInfo getSourceInfo()
const;
3454 StringRef getTestMacroName()
const;
3457 AssertionInfo m_info;
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,
3585 Totals
const& _totals );
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 {
3599 SectionStats( SectionInfo
const& _sectionInfo,
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();
3609 SectionInfo sectionInfo;
3611 double durationInSeconds;
3612 bool missingAssertions;
3615 struct TestCaseStats {
3616 TestCaseStats( TestCaseInfo
const& _testInfo,
3617 Totals
const& _totals,
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();
3628 TestCaseInfo testInfo;
3635 struct TestGroupStats {
3636 TestGroupStats( GroupInfo
const& _groupInfo,
3637 Totals
const& _totals,
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,
3654 Totals
const& _totals,
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;
3713 virtual void fatalErrorEncountered( StringRef
name );
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 );
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();
3808 void skipTest(TestCaseInfo
const&)
override {
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 {
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;
3865 SectionInfo
const& m_other;
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);
3920 void assertionStarting(AssertionInfo
const&)
override {}
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;
3964 void skipTest(TestCaseInfo
const&)
override {}
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 );
3994 void assertionStarting(AssertionInfo
const&)
override;
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 );
4049 static void use( Code _colourCode );
4052 bool m_moved =
false;
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
4120#define CATCH_REGISTER_REPORTER(name, reporterType)
4121#define CATCH_REGISTER_LISTENER(listenerType)
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;
4143 void assertionStarting(AssertionInfo
const&)
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)
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;
4179 void assertionStarting(AssertionInfo
const&)
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)
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 ) {
4291 ReusableStringStream rss;
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;
4382 void writeSourceInfo(SourceLineInfo
const& sourceInfo);
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;
4396 void assertionStarting(AssertionInfo
const&)
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;
4427#pragma clang diagnostic push
4428#pragma clang diagnostic ignored "-Wweak-vtables"
4439namespace TestCaseTracking {
4441 struct NameAndLocation {
4443 SourceLineInfo location;
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 );
4595using TestCaseTracking::ITracker;
4596using TestCaseTracking::TrackerContext;
4597using TestCaseTracking::SectionTracker;
4598using TestCaseTracking::IndexTracker;
4608 struct LeakDetector {
4624bool marginComparison(
double lhs,
double rhs,
double margin) {
4634 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
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")
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
4780#ifdef CATCH_DEFINED_NOMINMAX
4783#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
4784# undef WIN32_LEAN_AND_MEAN
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 );
4863 Totals runTest(TestCase
const& testCase);
4865 IConfigPtr config()
const;
4866 IStreamingReporter& reporter()
const;
4872 ( AssertionInfo
const&
info,
4873 ITransientExpression
const& expr,
4874 AssertionReaction& reaction )
override;
4876 ( AssertionInfo
const&
info,
4877 ResultWas::OfType resultType,
4878 StringRef
const& message,
4879 AssertionReaction& reaction )
override;
4880 void handleUnexpectedExceptionNotThrown
4881 ( AssertionInfo
const&
info,
4882 AssertionReaction& reaction )
override;
4883 void handleUnexpectedInflightException
4884 ( AssertionInfo
const&
info,
4885 std::string
const& message,
4886 AssertionReaction& reaction )
override;
4887 void handleIncomplete
4888 ( AssertionInfo
const&
info )
override;
4890 ( AssertionInfo
const &
info,
4891 ResultWas::OfType resultType,
4892 AssertionReaction &reaction )
override;
4894 bool sectionStarted( SectionInfo
const& sectionInfo, Counts& assertions )
override;
4896 void sectionEnded( SectionEndInfo
const& endInfo )
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 );
4931 ( AssertionInfo const &
info,
4932 ResultWas::OfType resultType,
4933 ITransientExpression const *expr,
4936 void populateReaction( AssertionReaction& reaction );
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;
4952 AssertionInfo m_lastAssertionInfo;
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;
4966 auto operator <<( std::ostream& os, ITransientExpression
const& expr ) -> std::ostream& {
4967 expr.streamReconstructedExpression( os );
4971 LazyExpression::LazyExpression(
bool isNegated )
4972 : m_isNegated( isNegated )
4977 LazyExpression::operator bool()
const {
4978 return m_transientExpression !=
nullptr;
4982 if( lazyExpr.m_isNegated )
4986 if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
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 )
5028 throw Catch::TestFailureException();
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;
5082 m_resultData(
data )
5086 bool AssertionResult::succeeded()
const {
5091 bool AssertionResult::isOk()
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;
5190 handler.handleExpr( expr );
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
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
5264namespace 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 );
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 {
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 ) {
5437 auto operator + ( Column
const& other ) -> Columns;
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;
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() }; }
5531 auto operator += ( Column
const& col ) -> Columns& {
5532 m_columns.push_back( col );
5535 auto operator + ( Column
const& col ) -> Columns {
5536 Columns combined = *
this;
5541 inline friend std::ostream&
operator << ( std::ostream& os, Columns
const& cols ) {
5544 for(
auto line : cols ) {
5554 auto toString() const -> std::
string {
5555 std::ostringstream oss;
5561 inline auto Column::operator + ( Column
const& other ) -> Columns {
5576#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
5577#define CATCH_PLATFORM_WINDOWS
5580namespace 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;
5595 using ArgType =
typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
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); }
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);
5883 struct NonCopyable {
5884 NonCopyable() =
default;
5885 NonCopyable( NonCopyable
const & ) =
delete;
5886 NonCopyable( NonCopyable && ) =
delete;
5887 NonCopyable &operator=( NonCopyable
const & ) =
delete;
5888 NonCopyable &operator=( NonCopyable && ) =
delete;
5891 struct BoundRef : NonCopyable {
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) ;
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 )
6197 using ParserBase::parse;
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();
6374 using ParserBase::parse;
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>
6425 auto ComposableParserImpl<DerivedT>::operator|(
T const &other )
const ->
Parser {
6426 return Parser() |
static_cast<DerivedT
const &
>( *this ) | other;
6431using detail::Parser;
6443using detail::ExeName;
6449using detail::ParseResultType;
6452using 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();
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; }
6756 unsigned int Config::rngSeed()
const {
return m_data.rngSeed; }
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 );
6865 HANDLE stdoutHandle;
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();
6966 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
6974 Colour::Colour( Code _colourCode ) {
use( _colourCode ); }
6975 Colour::Colour(
Colour&& rhs )
noexcept {
6976 m_moved = rhs.m_moved;
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 );
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;
7038 IRunner* m_runner =
nullptr;
7039 IResultCapture* m_resultCapture =
nullptr;
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
7093# include <stdbool.h>
7094# include <sys/types.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;
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();
7228 virtual void registerTranslator(
const IExceptionTranslator* translator );
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 ) );
7251 std::string ExceptionTranslatorRegistry::translateActiveException()
const {
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 );
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() {
7370bool FatalConditionHandler::isSet =
false;
7371ULONG FatalConditionHandler::guaranteeSize = 0;
7372PVOID 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() {}
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();
7563 builder.m_info.message = builder.m_stream.str();
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;
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
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 <<
" ";
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 );
7898enum class FloatingPointKind : uint8_t {
7908template <
typename T>
7912struct 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));
7921struct 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));
7929template <
typename T>
7931 return Converter<T>(t);
7934template <
typename FP>
7935bool almostEqualUlps(FP lhs, FP rhs,
int maxUlpDiff) {
7938 if (std::isnan(lhs) || std::isnan(rhs)) {
7945 if ((lc.i < 0) != (rc.i < 0)) {
7950 auto ulpDiff = std::abs(lc.i - rc.i);
7951 return ulpDiff <= maxUlpDiff;
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 {
7973 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
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" : "");
8000Floating::WithinUlpsMatcher
WithinULP(
double target,
int maxUlpDiff) {
8001 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
8004Floating::WithinUlpsMatcher
WithinULP(
float target,
int maxUlpDiff) {
8005 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
8009 return Floating::WithinAbsMatcher(target,
margin);
8020 return "matches undescribed predicate";
8022 return "matches predicate: \"" + desc + '"';
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;
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");
8108 StdString::EqualsMatcher
Equals( std::string
const&
str, CaseSensitive::Choice caseSensitivity ) {
8109 return StdString::EqualsMatcher( StdString::CasedString(
str, caseSensitivity) );
8111 StdString::ContainsMatcher
Contains( std::string
const&
str, CaseSensitive::Choice caseSensitivity ) {
8112 return StdString::ContainsMatcher( StdString::CasedString(
str, caseSensitivity) );
8114 StdString::EndsWithMatcher
EndsWith( std::string
const&
str, CaseSensitive::Choice caseSensitivity ) {
8115 return StdString::EndsWithMatcher( StdString::CasedString(
str, caseSensitivity) );
8117 StdString::StartsWithMatcher
StartsWith( std::string
const&
str, CaseSensitive::Choice caseSensitivity ) {
8118 return StdString::StartsWithMatcher( StdString::CasedString(
str, caseSensitivity) );
8121 StdString::RegexMatcher
Matches(std::string
const& regex, CaseSensitive::Choice caseSensitivity) {
8122 return StdString::RegexMatcher(regex, caseSensitivity);
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 )
8171 m_info.message = builder.m_stream.str();
8176 if ( !uncaught_exceptions() ){
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)();
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;
8272 std::ios_base::Init m_ostreamInit;
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;
8306 void registerReporter( std::string
const&
name, IReporterFactoryPtr
const& factory );
8307 void registerListener( IReporterFactoryPtr
const& factory );
8309 FactoryMap
const& getFactories()
const override;
8310 Listeners
const& getListeners()
const override;
8313 FactoryMap m_factories;
8314 Listeners m_listeners;
8328 TagAlias(std::string
const& _tag, SourceLineInfo _lineInfo);
8331 SourceLineInfo lineInfo;
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;
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;
8377 class RegistryHub :
public IRegistryHub,
public IMutableRegistryHub,
8378 private NonCopyable {
8381 RegistryHub() =
default;
8382 IReporterRegistry
const& getReporterRegistry()
const override {
8383 return m_reporterRegistry;
8385 ITestCaseRegistry
const& getTestCaseRegistry()
const override {
8386 return m_testCaseRegistry;
8388 IExceptionTranslatorRegistry& getExceptionTranslatorRegistry()
override {
8389 return m_exceptionTranslatorRegistry;
8391 ITagAliasRegistry
const& getTagAliasRegistry()
const override {
8392 return m_tagAliasRegistry;
8394 StartupExceptionRegistry
const& getStartupExceptionRegistry()
const override {
8395 return m_exceptionRegistry;
8399 void registerReporter( std::string
const&
name, IReporterFactoryPtr
const& factory )
override {
8400 m_reporterRegistry.registerReporter(
name, factory );
8402 void registerListener( IReporterFactoryPtr
const& factory )
override {
8403 m_reporterRegistry.registerListener( factory );
8405 void registerTest( TestCase
const& testInfo )
override {
8406 m_testCaseRegistry.registerTest( testInfo );
8408 void registerTranslator(
const IExceptionTranslator* translator )
override {
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;
8445 ReusableStringStream::cleanup();
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);
8469 void ReporterRegistry::registerListener( IReporterFactoryPtr
const& factory ) {
8470 m_listeners.push_back( factory );
8473 IReporterRegistry::FactoryMap
const& ReporterRegistry::getFactories()
const {
8476 IReporterRegistry::Listeners
const& ReporterRegistry::getListeners()
const {
8486 bool isOk( ResultWas::OfType resultType ) {
8487 return ( resultType & ResultWas::FailureBit ) == 0;
8490 return flags == ResultWas::Info;
8493 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
8494 return static_cast<ResultDisposition::Flags
>(
static_cast<int>( lhs ) |
static_cast<int>( rhs ) );
8498 bool shouldSuppressFailure(
int flags ) {
return ( flags & ResultDisposition::SuppressFail ) != 0; }
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 {
8529 ReusableStringStream m_rss;
8530 RedirectedStream m_cout;
8532 RedirectedStdOut() : m_cout(
Catch::
cout(), m_rss.
get() ) {}
8533 auto str() const -> std::
string {
return m_rss.str(); }
8539 class RedirectedStdErr {
8540 ReusableStringStream m_rss;
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)),
8556 m_lastAssertionInfo{ StringRef(), SourceLineInfo(
"",0), StringRef(), ResultDisposition::
Normal },
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;
8583 auto const& testInfo = testCase.getTestCaseInfo();
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());
8599 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
8600 deltaTotals.assertions.failed++;
8601 deltaTotals.testCases.passed--;
8602 deltaTotals.testCases.failed++;
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) {
8627 m_totals.assertions.passed++;
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++;
8676 assertions.failed++;
8681 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
8682 bool missingAssertions = testForMissingAssertions(assertions);
8684 if (!m_activeSections.empty()) {
8685 m_activeSections.back()->close();
8686 m_activeSections.pop_back();
8689 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
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);
8750 assertions.failed = 1;
8751 SectionStats testCaseSectionStats(testCaseSection, assertions, 0,
false);
8752 m_reporter->sectionEnded(testCaseSectionStats);
8754 auto const& testInfo = m_activeTestCase->getTestCaseInfo();
8758 deltaTotals.assertions.failed = 1;
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();
8808 duration = timer.getElapsedSeconds();
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 );
8924 reaction.shouldDebugBreak = m_config->shouldDebugBreak();
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 ) );
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];
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;
9435 FileStream( StringRef filename ) {
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;
9453 CoutStream() : m_os(
Catch::
cout().rdbuf() ) {}
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
9554 std::ostream&
cout() {
return std::cout; }
9555 std::ostream&
cerr() {
return std::cerr; }
9556 std::ostream&
clog() {
return std::clog; }
9560#if defined(__clang__)
9561# pragma clang diagnostic pop
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;
9627 os << pluraliser.m_count <<
' ' << pluraliser.m_label;
9628 if( pluraliser.m_count != 1 )
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;
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 )
9699 size() == other.size() &&
9700 (std::strncmp( m_start, other.m_start,
size() ) == 0);
9707 return m_start[index];
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 );
9741 return os.write(
str.currentData(),
str.size());
9745 lhs.append(rhs.currentData(), rhs.size());
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() {
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 ) {
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(
"." );
9902 void setTags(
TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
9904 tags.erase(std::unique(
begin(tags),
end(tags)),
end(tags));
9905 testCaseInfo.lcaseTags.clear();
9907 for(
auto const&
tag : tags ) {
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 );
9945 std::size_t full_size = 2 *
tags.size();
9946 for (
const auto&
tag :
tags) {
9949 ret.reserve(full_size);
9950 for (
const auto&
tag :
tags) {
9963 other.name = _newName;
9972 return test.get() == other.test.get() &&
9973 name == other.name &&
9978 return name < other.name;
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;
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 ) {
10040 std::string
name = testCase.getTestCaseInfo().name;
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>
10089#include <stdexcept>
10093#if defined(__clang__)
10094# pragma clang diagnostic push
10095# pragma clang diagnostic ignored "-Wexit-time-destructors"
10099namespace 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;
10348using TestCaseTracking::ITracker;
10349using TestCaseTracking::TrackerContext;
10350using TestCaseTracking::SectionTracker;
10351using 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 {
10410 return std::find(
begin(testCase.lcaseTags),
10411 end(testCase.lcaseTags),
10412 m_tag) !=
end(testCase.lcaseTags);
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 ) {}
10445 TestSpecParser& TestSpecParser::parse( std::string
const&
arg ) {
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();
10524static 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;
10569 auto Timer::getElapsedNanoseconds() const -> uint64_t {
10572 auto Timer::getElapsedMicroseconds() const -> uint64_t {
10573 return getElapsedNanoseconds()/1000;
10575 auto Timer::getElapsedMilliseconds() const ->
unsigned int {
10576 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
10578 auto Timer::getElapsedSeconds() const ->
double {
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
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);
10633 ReusableStringStream rss;
10634 rss <<
"0x" << std::setfill(
'0') << std::hex;
10635 for( ; i !=
end; i += inc )
10636 rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
10641template<
typename T>
10642std::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) : '?';
10697 return ::Catch::Detail::stringify(s);
10703 return ::Catch::Detail::stringify(std::string{
str });
10705 return{
"{null string}" };
10710 return ::Catch::Detail::stringify(std::string{
str });
10712 return{
"{null string}" };
10715#ifdef CATCH_CONFIG_WCHAR
10718 return ::Catch::Detail::stringify(std::wstring{
str });
10720 return{
"{null string}" };
10725 return ::Catch::Detail::stringify(std::wstring{
str });
10727 return{
"{null string}" };
10733 return ::Catch::Detail::stringify(
static_cast<long long>(value));
10736 return ::Catch::Detail::stringify(
static_cast<long long>(value));
10741 if (value > Detail::hexThreshold) {
10742 rss <<
" (0x" << std::hex << value <<
')';
10748 return ::Catch::Detail::stringify(
static_cast<unsigned long long>(value));
10751 return ::Catch::Detail::stringify(
static_cast<unsigned long long>(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 <
' ') {
10776 return ::Catch::Detail::stringify(
static_cast<unsigned int>(value));
10778 char chstr[] =
"' '";
10784 return ::Catch::Detail::stringify(
static_cast<char>(c));
10787 return ::Catch::Detail::stringify(
static_cast<char>(c));
10795 return fpToString(value, 5) + '
f';
10798 return fpToString(value, 10);
10801std::string ratio_string<std::atto>::symbol() {
return "a"; }
10802std::string ratio_string<std::femto>::symbol() {
return "f"; }
10803std::string ratio_string<std::pico>::symbol() {
return "p"; }
10804std::string ratio_string<std::nano>::symbol() {
return "n"; }
10805std::string ratio_string<std::micro>::symbol() {
return "u"; }
10806std::string ratio_string<std::milli>::symbol() {
return "m"; }
10810#if defined(__clang__)
10811# pragma clang diagnostic pop
10858 Totals diff = *
this - prevTotals;
10859 if( diff.assertions.failed > 0 )
10861 else if( diff.assertions.failedButOk > 0 )
10872#include <exception>
10875 bool uncaught_exceptions() {
10876#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
10877 return std::uncaught_exceptions() > 0;
10879 return std::uncaught_exception();
10891 (
unsigned int _majorVersion,
10892 unsigned int _minorVersion,
10893 unsigned int _patchNumber,
10894 char const *
const _branchName,
10895 unsigned int _buildNumber )
10896 : majorVersion( _majorVersion ),
10897 minorVersion( _minorVersion ),
10898 patchNumber( _patchNumber ),
10899 branchName( _branchName ),
10900 buildNumber( _buildNumber )
10903 std::ostream&
operator << ( std::ostream& os, Version
const& version ) {
10904 os << version.majorVersion <<
'.'
10905 << version.minorVersion <<
'.'
10906 << version.patchNumber;
10908 if (version.branchName[0]) {
10909 os <<
'-' << version.branchName
10910 <<
'.' << version.buildNumber;
10915 Version
const& libraryVersion() {
10916 static Version version( 2, 2, 2,
"", 0 );
10928 WildcardPattern::WildcardPattern( std::string
const& pattern,
10930 : m_caseSensitivity( caseSensitivity ),
10931 m_pattern( adjustCase( pattern ) )
10934 m_pattern = m_pattern.substr( 1 );
10935 m_wildcard = WildcardAtStart;
10937 if(
endsWith( m_pattern,
'*' ) ) {
10938 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
10939 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
10943 bool WildcardPattern::matches( std::string
const&
str )
const {
10944 switch( m_wildcard ) {
10946 return m_pattern == adjustCase(
str );
10947 case WildcardAtStart:
10949 case WildcardAtEnd:
10951 case WildcardAtBothEnds:
10954 CATCH_INTERNAL_ERROR(
"Unknown enum" );
10958 std::string WildcardPattern::adjustCase( std::string
const&
str )
const {
10967using uchar =
unsigned char;
10973 size_t trailingBytes(
unsigned char c) {
10974 if ((c & 0xE0) == 0xC0) {
10977 if ((c & 0xF0) == 0xE0) {
10980 if ((c & 0xF8) == 0xF0) {
10983 CATCH_INTERNAL_ERROR(
"Invalid multibyte utf-8 start byte encountered");
10986 uint32_t headerValue(
unsigned char c) {
10987 if ((c & 0xE0) == 0xC0) {
10990 if ((c & 0xF0) == 0xE0) {
10993 if ((c & 0xF8) == 0xF0) {
10996 CATCH_INTERNAL_ERROR(
"Invalid multibyte utf-8 start byte encountered");
10999 void hexEscapeChar(std::ostream& os,
unsigned char c) {
11001 << std::uppercase << std::hex << std::setfill(
'0') << std::setw(2)
11002 <<
static_cast<int>(c);
11007 XmlEncode::XmlEncode( std::string
const&
str, ForWhat forWhat )
11009 m_forWhat( forWhat )
11012 void XmlEncode::encodeTo( std::ostream& os )
const {
11016 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
11017 uchar c = m_str[idx];
11019 case '<': os <<
"<";
break;
11020 case '&': os <<
"&";
break;
11024 if (idx > 2 && m_str[idx - 1] ==
']' && m_str[idx - 2] ==
']')
11031 if (m_forWhat == ForAttributes)
11042 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
11043 hexEscapeChar(os, c);
11061 hexEscapeChar(os, c);
11065 auto encBytes = trailingBytes(c);
11067 if (idx + encBytes - 1 >= m_str.size()) {
11068 hexEscapeChar(os, c);
11075 uint32_t value = headerValue(c);
11076 for (std::size_t n = 1; n < encBytes; ++n) {
11077 uchar nc = m_str[idx + n];
11078 valid &= ((nc & 0xC0) == 0x80);
11079 value = (value << 6) | (nc & 0x3F);
11087 (0x80 <= value && value < 0x800 && encBytes > 2) ||
11088 (0x800 < value && value < 0x10000 && encBytes > 3) ||
11090 (value >= 0x110000)
11092 hexEscapeChar(os, c);
11097 for (std::size_t n = 0; n < encBytes; ++n) {
11098 os << m_str[idx + n];
11100 idx += encBytes - 1;
11106 std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode ) {
11107 xmlEncode.encodeTo( os );
11111 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
11112 : m_writer( writer )
11115 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other )
noexcept
11116 : m_writer( other.m_writer ){
11117 other.m_writer =
nullptr;
11119 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other )
noexcept {
11121 m_writer->endElement();
11123 m_writer = other.m_writer;
11124 other.m_writer =
nullptr;
11128 XmlWriter::ScopedElement::~ScopedElement() {
11130 m_writer->endElement();
11133 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string
const& text,
bool indent ) {
11134 m_writer->writeText( text, indent );
11138 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
11140 writeDeclaration();
11143 XmlWriter::~XmlWriter() {
11144 while( !m_tags.empty() )
11148 XmlWriter& XmlWriter::startElement( std::string
const&
name ) {
11150 newlineIfNecessary();
11151 m_os << m_indent <<
'<' <<
name;
11152 m_tags.push_back(
name );
11154 m_tagIsOpen =
true;
11158 XmlWriter::ScopedElement XmlWriter::scopedElement( std::string
const&
name ) {
11159 ScopedElement scoped(
this );
11160 startElement(
name );
11164 XmlWriter& XmlWriter::endElement() {
11165 newlineIfNecessary();
11166 m_indent = m_indent.substr( 0, m_indent.size()-2 );
11167 if( m_tagIsOpen ) {
11169 m_tagIsOpen =
false;
11172 m_os << m_indent <<
"</" << m_tags.back() <<
">";
11179 XmlWriter& XmlWriter::writeAttribute( std::string
const&
name, std::string
const& attribute ) {
11180 if( !
name.empty() && !attribute.empty() )
11181 m_os <<
' ' <<
name <<
"=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) <<
'"';
11185 XmlWriter& XmlWriter::writeAttribute( std::string
const&
name,
bool attribute ) {
11186 m_os <<
' ' <<
name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
'"';
11190 XmlWriter& XmlWriter::writeText( std::string
const& text,
bool indent ) {
11191 if( !text.empty() ){
11192 bool tagWasOpen = m_tagIsOpen;
11194 if( tagWasOpen && indent )
11196 m_os << XmlEncode( text );
11197 m_needsNewline =
true;
11202 XmlWriter& XmlWriter::writeComment( std::string
const& text ) {
11204 m_os << m_indent <<
"<!--" << text <<
"-->";
11205 m_needsNewline =
true;
11209 void XmlWriter::writeStylesheetRef( std::string
const&
url ) {
11210 m_os <<
"<?xml-stylesheet type=\"text/xsl\" href=\"" <<
url <<
"\"?>\n";
11213 XmlWriter& XmlWriter::writeBlankLine() {
11219 void XmlWriter::ensureTagClosed() {
11220 if( m_tagIsOpen ) {
11221 m_os <<
">" << std::endl;
11222 m_tagIsOpen =
false;
11226 void XmlWriter::writeDeclaration() {
11227 m_os <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
11230 void XmlWriter::newlineIfNecessary() {
11231 if( m_needsNewline ) {
11233 m_needsNewline =
false;
11247 void prepareExpandedExpression(AssertionResult& result) {
11248 result.getExpandedExpression();
11253 std::string getFormattedDuration(
double duration ) {
11258 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
11259 char buffer[maxDoubleSize];
11264 sprintf_s(buffer,
"%.3f", duration);
11266 sprintf(buffer,
"%.3f", duration);
11268 return std::string(buffer);
11271 TestEventListenerBase::TestEventListenerBase(ReporterConfig
const & _config)
11272 :StreamingReporterBase(_config) {}
11274 void TestEventListenerBase::assertionStarting(
AssertionInfo const &) {}
11276 bool TestEventListenerBase::assertionEnded(AssertionStats
const &) {
11286#ifdef CATCH_PLATFORM_MAC
11287 const char* failedString() {
return "FAILED"; }
11288 const char* passedString() {
return "PASSED"; }
11290 const char* failedString() {
return "failed"; }
11291 const char* passedString() {
return "passed"; }
11295 Catch::Colour::Code dimColour() {
return Catch::Colour::FileName; }
11297 std::string bothOrAll( std::size_t count ) {
11298 return count == 1 ? std::string() :
11299 count == 2 ?
"both " :
"all " ;
11312void printTotals(std::ostream& out,
const Totals& totals) {
11313 if (totals.testCases.total() == 0) {
11314 out <<
"No tests ran.";
11315 }
else if (totals.testCases.failed == totals.testCases.total()) {
11317 const std::string qualify_assertions_failed =
11318 totals.assertions.failed == totals.assertions.total() ?
11319 bothOrAll(totals.assertions.failed) : std::
string();
11321 "Failed " << bothOrAll(totals.testCases.failed)
11322 <<
pluralise(totals.testCases.failed,
"test case") <<
", "
11323 "failed " << qualify_assertions_failed <<
11324 pluralise(totals.assertions.failed,
"assertion") <<
'.';
11325 }
else if (totals.assertions.total() == 0) {
11327 "Passed " << bothOrAll(totals.testCases.total())
11328 <<
pluralise(totals.testCases.total(),
"test case")
11329 <<
" (no assertions).";
11330 }
else if (totals.assertions.failed) {
11333 "Failed " <<
pluralise(totals.testCases.failed,
"test case") <<
", "
11334 "failed " <<
pluralise(totals.assertions.failed,
"assertion") <<
'.';
11338 "Passed " << bothOrAll(totals.testCases.passed)
11339 <<
pluralise(totals.testCases.passed,
"test case") <<
11340 " with " <<
pluralise(totals.assertions.passed,
"assertion") <<
'.';
11345class AssertionPrinter {
11347 AssertionPrinter& operator= (AssertionPrinter
const&) =
delete;
11348 AssertionPrinter(AssertionPrinter
const&) =
delete;
11349 AssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
11351 , result(_stats.assertionResult)
11352 , messages(_stats.infoMessages)
11353 , itMessage(_stats.infoMessages.
begin())
11354 , printInfoMessages(_printInfoMessages) {}
11359 itMessage = messages.begin();
11361 switch (result.getResultType()) {
11362 case ResultWas::Ok:
11363 printResultType(Colour::ResultSuccess, passedString());
11364 printOriginalExpression();
11365 printReconstructedExpression();
11366 if (!result.hasExpression())
11367 printRemainingMessages(Colour::None);
11369 printRemainingMessages();
11371 case ResultWas::ExpressionFailed:
11373 printResultType(Colour::ResultSuccess, failedString() + std::string(
" - but was ok"));
11375 printResultType(Colour::Error, failedString());
11376 printOriginalExpression();
11377 printReconstructedExpression();
11378 printRemainingMessages();
11380 case ResultWas::ThrewException:
11381 printResultType(Colour::Error, failedString());
11382 printIssue(
"unexpected exception with message:");
11384 printExpressionWas();
11385 printRemainingMessages();
11387 case ResultWas::FatalErrorCondition:
11388 printResultType(Colour::Error, failedString());
11389 printIssue(
"fatal error condition with message:");
11391 printExpressionWas();
11392 printRemainingMessages();
11394 case ResultWas::DidntThrowException:
11395 printResultType(Colour::Error, failedString());
11396 printIssue(
"expected exception, got none");
11397 printExpressionWas();
11398 printRemainingMessages();
11400 case ResultWas::Info:
11401 printResultType(Colour::None,
"info");
11403 printRemainingMessages();
11405 case ResultWas::Warning:
11406 printResultType(Colour::None,
"warning");
11408 printRemainingMessages();
11410 case ResultWas::ExplicitFailure:
11411 printResultType(Colour::Error, failedString());
11412 printIssue(
"explicitly");
11413 printRemainingMessages(Colour::None);
11416 case ResultWas::Unknown:
11417 case ResultWas::FailureBit:
11418 case ResultWas::Exception:
11419 printResultType(Colour::Error,
"** internal error **");
11425 void printSourceInfo()
const {
11426 Colour colourGuard(Colour::FileName);
11427 stream << result.getSourceInfo() <<
':';
11430 void printResultType(Colour::Code
colour, std::string
const& passOrFail)
const {
11431 if (!passOrFail.empty()) {
11434 stream <<
' ' << passOrFail;
11440 void printIssue(std::string
const& issue)
const {
11441 stream <<
' ' << issue;
11444 void printExpressionWas() {
11445 if (result.hasExpression()) {
11449 stream <<
" expression was:";
11451 printOriginalExpression();
11455 void printOriginalExpression()
const {
11456 if (result.hasExpression()) {
11457 stream <<
' ' << result.getExpression();
11461 void printReconstructedExpression()
const {
11462 if (result.hasExpandedExpression()) {
11465 stream <<
" for: ";
11467 stream << result.getExpandedExpression();
11471 void printMessage() {
11472 if (itMessage != messages.end()) {
11473 stream <<
" '" << itMessage->message <<
'\'';
11478 void printRemainingMessages(Colour::Code
colour = dimColour()) {
11479 if (itMessage == messages.end())
11483 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
11484 const std::size_t N =
static_cast<std::size_t
>(std::distance(itMessage, itEnd));
11488 stream <<
" with " << pluralise(N,
"message") <<
':';
11491 for (; itMessage != itEnd; ) {
11493 if (printInfoMessages || itMessage->type != ResultWas::Info) {
11494 stream <<
" '" << itMessage->message <<
'\'';
11495 if (++itMessage != itEnd) {
11496 Colour colourGuard(dimColour());
11504 std::ostream& stream;
11505 AssertionResult
const& result;
11506 std::vector<MessageInfo> messages;
11507 std::vector<MessageInfo>::const_iterator itMessage;
11508 bool printInfoMessages;
11513 std::string CompactReporter::getDescription() {
11514 return "Reports test results on a single line, suitable for IDEs";
11517 ReporterPreferences CompactReporter::getPreferences()
const {
11518 ReporterPreferences prefs;
11519 prefs.shouldRedirectStdOut =
false;
11523 void CompactReporter::noMatchingTestCases( std::string
const& spec ) {
11524 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
11527 void CompactReporter::assertionStarting(
AssertionInfo const& ) {}
11529 bool CompactReporter::assertionEnded( AssertionStats
const& _assertionStats ) {
11530 AssertionResult
const& result = _assertionStats.assertionResult;
11532 bool printInfoMessages =
true;
11535 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
11538 printInfoMessages =
false;
11541 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
11544 stream << std::endl;
11548 void CompactReporter::sectionEnded(SectionStats
const& _sectionStats) {
11549 if (m_config->showDurations() == ShowDurations::Always) {
11550 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name << std::endl;
11554 void CompactReporter::testRunEnded( TestRunStats
const& _testRunStats ) {
11555 printTotals( stream, _testRunStats.totals );
11556 stream <<
'\n' << std::endl;
11557 StreamingReporterBase::testRunEnded( _testRunStats );
11560 CompactReporter::~CompactReporter() {}
11562 CATCH_REGISTER_REPORTER(
"compact", CompactReporter )
11571#if defined(_MSC_VER)
11572#pragma warning(push)
11573#pragma warning(disable:4061)
11583class ConsoleAssertionPrinter {
11585 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter
const&) =
delete;
11586 ConsoleAssertionPrinter(ConsoleAssertionPrinter
const&) =
delete;
11587 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
11590 result(_stats.assertionResult),
11592 message(result.getMessage()),
11593 messages(_stats.infoMessages),
11594 printInfoMessages(_printInfoMessages) {
11595 switch (result.getResultType()) {
11596 case ResultWas::Ok:
11597 colour = Colour::Success;
11598 passOrFail =
"PASSED";
11600 if (_stats.infoMessages.size() == 1)
11601 messageLabel =
"with message";
11602 if (_stats.infoMessages.size() > 1)
11603 messageLabel =
"with messages";
11605 case ResultWas::ExpressionFailed:
11606 if (result.isOk()) {
11607 colour = Colour::Success;
11608 passOrFail =
"FAILED - but was ok";
11610 colour = Colour::Error;
11611 passOrFail =
"FAILED";
11613 if (_stats.infoMessages.size() == 1)
11614 messageLabel =
"with message";
11615 if (_stats.infoMessages.size() > 1)
11616 messageLabel =
"with messages";
11618 case ResultWas::ThrewException:
11620 passOrFail =
"FAILED";
11621 messageLabel =
"due to unexpected exception with ";
11622 if (_stats.infoMessages.size() == 1)
11623 messageLabel +=
"message";
11624 if (_stats.infoMessages.size() > 1)
11625 messageLabel +=
"messages";
11627 case ResultWas::FatalErrorCondition:
11629 passOrFail =
"FAILED";
11630 messageLabel =
"due to a fatal error condition";
11632 case ResultWas::DidntThrowException:
11634 passOrFail =
"FAILED";
11635 messageLabel =
"because no exception was thrown where one was expected";
11637 case ResultWas::Info:
11638 messageLabel =
"info";
11640 case ResultWas::Warning:
11641 messageLabel =
"warning";
11643 case ResultWas::ExplicitFailure:
11644 passOrFail =
"FAILED";
11646 if (_stats.infoMessages.size() == 1)
11647 messageLabel =
"explicitly with message";
11648 if (_stats.infoMessages.size() > 1)
11649 messageLabel =
"explicitly with messages";
11652 case ResultWas::Unknown:
11653 case ResultWas::FailureBit:
11654 case ResultWas::Exception:
11655 passOrFail =
"** internal error **";
11661 void print()
const {
11663 if (stats.totals.assertions.total() > 0) {
11667 printOriginalExpression();
11668 printReconstructedExpression();
11676 void printResultType()
const {
11677 if (!passOrFail.empty()) {
11679 stream << passOrFail <<
":\n";
11682 void printOriginalExpression()
const {
11683 if (result.hasExpression()) {
11684 Colour colourGuard(Colour::OriginalExpression);
11686 stream << result.getExpressionInMacro();
11690 void printReconstructedExpression()
const {
11691 if (result.hasExpandedExpression()) {
11692 stream <<
"with expansion:\n";
11693 Colour colourGuard(Colour::ReconstructedExpression);
11694 stream << Column(result.getExpandedExpression()).indent(2) <<
'\n';
11697 void printMessage()
const {
11698 if (!messageLabel.empty())
11699 stream << messageLabel <<
':' <<
'\n';
11700 for (
auto const& msg : messages) {
11703 stream << Column(msg.message).indent(2) <<
'\n';
11706 void printSourceInfo()
const {
11707 Colour colourGuard(Colour::FileName);
11708 stream << result.getSourceInfo() <<
": ";
11711 std::ostream& stream;
11712 AssertionStats
const& stats;
11713 AssertionResult
const& result;
11715 std::string passOrFail;
11716 std::string messageLabel;
11717 std::string message;
11718 std::vector<MessageInfo> messages;
11719 bool printInfoMessages;
11722std::size_t makeRatio(std::size_t number, std::size_t total) {
11723 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
11724 return (ratio == 0 && number > 0) ? 1 : ratio;
11727std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {
11728 if (i > j && i > k)
11737 enum Justification { Left, Right };
11740 Justification justification;
11742struct ColumnBreak {};
11754 static const uint64_t s_nanosecondsInAMicrosecond = 1000;
11755 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
11756 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
11757 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
11759 uint64_t m_inNanoseconds;
11763 explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
11764 : m_inNanoseconds(inNanoseconds),
11766 if (m_units == Unit::Auto) {
11767 if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
11768 m_units = Unit::Nanoseconds;
11769 else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
11770 m_units = Unit::Microseconds;
11771 else if (m_inNanoseconds < s_nanosecondsInASecond)
11772 m_units = Unit::Milliseconds;
11773 else if (m_inNanoseconds < s_nanosecondsInAMinute)
11774 m_units = Unit::Seconds;
11776 m_units = Unit::Minutes;
11781 auto value() const ->
double {
11783 case Unit::Microseconds:
11784 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMicrosecond);
11785 case Unit::Milliseconds:
11786 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMillisecond);
11787 case Unit::Seconds:
11788 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInASecond);
11789 case Unit::Minutes:
11790 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMinute);
11792 return static_cast<double>(m_inNanoseconds);
11795 auto unitsAsString() const -> std::
string {
11797 case Unit::Nanoseconds:
11799 case Unit::Microseconds:
11801 case Unit::Milliseconds:
11803 case Unit::Seconds:
11805 case Unit::Minutes:
11808 return "** internal error **";
11812 friend auto operator << (std::ostream& os, Duration
const& duration) -> std::ostream& {
11813 return os << duration.value() <<
" " << duration.unitsAsString();
11818class TablePrinter {
11819 std::ostream& m_os;
11820 std::vector<ColumnInfo> m_columnInfos;
11821 std::ostringstream m_oss;
11822 int m_currentColumn = -1;
11823 bool m_isOpen =
false;
11826 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
11828 m_columnInfos( std::move( columnInfos ) ) {}
11830 auto columnInfos() const -> std::vector<ColumnInfo> const& {
11831 return m_columnInfos;
11837 *
this << RowBreak();
11838 for (
auto const&
info : m_columnInfos)
11839 *
this <<
info.name << ColumnBreak();
11840 *
this << RowBreak();
11841 m_os << Catch::getLineOfChars<
'-'>() <<
"\n";
11846 *
this << RowBreak();
11852 template<
typename T>
11853 friend TablePrinter&
operator << (TablePrinter& tp, T
const& value) {
11858 friend TablePrinter&
operator << (TablePrinter& tp, ColumnBreak) {
11859 auto colStr = tp.m_oss.str();
11861 auto strSize = Catch::StringRef(colStr).numberOfCharacters();
11864 if (tp.m_currentColumn ==
static_cast<int>(tp.m_columnInfos.size() - 1)) {
11865 tp.m_currentColumn = -1;
11868 tp.m_currentColumn++;
11870 auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
11871 auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width))
11872 ? std::string(colInfo.width - (strSize + 2), ' ')
11874 if (colInfo.justification == ColumnInfo::Left)
11875 tp.m_os << colStr << padding <<
" ";
11877 tp.m_os << padding << colStr <<
" ";
11881 friend TablePrinter&
operator << (TablePrinter& tp, RowBreak) {
11882 if (tp.m_currentColumn > 0) {
11884 tp.m_currentColumn = -1;
11890ConsoleReporter::ConsoleReporter(ReporterConfig
const& config)
11891 : StreamingReporterBase(config),
11892 m_tablePrinter(new TablePrinter(config.stream(),
11894 {
"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
11895 {
"iters", 8, ColumnInfo::Right },
11896 {
"elapsed ns", 14, ColumnInfo::Right },
11897 {
"average", 14, ColumnInfo::Right }
11899ConsoleReporter::~ConsoleReporter() =
default;
11901std::string ConsoleReporter::getDescription() {
11902 return "Reports test results as plain lines of text";
11905void ConsoleReporter::noMatchingTestCases(std::string
const& spec) {
11906 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
11909void ConsoleReporter::assertionStarting(
AssertionInfo const&) {}
11911bool ConsoleReporter::assertionEnded(AssertionStats
const& _assertionStats) {
11912 AssertionResult
const& result = _assertionStats.assertionResult;
11914 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
11922 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
11924 stream << std::endl;
11928void ConsoleReporter::sectionStarting(
SectionInfo const& _sectionInfo) {
11929 m_headerPrinted =
false;
11930 StreamingReporterBase::sectionStarting(_sectionInfo);
11932void ConsoleReporter::sectionEnded(SectionStats
const& _sectionStats) {
11933 m_tablePrinter->close();
11934 if (_sectionStats.missingAssertions) {
11937 if (m_sectionStack.size() > 1)
11938 stream <<
"\nNo assertions in section";
11940 stream <<
"\nNo assertions in test case";
11941 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" << std::endl;
11943 if (m_config->showDurations() == ShowDurations::Always) {
11944 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name << std::endl;
11946 if (m_headerPrinted) {
11947 m_headerPrinted =
false;
11949 StreamingReporterBase::sectionEnded(_sectionStats);
11952void ConsoleReporter::benchmarkStarting(BenchmarkInfo
const&
info) {
11953 lazyPrintWithoutClosingBenchmarkTable();
11955 auto nameCol = Column(
info.name ).width(
static_cast<std::size_t
>( m_tablePrinter->columnInfos()[0].width - 2 ) );
11957 bool firstLine =
true;
11958 for (
auto line : nameCol) {
11960 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
11964 (*m_tablePrinter) << line << ColumnBreak();
11967void ConsoleReporter::benchmarkEnded(BenchmarkStats
const& stats) {
11968 Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
11970 << stats.iterations << ColumnBreak()
11971 << stats.elapsedTimeInNanoseconds << ColumnBreak()
11972 << average << ColumnBreak();
11975void ConsoleReporter::testCaseEnded(TestCaseStats
const& _testCaseStats) {
11976 m_tablePrinter->close();
11977 StreamingReporterBase::testCaseEnded(_testCaseStats);
11978 m_headerPrinted =
false;
11980void ConsoleReporter::testGroupEnded(TestGroupStats
const& _testGroupStats) {
11981 if (currentGroupInfo.used) {
11982 printSummaryDivider();
11983 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
11984 printTotals(_testGroupStats.totals);
11985 stream <<
'\n' << std::endl;
11987 StreamingReporterBase::testGroupEnded(_testGroupStats);
11989void ConsoleReporter::testRunEnded(TestRunStats
const& _testRunStats) {
11990 printTotalsDivider(_testRunStats.totals);
11991 printTotals(_testRunStats.totals);
11992 stream << std::endl;
11993 StreamingReporterBase::testRunEnded(_testRunStats);
11996void ConsoleReporter::lazyPrint() {
11998 m_tablePrinter->close();
11999 lazyPrintWithoutClosingBenchmarkTable();
12002void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
12004 if (!currentTestRunInfo.used)
12005 lazyPrintRunInfo();
12006 if (!currentGroupInfo.used)
12007 lazyPrintGroupInfo();
12009 if (!m_headerPrinted) {
12010 printTestCaseAndSectionHeader();
12011 m_headerPrinted =
true;
12014void ConsoleReporter::lazyPrintRunInfo() {
12015 stream << '\n' << getLineOfChars<'~'>() <<
'\n';
12017 stream << currentTestRunInfo->name
12018 <<
" is a Catch v" << libraryVersion() <<
" host application.\n"
12019 <<
"Run with -? for options\n\n";
12021 if (m_config->rngSeed() != 0)
12022 stream <<
"Randomness seeded to: " << m_config->rngSeed() <<
"\n\n";
12024 currentTestRunInfo.used =
true;
12026void ConsoleReporter::lazyPrintGroupInfo() {
12027 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
12028 printClosedHeader(
"Group: " + currentGroupInfo->name);
12029 currentGroupInfo.used =
true;
12032void ConsoleReporter::printTestCaseAndSectionHeader() {
12033 assert(!m_sectionStack.empty());
12034 printOpenHeader(currentTestCaseInfo->name);
12036 if (m_sectionStack.size() > 1) {
12037 Colour colourGuard(Colour::Headers);
12040 it = m_sectionStack.begin() + 1,
12041 itEnd = m_sectionStack.
end();
12042 for (; it != itEnd; ++it)
12043 printHeaderString(it->
name, 2);
12048 if (!lineInfo.empty()) {
12049 stream << getLineOfChars<
'-'>() <<
'\n';
12050 Colour colourGuard(Colour::FileName);
12051 stream << lineInfo <<
'\n';
12053 stream << getLineOfChars<
'.'>() <<
'\n' << std::endl;
12056void ConsoleReporter::printClosedHeader(std::string
const& _name) {
12057 printOpenHeader(_name);
12058 stream << getLineOfChars<
'.'>() <<
'\n';
12060void ConsoleReporter::printOpenHeader(std::string
const& _name) {
12061 stream << getLineOfChars<
'-'>() <<
'\n';
12063 Colour colourGuard(Colour::Headers);
12064 printHeaderString(_name);
12070void ConsoleReporter::printHeaderString(std::string
const& _string, std::size_t indent) {
12071 std::size_t i = _string.find(
": ");
12072 if (i != std::string::npos)
12076 stream << Column(_string).indent(indent + i).initialIndent(indent) <<
'\n';
12079struct SummaryColumn {
12081 SummaryColumn( std::string _label, Colour::Code _colour )
12082 : label( std::move( _label ) ),
12084 SummaryColumn addRow( std::size_t count ) {
12085 ReusableStringStream rss;
12087 std::string row = rss.str();
12088 for (
auto& oldRow : rows) {
12089 while (oldRow.size() < row.size())
12090 oldRow =
' ' + oldRow;
12091 while (oldRow.size() > row.size())
12094 rows.push_back(row);
12100 std::vector<std::string> rows;
12104void ConsoleReporter::printTotals(
Totals const& totals ) {
12105 if (totals.testCases.total() == 0) {
12106 stream <<
Colour(Colour::Warning) <<
"No tests ran\n";
12107 }
else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {
12108 stream <<
Colour(Colour::ResultSuccess) <<
"All tests passed";
12110 <<
pluralise(totals.assertions.passed,
"assertion") <<
" in "
12111 <<
pluralise(totals.testCases.passed,
"test case") <<
')'
12115 std::vector<SummaryColumn> columns;
12116 columns.push_back(SummaryColumn(
"", Colour::None)
12117 .addRow(totals.testCases.total())
12118 .addRow(totals.assertions.total()));
12119 columns.push_back(SummaryColumn(
"passed", Colour::Success)
12120 .addRow(totals.testCases.passed)
12121 .addRow(totals.assertions.passed));
12122 columns.push_back(SummaryColumn(
"failed", Colour::ResultError)
12123 .addRow(totals.testCases.failed)
12124 .addRow(totals.assertions.failed));
12125 columns.push_back(SummaryColumn(
"failed as expected", Colour::ResultExpectedFailure)
12126 .addRow(totals.testCases.failedButOk)
12127 .addRow(totals.assertions.failedButOk));
12129 printSummaryRow(
"test cases", columns, 0);
12130 printSummaryRow(
"assertions", columns, 1);
12133void ConsoleReporter::printSummaryRow(std::string
const& label, std::vector<SummaryColumn>
const& cols, std::size_t row) {
12134 for (
auto col : cols) {
12135 std::string value = col.rows[row];
12136 if (col.label.empty()) {
12137 stream << label <<
": ";
12141 stream <<
Colour(Colour::Warning) <<
"- none -";
12142 }
else if (value !=
"0") {
12143 stream <<
Colour(Colour::LightGrey) <<
" | ";
12144 stream <<
Colour(col.colour)
12145 << value <<
' ' << col.label;
12151void ConsoleReporter::printTotalsDivider(
Totals const& totals) {
12152 if (totals.testCases.total() > 0) {
12153 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
12154 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
12155 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
12156 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
12157 findMax(failedRatio, failedButOkRatio, passedRatio)++;
12158 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
12159 findMax(failedRatio, failedButOkRatio, passedRatio)--;
12161 stream <<
Colour(Colour::Error) << std::string(failedRatio,
'=');
12162 stream <<
Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio,
'=');
12163 if (totals.testCases.allPassed())
12164 stream <<
Colour(Colour::ResultSuccess) << std::string(passedRatio,
'=');
12166 stream <<
Colour(Colour::Success) << std::string(passedRatio,
'=');
12168 stream <<
Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1,
'=');
12172void ConsoleReporter::printSummaryDivider() {
12173 stream << getLineOfChars<
'-'>() <<
'\n';
12176CATCH_REGISTER_REPORTER(
"console", ConsoleReporter)
12180#if defined(_MSC_VER)
12181#pragma warning(pop)
12189#include <algorithm>
12194 std::string getCurrentTimestamp() {
12198 std::time(&rawtime);
12199 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
12202 std::tm timeInfo = {};
12203 gmtime_s(&timeInfo, &rawtime);
12206 timeInfo = std::gmtime(&rawtime);
12209 char timeStamp[timeStampSize];
12210 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
12213 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
12215 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
12217 return std::string(timeStamp);
12220 std::string fileNameTag(
const std::vector<std::string> &tags) {
12221 auto it = std::find_if(
begin(tags),
12223 [] (std::string
const&
tag) {
return tag.front() ==
'#'; });
12224 if (it != tags.end())
12225 return it->substr(1);
12226 return std::string();
12230 JunitReporter::JunitReporter( ReporterConfig
const& _config )
12231 : CumulativeReporterBase( _config ),
12232 xml( _config.stream() )
12234 m_reporterPrefs.shouldRedirectStdOut =
true;
12237 JunitReporter::~JunitReporter() {}
12239 std::string JunitReporter::getDescription() {
12240 return "Reports test results in an XML format that looks like Ant's junitreport target";
12243 void JunitReporter::noMatchingTestCases( std::string
const& ) {}
12245 void JunitReporter::testRunStarting( TestRunInfo
const& runInfo ) {
12246 CumulativeReporterBase::testRunStarting( runInfo );
12247 xml.startElement(
"testsuites" );
12250 void JunitReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
12251 suiteTimer.start();
12252 stdOutForSuite.clear();
12253 stdErrForSuite.clear();
12254 unexpectedExceptions = 0;
12255 CumulativeReporterBase::testGroupStarting( groupInfo );
12258 void JunitReporter::testCaseStarting(
TestCaseInfo const& testCaseInfo ) {
12259 m_okToFail = testCaseInfo.okToFail();
12262 bool JunitReporter::assertionEnded( AssertionStats
const& assertionStats ) {
12264 unexpectedExceptions++;
12265 return CumulativeReporterBase::assertionEnded( assertionStats );
12268 void JunitReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
12269 stdOutForSuite += testCaseStats.stdOut;
12270 stdErrForSuite += testCaseStats.stdErr;
12271 CumulativeReporterBase::testCaseEnded( testCaseStats );
12274 void JunitReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
12275 double suiteTime = suiteTimer.getElapsedSeconds();
12276 CumulativeReporterBase::testGroupEnded( testGroupStats );
12277 writeGroup( *m_testGroups.back(), suiteTime );
12280 void JunitReporter::testRunEndedCumulative() {
12284 void JunitReporter::writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
12285 XmlWriter::ScopedElement
e = xml.scopedElement(
"testsuite" );
12286 TestGroupStats
const& stats = groupNode.value;
12287 xml.writeAttribute(
"name", stats.groupInfo.name );
12288 xml.writeAttribute(
"errors", unexpectedExceptions );
12289 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
12290 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
12291 xml.writeAttribute(
"hostname",
"tbd" );
12292 if( m_config->showDurations() == ShowDurations::Never )
12293 xml.writeAttribute(
"time",
"" );
12295 xml.writeAttribute(
"time", suiteTime );
12296 xml.writeAttribute(
"timestamp", getCurrentTimestamp() );
12299 for(
auto const& child : groupNode.children )
12300 writeTestCase( *child );
12302 xml.scopedElement(
"system-out" ).writeText(
trim( stdOutForSuite ),
false );
12303 xml.scopedElement(
"system-err" ).writeText(
trim( stdErrForSuite ),
false );
12306 void JunitReporter::writeTestCase( TestCaseNode
const& testCaseNode ) {
12307 TestCaseStats
const& stats = testCaseNode.value;
12311 assert( testCaseNode.children.size() == 1 );
12312 SectionNode
const& rootSection = *testCaseNode.children.front();
12314 std::string className = stats.testInfo.className;
12316 if( className.empty() ) {
12317 className = fileNameTag(stats.testInfo.tags);
12318 if ( className.empty() )
12319 className =
"global";
12322 if ( !m_config->name().empty() )
12323 className = m_config->name() + "." + className;
12325 writeSection( className,
"", rootSection );
12328 void JunitReporter::writeSection( std::string
const& className,
12329 std::string
const& rootName,
12330 SectionNode
const& sectionNode ) {
12331 std::string
name =
trim( sectionNode.stats.sectionInfo.name );
12332 if( !rootName.empty() )
12335 if( !sectionNode.assertions.empty() ||
12336 !sectionNode.stdOut.empty() ||
12337 !sectionNode.stdErr.empty() ) {
12338 XmlWriter::ScopedElement
e = xml.scopedElement(
"testcase" );
12339 if( className.empty() ) {
12340 xml.writeAttribute(
"classname",
name );
12341 xml.writeAttribute(
"name",
"root" );
12344 xml.writeAttribute(
"classname", className );
12345 xml.writeAttribute(
"name",
name );
12349 writeAssertions( sectionNode );
12351 if( !sectionNode.stdOut.empty() )
12352 xml.scopedElement(
"system-out" ).writeText(
trim( sectionNode.stdOut ),
false );
12353 if( !sectionNode.stdErr.empty() )
12354 xml.scopedElement(
"system-err" ).writeText(
trim( sectionNode.stdErr ),
false );
12356 for(
auto const& childNode : sectionNode.childSections )
12357 if( className.empty() )
12358 writeSection(
name,
"", *childNode );
12360 writeSection( className,
name, *childNode );
12363 void JunitReporter::writeAssertions( SectionNode
const& sectionNode ) {
12364 for(
auto const& assertion : sectionNode.assertions )
12365 writeAssertion( assertion );
12368 void JunitReporter::writeAssertion( AssertionStats
const& stats ) {
12369 AssertionResult
const& result = stats.assertionResult;
12370 if( !result.isOk() ) {
12371 std::string elementName;
12372 switch( result.getResultType() ) {
12375 elementName =
"error";
12378 elementName =
"failure";
12381 elementName =
"failure";
12384 elementName =
"failure";
12394 elementName =
"internalError";
12398 XmlWriter::ScopedElement
e = xml.scopedElement( elementName );
12400 xml.writeAttribute(
"message", result.getExpandedExpression() );
12401 xml.writeAttribute(
"type", result.getTestMacroName() );
12404 if( !result.getMessage().empty() )
12405 rss << result.getMessage() <<
'\n';
12406 for(
auto const& msg : stats.infoMessages )
12408 rss << msg.message <<
'\n';
12410 rss <<
"at " << result.getSourceInfo();
12411 xml.writeText( rss.str(),
false );
12415 CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
12423 void MultipleReporters::add( IStreamingReporterPtr&& reporter ) {
12424 m_reporters.push_back( std::move( reporter ) );
12427 ReporterPreferences MultipleReporters::getPreferences()
const {
12428 return m_reporters[0]->getPreferences();
12431 std::set<Verbosity> MultipleReporters::getSupportedVerbosities() {
12432 return std::set<Verbosity>{ };
12435 void MultipleReporters::noMatchingTestCases( std::string
const& spec ) {
12436 for(
auto const& reporter : m_reporters )
12437 reporter->noMatchingTestCases( spec );
12440 void MultipleReporters::benchmarkStarting( BenchmarkInfo
const& benchmarkInfo ) {
12441 for(
auto const& reporter : m_reporters )
12442 reporter->benchmarkStarting( benchmarkInfo );
12444 void MultipleReporters::benchmarkEnded( BenchmarkStats
const& benchmarkStats ) {
12445 for(
auto const& reporter : m_reporters )
12446 reporter->benchmarkEnded( benchmarkStats );
12449 void MultipleReporters::testRunStarting( TestRunInfo
const& testRunInfo ) {
12450 for(
auto const& reporter : m_reporters )
12451 reporter->testRunStarting( testRunInfo );
12454 void MultipleReporters::testGroupStarting( GroupInfo
const& groupInfo ) {
12455 for(
auto const& reporter : m_reporters )
12456 reporter->testGroupStarting( groupInfo );
12459 void MultipleReporters::testCaseStarting(
TestCaseInfo const& testInfo ) {
12460 for(
auto const& reporter : m_reporters )
12461 reporter->testCaseStarting( testInfo );
12464 void MultipleReporters::sectionStarting(
SectionInfo const& sectionInfo ) {
12465 for(
auto const& reporter : m_reporters )
12466 reporter->sectionStarting( sectionInfo );
12469 void MultipleReporters::assertionStarting(
AssertionInfo const& assertionInfo ) {
12470 for(
auto const& reporter : m_reporters )
12471 reporter->assertionStarting( assertionInfo );
12475 bool MultipleReporters::assertionEnded( AssertionStats
const& assertionStats ) {
12476 bool clearBuffer =
false;
12477 for(
auto const& reporter : m_reporters )
12478 clearBuffer |= reporter->assertionEnded( assertionStats );
12479 return clearBuffer;
12482 void MultipleReporters::sectionEnded( SectionStats
const& sectionStats ) {
12483 for(
auto const& reporter : m_reporters )
12484 reporter->sectionEnded( sectionStats );
12487 void MultipleReporters::testCaseEnded( TestCaseStats
const& testCaseStats ) {
12488 for(
auto const& reporter : m_reporters )
12489 reporter->testCaseEnded( testCaseStats );
12492 void MultipleReporters::testGroupEnded( TestGroupStats
const& testGroupStats ) {
12493 for(
auto const& reporter : m_reporters )
12494 reporter->testGroupEnded( testGroupStats );
12497 void MultipleReporters::testRunEnded( TestRunStats
const& testRunStats ) {
12498 for(
auto const& reporter : m_reporters )
12499 reporter->testRunEnded( testRunStats );
12502 void MultipleReporters::skipTest(
TestCaseInfo const& testInfo ) {
12503 for(
auto const& reporter : m_reporters )
12504 reporter->skipTest( testInfo );
12507 bool MultipleReporters::isMulti()
const {
12515#if defined(_MSC_VER)
12516#pragma warning(push)
12517#pragma warning(disable:4061)
12523 XmlReporter::XmlReporter( ReporterConfig
const& _config )
12524 : StreamingReporterBase( _config ),
12525 m_xml(_config.stream())
12527 m_reporterPrefs.shouldRedirectStdOut =
true;
12530 XmlReporter::~XmlReporter() =
default;
12532 std::string XmlReporter::getDescription() {
12533 return "Reports test results as an XML document";
12536 std::string XmlReporter::getStylesheetRef()
const {
12537 return std::string();
12540 void XmlReporter::writeSourceInfo(
SourceLineInfo const& sourceInfo ) {
12542 .writeAttribute(
"filename", sourceInfo.file )
12543 .writeAttribute(
"line", sourceInfo.line );
12546 void XmlReporter::noMatchingTestCases( std::string
const& s ) {
12547 StreamingReporterBase::noMatchingTestCases( s );
12550 void XmlReporter::testRunStarting( TestRunInfo
const& testInfo ) {
12551 StreamingReporterBase::testRunStarting( testInfo );
12552 std::string stylesheetRef = getStylesheetRef();
12553 if( !stylesheetRef.empty() )
12554 m_xml.writeStylesheetRef( stylesheetRef );
12555 m_xml.startElement(
"Catch" );
12556 if( !m_config->name().empty() )
12557 m_xml.writeAttribute(
"name", m_config->name() );
12560 void XmlReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
12561 StreamingReporterBase::testGroupStarting( groupInfo );
12562 m_xml.startElement(
"Group" )
12563 .writeAttribute(
"name", groupInfo.name );
12566 void XmlReporter::testCaseStarting(
TestCaseInfo const& testInfo ) {
12567 StreamingReporterBase::testCaseStarting(testInfo);
12568 m_xml.startElement(
"TestCase" )
12569 .writeAttribute(
"name",
trim( testInfo.name ) )
12570 .writeAttribute(
"description", testInfo.description )
12571 .writeAttribute(
"tags", testInfo.tagsAsString() );
12573 writeSourceInfo( testInfo.lineInfo );
12575 if ( m_config->showDurations() == ShowDurations::Always )
12576 m_testCaseTimer.start();
12577 m_xml.ensureTagClosed();
12580 void XmlReporter::sectionStarting(
SectionInfo const& sectionInfo ) {
12581 StreamingReporterBase::sectionStarting( sectionInfo );
12582 if( m_sectionDepth++ > 0 ) {
12583 m_xml.startElement(
"Section" )
12584 .writeAttribute(
"name",
trim( sectionInfo.name ) )
12585 .writeAttribute(
"description", sectionInfo.description );
12586 writeSourceInfo( sectionInfo.lineInfo );
12587 m_xml.ensureTagClosed();
12591 void XmlReporter::assertionStarting(
AssertionInfo const& ) { }
12593 bool XmlReporter::assertionEnded( AssertionStats
const& assertionStats ) {
12595 AssertionResult
const& result = assertionStats.assertionResult;
12597 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
12601 for(
auto const& msg : assertionStats.infoMessages ) {
12603 m_xml.scopedElement(
"Info" )
12604 .writeText( msg.message );
12606 m_xml.scopedElement(
"Warning" )
12607 .writeText( msg.message );
12617 if( result.hasExpression() ) {
12618 m_xml.startElement(
"Expression" )
12619 .writeAttribute(
"success", result.succeeded() )
12620 .writeAttribute(
"type", result.getTestMacroName() );
12622 writeSourceInfo( result.getSourceInfo() );
12624 m_xml.scopedElement(
"Original" )
12625 .writeText( result.getExpression() );
12626 m_xml.scopedElement(
"Expanded" )
12627 .writeText( result.getExpandedExpression() );
12631 switch( result.getResultType() ) {
12633 m_xml.startElement(
"Exception" );
12634 writeSourceInfo( result.getSourceInfo() );
12635 m_xml.writeText( result.getMessage() );
12636 m_xml.endElement();
12639 m_xml.startElement(
"FatalErrorCondition" );
12640 writeSourceInfo( result.getSourceInfo() );
12641 m_xml.writeText( result.getMessage() );
12642 m_xml.endElement();
12645 m_xml.scopedElement(
"Info" )
12646 .writeText( result.getMessage() );
12652 m_xml.startElement(
"Failure" );
12653 writeSourceInfo( result.getSourceInfo() );
12654 m_xml.writeText( result.getMessage() );
12655 m_xml.endElement();
12661 if( result.hasExpression() )
12662 m_xml.endElement();
12667 void XmlReporter::sectionEnded( SectionStats
const& sectionStats ) {
12668 StreamingReporterBase::sectionEnded( sectionStats );
12669 if( --m_sectionDepth > 0 ) {
12670 XmlWriter::ScopedElement
e = m_xml.scopedElement(
"OverallResults" );
12671 e.writeAttribute(
"successes", sectionStats.assertions.passed );
12672 e.writeAttribute(
"failures", sectionStats.assertions.failed );
12673 e.writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
12675 if ( m_config->showDurations() == ShowDurations::Always )
12676 e.writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
12678 m_xml.endElement();
12682 void XmlReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
12683 StreamingReporterBase::testCaseEnded( testCaseStats );
12684 XmlWriter::ScopedElement
e = m_xml.scopedElement(
"OverallResult" );
12685 e.writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
12687 if ( m_config->showDurations() == ShowDurations::Always )
12688 e.writeAttribute(
"durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
12690 if( !testCaseStats.stdOut.empty() )
12691 m_xml.scopedElement(
"StdOut" ).writeText(
trim( testCaseStats.stdOut ),
false );
12692 if( !testCaseStats.stdErr.empty() )
12693 m_xml.scopedElement(
"StdErr" ).writeText(
trim( testCaseStats.stdErr ),
false );
12695 m_xml.endElement();
12698 void XmlReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
12699 StreamingReporterBase::testGroupEnded( testGroupStats );
12701 m_xml.scopedElement(
"OverallResults" )
12702 .writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
12703 .writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
12704 .writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
12705 m_xml.endElement();
12708 void XmlReporter::testRunEnded( TestRunStats
const& testRunStats ) {
12709 StreamingReporterBase::testRunEnded( testRunStats );
12710 m_xml.scopedElement(
"OverallResults" )
12711 .writeAttribute(
"successes", testRunStats.totals.assertions.passed )
12712 .writeAttribute(
"failures", testRunStats.totals.assertions.failed )
12713 .writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
12714 m_xml.endElement();
12717 CATCH_REGISTER_REPORTER(
"xml", XmlReporter )
12721#if defined(_MSC_VER)
12722#pragma warning(pop)
12727 LeakDetector leakDetector;
12731#pragma clang diagnostic pop
12737#ifdef CATCH_CONFIG_MAIN
12742#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
12744extern "C" int wmain (
int argc,
wchar_t * argv[],
wchar_t * []) {
12747int main (
int argc,
char * argv[]) {
12750 return Catch::Session().run( argc, argv );
12756int main (
int argc,
char *
const argv[]) {
12757#if !CATCH_ARC_ENABLED
12758 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
12761 Catch::registerTestMethods();
12762 int result = Catch::Session().run( argc, (
char**)argv );
12764#if !CATCH_ARC_ENABLED
12776#if !defined(CATCH_CONFIG_IMPL_ONLY)
12778#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
12779# undef CLARA_CONFIG_MAIN
12782#if !defined(CATCH_CONFIG_DISABLE)
12785#ifdef CATCH_CONFIG_PREFIX_ALL
12787#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
12788#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
12790#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ )
12791#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
12792#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
12793#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12794#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
12796#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
12798#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12799#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
12800#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12801#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12802#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
12804#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ )
12805#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
12806#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
12807#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12808#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
12810#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12812#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12813#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
12815#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
12818#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
12819#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
12820#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
12822#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
12823#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
12824#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
12825#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
12826#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
12827#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
12828#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12829#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12831#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
12834#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
12835#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
12836#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc )
12837#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc )
12838#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
12839#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc )
12840#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
12845#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
12846#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
12848#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
12849#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
12850#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
12851#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12852#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
12854#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
12856#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12857#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
12858#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12859#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12860#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
12862#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12863#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
12864#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
12865#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12866#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
12868#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12870#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12871#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
12873#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
12876#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
12877#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
12878#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
12880#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
12881#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
12882#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
12883#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
12884#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
12885#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
12886#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12887#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
12888#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
12892#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
12895#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
12896#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
12898#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc )
12899#define WHEN( desc ) SECTION( std::string(" When: ") + desc )
12900#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc )
12901#define THEN( desc ) SECTION( std::string(" Then: ") + desc )
12902#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc )
12909#ifdef CATCH_CONFIG_PREFIX_ALL
12911#define CATCH_REQUIRE( ... ) (void)(0)
12912#define CATCH_REQUIRE_FALSE( ... ) (void)(0)
12914#define CATCH_REQUIRE_THROWS( ... ) (void)(0)
12915#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
12916#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
12917#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12918#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
12920#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
12922#define CATCH_CHECK( ... ) (void)(0)
12923#define CATCH_CHECK_FALSE( ... ) (void)(0)
12924#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__)
12925#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
12926#define CATCH_CHECK_NOFAIL( ... ) (void)(0)
12928#define CATCH_CHECK_THROWS( ... ) (void)(0)
12929#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
12930#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0)
12931#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12932#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
12934#define CATCH_CHECK_NOTHROW( ... ) (void)(0)
12936#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12937#define CATCH_CHECK_THAT( arg, matcher ) (void)(0)
12939#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
12942#define CATCH_INFO( msg ) (void)(0)
12943#define CATCH_WARN( msg ) (void)(0)
12944#define CATCH_CAPTURE( msg ) (void)(0)
12946#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
12947#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
12948#define CATCH_METHOD_AS_TEST_CASE( method, ... )
12949#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
12950#define CATCH_SECTION( ... )
12951#define CATCH_FAIL( ... ) (void)(0)
12952#define CATCH_FAIL_CHECK( ... ) (void)(0)
12953#define CATCH_SUCCEED( ... ) (void)(0)
12955#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
12958#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
12959#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 )
12960#define CATCH_GIVEN( desc )
12961#define CATCH_WHEN( desc )
12962#define CATCH_AND_WHEN( desc )
12963#define CATCH_THEN( desc )
12964#define CATCH_AND_THEN( desc )
12969#define REQUIRE( ... ) (void)(0)
12970#define REQUIRE_FALSE( ... ) (void)(0)
12972#define REQUIRE_THROWS( ... ) (void)(0)
12973#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
12974#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
12975#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12976#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
12978#define REQUIRE_NOTHROW( ... ) (void)(0)
12980#define CHECK( ... ) (void)(0)
12981#define CHECK_FALSE( ... ) (void)(0)
12982#define CHECKED_IF( ... ) if (__VA_ARGS__)
12983#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
12984#define CHECK_NOFAIL( ... ) (void)(0)
12986#define CHECK_THROWS( ... ) (void)(0)
12987#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
12988#define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
12989#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12990#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
12992#define CHECK_NOTHROW( ... ) (void)(0)
12994#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
12995#define CHECK_THAT( arg, matcher ) (void)(0)
12997#define REQUIRE_THAT( arg, matcher ) (void)(0)
13000#define INFO( msg ) (void)(0)
13001#define WARN( msg ) (void)(0)
13002#define CAPTURE( msg ) (void)(0)
13004#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13005#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13006#define METHOD_AS_TEST_CASE( method, ... )
13007#define REGISTER_TEST_CASE( Function, ... ) (void)(0)
13008#define SECTION( ... )
13009#define FAIL( ... ) (void)(0)
13010#define FAIL_CHECK( ... ) (void)(0)
13011#define SUCCEED( ... ) (void)(0)
13012#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13016#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
13019#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )
13020#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
13022#define GIVEN( desc )
13023#define WHEN( desc )
13024#define AND_WHEN( desc )
13025#define THEN( desc )
13026#define AND_THEN( desc )
13039# pragma warning(pop)
13041# pragma clang diagnostic pop
13043#elif defined __GNUC__
13044# pragma GCC diagnostic pop
int main()
Definition test.cpp:87
char chars[]
Definition test.cpp:102
Env e
Definition Common.cc:2
Type
Definition Database.hh:9
void print(const VoxFrame &f)
Definition GameApi.cc:22580
bool operator<(const Dep &a1, const Dep &a2)
Definition GameApi_dep_add_find.cc:2905
std::string toLower(std::string s)
Definition GameApi_dep_env.cc:4600
float arg(Complex z)
Definition GameApi_pl.cc:31413
std::string trim(std::string s)
Definition Shader.cc:6754
std::vector< Item * > functions()
Definition accel.cc:335
int add(void *w)
Definition ui.cc:341
void * find(int i)
Definition ui.cc:347
void use(T)
Definition boxed_cast_test.cpp:8
std::ostream & operator<<(std::ostream &, Catch_global_namespace_dummy)
#define CATCH_INTERNAL_LINEINFO
Definition catch.hpp:308
void info(std::string info)
Definition check.cc:24
Definition catch.hpp:1541
auto allowThrows() const -> bool
~AssertionHandler()
Definition catch.hpp:1553
void handleExpr(ExprLhs< T > const &expr)
Definition catch.hpp:1560
void handleExceptionNotThrownAsExpected()
void handleThrowingCallSkipped()
AssertionHandler(StringRef macroName, SourceLineInfo const &lineInfo, StringRef capturedExpression, ResultDisposition::Flags resultDisposition)
void handleUnexpectedExceptionNotThrown()
void handleUnexpectedInflightException()
void handleExceptionThrownAsExpected()
void handleMessage(ResultWas::OfType resultType, StringRef const &message)
void handleExpr(ITransientExpression const &expr)
void increment()
Definition catch.hpp:1920
auto needsMoreIterations() -> bool
BenchmarkLooper(StringRef name)
Definition catch.hpp:1906
Definition catch.hpp:1315
BinaryExpr(bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs)
Definition catch.hpp:1326
Definition catch.hpp:2063
Approx & epsilon(T const &newEpsilon)
Definition catch.hpp:2127
Approx & margin(T const &newMargin)
Definition catch.hpp:2140
Approx & scale(T const &newScale)
Definition catch.hpp:2154
std::string toString() const
Approx(T const &value)
Definition catch.hpp:2082
Approx operator()(T const &value)
Definition catch.hpp:2073
static const bool value
Definition catch.hpp:766
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
Definition catch.hpp:2037
Definition catch.hpp:1373
auto operator!=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition catch.hpp:1387
auto operator>=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition catch.hpp:1403
auto operator>(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition catch.hpp:1395
auto operator<=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition catch.hpp:1407
auto makeUnaryExpr() const -> UnaryExpr< LhsT >
Definition catch.hpp:1411
ExprLhs(LhsT lhs)
Definition catch.hpp:1376
auto operator==(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition catch.hpp:1379
auto operator<(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition catch.hpp:1399
Definition catch.hpp:1519
LazyExpression & operator=(LazyExpression const &)=delete
friend class AssertionHandler
Definition catch.hpp:1520
LazyExpression(bool isNegated)
friend struct AssertionStats
Definition catch.hpp:1521
friend auto operator<<(std::ostream &os, LazyExpression const &lazyExpr) -> std::ostream &
LazyExpression(LazyExpression const &other)
friend class RunContext
Definition catch.hpp:1522
Definition catch.hpp:2691
MatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef matcherString)
Definition catch.hpp:2696
void streamReconstructedExpression(std::ostream &os) const override
Definition catch.hpp:2703
Definition catch.hpp:2412
bool match(T const &item) const override
Definition catch.hpp:2422
PredicateMatcher(std::function< bool(T const &)> const &elem, std::string const &descr)
Definition catch.hpp:2417
std::string describe() const override
Definition catch.hpp:2426
std::string toString() const
virtual ~MatcherUntypedBase()
virtual std::string describe() const =0
std::string m_cachedToString
Definition catch.hpp:2231
MatcherUntypedBase(MatcherUntypedBase const &)=default
MatcherUntypedBase()=default
auto str() const -> std::string
auto get() -> std::ostream &
Definition catch.hpp:678
ScopedMessage(MessageBuilder const &builder)
MessageInfo m_info
Definition catch.hpp:1638
Section(SectionInfo const &info)
std::size_t size_type
Definition catch.hpp:379
auto operator=(StringRef const &other) noexcept -> StringRef &
Definition catch.hpp:427
auto c_str() const -> char const *
auto substr(size_type start, size_type size) const noexcept -> StringRef
StringRef(StringRef const &other) noexcept
Definition catch.hpp:398
StringRef(char const *rawChars, size_type size) noexcept
Definition catch.hpp:413
~StringRef() noexcept
Definition catch.hpp:423
StringRef(StringRef &&other) noexcept
Definition catch.hpp:403
friend struct StringRefTestAccess
Definition catch.hpp:382
auto operator[](size_type index) const noexcept -> char
auto numberOfCharacters() const noexcept -> size_type
StringRef(std::string const &stdString) noexcept
Definition catch.hpp:418
void swap(StringRef &other) noexcept
StringRef() noexcept
Definition catch.hpp:394
auto operator!=(StringRef const &other) const noexcept -> bool
auto operator==(StringRef const &other) const noexcept -> bool
auto empty() const noexcept -> bool
Definition catch.hpp:446
auto size() const noexcept -> size_type
Definition catch.hpp:449
StringRef(char const *rawChars) noexcept
auto currentData() const noexcept -> char const *
Definition catch.hpp:2809
bool operator<(TestCase const &other) const
TestCase withName(std::string const &_newName) const
bool operator==(TestCase const &other) const
TestCaseInfo const & getTestCaseInfo() const
TestCase(ITestInvoker *testCase, TestCaseInfo &&info)
TestInvokerAsMethod(void(C::*testAsMethod)()) noexcept
Definition catch.hpp:488
void invoke() const override
Definition catch.hpp:490
Definition catch.hpp:1848
auto getElapsedSeconds() const -> double
auto getElapsedMilliseconds() const -> unsigned int
auto getElapsedMicroseconds() const -> uint64_t
auto getElapsedNanoseconds() const -> uint64_t
Definition catch.hpp:1335
UnaryExpr(LhsT lhs)
Definition catch.hpp:1343
Definition Effect.hh:1305
Definition Language.hh:26
void start()
Definition Main.cc:211
if( $mode==true)
Definition get_file_size.php:77
void function(void)
Definition memory_leak_test.cpp:26
convert($d)
Definition mesh_api.php:35
ret($return)
Definition mesh_login_result.php:5
left margin
Definition mesh_preview.php:76
d
Definition meshpage.php:3895
iVBORw0KGgoAAAANSUhEUgAAANcAAAB5CAMAAACdtUQZAAAA51BMVEX</div ></div >< div style="padding: 0px 0px; width: 1324px;">< div style="height: 400px; width: 1324px;"></div >< div itemscope itemtype="https: </div><div itemscope itemtype="https:</div >< div itemscope itemtype="https: </div></div><p><div style="padding:0px 0px;width:1324px;"><div></div><div itemscope itemtype="https:< ul >< li >< b > Application name
8AkrcAgqgAs9wqQ0ey2tkAo8gAuuQfeI4hPUH09fXHy8z4+fng4uNKXF/Lz9BzfoAcgpkQMTUAKjAbOT4Qr9AXhJ8Rl7ktMCwTosA...
Definition meshpage.php:1610
lazy data
Definition meshpage.php:1583
str
Definition meshpage.php:1778
tag
Definition meshpage.php:1785
n< br > font size
Definition meshpage.php:3536
url
Definition meshpage.php:1781
std::string convertUnknownEnumToString(E e)
Definition catch.hpp:830
const std::string unprintableString
std::string rangeToString(InputIterator first, InputIterator last)
Definition catch.hpp:988
std::enable_if<!std::is_enum< T >::value, std::string >::type convertUnstreamable(T const &value)
Definition catch.hpp:773
std::string rawMemoryToString(const void *object, std::size_t size)
std::string stringify(const T &e)
Definition catch.hpp:825
Definition catch.hpp:2363
Definition catch.hpp:2407
std::string finalizeDescription(const std::string &desc)
Definition catch.hpp:2405
Definition catch.hpp:2215
Definition catch.hpp:2453
Definition catch.hpp:2523
bool contains(InputIterator first, InputIterator last, T const &item)
Definition catch.hpp:2535
size_t count(InputIterator first, InputIterator last, T const &item)
Definition catch.hpp:2525
Definition catch.hpp:2522
Definition catch.hpp:2214
StdString::ContainsMatcher Contains(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Floating::WithinAbsMatcher WithinAbs(double target, double margin)
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
Definition catch.hpp:2438
StdString::RegexMatcher Matches(std::string const ®ex, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Vector::ContainsElementMatcher< T > VectorContains(T const &comparator)
Definition catch.hpp:2670
StdString::StartsWithMatcher StartsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Vector::UnorderedEqualsMatcher< T > UnorderedEquals(std::vector< T > const &target)
Definition catch.hpp:2680
StdString::EndsWithMatcher EndsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff)
StdString::EqualsMatcher Equals(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
T const & operator+(T const &value, StreamEndStop)
Definition catch.hpp:303
void toLowerInPlace(std::string &s)
std::string trim(std::string const &str)
auto makeMatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef matcherString) -> MatchExpr< ArgT, MatcherT >
Definition catch.hpp:2718
std::vector< TestCase > filterTests(std::vector< TestCase > const &testCases, TestSpec const &testSpec, IConfig const &config)
std::vector< std::unique_ptr< IExceptionTranslator const > > ExceptionTranslators
Definition catch.hpp:1997
std::shared_ptr< IReporterFactory > IReporterFactoryPtr
Definition catch.hpp:1952
void formatReconstructedExpression(std::ostream &os, std::string const &lhs, StringRef op, std::string const &rhs)
bool isOk(ResultWas::OfType resultType)
void handleExceptionMatchExpr(AssertionHandler &handler, std::string const &str, StringRef matcherString)
bool isJustInfo(int flags)
IMutableRegistryHub & getMutableRegistryHub()
TestCase makeTestCase(ITestInvoker *testCase, std::string const &className, NameAndTags const &nameAndTags, SourceLineInfo const &lineInfo)
auto operator+=(std::string &lhs, StringRef const &sr) -> std::string &
void handleExpression(ITransientExpression const &expr)
bool startsWith(std::string const &s, std::string const &prefix)
Matchers::Impl::MatcherBase< std::string > StringMatcher
Definition catch.hpp:2713
IRegistryHub & getRegistryHub()
std::string(*)() exceptionTranslateFunction
Definition catch.hpp:1994
bool shouldContinueOnFailure(int flags)
auto compareNotEqual(LhsT const &lhs, RhsT &&rhs) -> bool
Definition catch.hpp:1362
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
bool isFalseTest(int flags)
Definition catch.hpp:612
std::vector< TestCase > const & getAllTestCasesSorted(IConfig const &config)
auto getCurrentNanosecondsSinceEpoch() -> uint64_t
bool contains(std::string const &s, std::string const &infix)
bool matchTest(TestCase const &testCase, TestSpec const &testSpec, IConfig const &config)
ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
auto makeTestInvoker(void(*testAsFunction)()) noexcept -> ITestInvoker *
bool shouldSuppressFailure(int flags)
std::string toLower(std::string const &s)
std::shared_ptr< ITestInvoker > ITestCasePtr
Definition catch.hpp:342
auto getEstimatedClockResolution() -> uint64_t
bool endsWith(std::string const &s, std::string const &suffix)
std::string translateActiveException()
std::string rangeToString(Range const &range)
Definition catch.hpp:1122
auto makeStream(StringRef const &filename) -> IStream const *
IResultCapture & getResultCapture()
auto compareEqual(LhsT const &lhs, RhsT const &rhs) -> bool
Definition catch.hpp:1351
bool replaceInPlace(std::string &str, std::string const &replaceThis, std::string const &withThis)
Numeric sum(Range c)
Returns the sum total of the values in the Range c.
class ChaiScript_Language::Function max(Object a, Object b)
Returns the max of a or b. Requires that operator>(a, b) exists Equivalent to.
Object filter(Container c, Function f)
Takes elements from Container c that match function f, return them.
size_t count(const T &t_target, const typename T::key_type &t_key)
Definition bootstrap_stl.hpp:104
std::shared_ptr< B > make_shared(Arg &&... arg)
Definition chaiscript_defines.hpp:87
@ Method
Definition chaiscript_common.hpp:68
@ Arg
Definition chaiscript_common.hpp:69
@ Class
Definition chaiscript_common.hpp:69
@ Catch
Definition chaiscript_common.hpp:68
Mode
Definition mesh_prediction_scheme_constrained_multi_parallelogram_shared.h:23
@ None
Definition httplib.h:3086
@ Normal
Definition httplib.h:3752
Error
Definition httplib.h:1399
@ Success
Definition httplib.h:1400
std::unordered_multimap< std::string, std::string, detail::case_ignore::hash, detail::case_ignore::equal_to > Headers
Definition httplib.h:888
@ object
object (unordered set of name/value pairs)
Definition json.hpp:1221
@ string
string value
Definition json.hpp:1223
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:1781
*specialization for std::less< value_t > *see nlohmann::detail::value_t rhs const noexcept
Definition json.hpp:20328
P colour(EveryApi &ev, P p1, unsigned int col)
Definition test.cpp:106
double f(const std::string &, double, bool) noexcept
Definition profile_cpp_calls_2.cpp:4
bool operator==(const short_alloc< T, N, A1 > &x, const short_alloc< U, M, A2 > &y) noexcept
Definition short_alloc.hpp:145
bool operator!=(const short_alloc< T, N, A1 > &x, const short_alloc< U, M, A2 > &y) noexcept
Definition short_alloc.hpp:153
SourceLineInfo lineInfo
Definition catch.hpp:623
ResultDisposition::Flags resultDisposition
Definition catch.hpp:625
StringRef macroName
Definition catch.hpp:622
StringRef capturedExpression
Definition catch.hpp:624
Definition catch.hpp:1536
bool shouldThrow
Definition catch.hpp:1538
bool shouldDebugBreak
Definition catch.hpp:1537
AutoReg(ITestInvoker *invoker, SourceLineInfo const &lineInfo, StringRef const &classOrMethod, NameAndTags const &nameAndTags) noexcept
Choice
Definition catch.hpp:256
@ No
Definition catch.hpp:258
@ Yes
Definition catch.hpp:257
Definition catch.hpp:1786
Counts & operator+=(Counts const &other)
std::size_t failed
Definition catch.hpp:1795
std::size_t total() const
Counts operator-(Counts const &other) const
std::size_t failedButOk
Definition catch.hpp:1796
std::size_t passed
Definition catch.hpp:1794
Definition catch.hpp:1423
auto operator<=(T const &lhs) -> ExprLhs< T const & >
Definition catch.hpp:1425
Definition catch.hpp:2004
virtual ~IExceptionTranslatorRegistry()
virtual std::string translateActiveException() const =0
Definition catch.hpp:1999
virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const =0
virtual ~IExceptionTranslator()
Definition catch.hpp:1966
virtual void registerTest(TestCase const &testInfo)=0
virtual void registerReporter(std::string const &name, IReporterFactoryPtr const &factory)=0
virtual void registerStartupException() noexcept=0
virtual ~IMutableRegistryHub()
virtual void registerListener(IReporterFactoryPtr const &factory)=0
virtual void registerTagAlias(std::string const &alias, std::string const &tag, SourceLineInfo const &lineInfo)=0
virtual void registerTranslator(const IExceptionTranslator *translator)=0
Definition catch.hpp:1954
virtual ITestCaseRegistry const & getTestCaseRegistry() const =0
virtual ITagAliasRegistry const & getTagAliasRegistry() const =0
virtual StartupExceptionRegistry const & getStartupExceptionRegistry() const =0
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry()=0
virtual IReporterRegistry const & getReporterRegistry() const =0
Definition catch.hpp:1459
virtual void handleMessage(AssertionInfo const &info, ResultWas::OfType resultType, StringRef const &message, AssertionReaction &reaction)=0
virtual void benchmarkStarting(BenchmarkInfo const &info)=0
virtual const AssertionResult * getLastResult() const =0
virtual ~IResultCapture()
virtual void popScopedMessage(MessageInfo const &message)=0
virtual void handleFatalErrorCondition(StringRef message)=0
virtual void sectionEnded(SectionEndInfo const &endInfo)=0
virtual void handleExpr(AssertionInfo const &info, ITransientExpression const &expr, AssertionReaction &reaction)=0
virtual bool sectionStarted(SectionInfo const §ionInfo, Counts &assertions)=0
virtual void handleUnexpectedExceptionNotThrown(AssertionInfo const &info, AssertionReaction &reaction)=0
virtual void benchmarkEnded(BenchmarkStats const &stats)=0
virtual void handleIncomplete(AssertionInfo const &info)=0
virtual void pushScopedMessage(MessageInfo const &message)=0
virtual bool lastAssertionPassed()=0
virtual void assertionPassed()=0
virtual void handleNonExpr(AssertionInfo const &info, ResultWas::OfType resultType, AssertionReaction &reaction)=0
virtual void exceptionEarlyReported()=0
virtual std::string getCurrentTestName() const =0
virtual void handleUnexpectedInflightException(AssertionInfo const &info, std::string const &message, AssertionReaction &reaction)=0
virtual void sectionEndedEarly(SectionEndInfo const &endInfo)=0
Definition catch.hpp:2842
virtual bool aborting() const =0
virtual std::ostream & stream() const =0
virtual std::vector< TestCase > const & getAllTestsSorted(IConfig const &config) const =0
virtual std::vector< TestCase > const & getAllTests() const =0
virtual ~ITestCaseRegistry()
virtual void invoke() const =0
Definition catch.hpp:1293
auto getResult() const -> bool
Definition catch.hpp:1295
auto isBinaryExpression() const -> bool
Definition catch.hpp:1294
bool m_result
Definition catch.hpp:1308
bool m_isBinaryExpression
Definition catch.hpp:1307
virtual void streamReconstructedExpression(std::ostream &os) const =0
ITransientExpression(bool isBinaryExpression, bool result)
Definition catch.hpp:1298
virtual ~ITransientExpression()
MatchNotOf< T > operator!() const
Definition catch.hpp:2341
MatchAnyOf< T > operator||(MatcherBase const &other) const
Definition catch.hpp:2337
MatchAllOf< T > operator&&(MatcherBase const &other) const
Definition catch.hpp:2333
Definition catch.hpp:2367
std::string describe() const override
WithinAbsMatcher(double target, double margin)
bool match(double const &matchee) const override
Definition catch.hpp:2376
WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
bool match(double const &matchee) const override
std::string describe() const override
Definition catch.hpp:2252
std::vector< MatcherBase< ArgT > const * > m_matchers
Definition catch.hpp:2281
std::string describe() const override
Definition catch.hpp:2260
bool match(ArgT const &arg) const override
Definition catch.hpp:2253
Definition catch.hpp:2284
std::vector< MatcherBase< ArgT > const * > m_matchers
Definition catch.hpp:2314
std::string describe() const override
Definition catch.hpp:2293
bool match(ArgT const &arg) const override
Definition catch.hpp:2286
Definition catch.hpp:2318
bool match(ArgT const &arg) const override
Definition catch.hpp:2322
MatchNotOf(MatcherBase< ArgT > const &underlyingMatcher)
Definition catch.hpp:2320
std::string describe() const override
Definition catch.hpp:2326
MatcherBase< ArgT > const & m_underlyingMatcher
Definition catch.hpp:2329
Definition catch.hpp:2244
virtual bool match(PtrT *arg) const =0
Definition catch.hpp:2235
virtual bool match(ObjectT const &arg) const =0
Definition catch.hpp:2456
std::string adjustString(std::string const &str) const
std::string caseSensitivitySuffix() const
CasedString(std::string const &str, CaseSensitive::Choice caseSensitivity)
std::string m_str
Definition catch.hpp:2462
CaseSensitive::Choice m_caseSensitivity
Definition catch.hpp:2461
Definition catch.hpp:2477
bool match(std::string const &source) const override
ContainsMatcher(CasedString const &comparator)
Definition catch.hpp:2485
EndsWithMatcher(CasedString const &comparator)
bool match(std::string const &source) const override
Definition catch.hpp:2473
bool match(std::string const &source) const override
EqualsMatcher(CasedString const &comparator)
Definition catch.hpp:2490
std::string describe() const override
bool match(std::string const &matchee) const override
RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity)
Definition catch.hpp:2481
StartsWithMatcher(CasedString const &comparator)
bool match(std::string const &source) const override
CasedString m_comparator
Definition catch.hpp:2469
StringMatcherBase(std::string const &operation, CasedString const &comparator)
std::string describe() const override
std::string m_operation
Definition catch.hpp:2470
Definition catch.hpp:2546
ContainsElementMatcher(T const &comparator)
Definition catch.hpp:2548
bool match(std::vector< T > const &v) const override
Definition catch.hpp:2550
T const & m_comparator
Definition catch.hpp:2563
std::string describe() const override
Definition catch.hpp:2559
Definition catch.hpp:2567
std::vector< T > const & m_comparator
Definition catch.hpp:2593
std::string describe() const override
Definition catch.hpp:2589
ContainsMatcher(std::vector< T > const &comparator)
Definition catch.hpp:2569
bool match(std::vector< T > const &v) const override
Definition catch.hpp:2571
Definition catch.hpp:2597
bool match(std::vector< T > const &v) const override
Definition catch.hpp:2601
std::string describe() const override
Definition catch.hpp:2613
EqualsMatcher(std::vector< T > const &comparator)
Definition catch.hpp:2599
std::vector< T > const & m_comparator
Definition catch.hpp:2616
Definition catch.hpp:2620
bool match(std::vector< T > const &vec) const override
Definition catch.hpp:2622
UnorderedEqualsMatcher(std::vector< T > const &target)
Definition catch.hpp:2621
std::string describe() const override
Definition catch.hpp:2652
Definition catch.hpp:1619
MessageInfo m_info
Definition catch.hpp:1630
MessageBuilder(std::string const ¯oName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
MessageBuilder & operator<<(T const &value)
Definition catch.hpp:1625
Definition catch.hpp:1591
std::string macroName
Definition catch.hpp:1596
MessageInfo(std::string const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
unsigned int sequence
Definition catch.hpp:1600
bool operator<(MessageInfo const &other) const
SourceLineInfo lineInfo
Definition catch.hpp:1598
std::string message
Definition catch.hpp:1597
ResultWas::OfType type
Definition catch.hpp:1599
bool operator==(MessageInfo const &other) const
Definition catch.hpp:1608
MessageStream & operator<<(T const &value)
Definition catch.hpp:1611
ReusableStringStream m_stream
Definition catch.hpp:1616
RegistrarForTagAliases(char const *alias, char const *tag, SourceLineInfo const &lineInfo)
Flags
Definition catch.hpp:601
@ SuppressFail
Definition catch.hpp:606
@ FalseTest
Definition catch.hpp:605
@ ContinueOnFailure
Definition catch.hpp:604
@ Normal
Definition catch.hpp:602
OfType
Definition catch.hpp:577
@ FailureBit
Definition catch.hpp:583
@ Info
Definition catch.hpp:580
@ ThrewException
Definition catch.hpp:590
@ ExpressionFailed
Definition catch.hpp:585
@ Unknown
Definition catch.hpp:578
@ Warning
Definition catch.hpp:581
@ FatalErrorCondition
Definition catch.hpp:593
@ DidntThrowException
Definition catch.hpp:591
@ Exception
Definition catch.hpp:588
@ ExplicitFailure
Definition catch.hpp:586
@ Ok
Definition catch.hpp:579
Definition catch.hpp:1828
SectionInfo sectionInfo
Definition catch.hpp:1831
double durationInSeconds
Definition catch.hpp:1833
SectionEndInfo(SectionInfo const &_sectionInfo, Counts const &_prevAssertions, double _durationInSeconds)
Counts prevAssertions
Definition catch.hpp:1832
Definition catch.hpp:1817
std::string description
Definition catch.hpp:1824
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name, std::string const &_description=std::string())
std::string name
Definition catch.hpp:1823
SourceLineInfo lineInfo
Definition catch.hpp:1825
bool empty() const noexcept
SourceLineInfo(char const *_file, std::size_t _line) noexcept
Definition catch.hpp:275
SourceLineInfo(SourceLineInfo &&)=default
SourceLineInfo(SourceLineInfo const &other)=default
std::size_t line
Definition catch.hpp:290
SourceLineInfo & operator=(SourceLineInfo const &)=default
char const * file
Definition catch.hpp:289
bool operator==(SourceLineInfo const &other) const noexcept
bool operator<(SourceLineInfo const &other) const noexcept
std::string operator+() const
static std::string convert(Catch::Detail::Approx const &value)
static std::string convert(R const &range)
Definition catch.hpp:1145
static std::string convert(R C::*p)
Definition catch.hpp:968
static std::string convert(U *p)
Definition catch.hpp:957
static std::string convert(T const(&arr)[SZ])
Definition catch.hpp:1152
static std::string convert(bool b)
static std::string convert(char c)
static std::string convert(char *str)
static std::string convert(char const *str)
static std::string convert(char const *str)
Definition catch.hpp:880
static std::string convert(double value)
static std::string convert(float value)
static std::string convert(int value)
static std::string convert(long value)
static std::string convert(long long value)
static std::string convert(signed char c)
static std::string convert(signed char const *str)
Definition catch.hpp:886
static std::string convert(std::nullptr_t)
static std::string convert(const std::string &str)
static std::string convert(const std::wstring &wstr)
static std::string convert(unsigned char c)
static std::string convert(unsigned char const *str)
Definition catch.hpp:892
static std::string convert(unsigned int value)
static std::string convert(unsigned long value)
static std::string convert(unsigned long long value)
static std::string convert(wchar_t *str)
static std::string convert(wchar_t const *str)
static std::enable_if<::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
Definition catch.hpp:806
static std::enable_if<!::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
Definition catch.hpp:815
Definition catch.hpp:2774
friend void setTags(TestCaseInfo &testCaseInfo, std::vector< std::string > tags)
std::vector< std::string > tags
Definition catch.hpp:2803
std::string tagsAsString() const
std::string className
Definition catch.hpp:2801
std::string description
Definition catch.hpp:2802
SpecialProperties
Definition catch.hpp:2775
@ NonPortable
Definition catch.hpp:2781
@ Throws
Definition catch.hpp:2780
@ Benchmark
Definition catch.hpp:2782
@ MayFail
Definition catch.hpp:2779
@ IsHidden
Definition catch.hpp:2777
@ ShouldFail
Definition catch.hpp:2778
@ None
Definition catch.hpp:2776
std::string name
Definition catch.hpp:2800
std::vector< std::string > lcaseTags
Definition catch.hpp:2804
SourceLineInfo lineInfo
Definition catch.hpp:2805
bool expectedToFail() const
TestCaseInfo(std::string const &_name, std::string const &_className, std::string const &_description, std::vector< std::string > const &_tags, SourceLineInfo const &_lineInfo)
SpecialProperties properties
Definition catch.hpp:2806
Definition catch.hpp:1514
Definition catch.hpp:1799
Totals delta(Totals const &prevTotals) const
int error
Definition catch.hpp:1806
Counts assertions
Definition catch.hpp:1807
Totals operator-(Totals const &other) const
Totals & operator+=(Totals const &other)
Counts testCases
Definition catch.hpp:1808
Definition catch.hpp:1108
static const bool value
Definition catch.hpp:1109
Definition catch.hpp:1098
Definition catch.hpp:2194
std::size_t m_count
Definition catch.hpp:2199
pluralise(std::size_t count, std::string const &label)
std::string m_label
Definition catch.hpp:2200
std::string Colour(unsigned int colour)
Definition ui.cc:55