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 3
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) || defined(__MINGW32__)
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
169#if defined(__ANDROID__)
170# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
175#if defined(__MINGW32__)
176# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
194# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
199# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
200# define CATCH_CONFIG_COLOUR_NONE
202# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
211# define CATCH_INTERNAL_CONFIG_NO_WCHAR
221#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
222 #define CATCH_INTERNAL_CONFIG_COUNTER
225#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
226# define CATCH_CONFIG_COUNTER
228#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
229# define CATCH_CONFIG_WINDOWS_SEH
232#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)
233# define CATCH_CONFIG_POSIX_SIGNALS
236#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
237# define CATCH_CONFIG_WCHAR
240#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
241# define CATCH_CONFIG_CPP11_TO_STRING
244#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
245# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
248#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
249# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
250# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
252#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
253# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
254# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
258#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
259#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
260#ifdef CATCH_CONFIG_COUNTER
261# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
263# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
324#define CATCH_INTERNAL_LINEINFO \
325 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
336#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
337 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
338 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
339 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
370 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config );
403 char* m_data =
nullptr;
405 void takeOwnership();
407 static constexpr char const*
const s_empty =
"";
415 : m_start( other.m_start ),
416 m_size( other.m_size )
420 : m_start( other.m_start ),
421 m_size( other.m_size ),
422 m_data( other.m_data )
424 other.m_data =
nullptr;
430 : m_start( rawChars ),
435 : m_start( stdString.c_str() ),
436 m_size( stdString.size() )
446 m_start = other.m_start;
447 m_size = other.m_size;
462 auto empty() const noexcept ->
bool {
480 auto isOwned() const noexcept ->
bool;
481 auto isSubstring() const noexcept ->
bool;
485 auto operator + (
StringRef const& lhs,
char const* rhs ) -> std::
string;
486 auto operator + (
char const* lhs,
StringRef const& rhs ) -> std::
string;
488 auto operator += ( std::
string& lhs,
StringRef const& sr ) -> std::
string&;
489 auto operator << ( std::ostream& os,
StringRef const& sr ) -> std::ostream&;
491 inline auto operator "" _sr(
char const* rawChars, std::
size_t size ) noexcept ->
StringRef {
502 void (C::*m_testAsMethod)();
508 (obj.*m_testAsMethod)();
532#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
533#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
534#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
535#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
537#if defined(CATCH_CONFIG_DISABLE)
538 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
539 static void TestName()
540 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
542 struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
546 void TestName::test()
551 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
552 static void TestName(); \
553 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
554 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); }
\
555 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
556 static void TestName()
557 #define INTERNAL_CATCH_TESTCASE( ... ) \
558 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
561 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
562 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
563 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); }
\
564 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
567 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
568 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
570 struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
573 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); \
575 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
576 void TestName::test()
577 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
578 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
581 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
582 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
583 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } );
\
584 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
662#include <type_traits>
680 virtual std::ostream&
stream()
const = 0;
692 auto str() const -> std::
string;
699 auto get() -> std::ostream& {
return *m_oss; }
710#import <Foundation/Foundation.h>
713#define CATCH_ARC_ENABLED __has_feature(objc_arc)
715#define CATCH_ARC_ENABLED 0
718void arcSafeRelease( NSObject* obj );
719id performOptionalSelector(
id obj,
SEL sel );
721#if !CATCH_ARC_ENABLED
722inline void arcSafeRelease( NSObject* obj ) {
725inline id performOptionalSelector(
id obj,
SEL sel ) {
726 if( [obj respondsToSelector: sel] )
727 return [obj performSelector: sel];
730#define CATCH_UNSAFE_UNRETAINED
731#define CATCH_ARC_STRONG
733inline void arcSafeRelease( NSObject* ){}
734inline id performOptionalSelector(
id obj,
SEL sel ) {
736#pragma clang diagnostic push
737#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
739 if( [obj respondsToSelector: sel] )
740 return [obj performSelector: sel];
742#pragma clang diagnostic pop
746#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
747#define CATCH_ARC_STRONG __strong
755#pragma warning(disable:4180)
779 template<
typename SS,
typename TT>
780 static auto test(
int)
781 ->
decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
783 template<
typename,
typename>
784 static auto test(...)->std::false_type;
787 static const bool value =
decltype(test<std::ostream, const T&>(0))
::value;
794 typename std::enable_if<
800 typename std::enable_if<
807 typename std::enable_if<
819 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
820 cli::pin_ptr<System::Byte> p = &bytes[0];
821 return std::string(
reinterpret_cast<char const *
>(p), bytes->Length);
828 template <
typename T,
typename =
void>
830 template <
typename Fake = T>
837 rss.operator<<(
value);
841 template <
typename Fake = T>
845#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
848 return CATCH_CONFIG_FALLBACK_STRINGIFIER(
value);
857 template <
typename T>
859 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(
e);
868 template <
typename T>
870 return ::Catch::StringMaker<T^>::convert(
e);
882#ifdef CATCH_CONFIG_WCHAR
898#ifdef CATCH_CONFIG_WCHAR
987 template <
typename T>
989 template <
typename U>
999 template <
typename R,
typename C>
1010#if defined(_MANAGED)
1011 template <
typename T>
1012 struct StringMaker<T^> {
1014 return ::Catch::Detail::clrReferenceToString(ref);
1020 template<
typename InputIterator>
1024 if (first != last) {
1026 for (++first; first != last; ++first)
1036 struct StringMaker<NSString*> {
1044 struct StringMaker<NSObject*> {
1064#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
1065# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
1066# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
1067# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
1071#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
1074 template<
typename T1,
typename T2>
1075 struct StringMaker<std::pair<T1, T2> > {
1077 ReusableStringStream rss;
1090#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
1099 struct TupleElementPrinter {
1100 static void print(
const Tuple& tuple, std::ostream& os) {
1101 os << (N ?
", " :
" ")
1103 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
1111 struct TupleElementPrinter<Tuple, N,
false> {
1112 static void print(
const Tuple&, std::ostream&) {}
1117 template<
typename ...Types>
1118 struct StringMaker<std::tuple<Types...>> {
1120 ReusableStringStream rss;
1122 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
1140 template <
typename T>
1147#if defined(_MANAGED)
1148 template <
typename T>
1150 static const bool value =
false;
1154 template<
typename Range>
1160 template<
typename Allocator>
1176 template<
typename R>
1177 struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
1183 template <
typename T,
int SZ>
1193#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
1200template <
class Ratio>
1201struct ratio_string {
1205template <
class Ratio>
1208 rss <<
'[' << Ratio::num <<
'/'
1209 << Ratio::den <<
']';
1213struct ratio_string<std::atto> {
1217struct ratio_string<std::femto> {
1221struct ratio_string<std::pico> {
1225struct ratio_string<std::nano> {
1229struct ratio_string<std::
micro> {
1233struct ratio_string<std::
milli> {
1239 template<
typename Value,
typename Ratio>
1240 struct StringMaker<std::chrono::duration<Value, Ratio>> {
1242 ReusableStringStream rss;
1243 rss << duration.count() <<
' ' << ratio_string<Ratio>::symbol() <<
's';
1247 template<
typename Value>
1248 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
1249 static std::string convert(std::chrono::duration<Value, std::ratio<1>>
const& duration) {
1250 ReusableStringStream rss;
1251 rss << duration.count() <<
" s";
1255 template<
typename Value>
1256 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
1257 static std::string convert(std::chrono::duration<Value, std::ratio<60>>
const& duration) {
1258 ReusableStringStream rss;
1259 rss << duration.count() <<
" m";
1263 template<
typename Value>
1264 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
1265 static std::string convert(std::chrono::duration<Value, std::ratio<3600>>
const& duration) {
1266 ReusableStringStream rss;
1267 rss << duration.count() <<
" h";
1275 template<
typename Clock,
typename Duration>
1282 template<
typename Duration>
1288 std::tm timeInfo = {};
1289 gmtime_s(&timeInfo, &converted);
1291 std::tm* timeInfo = std::gmtime(&converted);
1294 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
1295 char timeStamp[timeStampSize];
1296 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
1299 std::strftime(timeStamp, timeStampSize,
fmt, &timeInfo);
1301 std::strftime(timeStamp, timeStampSize,
fmt, timeInfo);
1317#pragma warning(push)
1318#pragma warning(disable:4389)
1319#pragma warning(disable:4018)
1320#pragma warning(disable:4312)
1321#pragma warning(disable:4180)
1347 template<
typename LhsT,
typename RhsT>
1353 void streamReconstructedExpression( std::ostream &os )
const override {
1367 template<
typename LhsT>
1371 void streamReconstructedExpression( std::ostream &os )
const override {
1383 template<
typename LhsT,
typename RhsT>
1384 auto compareEqual( LhsT
const& lhs, RhsT
const& rhs ) ->
bool {
return static_cast<bool>(lhs == rhs); }
1385 template<
typename T>
1386 auto compareEqual( T*
const& lhs,
int rhs ) ->
bool {
return lhs ==
reinterpret_cast<void const*
>( rhs ); }
1387 template<
typename T>
1388 auto compareEqual( T*
const& lhs,
long rhs ) ->
bool {
return lhs ==
reinterpret_cast<void const*
>( rhs ); }
1389 template<
typename T>
1390 auto compareEqual(
int lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) == rhs; }
1391 template<
typename T>
1392 auto compareEqual(
long lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) == rhs; }
1394 template<
typename LhsT,
typename RhsT>
1395 auto compareNotEqual( LhsT
const& lhs, RhsT&& rhs ) ->
bool {
return static_cast<bool>(lhs != rhs); }
1396 template<
typename T>
1397 auto compareNotEqual( T*
const& lhs,
int rhs ) ->
bool {
return lhs !=
reinterpret_cast<void const*
>( rhs ); }
1398 template<
typename T>
1399 auto compareNotEqual( T*
const& lhs,
long rhs ) ->
bool {
return lhs !=
reinterpret_cast<void const*
>( rhs ); }
1400 template<
typename T>
1401 auto compareNotEqual(
int lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) != rhs; }
1402 template<
typename T>
1403 auto compareNotEqual(
long lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) != rhs; }
1405 template<
typename LhsT>
1411 template<
typename RhsT>
1413 return {
compareEqual( m_lhs, rhs ), m_lhs,
"==", rhs };
1416 return { m_lhs == rhs, m_lhs,
"==", rhs };
1419 template<
typename RhsT>
1424 return { m_lhs != rhs, m_lhs,
"!=", rhs };
1427 template<
typename RhsT>
1429 return {
static_cast<bool>(m_lhs > rhs), m_lhs,
">", rhs };
1431 template<
typename RhsT>
1433 return {
static_cast<bool>(m_lhs < rhs), m_lhs,
"<", rhs };
1435 template<
typename RhsT>
1437 return {
static_cast<bool>(m_lhs >= rhs), m_lhs,
">=", rhs };
1439 template<
typename RhsT>
1441 return {
static_cast<bool>(m_lhs <= rhs), m_lhs,
"<=", rhs };
1451 template<
typename T>
1457 template<
typename T>
1480 class AssertionResult;
1481 struct AssertionInfo;
1483 struct SectionEndInfo;
1486 struct BenchmarkInfo;
1487 struct BenchmarkStats;
1488 struct AssertionReaction;
1490 struct ITransientExpression;
1497 Counts& assertions ) = 0;
1548 struct AssertionResultData;
1577 bool m_completed =
false;
1587 if ( !m_completed ) {
1592 template<
typename T>
1638 static unsigned int globalCount;
1643 template<
typename T>
1657 template<
typename T>
1677#if !defined(CATCH_CONFIG_DISABLE)
1679#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
1680 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
1682 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
1685#if defined(CATCH_CONFIG_FAST_COMPILE)
1690#define INTERNAL_CATCH_TRY
1691#define INTERNAL_CATCH_CATCH( capturer )
1695#define INTERNAL_CATCH_TRY try
1696#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
1700#define INTERNAL_CATCH_REACT( handler ) handler.complete();
1703#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
1705 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
1706 INTERNAL_CATCH_TRY { \
1707 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
1708 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
1709 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
1710 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
1711 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1712 } while( (void)0, false && static_cast<bool>( !!(__VA_ARGS__) ) )
1716#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
1717 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
1718 if( Catch::getResultCapture().lastAssertionPassed() )
1721#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
1722 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
1723 if( !Catch::getResultCapture().lastAssertionPassed() )
1726#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
1728 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
1730 static_cast<void>(__VA_ARGS__); \
1731 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
1734 catchAssertionHandler.handleUnexpectedInflightException(); \
1736 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1740#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
1742 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
1743 if( catchAssertionHandler.allowThrows() ) \
1745 static_cast<void>(__VA_ARGS__); \
1746 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
1749 catchAssertionHandler.handleExceptionThrownAsExpected(); \
1752 catchAssertionHandler.handleThrowingCallSkipped(); \
1753 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1757#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
1759 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
1760 if( catchAssertionHandler.allowThrows() ) \
1762 static_cast<void>(expr); \
1763 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
1765 catch( exceptionType const& ) { \
1766 catchAssertionHandler.handleExceptionThrownAsExpected(); \
1769 catchAssertionHandler.handleUnexpectedInflightException(); \
1772 catchAssertionHandler.handleThrowingCallSkipped(); \
1773 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1777#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
1779 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
1780 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
1781 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1785#define INTERNAL_CATCH_INFO( macroName, log ) \
1786 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
1790#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
1792 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
1793 if( catchAssertionHandler.allowThrows() ) \
1795 static_cast<void>(__VA_ARGS__); \
1796 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
1799 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
1802 catchAssertionHandler.handleThrowingCallSkipped(); \
1803 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1827 std::size_t passed = 0;
1828 std::size_t failed = 0;
1829 std::size_t failedButOk = 0;
1882 uint64_t m_nanoseconds = 0;
1886 auto getElapsedMicroseconds() const -> uint64_t;
1887 auto getElapsedMilliseconds() const ->
unsigned int;
1888 auto getElapsedSeconds() const ->
double;
1911 bool m_sectionIncluded;
1917 #define INTERNAL_CATCH_SECTION( ... ) \
1918 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
1931 std::size_t m_count = 0;
1932 std::size_t m_iterationsToRun = 1;
1933 uint64_t m_resolution;
1936 static auto getResolution() -> uint64_t;
1941 m_resolution( getResolution() )
1948 if( m_count < m_iterationsToRun )
1950 return needsMoreIterations();
1963#define BENCHMARK( name ) \
1964 for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() )
1977 struct ITestCaseRegistry;
1978 struct IExceptionTranslatorRegistry;
1979 struct IExceptionTranslator;
1980 struct IReporterRegistry;
1981 struct IReporterFactory;
1982 struct ITagAliasRegistry;
1983 class StartupExceptionRegistry;
2017#if defined(CATCH_CONFIG_DISABLE)
2018 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
2019 static std::string translatorName( signature )
2034 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const = 0;
2044 template<
typename T>
2048 ExceptionTranslator(
std::string(*translateFunction)( T& ) )
2049 : m_translateFunction( translateFunction )
2052 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const override {
2055 std::rethrow_exception(std::current_exception());
2057 return (*it)->translate( it+1, itEnd );
2060 return m_translateFunction( ex );
2069 template<
typename T>
2072 (
new ExceptionTranslator<T>( translateFunction ) );
2078#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2079 static std::string translatorName( signature ); \
2080 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
2081 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
2082 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
2083 static std::string translatorName( signature )
2085#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
2090#include <type_traits>
2098 bool equalityComparisonImpl(
double other)
const;
2109 approx.
margin( m_margin );
2110 approx.
scale( m_scale );
2120 auto lhs_v =
static_cast<double>(lhs);
2121 return rhs.equalityComparisonImpl(lhs_v);
2141 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
2146 return lhs.m_value <
static_cast<double>(rhs) || lhs == rhs;
2151 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
2156 return lhs.m_value >
static_cast<double>(rhs) || lhs == rhs;
2161 double epsilonAsDouble =
static_cast<double>(newEpsilon);
2162 if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) {
2163 throw std::domain_error
2164 (
"Invalid Approx::epsilon: " +
2166 ", Approx::epsilon has to be between 0 and 1" );
2168 m_epsilon = epsilonAsDouble;
2174 double marginAsDouble =
static_cast<double>(newMargin);
2175 if( marginAsDouble < 0 ) {
2176 throw std::domain_error
2177 (
"Invalid Approx::margin: " +
2179 ", Approx::Margin has to be non-negative." );
2182 m_margin = marginAsDouble;
2188 m_scale =
static_cast<double>(newScale);
2238#ifndef CATCH_CONFIG_DISABLE_MATCHERS
2267 template<
typename ObjectT>
2269 virtual bool match( ObjectT
const& arg )
const = 0;
2271 template<
typename PtrT>
2273 virtual bool match( PtrT* arg )
const = 0;
2276 template<
typename T>
2284 template<
typename ArgT>
2286 bool match( ArgT
const& arg )
const override {
2287 for(
auto matcher : m_matchers ) {
2288 if (!matcher->match(arg))
2295 description.reserve( 4 + m_matchers.size()*32 );
2296 description +=
"( ";
2298 for(
auto matcher : m_matchers ) {
2302 description +=
" and ";
2303 description += matcher->toString();
2305 description +=
" )";
2310 m_matchers.push_back( &other );
2316 template<
typename ArgT>
2319 bool match( ArgT
const& arg )
const override {
2320 for(
auto matcher : m_matchers ) {
2321 if (matcher->match(arg))
2328 description.reserve( 4 + m_matchers.size()*32 );
2329 description +=
"( ";
2331 for(
auto matcher : m_matchers ) {
2335 description +=
" or ";
2336 description += matcher->toString();
2338 description +=
" )";
2343 m_matchers.push_back( &other );
2350 template<
typename ArgT>
2355 bool match( ArgT
const& arg )
const override {
2356 return !m_underlyingMatcher.match( arg );
2360 return "not " + m_underlyingMatcher.toString();
2365 template<
typename T>
2369 template<
typename T>
2373 template<
typename T>
2382using namespace Matchers;
2390#include <type_traits>
2396 namespace Floating {
2398 enum class FloatingPointKind : uint8_t;
2402 bool match(
double const& matchee)
const override;
2411 bool match(
double const& matchee)
const override;
2416 FloatingPointKind m_type;
2433#include <functional>
2444template <
typename T>
2451 :m_predicate(std::move(elem)),
2456 return m_predicate(
item);
2460 return m_description;
2470 template<
typename T>
2486 namespace StdString {
2557 template <
typename InputIterator,
typename T>
2558 size_t count(InputIterator first, InputIterator last, T
const&
item) {
2560 for (; first != last; ++first) {
2561 if (*first ==
item) {
2567 template <
typename InputIterator,
typename T>
2569 for (; first != last; ++first) {
2570 if (*first ==
item) {
2578 template<
typename T>
2583 bool match(std::vector<T>
const &v)
const override {
2584 for (
auto const& el : v) {
2585 if (el == m_comparator) {
2599 template<
typename T>
2604 bool match(std::vector<T>
const &v)
const override {
2606 if (m_comparator.size() > v.size())
2608 for (
auto const& comparator : m_comparator) {
2609 auto present =
false;
2610 for (
const auto& el : v) {
2611 if (el == comparator) {
2629 template<
typename T>
2634 bool match(std::vector<T>
const &v)
const override {
2639 if (m_comparator.size() != v.size())
2641 for (std::size_t i = 0; i < v.size(); ++i)
2642 if (m_comparator[i] != v[i])
2652 template<
typename T>
2655 bool match(std::vector<T>
const& vec)
const override {
2658 if (m_target.size() != vec.size()) {
2661 auto lfirst = m_target.begin(), llast = m_target.end();
2662 auto rfirst = vec.begin(), rlast = vec.end();
2664 while (lfirst != llast && *lfirst != *rfirst) {
2667 if (lfirst == llast) {
2671 for (
auto mid = lfirst; mid != llast; ++mid) {
2677 if (num_vec == 0 ||
Detail::count(lfirst, llast, *mid) != num_vec) {
2689 std::vector<T>
const& m_target;
2697 template<
typename T>
2702 template<
typename T>
2707 template<
typename T>
2712 template<
typename T>
2723 template<
typename ArgT,
typename MatcherT>
2732 m_matcher( matcher ),
2733 m_matcherString( matcherString )
2737 auto matcherAsString = m_matcher.toString();
2740 os << m_matcherString;
2742 os << matcherAsString;
2750 template<
typename ArgT,
typename MatcherT>
2758#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
2760 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
2761 INTERNAL_CATCH_TRY { \
2762 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \
2763 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
2764 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2768#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
2770 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
2771 if( catchAssertionHandler.allowThrows() ) \
2773 static_cast<void>(__VA_ARGS__ ); \
2774 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2776 catch( exceptionType const& ex ) { \
2777 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \
2780 catchAssertionHandler.handleUnexpectedInflightException(); \
2783 catchAssertionHandler.handleThrowingCallSkipped(); \
2784 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2799#pragma clang diagnostic push
2800#pragma clang diagnostic ignored "-Wpadded"
2805 struct ITestInvoker;
2811 ShouldFail = 1 << 2,
2814 NonPortable = 1 << 5,
2821 std::vector<std::string>
const& _tags,
2827 bool throws()
const;
2857 std::shared_ptr<ITestInvoker> test;
2867#pragma clang diagnostic pop
2886#import <objc/runtime.h>
2908 class OcMethod :
public ITestInvoker {
2911 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2913 virtual void invoke()
const {
2914 id obj = [[m_cls alloc] init];
2916 performOptionalSelector( obj,
@selector(setUp) );
2917 performOptionalSelector( obj, m_sel );
2918 performOptionalSelector( obj,
@selector(tearDown) );
2920 arcSafeRelease( obj );
2923 virtual ~OcMethod() {}
2934 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2935 SEL sel = NSSelectorFromString( selStr );
2936 arcSafeRelease( selStr );
2937 id value = performOptionalSelector( cls, sel );
2939 return [(NSString*)value UTF8String];
2944 inline std::size_t registerTestMethods() {
2945 std::size_t noTestMethods = 0;
2946 int noClasses = objc_getClassList(
nullptr, 0 );
2948 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc(
sizeof(Class) * noClasses);
2949 objc_getClassList( classes, noClasses );
2951 for(
int c = 0; c < noClasses; c++ ) {
2952 Class cls = classes[c];
2955 Method* methods = class_copyMethodList( cls, &
count );
2956 for( u_int m = 0; m <
count ; m++ ) {
2957 SEL selector = method_getName(methods[m]);
2959 if(
startsWith( methodName,
"Catch_TestCase_" ) ) {
2960 std::string testCaseName = methodName.substr( 15 );
2961 std::string name = Detail::getAnnotation( cls,
"Name", testCaseName );
2962 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
2963 const char* className = class_getName( cls );
2972 return noTestMethods;
2975#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
2977 namespace Matchers {
2979 namespace NSStringMatchers {
2981 struct StringHolder : MatcherBase<NSString*>{
2982 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2983 StringHolder( StringHolder
const& other ) : m_substr( [other.m_substr copy] ){}
2985 arcSafeRelease( m_substr );
2988 bool match( NSString* arg )
const override {
2992 NSString* CATCH_ARC_STRONG m_substr;
2995 struct Equals : StringHolder {
2996 Equals( NSString* substr ) : StringHolder( substr ){}
2998 bool match( NSString* str )
const override {
2999 return (str != nil || m_substr == nil ) &&
3000 [str isEqualToString:m_substr];
3004 return "equals string: " +
Catch::Detail::stringify( m_substr );
3009 Contains( NSString* substr ) : StringHolder( substr ){}
3011 bool match( NSString* str )
const {
3012 return (str != nil || m_substr == nil ) &&
3013 [str rangeOfString:m_substr].location != NSNotFound;
3017 return "contains string: " +
Catch::Detail::stringify( m_substr );
3022 StartsWith( NSString* substr ) : StringHolder( substr ){}
3024 bool match( NSString* str )
const override {
3025 return (str != nil || m_substr == nil ) &&
3026 [str rangeOfString:m_substr].location == 0;
3030 return "starts with: " +
Catch::Detail::stringify( m_substr );
3034 EndsWith( NSString* substr ) : StringHolder( substr ){}
3036 bool match( NSString* str )
const override {
3037 return (str != nil || m_substr == nil ) &&
3038 [str rangeOfString:m_substr].location == [str length] - [m_substr
length];
3042 return "ends with: " +
Catch::Detail::stringify( m_substr );
3063 using namespace Matchers;
3070#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix
3071#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \
3072+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \
3076+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \
3080-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )
3082#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )
3087#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES
3099#pragma clang diagnostic push
3100#pragma clang diagnostic ignored "-Wpadded"
3106#pragma clang diagnostic push
3107#pragma clang diagnostic ignored "-Wpadded"
3114 class WildcardPattern {
3115 enum WildcardPosition {
3117 WildcardAtStart = 1,
3119 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3125 virtual ~WildcardPattern() =
default;
3126 virtual bool matches(
std::string const& str )
const;
3131 WildcardPosition m_wildcard = NoWildcard;
3146 virtual bool matches( TestCaseInfo
const& testCase )
const = 0;
3148 using PatternPtr = std::shared_ptr<Pattern>;
3150 class NamePattern :
public Pattern {
3153 virtual ~NamePattern();
3154 virtual bool matches( TestCaseInfo
const& testCase )
const override;
3156 WildcardPattern m_wildcardPattern;
3159 class TagPattern :
public Pattern {
3162 virtual ~TagPattern();
3163 virtual bool matches( TestCaseInfo
const& testCase )
const override;
3168 class ExcludedPattern :
public Pattern {
3170 ExcludedPattern( PatternPtr
const& underlyingPattern );
3171 virtual ~ExcludedPattern();
3172 virtual bool matches( TestCaseInfo
const& testCase )
const override;
3174 PatternPtr m_underlyingPattern;
3178 std::vector<PatternPtr> m_patterns;
3180 bool matches( TestCaseInfo
const& testCase )
const;
3184 bool hasFilters()
const;
3185 bool matches( TestCaseInfo
const& testCase )
const;
3188 std::vector<Filter> m_filters;
3190 friend class TestSpecParser;
3195#pragma clang diagnostic pop
3207 struct ITagAliasRegistry {
3208 virtual ~ITagAliasRegistry();
3210 virtual TagAlias
const* find(
std::string const& alias )
const = 0;
3213 static ITagAliasRegistry
const&
get();
3221 class TestSpecParser {
3222 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
3224 bool m_exclusion =
false;
3225 std::size_t m_start = std::string::npos, m_pos = 0;
3227 std::vector<std::size_t> m_escapeChars;
3228 TestSpec::Filter m_currentFilter;
3229 TestSpec m_testSpec;
3230 ITagAliasRegistry
const* m_tagAliases =
nullptr;
3233 TestSpecParser( ITagAliasRegistry
const& tagAliases );
3236 TestSpec testSpec();
3239 void visitChar(
char c );
3240 void startNewMode( Mode mode, std::size_t start );
3244 template<
typename T>
3247 for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
3248 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
3249 m_escapeChars.clear();
3252 token = token.substr( 8 );
3254 if( !token.empty() ) {
3255 TestSpec::PatternPtr pattern = std::make_shared<T>( token );
3257 pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
3258 m_currentFilter.m_patterns.push_back( pattern );
3260 m_exclusion =
false;
3271#pragma clang diagnostic pop
3284 enum class Verbosity {
3290 struct WarnAbout {
enum What {
3292 NoAssertions = 0x01,
3296 struct ShowDurations {
enum OrNot {
3301 struct RunTests {
enum InWhatOrder {
3303 InLexicographicalOrder,
3306 struct UseColour {
enum YesOrNo {
3311 struct WaitForKeypress {
enum When {
3315 BeforeStartAndExit = BeforeStart | BeforeExit
3320 struct IConfig : NonCopyable {
3325 virtual std::ostream& stream()
const = 0;
3327 virtual bool includeSuccessfulResults()
const = 0;
3328 virtual bool shouldDebugBreak()
const = 0;
3329 virtual bool warnAboutMissingAssertions()
const = 0;
3330 virtual bool warnAboutNoTests()
const = 0;
3331 virtual int abortAfter()
const = 0;
3332 virtual bool showInvisibles()
const = 0;
3333 virtual ShowDurations::OrNot showDurations()
const = 0;
3334 virtual TestSpec
const& testSpec()
const = 0;
3335 virtual bool hasTestFilters()
const = 0;
3336 virtual RunTests::InWhatOrder runOrder()
const = 0;
3337 virtual unsigned int rngSeed()
const = 0;
3338 virtual int benchmarkResolutionMultiple()
const = 0;
3339 virtual UseColour::YesOrNo useColour()
const = 0;
3340 virtual std::vector<std::string>
const& getSectionsToRun()
const = 0;
3341 virtual Verbosity verbosity()
const = 0;
3344 using IConfigPtr = std::shared_ptr<IConfig const>;
3354#ifndef CATCH_CONFIG_CONSOLE_WIDTH
3355#define CATCH_CONFIG_CONSOLE_WIDTH 80
3363 bool listTests =
false;
3364 bool listTags =
false;
3365 bool listReporters =
false;
3366 bool listTestNamesOnly =
false;
3368 bool showSuccessfulTests =
false;
3369 bool shouldDebugBreak =
false;
3370 bool noThrow =
false;
3371 bool showHelp =
false;
3372 bool showInvisibles =
false;
3373 bool filenamesAsTags =
false;
3374 bool libIdentify =
false;
3376 int abortAfter = -1;
3378 int benchmarkResolutionMultiple = 100;
3380 Verbosity verbosity = Verbosity::Normal;
3381 WarnAbout::What warnings = WarnAbout::Nothing;
3382 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
3383 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
3384 UseColour::YesOrNo useColour = UseColour::Auto;
3385 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
3390#ifndef CATCH_CONFIG_DEFAULT_REPORTER
3391#define CATCH_CONFIG_DEFAULT_REPORTER "console"
3393 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
3394#undef CATCH_CONFIG_DEFAULT_REPORTER
3396 std::vector<std::string> testsOrTags;
3397 std::vector<std::string> sectionsToRun;
3400 class Config :
public IConfig {
3404 Config( ConfigData
const&
data );
3405 virtual ~Config() =
default;
3409 bool listTests()
const;
3410 bool listTestNamesOnly()
const;
3411 bool listTags()
const;
3412 bool listReporters()
const;
3417 std::vector<std::string>
const& getTestsOrTags()
const;
3418 std::vector<std::string>
const& getSectionsToRun()
const override;
3420 virtual TestSpec
const& testSpec()
const override;
3421 bool hasTestFilters()
const override;
3423 bool showHelp()
const;
3427 std::ostream& stream()
const override;
3429 bool includeSuccessfulResults()
const override;
3430 bool warnAboutMissingAssertions()
const override;
3431 bool warnAboutNoTests()
const override;
3432 ShowDurations::OrNot showDurations()
const override;
3433 RunTests::InWhatOrder runOrder()
const override;
3434 unsigned int rngSeed()
const override;
3435 int benchmarkResolutionMultiple()
const override;
3436 UseColour::YesOrNo useColour()
const override;
3437 bool shouldDebugBreak()
const override;
3438 int abortAfter()
const override;
3439 bool showInvisibles()
const override;
3440 Verbosity verbosity()
const override;
3444 IStream
const* openStream();
3447 std::unique_ptr<IStream const> m_stream;
3448 TestSpec m_testSpec;
3449 bool m_hasTestFilters =
false;
3461 struct AssertionResultData
3463 AssertionResultData() =
delete;
3465 AssertionResultData(
ResultWas::OfType _resultType, LazyExpression
const& _lazyExpression );
3469 LazyExpression lazyExpression;
3475 class AssertionResult {
3477 AssertionResult() =
delete;
3478 AssertionResult( AssertionInfo
const& info, AssertionResultData
const&
data );
3481 bool succeeded()
const;
3483 bool hasExpression()
const;
3484 bool hasMessage()
const;
3487 bool hasExpandedExpression()
const;
3490 SourceLineInfo getSourceInfo()
const;
3491 StringRef getTestMacroName()
const;
3494 AssertionInfo m_info;
3495 AssertionResultData m_resultData;
3506 template<
typename T>
3509 Option() : nullableValue( nullptr ) {}
3510 Option( T
const& _value )
3511 : nullableValue( new( storage ) T( _value ) )
3513 Option( Option
const& _other )
3514 : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )
3521 Option& operator= ( Option
const& _other ) {
3522 if( &_other !=
this ) {
3525 nullableValue =
new( storage ) T( *_other );
3529 Option& operator = ( T
const& _value ) {
3531 nullableValue =
new( storage ) T( _value );
3537 nullableValue->~T();
3538 nullableValue =
nullptr;
3541 T&
operator*() {
return *nullableValue; }
3542 T
const&
operator*()
const {
return *nullableValue; }
3543 T* operator->() {
return nullableValue; }
3544 const T* operator->()
const {
return nullableValue; }
3546 T valueOr( T
const& defaultValue )
const {
3547 return nullableValue ? *nullableValue : defaultValue;
3550 bool some()
const {
return nullableValue !=
nullptr; }
3551 bool none()
const {
return nullableValue ==
nullptr; }
3553 bool operator !()
const {
return nullableValue ==
nullptr; }
3554 explicit operator bool()
const {
3560 alignas(
alignof(T))
char storage[sizeof(T)];
3574 struct ReporterConfig {
3575 explicit ReporterConfig( IConfigPtr
const& _fullConfig );
3577 ReporterConfig( IConfigPtr
const& _fullConfig, std::ostream& _stream );
3579 std::ostream& stream()
const;
3580 IConfigPtr fullConfig()
const;
3583 std::ostream* m_stream;
3584 IConfigPtr m_fullConfig;
3587 struct ReporterPreferences {
3588 bool shouldRedirectStdOut =
false;
3591 template<
typename T>
3592 struct LazyStat : Option<T> {
3593 LazyStat& operator=( T
const& _value ) {
3594 Option<T>::operator=( _value );
3605 struct TestRunInfo {
3611 std::size_t _groupIndex,
3612 std::size_t _groupsCount );
3615 std::size_t groupIndex;
3616 std::size_t groupsCounts;
3619 struct AssertionStats {
3620 AssertionStats( AssertionResult
const& _assertionResult,
3621 std::vector<MessageInfo>
const& _infoMessages,
3622 Totals
const& _totals );
3624 AssertionStats( AssertionStats
const& ) =
default;
3625 AssertionStats( AssertionStats && ) =
default;
3626 AssertionStats& operator = ( AssertionStats
const& ) =
default;
3627 AssertionStats& operator = ( AssertionStats && ) =
default;
3628 virtual ~AssertionStats();
3630 AssertionResult assertionResult;
3631 std::vector<MessageInfo> infoMessages;
3635 struct SectionStats {
3636 SectionStats( SectionInfo
const& _sectionInfo,
3637 Counts
const& _assertions,
3638 double _durationInSeconds,
3639 bool _missingAssertions );
3640 SectionStats( SectionStats
const& ) =
default;
3641 SectionStats( SectionStats && ) =
default;
3642 SectionStats& operator = ( SectionStats
const& ) =
default;
3643 SectionStats& operator = ( SectionStats && ) =
default;
3644 virtual ~SectionStats();
3646 SectionInfo sectionInfo;
3648 double durationInSeconds;
3649 bool missingAssertions;
3652 struct TestCaseStats {
3653 TestCaseStats( TestCaseInfo
const& _testInfo,
3654 Totals
const& _totals,
3659 TestCaseStats( TestCaseStats
const& ) =
default;
3660 TestCaseStats( TestCaseStats && ) =
default;
3661 TestCaseStats& operator = ( TestCaseStats
const& ) =
default;
3662 TestCaseStats& operator = ( TestCaseStats && ) =
default;
3663 virtual ~TestCaseStats();
3665 TestCaseInfo testInfo;
3672 struct TestGroupStats {
3673 TestGroupStats( GroupInfo
const& _groupInfo,
3674 Totals
const& _totals,
3676 TestGroupStats( GroupInfo
const& _groupInfo );
3678 TestGroupStats( TestGroupStats
const& ) =
default;
3679 TestGroupStats( TestGroupStats && ) =
default;
3680 TestGroupStats& operator = ( TestGroupStats
const& ) =
default;
3681 TestGroupStats& operator = ( TestGroupStats && ) =
default;
3682 virtual ~TestGroupStats();
3684 GroupInfo groupInfo;
3689 struct TestRunStats {
3690 TestRunStats( TestRunInfo
const& _runInfo,
3691 Totals
const& _totals,
3694 TestRunStats( TestRunStats
const& ) =
default;
3695 TestRunStats( TestRunStats && ) =
default;
3696 TestRunStats& operator = ( TestRunStats
const& ) =
default;
3697 TestRunStats& operator = ( TestRunStats && ) =
default;
3698 virtual ~TestRunStats();
3700 TestRunInfo runInfo;
3705 struct BenchmarkInfo {
3708 struct BenchmarkStats {
3710 std::size_t iterations;
3711 uint64_t elapsedTimeInNanoseconds;
3714 struct IStreamingReporter {
3715 virtual ~IStreamingReporter() =
default;
3721 virtual ReporterPreferences getPreferences()
const = 0;
3723 virtual void noMatchingTestCases(
std::string const& spec ) = 0;
3725 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
3726 virtual void testGroupStarting( GroupInfo
const& groupInfo ) = 0;
3728 virtual void testCaseStarting( TestCaseInfo
const& testInfo ) = 0;
3729 virtual void sectionStarting( SectionInfo
const& sectionInfo ) = 0;
3732 virtual void benchmarkStarting( BenchmarkInfo
const& ) {}
3734 virtual void assertionStarting( AssertionInfo
const& assertionInfo ) = 0;
3737 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
3740 virtual void benchmarkEnded( BenchmarkStats
const& ) {}
3742 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
3743 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
3744 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
3745 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
3747 virtual void skipTest( TestCaseInfo
const& testInfo ) = 0;
3750 virtual void fatalErrorEncountered( StringRef
name );
3752 virtual bool isMulti()
const;
3754 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
3756 struct IReporterFactory {
3757 virtual ~IReporterFactory();
3758 virtual IStreamingReporterPtr create( ReporterConfig
const& config )
const = 0;
3763 struct IReporterRegistry {
3764 using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
3765 using Listeners = std::vector<IReporterFactoryPtr>;
3767 virtual ~IReporterRegistry();
3768 virtual IStreamingReporterPtr create(
std::string const&
name, IConfigPtr
const& config )
const = 0;
3769 virtual FactoryMap
const& getFactories()
const = 0;
3770 virtual Listeners
const& getListeners()
const = 0;
3785 void prepareExpandedExpression(AssertionResult& result);
3788 std::string getFormattedDuration(
double duration );
3790 template<
typename DerivedT>
3791 struct StreamingReporterBase : IStreamingReporter {
3793 StreamingReporterBase( ReporterConfig
const& _config )
3794 : m_config( _config.fullConfig() ),
3795 stream( _config.stream() )
3797 m_reporterPrefs.shouldRedirectStdOut =
false;
3798 if( !DerivedT::getSupportedVerbosities().
count( m_config->verbosity() ) )
3799 throw std::domain_error(
"Verbosity level not supported by this reporter" );
3802 ReporterPreferences getPreferences()
const override {
3803 return m_reporterPrefs;
3806 static std::set<Verbosity> getSupportedVerbosities() {
3807 return { Verbosity::Normal };
3810 ~StreamingReporterBase()
override =
default;
3812 void noMatchingTestCases(
std::string const&)
override {}
3814 void testRunStarting(TestRunInfo
const& _testRunInfo)
override {
3815 currentTestRunInfo = _testRunInfo;
3817 void testGroupStarting(GroupInfo
const& _groupInfo)
override {
3818 currentGroupInfo = _groupInfo;
3821 void testCaseStarting(TestCaseInfo
const& _testInfo)
override {
3822 currentTestCaseInfo = _testInfo;
3824 void sectionStarting(SectionInfo
const& _sectionInfo)
override {
3825 m_sectionStack.push_back(_sectionInfo);
3828 void sectionEnded(SectionStats
const& )
override {
3829 m_sectionStack.pop_back();
3831 void testCaseEnded(TestCaseStats
const& )
override {
3832 currentTestCaseInfo.reset();
3834 void testGroupEnded(TestGroupStats
const& )
override {
3835 currentGroupInfo.reset();
3837 void testRunEnded(TestRunStats
const& )
override {
3838 currentTestCaseInfo.reset();
3839 currentGroupInfo.reset();
3840 currentTestRunInfo.reset();
3843 void skipTest(TestCaseInfo
const&)
override {
3848 IConfigPtr m_config;
3849 std::ostream& stream;
3851 LazyStat<TestRunInfo> currentTestRunInfo;
3852 LazyStat<GroupInfo> currentGroupInfo;
3853 LazyStat<TestCaseInfo> currentTestCaseInfo;
3855 std::vector<SectionInfo> m_sectionStack;
3856 ReporterPreferences m_reporterPrefs;
3859 template<
typename DerivedT>
3860 struct CumulativeReporterBase : IStreamingReporter {
3861 template<
typename T,
typename ChildNodeT>
3863 explicit Node( T
const& _value ) :
value( _value ) {}
3866 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
3868 ChildNodes children;
3870 struct SectionNode {
3871 explicit SectionNode(SectionStats
const& _stats) : stats(_stats) {}
3872 virtual ~SectionNode() =
default;
3874 bool operator == (SectionNode
const& other)
const {
3875 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
3877 bool operator == (std::shared_ptr<SectionNode>
const& other)
const {
3882 using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
3883 using Assertions = std::vector<AssertionStats>;
3884 ChildSections childSections;
3885 Assertions assertions;
3890 struct BySectionInfo {
3891 BySectionInfo( SectionInfo
const& other ) : m_other( other ) {}
3892 BySectionInfo( BySectionInfo
const& other ) : m_other( other.m_other ) {}
3893 bool operator() (std::shared_ptr<SectionNode>
const& node)
const {
3894 return ((node->stats.sectionInfo.name == m_other.name) &&
3895 (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
3897 void operator=(BySectionInfo
const&) =
delete;
3900 SectionInfo
const& m_other;
3903 using TestCaseNode = Node<TestCaseStats, SectionNode>;
3904 using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
3905 using TestRunNode = Node<TestRunStats, TestGroupNode>;
3907 CumulativeReporterBase( ReporterConfig
const& _config )
3908 : m_config( _config.fullConfig() ),
3909 stream( _config.stream() )
3911 m_reporterPrefs.shouldRedirectStdOut =
false;
3912 if( !DerivedT::getSupportedVerbosities().
count( m_config->verbosity() ) )
3913 throw std::domain_error(
"Verbosity level not supported by this reporter" );
3915 ~CumulativeReporterBase()
override =
default;
3917 ReporterPreferences getPreferences()
const override {
3918 return m_reporterPrefs;
3921 static std::set<Verbosity> getSupportedVerbosities() {
3922 return { Verbosity::Normal };
3925 void testRunStarting( TestRunInfo
const& )
override {}
3926 void testGroupStarting( GroupInfo
const& )
override {}
3928 void testCaseStarting( TestCaseInfo
const& )
override {}
3930 void sectionStarting( SectionInfo
const& sectionInfo )
override {
3931 SectionStats incompleteStats( sectionInfo, Counts(), 0,
false );
3932 std::shared_ptr<SectionNode> node;
3933 if( m_sectionStack.empty() ) {
3934 if( !m_rootSection )
3935 m_rootSection = std::make_shared<SectionNode>( incompleteStats );
3936 node = m_rootSection;
3939 SectionNode& parentNode = *m_sectionStack.back();
3941 std::find_if( parentNode.childSections.begin(),
3942 parentNode.childSections.end(),
3943 BySectionInfo( sectionInfo ) );
3944 if( it == parentNode.childSections.end() ) {
3945 node = std::make_shared<SectionNode>( incompleteStats );
3946 parentNode.childSections.push_back( node );
3951 m_sectionStack.push_back( node );
3952 m_deepestSection = std::move(node);
3955 void assertionStarting(AssertionInfo
const&)
override {}
3957 bool assertionEnded(AssertionStats
const& assertionStats)
override {
3958 assert(!m_sectionStack.empty());
3964 prepareExpandedExpression(
const_cast<AssertionResult&
>( assertionStats.assertionResult ) );
3965 SectionNode& sectionNode = *m_sectionStack.back();
3966 sectionNode.assertions.push_back(assertionStats);
3969 void sectionEnded(SectionStats
const& sectionStats)
override {
3970 assert(!m_sectionStack.empty());
3971 SectionNode& node = *m_sectionStack.back();
3972 node.stats = sectionStats;
3973 m_sectionStack.pop_back();
3975 void testCaseEnded(TestCaseStats
const& testCaseStats)
override {
3976 auto node = std::make_shared<TestCaseNode>(testCaseStats);
3977 assert(m_sectionStack.size() == 0);
3978 node->children.push_back(m_rootSection);
3979 m_testCases.push_back(node);
3980 m_rootSection.reset();
3982 assert(m_deepestSection);
3983 m_deepestSection->stdOut = testCaseStats.stdOut;
3984 m_deepestSection->stdErr = testCaseStats.stdErr;
3986 void testGroupEnded(TestGroupStats
const& testGroupStats)
override {
3987 auto node = std::make_shared<TestGroupNode>(testGroupStats);
3988 node->children.swap(m_testCases);
3989 m_testGroups.push_back(node);
3991 void testRunEnded(TestRunStats
const& testRunStats)
override {
3992 auto node = std::make_shared<TestRunNode>(testRunStats);
3993 node->children.swap(m_testGroups);
3994 m_testRuns.push_back(node);
3995 testRunEndedCumulative();
3997 virtual void testRunEndedCumulative() = 0;
3999 void skipTest(TestCaseInfo
const&)
override {}
4001 IConfigPtr m_config;
4002 std::ostream& stream;
4003 std::vector<AssertionStats> m_assertions;
4004 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
4005 std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
4006 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
4008 std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
4010 std::shared_ptr<SectionNode> m_rootSection;
4011 std::shared_ptr<SectionNode> m_deepestSection;
4012 std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
4013 ReporterPreferences m_reporterPrefs;
4017 char const* getLineOfChars() {
4018 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
4020 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
4021 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
4026 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
4027 TestEventListenerBase( ReporterConfig
const& _config );
4029 void assertionStarting(AssertionInfo
const&)
override;
4030 bool assertionEnded(AssertionStats
const&)
override;
4054 BrightRed = Bright | Red,
4055 BrightGreen = Bright | Green,
4056 LightGrey = Bright | Grey,
4057 BrightWhite = Bright | White,
4058 BrightYellow = Bright | Yellow,
4061 FileName = LightGrey,
4063 ResultError = BrightRed,
4064 ResultSuccess = BrightGreen,
4065 ResultExpectedFailure =
Warning,
4070 OriginalExpression = Cyan,
4071 ReconstructedExpression = BrightYellow,
4073 SecondaryText = LightGrey,
4078 Colour( Code _colourCode );
4079 Colour( Colour&& other )
noexcept;
4080 Colour& operator=( Colour&& other )
noexcept;
4084 static void use( Code _colourCode );
4087 bool m_moved =
false;
4090 std::ostream&
operator << ( std::ostream& os, Colour
const& );
4100 template<
typename T>
4101 class ReporterRegistrar {
4103 class ReporterFactory :
public IReporterFactory {
4105 virtual IStreamingReporterPtr create( ReporterConfig
const& config )
const override {
4106 return std::unique_ptr<T>(
new T( config ) );
4109 virtual std::string getDescription()
const override {
4110 return T::getDescription();
4121 template<
typename T>
4122 class ListenerRegistrar {
4124 class ListenerFactory :
public IReporterFactory {
4126 virtual IStreamingReporterPtr create( ReporterConfig
const& config )
const override {
4127 return std::unique_ptr<T>(
new T( config ) );
4129 virtual std::string getDescription()
const override {
4136 ListenerRegistrar() {
4142#if !defined(CATCH_CONFIG_DISABLE)
4144#define CATCH_REGISTER_REPORTER( name, reporterType ) \
4145 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
4146 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
4147 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
4149#define CATCH_REGISTER_LISTENER( listenerType ) \
4150 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
4151 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
4152 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
4155#define CATCH_REGISTER_REPORTER(name, reporterType)
4156#define CATCH_REGISTER_LISTENER(listenerType)
4166 struct CompactReporter : StreamingReporterBase<CompactReporter> {
4168 using StreamingReporterBase::StreamingReporterBase;
4170 ~CompactReporter()
override;
4174 ReporterPreferences getPreferences()
const override;
4176 void noMatchingTestCases(
std::string const& spec)
override;
4178 void assertionStarting(AssertionInfo
const&)
override;
4180 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
4182 void sectionEnded(SectionStats
const& _sectionStats)
override;
4184 void testRunEnded(TestRunStats
const& _testRunStats)
override;
4193#if defined(_MSC_VER)
4194#pragma warning(push)
4195#pragma warning(disable:4061)
4202 struct SummaryColumn;
4205 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
4206 std::unique_ptr<TablePrinter> m_tablePrinter;
4208 ConsoleReporter(ReporterConfig
const& config);
4209 ~ConsoleReporter()
override;
4212 void noMatchingTestCases(
std::string const& spec)
override;
4214 void assertionStarting(AssertionInfo
const&)
override;
4216 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
4218 void sectionStarting(SectionInfo
const& _sectionInfo)
override;
4219 void sectionEnded(SectionStats
const& _sectionStats)
override;
4221 void benchmarkStarting(BenchmarkInfo
const& info)
override;
4222 void benchmarkEnded(BenchmarkStats
const& stats)
override;
4224 void testCaseEnded(TestCaseStats
const& _testCaseStats)
override;
4225 void testGroupEnded(TestGroupStats
const& _testGroupStats)
override;
4226 void testRunEnded(TestRunStats
const& _testRunStats)
override;
4232 void lazyPrintWithoutClosingBenchmarkTable();
4233 void lazyPrintRunInfo();
4234 void lazyPrintGroupInfo();
4235 void printTestCaseAndSectionHeader();
4242 void printHeaderString(
std::string const& _string, std::size_t indent = 0);
4244 void printTotals(Totals
const& totals);
4245 void printSummaryRow(
std::string const& label, std::vector<SummaryColumn>
const& cols, std::size_t row);
4247 void printTotalsDivider(Totals
const& totals);
4248 void printSummaryDivider();
4251 bool m_headerPrinted =
false;
4256#if defined(_MSC_VER)
4271 enum ForWhat { ForTextNodes, ForAttributes };
4273 XmlEncode(
std::string const& str, ForWhat forWhat = ForTextNodes );
4275 void encodeTo( std::ostream& os )
const;
4277 friend std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode );
4287 class ScopedElement {
4289 ScopedElement( XmlWriter* writer );
4291 ScopedElement( ScopedElement&& other )
noexcept;
4292 ScopedElement& operator=( ScopedElement&& other )
noexcept;
4296 ScopedElement& writeText(
std::string const& text,
bool indent =
true );
4298 template<
typename T>
4299 ScopedElement& writeAttribute(
std::string const&
name, T
const& attribute ) {
4300 m_writer->writeAttribute(
name, attribute );
4305 mutable XmlWriter* m_writer =
nullptr;
4311 XmlWriter( XmlWriter
const& ) =
delete;
4312 XmlWriter& operator=( XmlWriter
const& ) =
delete;
4318 XmlWriter& endElement();
4324 template<
typename T>
4325 XmlWriter& writeAttribute(
std::string const&
name, T
const& attribute ) {
4326 ReusableStringStream rss;
4328 return writeAttribute(
name, rss.str() );
4331 XmlWriter& writeText(
std::string const& text,
bool indent =
true );
4333 XmlWriter& writeComment(
std::string const& text );
4335 void writeStylesheetRef(
std::string const& url );
4337 XmlWriter& writeBlankLine();
4339 void ensureTagClosed();
4343 void writeDeclaration();
4345 void newlineIfNecessary();
4347 bool m_tagIsOpen =
false;
4348 bool m_needsNewline =
false;
4349 std::vector<std::string> m_tags;
4359 class JunitReporter :
public CumulativeReporterBase<JunitReporter> {
4361 JunitReporter(ReporterConfig
const& _config);
4363 ~JunitReporter()
override;
4367 void noMatchingTestCases(
std::string const& )
override;
4369 void testRunStarting(TestRunInfo
const& runInfo)
override;
4371 void testGroupStarting(GroupInfo
const& groupInfo)
override;
4373 void testCaseStarting(TestCaseInfo
const& testCaseInfo)
override;
4374 bool assertionEnded(AssertionStats
const& assertionStats)
override;
4376 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
4378 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
4380 void testRunEndedCumulative()
override;
4382 void writeGroup(TestGroupNode
const& groupNode,
double suiteTime);
4384 void writeTestCase(TestCaseNode
const& testCaseNode);
4388 SectionNode
const& sectionNode);
4390 void writeAssertions(SectionNode
const& sectionNode);
4391 void writeAssertion(AssertionStats
const& stats);
4397 unsigned int unexpectedExceptions = 0;
4398 bool m_okToFail =
false;
4407 class XmlReporter :
public StreamingReporterBase<XmlReporter> {
4409 XmlReporter(ReporterConfig
const& _config);
4411 ~XmlReporter()
override;
4417 void writeSourceInfo(SourceLineInfo
const& sourceInfo);
4421 void noMatchingTestCases(
std::string const& s)
override;
4423 void testRunStarting(TestRunInfo
const& testInfo)
override;
4425 void testGroupStarting(GroupInfo
const& groupInfo)
override;
4427 void testCaseStarting(TestCaseInfo
const& testInfo)
override;
4429 void sectionStarting(SectionInfo
const& sectionInfo)
override;
4431 void assertionStarting(AssertionInfo
const&)
override;
4433 bool assertionEnded(AssertionStats
const& assertionStats)
override;
4435 void sectionEnded(SectionStats
const& sectionStats)
override;
4437 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
4439 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
4441 void testRunEnded(TestRunStats
const& testRunStats)
override;
4444 Timer m_testCaseTimer;
4446 int m_sectionDepth = 0;
4462#pragma clang diagnostic push
4463#pragma clang diagnostic ignored "-Wweak-vtables"
4474namespace TestCaseTracking {
4476 struct NameAndLocation {
4478 SourceLineInfo location;
4480 NameAndLocation(
std::string const& _name, SourceLineInfo
const& _location );
4485 using ITrackerPtr = std::shared_ptr<ITracker>;
4488 virtual ~ITracker();
4491 virtual NameAndLocation
const& nameAndLocation()
const = 0;
4494 virtual bool isComplete()
const = 0;
4495 virtual bool isSuccessfullyCompleted()
const = 0;
4496 virtual bool isOpen()
const = 0;
4497 virtual bool hasChildren()
const = 0;
4499 virtual ITracker& parent() = 0;
4502 virtual void close() = 0;
4503 virtual void fail() = 0;
4504 virtual void markAsNeedingAnotherRun() = 0;
4506 virtual void addChild( ITrackerPtr
const& child ) = 0;
4507 virtual ITrackerPtr findChild( NameAndLocation
const& nameAndLocation ) = 0;
4508 virtual void openChild() = 0;
4511 virtual bool isSectionTracker()
const = 0;
4512 virtual bool isIndexTracker()
const = 0;
4515 class TrackerContext {
4523 ITrackerPtr m_rootTracker;
4524 ITracker* m_currentTracker =
nullptr;
4525 RunState m_runState = NotStarted;
4529 static TrackerContext& instance();
4531 ITracker& startRun();
4535 void completeCycle();
4537 bool completedCycle()
const;
4538 ITracker& currentTracker();
4539 void setCurrentTracker( ITracker* tracker );
4542 class TrackerBase :
public ITracker {
4549 CompletedSuccessfully,
4553 class TrackerHasName {
4554 NameAndLocation m_nameAndLocation;
4556 TrackerHasName( NameAndLocation
const& nameAndLocation );
4557 bool operator ()( ITrackerPtr
const& tracker )
const;
4560 using Children = std::vector<ITrackerPtr>;
4561 NameAndLocation m_nameAndLocation;
4562 TrackerContext& m_ctx;
4564 Children m_children;
4565 CycleState m_runState = NotStarted;
4568 TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
4570 NameAndLocation
const& nameAndLocation()
const override;
4571 bool isComplete()
const override;
4572 bool isSuccessfullyCompleted()
const override;
4573 bool isOpen()
const override;
4574 bool hasChildren()
const override;
4576 void addChild( ITrackerPtr
const& child )
override;
4578 ITrackerPtr findChild( NameAndLocation
const& nameAndLocation )
override;
4579 ITracker& parent()
override;
4581 void openChild()
override;
4583 bool isSectionTracker()
const override;
4584 bool isIndexTracker()
const override;
4588 void close()
override;
4589 void fail()
override;
4590 void markAsNeedingAnotherRun()
override;
4593 void moveToParent();
4597 class SectionTracker :
public TrackerBase {
4598 std::vector<std::string> m_filters;
4600 SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
4602 bool isSectionTracker()
const override;
4604 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation );
4608 void addInitialFilters( std::vector<std::string>
const& filters );
4609 void addNextFilters( std::vector<std::string>
const& filters );
4612 class IndexTracker :
public TrackerBase {
4616 IndexTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent,
int size );
4618 bool isIndexTracker()
const override;
4619 void close()
override;
4621 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation,
int size );
4630using TestCaseTracking::ITracker;
4631using TestCaseTracking::TrackerContext;
4632using TestCaseTracking::SectionTracker;
4633using TestCaseTracking::IndexTracker;
4643 struct LeakDetector {
4659bool marginComparison(
double lhs,
double rhs,
double margin) {
4660 return (lhs + margin >= rhs) && (rhs + margin >= lhs);
4668 Approx::Approx (
double value )
4669 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
4675 Approx Approx::custom() {
4680 ReusableStringStream rss;
4685 bool Approx::equalityComparisonImpl(
const double other)
const {
4688 return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
4694 return value.toString();
4707 struct IResultCapture;
4710 struct IMutableContext;
4712 using IConfigPtr = std::shared_ptr<IConfig const>;
4716 virtual ~IContext();
4719 virtual IRunner* getRunner() = 0;
4720 virtual IConfigPtr
const& getConfig()
const = 0;
4723 struct IMutableContext : IContext
4725 virtual ~IMutableContext();
4726 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
4727 virtual void setRunner( IRunner* runner ) = 0;
4728 virtual void setConfig( IConfigPtr
const& config ) = 0;
4731 static IMutableContext *currentContext;
4732 friend IMutableContext& getCurrentMutableContext();
4733 friend void cleanUpContext();
4734 static void createContext();
4737 inline IMutableContext& getCurrentMutableContext()
4739 if( !IMutableContext::currentContext )
4740 IMutableContext::createContext();
4741 return *IMutableContext::currentContext;
4744 inline IContext& getCurrentContext()
4746 return getCurrentMutableContext();
4749 void cleanUpContext();
4756 bool isDebuggerActive();
4759#ifdef CATCH_PLATFORM_MAC
4761 #define CATCH_TRAP() __asm__("int $3\n" : : )
4763#elif defined(CATCH_PLATFORM_LINUX)
4767 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
4768 #define CATCH_TRAP() asm volatile ("int $3")
4772 #define CATCH_TRAP() raise(SIGTRAP)
4774#elif defined(_MSC_VER)
4775 #define CATCH_TRAP() __debugbreak()
4776#elif defined(__MINGW32__)
4777 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
4778 #define CATCH_TRAP() DebugBreak()
4782 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
4785 inline void doNothing() {}
4787 #define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing()
4798#if defined(CATCH_PLATFORM_WINDOWS)
4800#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
4801# define CATCH_DEFINED_NOMINMAX
4804#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
4805# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
4806# define WIN32_LEAN_AND_MEAN
4815#ifdef CATCH_DEFINED_NOMINMAX
4818#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
4819# undef WIN32_LEAN_AND_MEAN
4825#if defined( CATCH_CONFIG_WINDOWS_SEH )
4829 struct FatalConditionHandler {
4831 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
4832 FatalConditionHandler();
4833 static void reset();
4834 ~FatalConditionHandler();
4838 static ULONG guaranteeSize;
4839 static PVOID exceptionHandlerHandle;
4844#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
4850 struct FatalConditionHandler {
4853 static struct sigaction oldSigActions[];
4854 static stack_t oldSigStack;
4855 static char altStackMem[];
4857 static void handleSignal(
int sig );
4859 FatalConditionHandler();
4860 ~FatalConditionHandler();
4861 static void reset();
4869 struct FatalConditionHandler {
4881 struct IMutableContext;
4885 class RunContext :
public IResultCapture,
public IRunner {
4888 RunContext( RunContext
const& ) =
delete;
4889 RunContext& operator =( RunContext
const& ) =
delete;
4891 explicit RunContext( IConfigPtr
const& _config, IStreamingReporterPtr&& reporter );
4893 ~RunContext()
override;
4895 void testGroupStarting(
std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
4896 void testGroupEnded(
std::string const& testSpec, Totals
const& totals, std::size_t groupIndex, std::size_t groupsCount );
4898 Totals runTest(TestCase
const& testCase);
4900 IConfigPtr config()
const;
4901 IStreamingReporter& reporter()
const;
4907 ( AssertionInfo
const& info,
4908 ITransientExpression
const& expr,
4909 AssertionReaction& reaction )
override;
4911 ( AssertionInfo
const& info,
4913 StringRef
const& message,
4914 AssertionReaction& reaction )
override;
4915 void handleUnexpectedExceptionNotThrown
4916 ( AssertionInfo
const& info,
4917 AssertionReaction& reaction )
override;
4918 void handleUnexpectedInflightException
4919 ( AssertionInfo
const& info,
4921 AssertionReaction& reaction )
override;
4922 void handleIncomplete
4923 ( AssertionInfo
const& info )
override;
4925 ( AssertionInfo
const &info,
4927 AssertionReaction &reaction )
override;
4929 bool sectionStarted( SectionInfo
const& sectionInfo, Counts& assertions )
override;
4931 void sectionEnded( SectionEndInfo
const& endInfo )
override;
4932 void sectionEndedEarly( SectionEndInfo
const& endInfo )
override;
4934 void benchmarkStarting( BenchmarkInfo
const& info )
override;
4935 void benchmarkEnded( BenchmarkStats
const& stats )
override;
4937 void pushScopedMessage( MessageInfo
const& message )
override;
4938 void popScopedMessage( MessageInfo
const& message )
override;
4942 const AssertionResult* getLastResult()
const override;
4944 void exceptionEarlyReported()
override;
4946 void handleFatalErrorCondition( StringRef message )
override;
4948 bool lastAssertionPassed()
override;
4950 void assertionPassed()
override;
4954 bool aborting() const final;
4958 void runCurrentTest( std::
string& redirectedCout, std::
string& redirectedCerr );
4959 void invokeActiveTestCase();
4961 void resetAssertionInfo();
4962 bool testForMissingAssertions( Counts& assertions );
4964 void assertionEnded( AssertionResult const& result );
4966 ( AssertionInfo const &info,
4967 ResultWas::OfType resultType,
4968 ITransientExpression const *expr,
4971 void populateReaction( AssertionReaction& reaction );
4975 void handleUnfinishedSections();
4977 TestRunInfo m_runInfo;
4978 IMutableContext& m_context;
4979 TestCase const* m_activeTestCase =
nullptr;
4980 ITracker* m_testCaseTracker;
4981 Option<AssertionResult> m_lastResult;
4983 IConfigPtr m_config;
4985 IStreamingReporterPtr m_reporter;
4986 std::vector<MessageInfo> m_messages;
4987 AssertionInfo m_lastAssertionInfo;
4988 std::vector<SectionEndInfo> m_unfinishedSections;
4989 std::vector<ITracker*> m_activeSections;
4990 TrackerContext m_trackerContext;
4991 bool m_lastAssertionPassed =
false;
4992 bool m_shouldReportUnexpected =
true;
4993 bool m_includeSuccessfulResults;
5001 auto operator <<( std::ostream& os, ITransientExpression
const& expr ) -> std::ostream& {
5002 expr.streamReconstructedExpression( os );
5007 : m_isNegated( isNegated )
5012 LazyExpression::operator
bool()
const {
5013 return m_transientExpression !=
nullptr;
5016 auto operator << ( std::ostream& os, LazyExpression
const& lazyExpr ) -> std::ostream& {
5017 if( lazyExpr.m_isNegated )
5021 if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
5022 os <<
"(" << *lazyExpr.m_transientExpression <<
")";
5024 os << *lazyExpr.m_transientExpression;
5027 os <<
"{** error - unchecked empty expression requested **}";
5033 ( StringRef macroName,
5034 SourceLineInfo
const& lineInfo,
5035 StringRef capturedExpression,
5037 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
5042 m_resultCapture.
handleExpr( m_assertionInfo, expr, m_reaction );
5045 m_resultCapture.
handleMessage( m_assertionInfo, resultType, message, m_reaction );
5049 return getCurrentContext().getConfig()->allowThrows();
5060 CATCH_BREAK_INTO_DEBUGGER();
5099 AssertionResultData::AssertionResultData(
ResultWas::OfType _resultType, LazyExpression
const & _lazyExpression):
5100 lazyExpression(_lazyExpression),
5101 resultType(_resultType) {}
5103 std::string AssertionResultData::reconstructExpression()
const {
5105 if( reconstructedExpression.empty() ) {
5106 if( lazyExpression ) {
5107 ReusableStringStream rss;
5108 rss << lazyExpression;
5109 reconstructedExpression = rss.str();
5112 return reconstructedExpression;
5115 AssertionResult::AssertionResult( AssertionInfo
const& info, AssertionResultData
const&
data )
5117 m_resultData(
data )
5121 bool AssertionResult::succeeded()
const {
5131 return m_resultData.resultType;
5134 bool AssertionResult::hasExpression()
const {
5135 return m_info.capturedExpression[0] != 0;
5138 bool AssertionResult::hasMessage()
const {
5139 return !m_resultData.message.empty();
5142 std::string AssertionResult::getExpression()
const {
5144 return "!(" + m_info.capturedExpression + ")";
5146 return m_info.capturedExpression;
5149 std::string AssertionResult::getExpressionInMacro()
const {
5151 if( m_info.macroName[0] == 0 )
5152 expr = m_info.capturedExpression;
5154 expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
5155 expr += m_info.macroName;
5157 expr += m_info.capturedExpression;
5163 bool AssertionResult::hasExpandedExpression()
const {
5164 return hasExpression() && getExpandedExpression() != getExpression();
5167 std::string AssertionResult::getExpandedExpression()
const {
5168 std::string expr = m_resultData.reconstructExpression();
5175 return m_resultData.message;
5177 SourceLineInfo AssertionResult::getSourceInfo()
const {
5178 return m_info.lineInfo;
5181 StringRef AssertionResult::getTestMacroName()
const {
5182 return m_info.macroName;
5191 auto BenchmarkLooper::getResolution() -> uint64_t {
5199 auto elapsed = m_timer.getElapsedNanoseconds();
5202 if( elapsed < m_resolution ) {
5203 m_iterationsToRun *= 10;
5217 using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
5224 MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
5225 handler.handleExpr( expr );
5237#ifdef CLARA_CONFIG_CONSOLE_WIDTH
5238#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
5239#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
5241#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
5244#pragma clang diagnostic push
5245#pragma clang diagnostic ignored "-Wweak-vtables"
5246#pragma clang diagnostic ignored "-Wexit-time-destructors"
5247#pragma clang diagnostic ignored "-Wshadow"
5261#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
5262#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
5265#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
5266#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
5269#ifndef CLARA_CONFIG_OPTIONAL_TYPE
5271#if __has_include(<optional>) && __cplusplus >= 201703L
5273#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
5295#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
5296#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
5299namespace Catch {
namespace clara {
namespace TextFlow {
5301 inline auto isWhitespace(
char c ) ->
bool {
5303 return chars.find( c ) != std::string::npos;
5305 inline auto isBreakableBefore(
char c ) ->
bool {
5307 return chars.find( c ) != std::string::npos;
5309 inline auto isBreakableAfter(
char c ) ->
bool {
5311 return chars.find( c ) != std::string::npos;
5317 std::vector<std::string> m_strings;
5318 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
5319 size_t m_indent = 0;
5320 size_t m_initialIndent = std::string::npos;
5326 Column
const& m_column;
5327 size_t m_stringIndex = 0;
5332 bool m_suffix =
false;
5334 iterator( Column
const& column,
size_t stringIndex )
5335 : m_column( column ),
5336 m_stringIndex( stringIndex )
5339 auto line() const -> std::
string const& {
return m_column.m_strings[m_stringIndex]; }
5341 auto isBoundary(
size_t at )
const ->
bool {
5343 assert( at <= line().size() );
5345 return at == line().size() ||
5346 ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) ||
5347 isBreakableBefore( line()[at] ) ||
5348 isBreakableAfter( line()[at-1] );
5352 assert( m_stringIndex < m_column.m_strings.size() );
5355 auto width = m_column.m_width-indent();
5357 while( m_end < line().size() && line()[m_end] !=
'\n' )
5360 if( m_end < m_pos + width ) {
5361 m_len = m_end - m_pos;
5365 while (len > 0 && !isBoundary(m_pos + len))
5367 while (len > 0 && isWhitespace( line()[m_pos + len - 1] ))
5379 auto indent() const ->
size_t {
5380 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
5381 return initial == std::string::npos ? m_column.m_indent : initial;
5385 return std::string( indent(),
' ' ) + (m_suffix ? plain + "-" : plain);
5389 explicit iterator( Column
const& column ) : m_column( column ) {
5390 assert( m_column.m_width > m_column.m_indent );
5391 assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent );
5398 assert( m_stringIndex < m_column.m_strings.size() );
5399 assert( m_pos <= m_end );
5400 if( m_pos + m_column.m_width < m_end )
5401 return addIndentAndSuffix(line().substr(m_pos, m_len));
5403 return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos));
5406 auto operator ++() -> iterator& {
5408 if( m_pos < line().size() && line()[m_pos] ==
'\n' )
5411 while( m_pos < line().size() && isWhitespace( line()[m_pos] ) )
5414 if( m_pos == line().size() ) {
5418 if( m_stringIndex < m_column.m_strings.size() )
5422 auto operator ++(
int) -> iterator {
5423 iterator prev( *
this );
5428 auto operator ==( iterator
const& other )
const ->
bool {
5430 m_pos == other.m_pos &&
5431 m_stringIndex == other.m_stringIndex &&
5432 &m_column == &other.m_column;
5434 auto operator !=( iterator
const& other )
const ->
bool {
5438 using const_iterator = iterator;
5440 explicit Column(
std::string const& text ) { m_strings.push_back( text ); }
5442 auto width(
size_t newWidth ) -> Column& {
5443 assert( newWidth > 0 );
5447 auto indent(
size_t newIndent ) -> Column& {
5448 m_indent = newIndent;
5451 auto initialIndent(
size_t newIndent ) -> Column& {
5452 m_initialIndent = newIndent;
5456 auto width() const ->
size_t {
return m_width; }
5457 auto begin() const -> iterator {
return iterator( *
this ); }
5458 auto end() const -> iterator {
return { *
this, m_strings.size() }; }
5460 inline friend std::ostream&
operator << ( std::ostream& os, Column
const& col ) {
5462 for(
auto line : col ) {
5472 auto operator + ( Column
const& other ) -> Columns;
5474 auto toString() const -> std::
string {
5475 std::ostringstream oss;
5481 class Spacer :
public Column {
5484 explicit Spacer(
size_t spaceWidth ) : Column(
"" ) {
5485 width( spaceWidth );
5490 std::vector<Column> m_columns;
5498 std::vector<Column>
const& m_columns;
5499 std::vector<Column::iterator> m_iterators;
5500 size_t m_activeIterators;
5502 iterator( Columns
const& columns, EndTag )
5503 : m_columns( columns.m_columns ),
5504 m_activeIterators( 0 )
5506 m_iterators.reserve( m_columns.size() );
5508 for(
auto const& col : m_columns )
5509 m_iterators.push_back( col.end() );
5513 explicit iterator( Columns
const& columns )
5514 : m_columns( columns.m_columns ),
5515 m_activeIterators( m_columns.size() )
5517 m_iterators.reserve( m_columns.size() );
5519 for(
auto const& col : m_columns )
5520 m_iterators.push_back( col.begin() );
5523 auto operator ==( iterator
const& other )
const ->
bool {
5524 return m_iterators == other.m_iterators;
5526 auto operator !=( iterator
const& other )
const ->
bool {
5527 return m_iterators != other.m_iterators;
5532 for(
size_t i = 0; i < m_columns.size(); ++i ) {
5533 auto width = m_columns[i].width();
5534 if( m_iterators[i] != m_columns[i].
end() ) {
5536 row += padding + col;
5537 if( col.size() < width )
5543 padding += std::string( width, ' ' );
5548 auto operator ++() -> iterator& {
5549 for(
size_t i = 0; i < m_columns.size(); ++i ) {
5550 if (m_iterators[i] != m_columns[i].
end())
5555 auto operator ++(
int) -> iterator {
5556 iterator prev( *
this );
5561 using const_iterator = iterator;
5563 auto begin() const -> iterator {
return iterator( *
this ); }
5564 auto end() const -> iterator {
return { *
this, iterator::EndTag() }; }
5566 auto operator += ( Column
const& col ) -> Columns& {
5567 m_columns.push_back( col );
5570 auto operator + ( Column
const& col ) -> Columns {
5571 Columns combined = *
this;
5576 inline friend std::ostream&
operator << ( std::ostream& os, Columns
const& cols ) {
5579 for(
auto line : cols ) {
5589 auto toString() const -> std::
string {
5590 std::ostringstream oss;
5611#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
5612#define CATCH_PLATFORM_WINDOWS
5615namespace Catch {
namespace clara {
5619 template<
typename L>
5620 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
5622 template<
typename ClassT,
typename ReturnT,
typename... Args>
5623 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
5624 static const bool isValid =
false;
5627 template<
typename ClassT,
typename ReturnT,
typename ArgT>
5628 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
5629 static const bool isValid =
true;
5630 using ArgType =
typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
5631 using ReturnType = ReturnT;
5640 std::vector<std::string> m_args;
5643 Args(
int argc,
char const*
const* argv )
5644 : m_exeName(argv[0]),
5645 m_args(argv + 1, argv + argc) {}
5647 Args( std::initializer_list<std::string> args )
5648 : m_exeName( *args.
begin() ),
5649 m_args( args.
begin()+1, args.
end() )
5652 auto exeName() const -> std::
string {
5667 inline auto isOptPrefix(
char c ) ->
bool {
5669#ifdef CATCH_PLATFORM_WINDOWS
5677 using Iterator = std::vector<std::string>::const_iterator;
5680 std::vector<Token> m_tokenBuffer;
5683 m_tokenBuffer.resize( 0 );
5686 while( it != itEnd && it->empty() )
5690 auto const &next = *it;
5691 if( isOptPrefix( next[0] ) ) {
5692 auto delimiterPos = next.find_first_of(
" :=" );
5693 if( delimiterPos != std::string::npos ) {
5694 m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
5695 m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
5697 if( next[1] !=
'-' && next.size() > 2 ) {
5699 for(
size_t i = 1; i < next.size(); ++i ) {
5701 m_tokenBuffer.push_back( { TokenType::Option, opt } );
5704 m_tokenBuffer.push_back( { TokenType::Option, next } );
5708 m_tokenBuffer.push_back( { TokenType::Argument, next } );
5714 explicit TokenStream( Args
const &args ) : TokenStream( args.m_args.
begin(), args.m_args.
end() ) {}
5716 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
5720 explicit operator bool()
const {
5721 return !m_tokenBuffer.empty() || it != itEnd;
5724 auto count() const ->
size_t {
return m_tokenBuffer.size() + (itEnd - it); }
5727 assert( !m_tokenBuffer.empty() );
5728 return m_tokenBuffer.front();
5731 auto operator->() const -> Token const * {
5732 assert( !m_tokenBuffer.empty() );
5733 return &m_tokenBuffer.front();
5736 auto operator++() -> TokenStream & {
5737 if( m_tokenBuffer.size() >= 2 ) {
5738 m_tokenBuffer.erase( m_tokenBuffer.begin() );
5751 Ok, LogicError, RuntimeError
5755 ResultBase( Type type ) : m_type( type ) {}
5756 virtual ~ResultBase() =
default;
5758 virtual void enforceOk()
const = 0;
5763 template<
typename T>
5764 class ResultValueBase :
public ResultBase {
5766 auto value() const -> T const & {
5772 ResultValueBase( Type type ) : ResultBase( type ) {}
5774 ResultValueBase( ResultValueBase
const &other ) : ResultBase( other ) {
5775 if( m_type == ResultBase::Ok )
5776 new( &m_value ) T( other.m_value );
5779 ResultValueBase( Type, T
const &
value ) : ResultBase( Ok ) {
5780 new( &m_value ) T(
value );
5783 auto operator=( ResultValueBase
const &other ) -> ResultValueBase & {
5784 if( m_type == ResultBase::Ok )
5786 ResultBase::operator=(other);
5787 if( m_type == ResultBase::Ok )
5788 new( &m_value ) T( other.m_value );
5792 ~ResultValueBase()
override {
5803 class ResultValueBase<void> :
public ResultBase {
5805 using ResultBase::ResultBase;
5808 template<
typename T =
void>
5809 class BasicResult :
public ResultValueBase<T> {
5811 template<
typename U>
5812 explicit BasicResult( BasicResult<U>
const &other )
5813 : ResultValueBase<T>( other.type() ),
5814 m_errorMessage( other.errorMessage() )
5816 assert( type() != ResultBase::Ok );
5819 template<
typename U>
5820 static auto ok( U
const &
value ) -> BasicResult {
return { ResultBase::Ok,
value }; }
5821 static auto ok() -> BasicResult {
return { ResultBase::Ok }; }
5822 static auto logicError(
std::string const &message ) -> BasicResult {
return { ResultBase::LogicError, message }; }
5823 static auto runtimeError(
std::string const &message ) -> BasicResult {
return { ResultBase::RuntimeError, message }; }
5825 explicit operator bool()
const {
return m_type == ResultBase::Ok; }
5826 auto type() const -> ResultBase::Type {
return m_type; }
5827 auto errorMessage() const -> std::
string {
return m_errorMessage; }
5830 void enforceOk()
const override {
5834 assert( m_type != ResultBase::LogicError );
5835 assert( m_type != ResultBase::RuntimeError );
5836 if( m_type != ResultBase::Ok )
5842 BasicResult( ResultBase::Type type,
std::string const &message )
5843 : ResultValueBase<T>(type),
5844 m_errorMessage(message)
5846 assert( m_type != ResultBase::Ok );
5849 using ResultValueBase<T>::ResultValueBase;
5850 using ResultBase::m_type;
5853 enum class ParseResultType {
5854 Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
5860 ParseState( ParseResultType type, TokenStream
const &remainingTokens )
5862 m_remainingTokens( remainingTokens )
5865 auto type() const -> ParseResultType {
return m_type; }
5866 auto remainingTokens() const -> TokenStream {
return m_remainingTokens; }
5869 ParseResultType m_type;
5870 TokenStream m_remainingTokens;
5873 using Result = BasicResult<void>;
5874 using ParserResult = BasicResult<ParseResultType>;
5875 using InternalParseResult = BasicResult<ParseState>;
5877 struct HelpColumns {
5882 template<
typename T>
5883 inline auto convertInto(
std::string const &source, T& target ) -> ParserResult {
5884 std::stringstream ss;
5888 return ParserResult::runtimeError(
"Unable to convert '" + source +
"' to destination type" );
5890 return ParserResult::ok( ParseResultType::Matched );
5894 return ParserResult::ok( ParseResultType::Matched );
5896 inline auto convertInto(
std::string const &source,
bool &target ) -> ParserResult {
5898 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), [](
char c ) { return static_cast<char>( ::tolower(c) ); } );
5899 if (srcLC ==
"y" || srcLC ==
"1" || srcLC ==
"true" || srcLC ==
"yes" || srcLC ==
"on")
5901 else if (srcLC ==
"n" || srcLC ==
"0" || srcLC ==
"false" || srcLC ==
"no" || srcLC ==
"off")
5904 return ParserResult::runtimeError(
"Expected a boolean value but did not recognise: '" + source +
"'" );
5905 return ParserResult::ok( ParseResultType::Matched );
5907#ifdef CLARA_CONFIG_OPTIONAL_TYPE
5908 template<
typename T>
5909 inline auto convertInto(
std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
5911 auto result = convertInto( source, temp );
5913 target = std::move(temp);
5918 struct NonCopyable {
5919 NonCopyable() =
default;
5920 NonCopyable( NonCopyable
const & ) =
delete;
5921 NonCopyable( NonCopyable && ) =
delete;
5922 NonCopyable &operator=( NonCopyable
const & ) =
delete;
5923 NonCopyable &operator=( NonCopyable && ) =
delete;
5926 struct BoundRef : NonCopyable {
5927 virtual ~BoundRef() =
default;
5928 virtual auto isContainer() const ->
bool {
return false; }
5929 virtual auto isFlag() const ->
bool {
return false; }
5931 struct BoundValueRefBase : BoundRef {
5932 virtual auto setValue(
std::string const &arg ) -> ParserResult = 0;
5934 struct BoundFlagRefBase : BoundRef {
5935 virtual auto setFlag(
bool flag ) -> ParserResult = 0;
5936 virtual auto isFlag() const ->
bool {
return true; }
5939 template<
typename T>
5940 struct BoundValueRef : BoundValueRefBase {
5943 explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
5945 auto setValue(
std::string const &arg ) -> ParserResult
override {
5946 return convertInto( arg, m_ref );
5950 template<
typename T>
5951 struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
5952 std::vector<T> &m_ref;
5954 explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
5956 auto isContainer() const ->
bool override {
return true; }
5958 auto setValue(
std::string const &arg ) -> ParserResult
override {
5960 auto result = convertInto( arg, temp );
5962 m_ref.push_back( temp );
5967 struct BoundFlagRef : BoundFlagRefBase {
5970 explicit BoundFlagRef(
bool &ref ) : m_ref( ref ) {}
5972 auto setFlag(
bool flag ) -> ParserResult
override {
5974 return ParserResult::ok( ParseResultType::Matched );
5978 template<
typename ReturnType>
5979 struct LambdaInvoker {
5982 template<
typename L,
typename ArgType>
5983 static auto invoke( L
const &lambda, ArgType
const &arg ) -> ParserResult {
5984 return lambda( arg );
5989 struct LambdaInvoker<void> {
5990 template<
typename L,
typename ArgType>
5991 static auto invoke( L
const &lambda, ArgType
const &arg ) -> ParserResult {
5993 return ParserResult::ok( ParseResultType::Matched );
5997 template<
typename ArgType,
typename L>
5998 inline auto invokeLambda( L
const &lambda,
std::string const &arg ) -> ParserResult {
6000 auto result = convertInto( arg, temp );
6003 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
6006 template<
typename L>
6007 struct BoundLambda : BoundValueRefBase {
6010 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
6011 explicit BoundLambda( L
const &lambda ) : m_lambda( lambda ) {}
6013 auto setValue(
std::string const &arg ) -> ParserResult
override {
6014 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
6018 template<
typename L>
6019 struct BoundFlagLambda : BoundFlagRefBase {
6022 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
6023 static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType,
bool>
::value,
"flags must be boolean" );
6025 explicit BoundFlagLambda( L
const &lambda ) : m_lambda( lambda ) {}
6027 auto setFlag(
bool flag ) -> ParserResult
override {
6028 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
6032 enum class Optionality { Optional, Required };
6038 virtual ~ParserBase() =
default;
6039 virtual auto validate() const -> Result {
return Result::ok(); }
6040 virtual auto parse(
std::string const& exeName, TokenStream
const &tokens)
const -> InternalParseResult = 0;
6041 virtual auto cardinality() const ->
size_t {
return 1; }
6043 auto parse( Args
const &args )
const -> InternalParseResult {
6044 return parse( args.exeName(), TokenStream( args ) );
6048 template<
typename DerivedT>
6049 class ComposableParserImpl :
public ParserBase {
6051 template<
typename T>
6052 auto operator|( T
const &other )
const -> Parser;
6054 template<
typename T>
6055 auto operator+( T
const &other )
const -> Parser;
6059 template<
typename DerivedT>
6060 class ParserRefImpl :
public ComposableParserImpl<DerivedT> {
6062 Optionality m_optionality = Optionality::Optional;
6063 std::shared_ptr<BoundRef> m_ref;
6067 explicit ParserRefImpl( std::shared_ptr<BoundRef>
const &ref ) : m_ref( ref ) {}
6070 template<
typename T>
6072 : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
6076 template<
typename LambdaT>
6077 ParserRefImpl( LambdaT
const &ref,
std::string const &hint )
6078 : m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
6082 auto operator()(
std::string const &description ) -> DerivedT & {
6083 m_description = description;
6084 return static_cast<DerivedT &
>( *this );
6087 auto optional() -> DerivedT & {
6088 m_optionality = Optionality::Optional;
6089 return static_cast<DerivedT &
>( *this );
6092 auto required() -> DerivedT & {
6093 m_optionality = Optionality::Required;
6094 return static_cast<DerivedT &
>( *this );
6097 auto isOptional() const ->
bool {
6098 return m_optionality == Optionality::Optional;
6101 auto cardinality() const ->
size_t override {
6102 if( m_ref->isContainer() )
6108 auto hint() const -> std::
string {
return m_hint; }
6111 class ExeName :
public ComposableParserImpl<ExeName> {
6112 std::shared_ptr<std::string> m_name;
6113 std::shared_ptr<BoundValueRefBase> m_ref;
6115 template<
typename LambdaT>
6116 static auto makeRef(LambdaT
const &lambda) -> std::shared_ptr<BoundValueRefBase> {
6117 return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
6121 ExeName() : m_name( std::make_shared<std::
string>(
"<executable>" ) ) {}
6123 explicit ExeName(
std::string &ref ) : ExeName() {
6124 m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
6127 template<
typename LambdaT>
6128 explicit ExeName( LambdaT
const& lambda ) : ExeName() {
6129 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );
6133 auto parse(
std::string const&, TokenStream
const &tokens )
const -> InternalParseResult
override {
6134 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
6137 auto name() const -> std::
string {
return *m_name; }
6138 auto set(
std::string const& newName ) -> ParserResult {
6140 auto lastSlash = newName.find_last_of(
"\\/" );
6141 auto filename = ( lastSlash == std::string::npos )
6143 : newName.substr( lastSlash+1 );
6147 return m_ref->setValue( filename );
6149 return ParserResult::ok( ParseResultType::Matched );
6153 class Arg :
public ParserRefImpl<Arg> {
6155 using ParserRefImpl::ParserRefImpl;
6157 auto parse(
std::string const &, TokenStream
const &tokens )
const -> InternalParseResult
override {
6158 auto validationResult = validate();
6159 if( !validationResult )
6160 return InternalParseResult( validationResult );
6162 auto remainingTokens = tokens;
6163 auto const &token = *remainingTokens;
6164 if( token.type != TokenType::Argument )
6165 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
6167 assert( !m_ref->isFlag() );
6168 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.get() );
6170 auto result = valueRef->setValue( remainingTokens->token );
6172 return InternalParseResult( result );
6174 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
6179#ifdef CATCH_PLATFORM_WINDOWS
6180 if( optName[0] ==
'/' )
6181 return "-" + optName.substr( 1 );
6187 class Opt :
public ParserRefImpl<Opt> {
6189 std::vector<std::string> m_optNames;
6192 template<
typename LambdaT>
6193 explicit Opt( LambdaT
const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
6195 explicit Opt(
bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}
6197 template<
typename LambdaT>
6198 Opt( LambdaT
const &ref,
std::string const &hint ) : ParserRefImpl( ref, hint ) {}
6200 template<
typename T>
6201 Opt( T &ref,
std::string const &hint ) : ParserRefImpl( ref, hint ) {}
6203 auto operator[](
std::string const &optName ) -> Opt & {
6204 m_optNames.push_back( optName );
6208 auto getHelpColumns() const -> std::vector<HelpColumns> {
6209 std::ostringstream oss;
6211 for(
auto const &opt : m_optNames ) {
6218 if( !m_hint.empty() )
6219 oss <<
" <" << m_hint <<
">";
6220 return { { oss.str(), m_description } };
6223 auto isMatch(
std::string const &optToken )
const ->
bool {
6224 auto normalisedToken = normaliseOpt( optToken );
6225 for(
auto const &
name : m_optNames ) {
6226 if( normaliseOpt(
name ) == normalisedToken )
6232 using ParserBase::parse;
6234 auto parse(
std::string const&, TokenStream
const &tokens )
const -> InternalParseResult
override {
6235 auto validationResult = validate();
6236 if( !validationResult )
6237 return InternalParseResult( validationResult );
6239 auto remainingTokens = tokens;
6240 if( remainingTokens && remainingTokens->type == TokenType::Option ) {
6241 auto const &token = *remainingTokens;
6242 if( isMatch(token.token ) ) {
6243 if( m_ref->isFlag() ) {
6244 auto flagRef =
static_cast<detail::BoundFlagRefBase*
>( m_ref.get() );
6245 auto result = flagRef->setFlag(
true );
6247 return InternalParseResult( result );
6248 if( result.value() == ParseResultType::ShortCircuitAll )
6249 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
6251 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.get() );
6253 if( !remainingTokens )
6254 return InternalParseResult::runtimeError(
"Expected argument following " + token.token );
6255 auto const &argToken = *remainingTokens;
6256 if( argToken.type != TokenType::Argument )
6257 return InternalParseResult::runtimeError(
"Expected argument following " + token.token );
6258 auto result = valueRef->setValue( argToken.token );
6260 return InternalParseResult( result );
6261 if( result.value() == ParseResultType::ShortCircuitAll )
6262 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
6264 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
6267 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
6270 auto validate() const -> Result
override {
6271 if( m_optNames.empty() )
6272 return Result::logicError(
"No options supplied to Opt" );
6273 for(
auto const &
name : m_optNames ) {
6275 return Result::logicError(
"Option name cannot be empty" );
6276#ifdef CATCH_PLATFORM_WINDOWS
6277 if(
name[0] !=
'-' &&
name[0] !=
'/' )
6278 return Result::logicError(
"Option name must begin with '-' or '/'" );
6280 if(
name[0] !=
'-' )
6281 return Result::logicError(
"Option name must begin with '-'" );
6284 return ParserRefImpl::validate();
6289 Help(
bool &showHelpFlag )
6290 : Opt([&](
bool flag ) {
6291 showHelpFlag = flag;
6292 return ParserResult::ok( ParseResultType::ShortCircuitAll );
6295 static_cast<Opt &
>( *this )
6296 (
"display usage information")
6297 [
"-?"][
"-h"][
"--help"]
6302 struct Parser : ParserBase {
6304 mutable ExeName m_exeName;
6305 std::vector<Opt> m_options;
6306 std::vector<Arg> m_args;
6308 auto operator|=( ExeName
const &exeName ) -> Parser & {
6309 m_exeName = exeName;
6313 auto operator|=( Arg
const &arg ) -> Parser & {
6314 m_args.push_back(arg);
6318 auto operator|=( Opt
const &opt ) -> Parser & {
6319 m_options.push_back(opt);
6323 auto operator|=( Parser
const &other ) -> Parser & {
6324 m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
6325 m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
6329 template<
typename T>
6330 auto operator|( T
const &other )
const -> Parser {
6331 return Parser( *
this ) |= other;
6335 template<
typename T>
6336 auto operator+=( T
const &other ) -> Parser & {
return operator|=( other ); }
6337 template<
typename T>
6340 auto getHelpColumns() const -> std::vector<HelpColumns> {
6341 std::vector<HelpColumns> cols;
6342 for (
auto const &o : m_options) {
6343 auto childCols = o.getHelpColumns();
6344 cols.insert( cols.end(), childCols.begin(), childCols.end() );
6349 void writeToStream( std::ostream &os )
const {
6350 if (!m_exeName.name().empty()) {
6351 os <<
"usage:\n" <<
" " << m_exeName.name() <<
" ";
6352 bool required =
true, first =
true;
6353 for(
auto const &arg : m_args ) {
6358 if( arg.isOptional() && required ) {
6362 os <<
"<" << arg.hint() <<
">";
6363 if( arg.cardinality() == 0 )
6368 if( !m_options.empty() )
6370 os <<
"\n\nwhere options are:" << std::endl;
6373 auto rows = getHelpColumns();
6374 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
6375 size_t optWidth = 0;
6376 for(
auto const &cols : rows )
6377 optWidth = (
std::max)(optWidth, cols.left.size() + 2);
6379 optWidth = (
std::min)(optWidth, consoleWidth/2);
6381 for(
auto const &cols : rows ) {
6383 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
6384 TextFlow::Spacer(4) +
6385 TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
6386 os << row << std::endl;
6390 friend auto operator<<( std::ostream &os, Parser
const &parser ) -> std::ostream& {
6391 parser.writeToStream( os );
6395 auto validate() const -> Result
override {
6396 for(
auto const &opt : m_options ) {
6397 auto result = opt.validate();
6401 for(
auto const &arg : m_args ) {
6402 auto result = arg.validate();
6406 return Result::ok();
6409 using ParserBase::parse;
6411 auto parse(
std::string const& exeName, TokenStream
const &tokens )
const -> InternalParseResult
override {
6414 ParserBase
const* parser =
nullptr;
6417 const size_t totalParsers = m_options.size() + m_args.size();
6418 assert( totalParsers < 512 );
6420 ParserInfo parseInfos[512];
6424 for (
auto const &opt : m_options) parseInfos[i++].parser = &opt;
6425 for (
auto const &arg : m_args) parseInfos[i++].parser = &arg;
6428 m_exeName.set( exeName );
6430 auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
6431 while( result.value().remainingTokens() ) {
6432 bool tokenParsed =
false;
6434 for(
size_t i = 0; i < totalParsers; ++i ) {
6435 auto& parseInfo = parseInfos[i];
6436 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
6437 result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
6440 if (result.value().type() != ParseResultType::NoMatch) {
6448 if( result.value().type() == ParseResultType::ShortCircuitAll )
6451 return InternalParseResult::runtimeError(
"Unrecognised token: " + result.value().remainingTokens()->token );
6458 template<
typename DerivedT>
6459 template<
typename T>
6461 return Parser() |
static_cast<DerivedT
const &
>( *this ) | other;
6466using detail::Parser;
6478using detail::ExeName;
6484using detail::ParseResultType;
6487using detail::ParserResult;
6493#pragma clang diagnostic pop
6497#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
6498#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
6499#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
6505 clara::Parser makeCommandLineParser( ConfigData& config );
6515 clara::Parser makeCommandLineParser( ConfigData& config ) {
6517 using namespace clara;
6519 auto const setWarning = [&](
std::string const& warning ) {
6520 auto warningSet = [&]() {
6521 if( warning ==
"NoAssertions" )
6522 return WarnAbout::NoAssertions;
6524 if ( warning ==
"NoTests" )
6525 return WarnAbout::NoTests;
6527 return WarnAbout::Nothing;
6530 if (warningSet == WarnAbout::Nothing)
6531 return ParserResult::runtimeError(
"Unrecognised warning: '" + warning +
"'" );
6532 config.warnings =
static_cast<WarnAbout::What
>( config.warnings | warningSet );
6533 return ParserResult::ok( ParseResultType::Matched );
6535 auto const loadTestNamesFromFile = [&](
std::string const& filename ) {
6536 std::ifstream f( filename.c_str() );
6538 return ParserResult::runtimeError(
"Unable to load input file: '" + filename +
"'" );
6541 while( std::getline( f, line ) ) {
6543 if( !line.empty() && !
startsWith( line,
'#' ) ) {
6545 line =
'"' + line + '"';
6546 config.testsOrTags.push_back( line +
',' );
6549 return ParserResult::ok( ParseResultType::Matched );
6551 auto const setTestOrder = [&](
std::string const& order ) {
6553 config.runOrder = RunTests::InDeclarationOrder;
6555 config.runOrder = RunTests::InLexicographicalOrder;
6557 config.runOrder = RunTests::InRandomOrder;
6559 return clara::ParserResult::runtimeError(
"Unrecognised ordering: '" + order +
"'" );
6560 return ParserResult::ok( ParseResultType::Matched );
6562 auto const setRngSeed = [&](
std::string const& seed ) {
6563 if( seed !=
"time" )
6564 return clara::detail::convertInto( seed, config.rngSeed );
6565 config.rngSeed =
static_cast<unsigned int>( std::time(
nullptr) );
6566 return ParserResult::ok( ParseResultType::Matched );
6568 auto const setColourUsage = [&](
std::string const& useColour ) {
6569 auto mode =
toLower( useColour );
6572 config.useColour = UseColour::Yes;
6573 else if( mode ==
"no" )
6574 config.useColour = UseColour::No;
6575 else if( mode ==
"auto" )
6576 config.useColour = UseColour::Auto;
6578 return ParserResult::runtimeError(
"colour mode must be one of: auto, yes or no. '" + useColour +
"' not recognised" );
6579 return ParserResult::ok( ParseResultType::Matched );
6581 auto const setWaitForKeypress = [&](
std::string const& keypress ) {
6582 auto keypressLc =
toLower( keypress );
6583 if( keypressLc ==
"start" )
6584 config.waitForKeypress = WaitForKeypress::BeforeStart;
6585 else if( keypressLc ==
"exit" )
6586 config.waitForKeypress = WaitForKeypress::BeforeExit;
6587 else if( keypressLc ==
"both" )
6588 config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
6590 return ParserResult::runtimeError(
"keypress argument must be one of: start, exit or both. '" + keypress +
"' not recognised" );
6591 return ParserResult::ok( ParseResultType::Matched );
6593 auto const setVerbosity = [&](
std::string const& verbosity ) {
6594 auto lcVerbosity =
toLower( verbosity );
6595 if( lcVerbosity ==
"quiet" )
6596 config.verbosity = Verbosity::Quiet;
6597 else if( lcVerbosity ==
"normal" )
6598 config.verbosity = Verbosity::Normal;
6599 else if( lcVerbosity ==
"high" )
6600 config.verbosity = Verbosity::High;
6602 return ParserResult::runtimeError(
"Unrecognised verbosity, '" + verbosity +
"'" );
6603 return ParserResult::ok( ParseResultType::Matched );
6607 = ExeName( config.processName )
6608 | Help( config.showHelp )
6609 | Opt( config.listTests )
6610 ["-l"]["--list-tests"]
6611 (
"list all/matching test cases" )
6612 | Opt( config.listTags )
6613 ["-t"]["--list-tags"]
6614 (
"list all/matching tags" )
6615 | Opt( config.showSuccessfulTests )
6617 (
"include successful tests in output" )
6618 | Opt( config.shouldDebugBreak )
6620 (
"break into debugger on failure" )
6621 | Opt( config.noThrow )
6623 (
"skip exception tests" )
6624 | Opt( config.showInvisibles )
6625 ["-i"]["--invisibles"]
6626 (
"show invisibles (tabs, newlines)" )
6627 | Opt( config.outputFilename,
"filename" )
6629 (
"output filename" )
6630 | Opt( config.reporterName,
"name" )
6631 ["-r"]["--reporter"]
6632 (
"reporter to use (defaults to console)" )
6633 | Opt( config.name,
"name" )
6636 | Opt( [&](
bool ){ config.abortAfter = 1; } )
6638 (
"abort at first failure" )
6639 | Opt( [&](
int x ){ config.abortAfter =
x; },
"no. failures" )
6641 (
"abort after x failures" )
6642 | Opt( setWarning,
"warning name" )
6644 (
"enable warnings" )
6645 | Opt( [&](
bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; },
"yes|no" )
6646 [
"-d"][
"--durations"]
6647 (
"show test durations" )
6648 | Opt( loadTestNamesFromFile,
"filename" )
6649 ["-f"]["--input-file"]
6650 (
"load test names to run from a file" )
6651 | Opt( config.filenamesAsTags )
6652 ["-#"]["--filenames-as-tags"]
6653 (
"adds a tag for the filename" )
6654 | Opt( config.sectionsToRun,
"section name" )
6656 (
"specify section to run" )
6657 | Opt( setVerbosity,
"quiet|normal|high" )
6658 ["-v"]["--verbosity"]
6659 (
"set output verbosity" )
6660 | Opt( config.listTestNamesOnly )
6661 ["--list-test-names-only"]
6662 (
"list all/matching test cases names only" )
6663 | Opt( config.listReporters )
6664 ["--list-reporters"]
6665 (
"list all reporters" )
6666 | Opt( setTestOrder,
"decl|lex|rand" )
6668 (
"test case order (defaults to decl)" )
6669 | Opt( setRngSeed,
"'time'|number" )
6671 (
"set a specific seed for random numbers" )
6672 | Opt( setColourUsage,
"yes|no" )
6674 (
"should output be colourised" )
6675 | Opt( config.libIdentify )
6677 (
"report name and version according to libidentify standard" )
6678 | Opt( setWaitForKeypress,
"start|exit|both" )
6679 ["--wait-for-keypress"]
6680 (
"waits for a keypress before exiting" )
6681 | Opt( config.benchmarkResolutionMultiple,
"multiplier" )
6682 ["--benchmark-resolution-multiple"]
6683 (
"multiple of clock resolution to run benchmarks" )
6685 | Arg( config.testsOrTags,
"test name|pattern|tags" )
6686 (
"which test or tests to use" );
6701 return file[0] ==
'\0';
6704 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
6707 return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
6710 std::ostream&
operator << ( std::ostream& os, SourceLineInfo
const& info ) {
6712 os << info.file <<
'(' << info.line <<
')';
6714 os << info.file <<
':' << info.line;
6734#define CATCH_PREPARE_EXCEPTION( type, msg ) \
6735 type( ( Catch::ReusableStringStream() << msg ).str() )
6736#define CATCH_INTERNAL_ERROR( msg ) \
6737 throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg);
6738#define CATCH_ERROR( msg ) \
6739 throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg )
6740#define CATCH_ENFORCE( condition, msg ) \
6741 do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
6746 Config::Config( ConfigData
const&
data )
6748 m_stream( openStream() )
6751 if (
data.testsOrTags.empty()) {
6752 parser.parse(
"~[.]");
6755 m_hasTestFilters =
true;
6756 for(
auto const& testOrTags :
data.testsOrTags )
6757 parser.parse( testOrTags );
6759 m_testSpec = parser.testSpec();
6763 return m_data.outputFilename ;
6766 bool Config::listTests()
const {
return m_data.listTests; }
6767 bool Config::listTestNamesOnly()
const {
return m_data.listTestNamesOnly; }
6768 bool Config::listTags()
const {
return m_data.listTags; }
6769 bool Config::listReporters()
const {
return m_data.listReporters; }
6771 std::string Config::getProcessName()
const {
return m_data.processName; }
6772 std::string const& Config::getReporterName()
const {
return m_data.reporterName; }
6774 std::vector<std::string>
const& Config::getTestsOrTags()
const {
return m_data.testsOrTags; }
6775 std::vector<std::string>
const& Config::getSectionsToRun()
const {
return m_data.sectionsToRun; }
6777 TestSpec
const& Config::testSpec()
const {
return m_testSpec; }
6778 bool Config::hasTestFilters()
const {
return m_hasTestFilters; }
6780 bool Config::showHelp()
const {
return m_data.showHelp; }
6783 bool Config::allowThrows()
const {
return !m_data.noThrow; }
6784 std::ostream& Config::stream()
const {
return m_stream->stream(); }
6786 bool Config::includeSuccessfulResults()
const {
return m_data.showSuccessfulTests; }
6787 bool Config::warnAboutMissingAssertions()
const {
return !!(m_data.warnings & WarnAbout::NoAssertions); }
6788 bool Config::warnAboutNoTests()
const {
return !!(m_data.warnings & WarnAbout::NoTests); }
6789 ShowDurations::OrNot Config::showDurations()
const {
return m_data.showDurations; }
6790 RunTests::InWhatOrder Config::runOrder()
const {
return m_data.runOrder; }
6792 int Config::benchmarkResolutionMultiple()
const {
return m_data.benchmarkResolutionMultiple; }
6793 UseColour::YesOrNo Config::useColour()
const {
return m_data.useColour; }
6794 bool Config::shouldDebugBreak()
const {
return m_data.shouldDebugBreak; }
6795 int Config::abortAfter()
const {
return m_data.abortAfter; }
6796 bool Config::showInvisibles()
const {
return m_data.showInvisibles; }
6797 Verbosity Config::verbosity()
const {
return m_data.verbosity; }
6799 IStream
const* Config::openStream() {
6807#if defined(__clang__)
6808# pragma clang diagnostic push
6809# pragma clang diagnostic ignored "-Wexit-time-destructors"
6832 struct IColourImpl {
6833 virtual ~IColourImpl() =
default;
6834 virtual void use( Colour::Code _colourCode ) = 0;
6837 struct NoColourImpl : IColourImpl {
6838 void use( Colour::Code ) {}
6840 static IColourImpl* instance() {
6841 static NoColourImpl s_instance;
6849#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
6850# ifdef CATCH_PLATFORM_WINDOWS
6851# define CATCH_CONFIG_COLOUR_WINDOWS
6853# define CATCH_CONFIG_COLOUR_ANSI
6857#if defined ( CATCH_CONFIG_COLOUR_WINDOWS )
6862 class Win32ColourImpl :
public IColourImpl {
6864 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
6866 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
6867 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
6868 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
6869 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
6872 virtual void use( Colour::Code _colourCode )
override {
6873 switch( _colourCode ) {
6874 case Colour::None:
return setTextAttribute( originalForegroundAttributes );
6875 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6876 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
6877 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
6878 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
6879 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
6880 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
6881 case Colour::Grey:
return setTextAttribute( 0 );
6883 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
6884 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
6885 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
6886 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6887 case Colour::BrightYellow:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
6889 case Colour::Bright: CATCH_INTERNAL_ERROR(
"not a colour" );
6892 CATCH_ERROR(
"Unknown colour requested" );
6897 void setTextAttribute( WORD _textAttribute ) {
6898 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
6900 HANDLE stdoutHandle;
6901 WORD originalForegroundAttributes;
6902 WORD originalBackgroundAttributes;
6905 IColourImpl* platformColourInstance() {
6906 static Win32ColourImpl s_instance;
6908 IConfigPtr config = getCurrentContext().getConfig();
6909 UseColour::YesOrNo colourMode = config
6910 ? config->useColour()
6912 if( colourMode == UseColour::Auto )
6913 colourMode = UseColour::Yes;
6914 return colourMode == UseColour::Yes
6916 : NoColourImpl::instance();
6922#elif defined( CATCH_CONFIG_COLOUR_ANSI )
6933 class PosixColourImpl :
public IColourImpl {
6935 virtual void use( Colour::Code _colourCode )
override {
6936 switch( _colourCode ) {
6938 case Colour::White:
return setColour(
"[0m" );
6939 case Colour::Red:
return setColour(
"[0;31m" );
6940 case Colour::Green:
return setColour(
"[0;32m" );
6941 case Colour::Blue:
return setColour(
"[0;34m" );
6942 case Colour::Cyan:
return setColour(
"[0;36m" );
6943 case Colour::Yellow:
return setColour(
"[0;33m" );
6944 case Colour::Grey:
return setColour(
"[1;30m" );
6946 case Colour::LightGrey:
return setColour(
"[0;37m" );
6947 case Colour::BrightRed:
return setColour(
"[1;31m" );
6948 case Colour::BrightGreen:
return setColour(
"[1;32m" );
6949 case Colour::BrightWhite:
return setColour(
"[1;37m" );
6950 case Colour::BrightYellow:
return setColour(
"[1;33m" );
6952 case Colour::Bright: CATCH_INTERNAL_ERROR(
"not a colour" );
6953 default: CATCH_INTERNAL_ERROR(
"Unknown colour requested" );
6956 static IColourImpl* instance() {
6957 static PosixColourImpl s_instance;
6962 void setColour(
const char* _escapeCode ) {
6967 bool useColourOnPlatform() {
6969#ifdef CATCH_PLATFORM_MAC
6970 !isDebuggerActive() &&
6972#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
6973 isatty(STDOUT_FILENO)
6979 IColourImpl* platformColourInstance() {
6981 IConfigPtr config = getCurrentContext().getConfig();
6982 UseColour::YesOrNo colourMode = config
6983 ? config->useColour()
6985 if( colourMode == UseColour::Auto )
6986 colourMode = useColourOnPlatform()
6989 return colourMode == UseColour::Yes
6990 ? PosixColourImpl::instance()
6991 : NoColourImpl::instance();
7001 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
7009 Colour::Colour( Code _colourCode ) { use( _colourCode ); }
7010 Colour::Colour( Colour&& rhs )
noexcept {
7011 m_moved = rhs.m_moved;
7014 Colour& Colour::operator=( Colour&& rhs )
noexcept {
7015 m_moved = rhs.m_moved;
7020 Colour::~Colour(){
if( !m_moved ) use( None ); }
7022 void Colour::use( Code _colourCode ) {
7023 static IColourImpl* impl = platformColourInstance();
7024 impl->use( _colourCode );
7027 std::ostream&
operator << ( std::ostream& os, Colour
const& ) {
7033#if defined(__clang__)
7034# pragma clang diagnostic pop
7042 class Context :
public IMutableContext, NonCopyable {
7046 return m_resultCapture;
7048 virtual IRunner* getRunner()
override {
7052 virtual IConfigPtr
const& getConfig()
const override {
7056 virtual ~Context()
override;
7059 virtual void setResultCapture( IResultCapture* resultCapture )
override {
7060 m_resultCapture = resultCapture;
7062 virtual void setRunner( IRunner* runner )
override {
7065 virtual void setConfig( IConfigPtr
const& config )
override {
7069 friend IMutableContext& getCurrentMutableContext();
7072 IConfigPtr m_config;
7073 IRunner* m_runner =
nullptr;
7074 IResultCapture* m_resultCapture =
nullptr;
7077 IMutableContext *IMutableContext::currentContext =
nullptr;
7079 void IMutableContext::createContext()
7081 currentContext =
new Context();
7084 void cleanUpContext() {
7085 delete IMutableContext::currentContext;
7086 IMutableContext::currentContext =
nullptr;
7088 IContext::~IContext() =
default;
7089 IMutableContext::~IMutableContext() =
default;
7090 Context::~Context() =
default;
7100 void writeToDebugConsole(
std::string const& text );
7104#ifdef CATCH_PLATFORM_WINDOWS
7107 void writeToDebugConsole(
std::string const& text ) {
7108 ::OutputDebugStringA( text.c_str() );
7115 void writeToDebugConsole(
std::string const& text ) {
7125#ifdef CATCH_PLATFORM_MAC
7129# include <sys/types.h>
7131# include <sys/sysctl.h>
7142 bool isDebuggerActive(){
7145 struct kinfo_proc info;
7151 info.kp_proc.p_flag = 0;
7158 mib[2] = KERN_PROC_PID;
7163 size =
sizeof(info);
7164 if( sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size,
nullptr, 0) != 0 ) {
7165 Catch::cerr() <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
7171 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
7175#elif defined(CATCH_PLATFORM_LINUX)
7187 bool isDebuggerActive(){
7191 std::ifstream in(
"/proc/self/status");
7192 for(
std::string line; std::getline(in, line); ) {
7193 static const int PREFIX_LEN = 11;
7194 if( line.compare(0, PREFIX_LEN,
"TracerPid:\t") == 0 ) {
7198 return line.length() > PREFIX_LEN && line[PREFIX_LEN] !=
'0';
7205#elif defined(_MSC_VER)
7206 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7208 bool isDebuggerActive() {
7209 return IsDebuggerPresent() != 0;
7212#elif defined(__MINGW32__)
7213 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7215 bool isDebuggerActive() {
7216 return IsDebuggerPresent() != 0;
7221 bool isDebuggerActive() {
return false; }
7232 if( lhs.size() + rhs.size() < 40 &&
7233 lhs.find(
'\n') == std::string::npos &&
7234 rhs.find(
'\n') == std::string::npos )
7235 os << lhs <<
" " << op <<
" " << rhs;
7237 os << lhs <<
"\n" << op <<
"\n" << rhs;
7246 ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
7247 ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
7260 class ExceptionTranslatorRegistry :
public IExceptionTranslatorRegistry {
7262 ~ExceptionTranslatorRegistry();
7263 virtual void registerTranslator(
const IExceptionTranslator* translator );
7268 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
7274#import "Foundation/Foundation.h"
7279 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
7282 void ExceptionTranslatorRegistry::registerTranslator(
const IExceptionTranslator* translator ) {
7283 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
7291 return tryTranslators();
7293 @catch (NSException *exception) {
7305 if (std::current_exception() ==
nullptr) {
7306 return "Non C++ exception. Possibly a CLR exception.";
7308 return tryTranslators();
7311 catch( TestFailureException& ) {
7312 std::rethrow_exception(std::current_exception());
7314 catch( std::exception& ex ) {
7320 catch(
const char* msg ) {
7324 return "Unknown exception";
7328 std::string ExceptionTranslatorRegistry::tryTranslators()
const {
7329 if( m_translators.empty() )
7330 std::rethrow_exception(std::current_exception());
7332 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
7338#if defined(__GNUC__)
7339# pragma GCC diagnostic push
7340# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
7343#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
7347 void reportFatal(
char const *
const message ) {
7348 Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
7354#if defined( CATCH_CONFIG_WINDOWS_SEH )
7357 struct SignalDefs { DWORD id;
const char*
name; };
7362 static SignalDefs signalDefs[] = {
7363 { EXCEPTION_ILLEGAL_INSTRUCTION,
"SIGILL - Illegal instruction signal" },
7364 { EXCEPTION_STACK_OVERFLOW,
"SIGSEGV - Stack overflow" },
7365 { EXCEPTION_ACCESS_VIOLATION,
"SIGSEGV - Segmentation violation signal" },
7366 { EXCEPTION_INT_DIVIDE_BY_ZERO,
"Divide by zero error" },
7369 LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
7370 for (
auto const& def : signalDefs) {
7371 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
7372 reportFatal(def.name);
7377 return EXCEPTION_CONTINUE_SEARCH;
7380 FatalConditionHandler::FatalConditionHandler() {
7384 guaranteeSize = 32 * 1024;
7385 exceptionHandlerHandle =
nullptr;
7387 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
7389 SetThreadStackGuarantee(&guaranteeSize);
7392 void FatalConditionHandler::reset() {
7394 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
7395 SetThreadStackGuarantee(&guaranteeSize);
7396 exceptionHandlerHandle =
nullptr;
7401 FatalConditionHandler::~FatalConditionHandler() {
7405bool FatalConditionHandler::isSet =
false;
7406ULONG FatalConditionHandler::guaranteeSize = 0;
7407PVOID FatalConditionHandler::exceptionHandlerHandle =
nullptr;
7411#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
7422 constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
7424 static SignalDefs signalDefs[] = {
7425 { SIGINT,
"SIGINT - Terminal interrupt signal" },
7426 { SIGILL,
"SIGILL - Illegal instruction signal" },
7427 { SIGFPE,
"SIGFPE - Floating point error signal" },
7428 { SIGSEGV,
"SIGSEGV - Segmentation violation signal" },
7429 { SIGTERM,
"SIGTERM - Termination request signal" },
7430 { SIGABRT,
"SIGABRT - Abort (abnormal termination) signal" }
7433 void FatalConditionHandler::handleSignal(
int sig ) {
7434 char const *
name =
"<unknown signal>";
7435 for (
auto const& def : signalDefs) {
7436 if (sig == def.id) {
7446 FatalConditionHandler::FatalConditionHandler() {
7449 sigStack.ss_sp = altStackMem;
7450 sigStack.ss_size = sigStackSize;
7451 sigStack.ss_flags = 0;
7452 sigaltstack(&sigStack, &oldSigStack);
7453 struct sigaction sa = { };
7455 sa.sa_handler = handleSignal;
7456 sa.sa_flags = SA_ONSTACK;
7457 for (std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i) {
7458 sigaction(signalDefs[i].
id, &sa, &oldSigActions[i]);
7462 FatalConditionHandler::~FatalConditionHandler() {
7466 void FatalConditionHandler::reset() {
7469 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i ) {
7470 sigaction(signalDefs[i].
id, &oldSigActions[i],
nullptr);
7473 sigaltstack(&oldSigStack,
nullptr);
7478 bool FatalConditionHandler::isSet =
false;
7479 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
7480 stack_t FatalConditionHandler::oldSigStack = {};
7481 char FatalConditionHandler::altStackMem[sigStackSize] = {};
7488 void FatalConditionHandler::reset() {}
7493#if defined(__GNUC__)
7494# pragma GCC diagnostic pop
7506 IConfig::~IConfig() =
default;
7529 class ListeningReporter :
public IStreamingReporter {
7530 using Reporters = std::vector<IStreamingReporterPtr>;
7531 Reporters m_listeners;
7532 IStreamingReporterPtr m_reporter =
nullptr;
7535 void addListener( IStreamingReporterPtr&& listener );
7536 void addReporter( IStreamingReporterPtr&& reporter );
7540 ReporterPreferences getPreferences()
const override;
7542 void noMatchingTestCases(
std::string const& spec )
override;
7544 static std::set<Verbosity> getSupportedVerbosities();
7546 void benchmarkStarting( BenchmarkInfo
const& benchmarkInfo )
override;
7547 void benchmarkEnded( BenchmarkStats
const& benchmarkStats )
override;
7549 void testRunStarting( TestRunInfo
const& testRunInfo )
override;
7550 void testGroupStarting( GroupInfo
const& groupInfo )
override;
7551 void testCaseStarting( TestCaseInfo
const& testInfo )
override;
7552 void sectionStarting( SectionInfo
const& sectionInfo )
override;
7553 void assertionStarting( AssertionInfo
const& assertionInfo )
override;
7556 bool assertionEnded( AssertionStats
const& assertionStats )
override;
7557 void sectionEnded( SectionStats
const& sectionStats )
override;
7558 void testCaseEnded( TestCaseStats
const& testCaseStats )
override;
7559 void testGroupEnded( TestGroupStats
const& testGroupStats )
override;
7560 void testRunEnded( TestRunStats
const& testRunStats )
override;
7562 void skipTest( TestCaseInfo
const& testInfo )
override;
7563 bool isMulti()
const override;
7572 ReporterConfig::ReporterConfig( IConfigPtr
const& _fullConfig )
7573 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
7575 ReporterConfig::ReporterConfig( IConfigPtr
const& _fullConfig, std::ostream& _stream )
7576 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
7578 std::ostream& ReporterConfig::stream()
const {
return *m_stream; }
7579 IConfigPtr ReporterConfig::fullConfig()
const {
return m_fullConfig; }
7581 TestRunInfo::TestRunInfo(
std::string const& _name ) :
name( _name ) {}
7584 std::size_t _groupIndex,
7585 std::size_t _groupsCount )
7587 groupIndex( _groupIndex ),
7588 groupsCounts( _groupsCount )
7591 AssertionStats::AssertionStats( AssertionResult
const& _assertionResult,
7592 std::vector<MessageInfo>
const& _infoMessages,
7593 Totals
const& _totals )
7594 : assertionResult( _assertionResult ),
7595 infoMessages( _infoMessages ),
7598 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
7600 if( assertionResult.hasMessage() ) {
7603 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
7604 builder << assertionResult.getMessage();
7605 builder.m_info.message = builder.m_stream.str();
7607 infoMessages.push_back( builder.m_info );
7611 AssertionStats::~AssertionStats() =
default;
7613 SectionStats::SectionStats( SectionInfo
const& _sectionInfo,
7614 Counts
const& _assertions,
7615 double _durationInSeconds,
7616 bool _missingAssertions )
7617 : sectionInfo( _sectionInfo ),
7618 assertions( _assertions ),
7619 durationInSeconds( _durationInSeconds ),
7620 missingAssertions( _missingAssertions )
7623 SectionStats::~SectionStats() =
default;
7625 TestCaseStats::TestCaseStats( TestCaseInfo
const& _testInfo,
7626 Totals
const& _totals,
7630 : testInfo( _testInfo ),
7634 aborting( _aborting )
7637 TestCaseStats::~TestCaseStats() =
default;
7639 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo,
7640 Totals
const& _totals,
7642 : groupInfo( _groupInfo ),
7644 aborting( _aborting )
7647 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo )
7648 : groupInfo( _groupInfo ),
7652 TestGroupStats::~TestGroupStats() =
default;
7654 TestRunStats::TestRunStats( TestRunInfo
const& _runInfo,
7655 Totals
const& _totals,
7657 : runInfo( _runInfo ),
7659 aborting( _aborting )
7662 TestRunStats::~TestRunStats() =
default;
7664 void IStreamingReporter::fatalErrorEncountered( StringRef ) {}
7665 bool IStreamingReporter::isMulti()
const {
return false; }
7667 IReporterFactory::~IReporterFactory() =
default;
7668 IReporterRegistry::~IReporterRegistry() =
default;
7687#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
7692 LeakDetector::LeakDetector() {
7693 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
7694 flag |= _CRTDBG_LEAK_CHECK_DF;
7695 flag |= _CRTDBG_ALLOC_MEM_DF;
7696 _CrtSetDbgFlag(flag);
7697 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
7698 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
7700 _CrtSetBreakAlloc(-1);
7706 Catch::LeakDetector::LeakDetector() {}
7718 std::size_t listTests( Config
const& config );
7720 std::size_t listTestsNamesOnly( Config
const& config );
7726 std::set<std::string> spellings;
7727 std::size_t
count = 0;
7730 std::size_t listTags( Config
const& config );
7732 std::size_t listReporters( Config
const& );
7734 Option<std::size_t> list( Config
const& config );
7742 using namespace clara::TextFlow;
7752 std::size_t listTests( Config
const& config ) {
7753 TestSpec testSpec = config.testSpec();
7754 if( config.hasTestFilters() )
7761 for(
auto const& testCaseInfo : matchedTestCases ) {
7762 Colour::Code colour = testCaseInfo.isHidden()
7763 ? Colour::SecondaryText
7765 Colour colourGuard( colour );
7767 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) <<
"\n";
7768 if( config.verbosity() >= Verbosity::High ) {
7770 std::string description = testCaseInfo.description;
7771 if( description.empty() )
7772 description =
"(NO DESCRIPTION)";
7773 Catch::cout() << Column( description ).indent(4) << std::endl;
7775 if( !testCaseInfo.tags.empty() )
7776 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) <<
"\n";
7779 if( !config.hasTestFilters() )
7780 Catch::cout() << pluralise( matchedTestCases.size(),
"test case" ) <<
'\n' << std::endl;
7782 Catch::cout() << pluralise( matchedTestCases.size(),
"matching test case" ) <<
'\n' << std::endl;
7783 return matchedTestCases.size();
7786 std::size_t listTestsNamesOnly( Config
const& config ) {
7787 TestSpec testSpec = config.testSpec();
7788 std::size_t matchedTests = 0;
7790 for(
auto const& testCaseInfo : matchedTestCases ) {
7796 if ( config.verbosity() >= Verbosity::High )
7800 return matchedTests;
7803 void TagInfo::add(
std::string const& spelling ) {
7805 spellings.insert( spelling );
7810 for(
auto const& spelling : spellings )
7811 out += "[" + spelling + "]";
7815 std::size_t listTags( Config
const& config ) {
7816 TestSpec testSpec = config.testSpec();
7817 if( config.hasTestFilters() )
7818 Catch::cout() <<
"Tags for matching test cases:\n";
7823 std::map<std::string, TagInfo> tagCounts;
7826 for(
auto const& testCase : matchedTestCases ) {
7827 for(
auto const& tagName : testCase.getTestCaseInfo().tags ) {
7829 auto countIt = tagCounts.find( lcaseTagName );
7830 if( countIt == tagCounts.end() )
7831 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
7832 countIt->second.add( tagName );
7836 for(
auto const& tagCount : tagCounts ) {
7837 ReusableStringStream rss;
7838 rss <<
" " << std::setw(2) << tagCount.second.count <<
" ";
7839 auto str = rss.str();
7840 auto wrapper = Column( tagCount.second.all() )
7842 .indent( str.size() )
7843 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
7846 Catch::cout() << pluralise( tagCounts.size(),
"tag" ) <<
'\n' << std::endl;
7847 return tagCounts.size();
7850 std::size_t listReporters( Config
const& ) {
7853 std::size_t maxNameLen = 0;
7854 for(
auto const& factoryKvp : factories )
7855 maxNameLen = (
std::max)( maxNameLen, factoryKvp.first.size() );
7857 for(
auto const& factoryKvp : factories ) {
7859 << Column( factoryKvp.first +
":" )
7861 .width( 5+maxNameLen )
7862 + Column( factoryKvp.
second->getDescription() )
7865 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
7869 return factories.size();
7872 Option<std::size_t> list( Config
const& config ) {
7873 Option<std::size_t> listedCount;
7874 if( config.listTests() )
7875 listedCount = listedCount.valueOr(0) + listTests( config );
7876 if( config.listTestNamesOnly() )
7877 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
7878 if( config.listTags() )
7879 listedCount = listedCount.valueOr(0) + listTags( config );
7880 if( config.listReporters() )
7881 listedCount = listedCount.valueOr(0) + listReporters( config );
7904using namespace Matchers;
7905using Matchers::Impl::MatcherBase;
7916 template <
typename T>
7918#if defined(CATCH_CONFIG_CPP11_TO_STRING)
7919 return std::to_string(
t);
7921 ReusableStringStream rss;
7937enum class FloatingPointKind : uint8_t {
7947template <
typename T>
7951struct Converter<float> {
7952 static_assert(
sizeof(float) ==
sizeof(int32_t),
"Important ULP matcher assumption violated");
7953 Converter(
float f) {
7954 std::memcpy(&i, &f,
sizeof(f));
7960struct Converter<double> {
7961 static_assert(
sizeof(double) ==
sizeof(int64_t),
"Important ULP matcher assumption violated");
7962 Converter(
double d) {
7963 std::memcpy(&i, &d,
sizeof(d));
7968template <
typename T>
7969auto convert(T
t) -> Converter<T> {
7970 return Converter<T>(
t);
7973template <
typename FP>
7974bool almostEqualUlps(FP lhs, FP rhs,
int maxUlpDiff) {
7977 if (std::isnan(lhs) || std::isnan(rhs)) {
7981 auto lc = convert(lhs);
7982 auto rc = convert(rhs);
7984 if ((lc.i < 0) != (rc.i < 0)) {
7989 auto ulpDiff = std::abs(lc.i - rc.i);
7990 return ulpDiff <= maxUlpDiff;
7999 :m_target{ target }, m_margin{ margin } {
8001 throw std::domain_error(
"Allowed margin difference has to be >= 0");
8007 bool WithinAbsMatcher::match(
double const& matchee)
const {
8008 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
8012 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
8015 WithinUlpsMatcher::WithinUlpsMatcher(
double target,
int ulps, FloatingPointKind baseType)
8016 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
8018 throw std::domain_error(
"Allowed ulp difference has to be >= 0");
8022 bool WithinUlpsMatcher::match(
double const& matchee)
const {
8025 return almostEqualUlps<float>(
static_cast<float>(matchee),
static_cast<float>(m_target), m_ulps);
8027 return almostEqualUlps<double>(matchee, m_target, m_ulps);
8029 throw std::domain_error(
"Unknown FloatingPointKind value");
8034 return "is within " +
Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::
Float)? "f" : "");
8039Floating::WithinUlpsMatcher
WithinULP(
double target,
int maxUlpDiff) {
8043Floating::WithinUlpsMatcher
WithinULP(
float target,
int maxUlpDiff) {
8047Floating::WithinAbsMatcher
WithinAbs(
double target,
double margin) {
8048 return Floating::WithinAbsMatcher(target, margin);
8059 return "matches undescribed predicate";
8061 return "matches predicate: \"" + desc + '"';
8072 namespace StdString {
8075 : m_caseSensitivity( caseSensitivity ),
8076 m_str( adjustString( str ) )
8083 std::string CasedString::caseSensitivitySuffix()
const {
8085 ?
" (case insensitive)"
8089 StringMatcherBase::StringMatcherBase(
std::string const& operation, CasedString
const& comparator )
8090 : m_comparator( comparator ),
8091 m_operation( operation ) {
8096 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
8097 m_comparator.caseSensitivitySuffix().size());
8098 description += m_operation;
8099 description += ": \"";
8100 description += m_comparator.m_str;
8101 description += "\"";
8102 description += m_comparator.caseSensitivitySuffix();
8106 EqualsMatcher::EqualsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"equals", comparator ) {}
8108 bool EqualsMatcher::match(
std::string const& source )
const {
8109 return m_comparator.adjustString( source ) == m_comparator.m_str;
8112 ContainsMatcher::ContainsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"contains", comparator ) {}
8114 bool ContainsMatcher::match(
std::string const& source )
const {
8115 return contains( m_comparator.adjustString( source ), m_comparator.m_str );
8118 StartsWithMatcher::StartsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"starts with", comparator ) {}
8120 bool StartsWithMatcher::match(
std::string const& source )
const {
8121 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8124 EndsWithMatcher::EndsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"ends with", comparator ) {}
8126 bool EndsWithMatcher::match(
std::string const& source )
const {
8127 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8132 bool RegexMatcher::match(
std::string const& matchee)
const {
8133 auto flags = std::regex::ECMAScript;
8134 if (m_caseSensitivity == CaseSensitive::Choice::No) {
8135 flags |= std::regex::icase;
8137 auto reg = std::regex(m_regex, flags);
8138 return std::regex_match(matchee, reg);
8142 return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");
8147 StdString::EqualsMatcher
Equals(
std::string const& str, CaseSensitive::Choice caseSensitivity ) {
8148 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
8150 StdString::ContainsMatcher
Contains(
std::string const& str, CaseSensitive::Choice caseSensitivity ) {
8151 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
8153 StdString::EndsWithMatcher
EndsWith(
std::string const& str, CaseSensitive::Choice caseSensitivity ) {
8154 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
8156 StdString::StartsWithMatcher
StartsWith(
std::string const& str, CaseSensitive::Choice caseSensitivity ) {
8157 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
8160 StdString::RegexMatcher
Matches(
std::string const& regex, CaseSensitive::Choice caseSensitivity) {
8161 return StdString::RegexMatcher(regex, caseSensitivity);
8172 bool uncaught_exceptions();
8179 SourceLineInfo
const& _lineInfo,
8181 : macroName( _macroName ),
8182 lineInfo( _lineInfo ),
8184 sequence( ++globalCount )
8196 unsigned int MessageInfo::globalCount = 0;
8201 SourceLineInfo
const& lineInfo,
8203 :m_info(macroName, lineInfo, type) {}
8208 : m_info( builder.m_info )
8210 m_info.message = builder.m_stream.str();
8215 if ( !uncaught_exceptions() ){
8224#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
8225#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
8233 class RedirectedStream {
8234 std::ostream& m_originalStream;
8235 std::ostream& m_redirectionStream;
8236 std::streambuf* m_prevBuf;
8239 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
8240 ~RedirectedStream();
8243 class RedirectedStdOut {
8244 ReusableStringStream m_rss;
8245 RedirectedStream m_cout;
8248 auto str() const -> std::
string;
8254 class RedirectedStdErr {
8255 ReusableStringStream m_rss;
8256 RedirectedStream m_cerr;
8257 RedirectedStream m_clog;
8260 auto str() const -> std::
string;
8269 TempFile(TempFile
const&) =
delete;
8270 TempFile& operator=(TempFile
const&) =
delete;
8271 TempFile(TempFile&&) =
delete;
8272 TempFile& operator=(TempFile&&) =
delete;
8277 std::FILE* getFile();
8281 std::FILE* m_file =
nullptr;
8282 #if defined(_MSC_VER)
8283 char m_buffer[L_tmpnam] = { 0 };
8287 class OutputRedirect {
8289 OutputRedirect(OutputRedirect
const&) =
delete;
8290 OutputRedirect& operator=(OutputRedirect
const&) =
delete;
8291 OutputRedirect(OutputRedirect&&) =
delete;
8292 OutputRedirect& operator=(OutputRedirect&&) =
delete;
8298 int m_originalStdout = -1;
8299 int m_originalStderr = -1;
8300 TempFile m_stdoutFile;
8301 TempFile m_stderrFile;
8316#if defined(_MSC_VER)
8320#define fileno _fileno
8327 RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
8328 : m_originalStream( originalStream ),
8329 m_redirectionStream( redirectionStream ),
8330 m_prevBuf( m_originalStream.rdbuf() )
8332 m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
8335 RedirectedStream::~RedirectedStream() {
8336 m_originalStream.rdbuf( m_prevBuf );
8339 RedirectedStdOut::RedirectedStdOut() : m_cout(
Catch::
cout(), m_rss.
get() ) {}
8340 auto RedirectedStdOut::str() const -> std::
string {
return m_rss.str(); }
8342 RedirectedStdErr::RedirectedStdErr()
8346 auto RedirectedStdErr::str() const -> std::
string {
return m_rss.str(); }
8348#if defined(_MSC_VER)
8349 TempFile::TempFile() {
8350 if (tmpnam_s(m_buffer)) {
8351 throw std::runtime_error(
"Could not get a temp filename");
8353 if (fopen_s(&m_file, m_buffer,
"w")) {
8355 if (strerror_s(
buffer, errno)) {
8356 throw std::runtime_error(
"Could not translate errno to string");
8358 throw std::runtime_error(
"Could not open the temp file: " +
std::string(m_buffer) +
buffer);
8362 TempFile::TempFile() {
8363 m_file = std::tmpfile();
8365 throw std::runtime_error(
"Could not create a temp file.");
8371 TempFile::~TempFile() {
8373 std::fclose(m_file);
8376#if defined(_MSC_VER)
8377 std::remove(m_buffer);
8381 FILE* TempFile::getFile() {
8386 std::stringstream sstr;
8388 std::rewind(m_file);
8396 m_originalStdout(dup(1)),
8397 m_originalStderr(dup(2)),
8398 m_stdoutDest(stdout_dest),
8399 m_stderrDest(stderr_dest) {
8400 dup2(fileno(m_stdoutFile.getFile()), 1);
8401 dup2(fileno(m_stderrFile.getFile()), 2);
8404 OutputRedirect::~OutputRedirect() {
8413 dup2(m_originalStdout, 1);
8414 dup2(m_originalStderr, 2);
8416 m_stdoutDest += m_stdoutFile.getContents();
8417 m_stderrDest += m_stderrFile.getContents();
8422#if defined(_MSC_VER)
8438 void seedRng( IConfig
const& config );
8442 struct RandomNumberGenerator {
8443 using result_type =
unsigned int;
8445 static constexpr result_type (
min)() {
return 0; }
8446 static constexpr result_type (
max)() {
return 1000000; }
8448 result_type operator()( result_type n )
const;
8449 result_type operator()()
const;
8451 template<
typename V>
8452 static void shuffle( V& vector ) {
8453 RandomNumberGenerator rng;
8454 std::shuffle( vector.begin(), vector.end(), rng );
8465 void seedRng( IConfig
const& config ) {
8466 if( config.rngSeed() != 0 )
8467 std::srand( config.rngSeed() );
8470 return getCurrentContext().getConfig()->rngSeed();
8473 RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n )
const {
8474 return std::rand() % n;
8476 RandomNumberGenerator::result_type RandomNumberGenerator::operator()()
const {
8477 return std::rand() % (
max)();
8496 std::vector<TestCase> sortTests( IConfig
const& config, std::vector<TestCase>
const& unsortedTestCases );
8497 bool matchTest( TestCase
const& testCase, TestSpec
const& testSpec, IConfig
const& config );
8499 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions );
8501 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config );
8504 class TestRegistry :
public ITestCaseRegistry {
8506 virtual ~TestRegistry() =
default;
8508 virtual void registerTest( TestCase
const& testCase );
8510 std::vector<TestCase>
const& getAllTests()
const override;
8511 std::vector<TestCase>
const& getAllTestsSorted( IConfig
const& config )
const override;
8514 std::vector<TestCase> m_functions;
8515 mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
8516 mutable std::vector<TestCase> m_sortedFunctions;
8517 std::size_t m_unnamedCount = 0;
8518 std::ios_base::Init m_ostreamInit;
8523 class TestInvokerAsFunction :
public ITestInvoker {
8524 void(*m_testAsFunction)();
8526 TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept;
8528 void invoke() const override;
8531 std::
string extractClassName( StringRef const& classOrQualifiedMethodName );
8544 class ReporterRegistry :
public IReporterRegistry {
8548 ~ReporterRegistry()
override;
8550 IStreamingReporterPtr create(
std::string const&
name, IConfigPtr
const& config )
const override;
8555 FactoryMap
const& getFactories()
const override;
8556 Listeners
const& getListeners()
const override;
8559 FactoryMap m_factories;
8560 Listeners m_listeners;
8574 TagAlias(
std::string const& _tag, SourceLineInfo _lineInfo);
8577 SourceLineInfo lineInfo;
8587 class TagAliasRegistry :
public ITagAliasRegistry {
8589 ~TagAliasRegistry()
override;
8590 TagAlias
const* find(
std::string const& alias )
const override;
8595 std::map<std::string, TagAlias> m_registry;
8608 class StartupExceptionRegistry {
8610 void add(std::exception_ptr
const& exception)
noexcept;
8611 std::vector<std::exception_ptr>
const& getExceptions() const noexcept;
8613 std::vector<std::exception_ptr> m_exceptions;
8623 class RegistryHub :
public IRegistryHub,
public IMutableRegistryHub,
8624 private NonCopyable {
8627 RegistryHub() =
default;
8628 IReporterRegistry
const& getReporterRegistry()
const override {
8629 return m_reporterRegistry;
8631 ITestCaseRegistry
const& getTestCaseRegistry()
const override {
8632 return m_testCaseRegistry;
8634 IExceptionTranslatorRegistry& getExceptionTranslatorRegistry()
override {
8635 return m_exceptionTranslatorRegistry;
8637 ITagAliasRegistry
const& getTagAliasRegistry()
const override {
8638 return m_tagAliasRegistry;
8640 StartupExceptionRegistry
const& getStartupExceptionRegistry()
const override {
8641 return m_exceptionRegistry;
8646 m_reporterRegistry.registerReporter(
name, factory );
8649 m_reporterRegistry.registerListener( factory );
8651 void registerTest( TestCase
const& testInfo )
override {
8652 m_testCaseRegistry.registerTest( testInfo );
8654 void registerTranslator(
const IExceptionTranslator* translator )
override {
8655 m_exceptionTranslatorRegistry.registerTranslator( translator );
8657 void registerTagAlias(
std::string const& alias,
std::string const& tag, SourceLineInfo
const& lineInfo )
override {
8658 m_tagAliasRegistry.add( alias, tag, lineInfo );
8660 void registerStartupException() noexcept
override {
8661 m_exceptionRegistry.add(std::current_exception());
8665 TestRegistry m_testCaseRegistry;
8666 ReporterRegistry m_reporterRegistry;
8667 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
8668 TagAliasRegistry m_tagAliasRegistry;
8669 StartupExceptionRegistry m_exceptionRegistry;
8673 RegistryHub*& getTheRegistryHub() {
8674 static RegistryHub* theRegistryHub =
nullptr;
8675 if( !theRegistryHub )
8676 theRegistryHub =
new RegistryHub();
8677 return theRegistryHub;
8682 return *getTheRegistryHub();
8685 return *getTheRegistryHub();
8688 delete getTheRegistryHub();
8689 getTheRegistryHub() =
nullptr;
8703 ReporterRegistry::~ReporterRegistry() =
default;
8705 IStreamingReporterPtr ReporterRegistry::create(
std::string const&
name, IConfigPtr
const& config )
const {
8706 auto it = m_factories.find(
name );
8707 if( it == m_factories.end() )
8709 return it->second->create( ReporterConfig( config ) );
8713 m_factories.emplace(
name, factory);
8716 m_listeners.push_back( factory );
8719 IReporterRegistry::FactoryMap
const& ReporterRegistry::getFactories()
const {
8722 IReporterRegistry::Listeners
const& ReporterRegistry::getListeners()
const {
8756 RunContext::RunContext(IConfigPtr
const& _config, IStreamingReporterPtr&& reporter)
8757 : m_runInfo(_config->
name()),
8758 m_context(getCurrentMutableContext()),
8760 m_reporter(std::move(reporter)),
8761 m_lastAssertionInfo{ StringRef(), SourceLineInfo(
"",0), StringRef(), ResultDisposition::Normal },
8762 m_includeSuccessfulResults( m_config->includeSuccessfulResults() )
8764 m_context.setRunner(
this);
8765 m_context.setConfig(m_config);
8766 m_context.setResultCapture(
this);
8767 m_reporter->testRunStarting(m_runInfo);
8770 RunContext::~RunContext() {
8771 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
8774 void RunContext::testGroupStarting(
std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
8775 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
8778 void RunContext::testGroupEnded(
std::string const& testSpec, Totals
const& totals, std::size_t groupIndex, std::size_t groupsCount) {
8779 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
8782 Totals RunContext::runTest(TestCase
const& testCase) {
8783 Totals prevTotals = m_totals;
8788 auto const& testInfo = testCase.getTestCaseInfo();
8790 m_reporter->testCaseStarting(testInfo);
8792 m_activeTestCase = &testCase;
8794 ITracker& rootTracker = m_trackerContext.startRun();
8795 assert(rootTracker.isSectionTracker());
8796 static_cast<SectionTracker&
>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
8798 m_trackerContext.startCycle();
8799 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
8800 runCurrentTest(redirectedCout, redirectedCerr);
8801 }
while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
8803 Totals deltaTotals = m_totals.delta(prevTotals);
8804 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
8805 deltaTotals.assertions.failed++;
8806 deltaTotals.testCases.passed--;
8807 deltaTotals.testCases.failed++;
8809 m_totals.testCases += deltaTotals.testCases;
8810 m_reporter->testCaseEnded(TestCaseStats(testInfo,
8816 m_activeTestCase =
nullptr;
8817 m_testCaseTracker =
nullptr;
8822 IConfigPtr RunContext::config()
const {
8826 IStreamingReporter& RunContext::reporter()
const {
8830 void RunContext::assertionEnded(AssertionResult
const & result) {
8832 m_totals.assertions.passed++;
8833 m_lastAssertionPassed =
true;
8834 }
else if (!result.isOk()) {
8835 m_lastAssertionPassed =
false;
8836 if( m_activeTestCase->getTestCaseInfo().okToFail() )
8837 m_totals.assertions.failedButOk++;
8839 m_totals.assertions.failed++;
8842 m_lastAssertionPassed =
true;
8847 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
8850 resetAssertionInfo();
8851 m_lastResult = result;
8853 void RunContext::resetAssertionInfo() {
8854 m_lastAssertionInfo.macroName = StringRef();
8855 m_lastAssertionInfo.capturedExpression =
"{Unknown expression after the reported line}"_sr;
8858 bool RunContext::sectionStarted(SectionInfo
const & sectionInfo, Counts & assertions) {
8859 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
8860 if (!sectionTracker.isOpen())
8862 m_activeSections.push_back(§ionTracker);
8864 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
8866 m_reporter->sectionStarting(sectionInfo);
8868 assertions = m_totals.assertions;
8873 bool RunContext::testForMissingAssertions(Counts& assertions) {
8874 if (assertions.total() != 0)
8876 if (!m_config->warnAboutMissingAssertions())
8878 if (m_trackerContext.currentTracker().hasChildren())
8880 m_totals.assertions.failed++;
8881 assertions.failed++;
8885 void RunContext::sectionEnded(SectionEndInfo
const & endInfo) {
8886 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
8887 bool missingAssertions = testForMissingAssertions(assertions);
8889 if (!m_activeSections.empty()) {
8890 m_activeSections.back()->close();
8891 m_activeSections.pop_back();
8894 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
8898 void RunContext::sectionEndedEarly(SectionEndInfo
const & endInfo) {
8899 if (m_unfinishedSections.empty())
8900 m_activeSections.back()->fail();
8902 m_activeSections.back()->close();
8903 m_activeSections.pop_back();
8905 m_unfinishedSections.push_back(endInfo);
8907 void RunContext::benchmarkStarting( BenchmarkInfo
const& info ) {
8908 m_reporter->benchmarkStarting( info );
8910 void RunContext::benchmarkEnded( BenchmarkStats
const& stats ) {
8911 m_reporter->benchmarkEnded( stats );
8914 void RunContext::pushScopedMessage(MessageInfo
const & message) {
8915 m_messages.push_back(message);
8918 void RunContext::popScopedMessage(MessageInfo
const & message) {
8919 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
8922 std::string RunContext::getCurrentTestName()
const {
8923 return m_activeTestCase
8924 ? m_activeTestCase->getTestCaseInfo().name
8928 const AssertionResult * RunContext::getLastResult()
const {
8929 return &(*m_lastResult);
8932 void RunContext::exceptionEarlyReported() {
8933 m_shouldReportUnexpected =
false;
8936 void RunContext::handleFatalErrorCondition( StringRef message ) {
8938 m_reporter->fatalErrorEncountered(message);
8943 tempResult.message = message;
8944 AssertionResult result(m_lastAssertionInfo, tempResult);
8946 assertionEnded(result);
8948 handleUnfinishedSections();
8951 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
8952 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
8955 assertions.failed = 1;
8956 SectionStats testCaseSectionStats(testCaseSection, assertions, 0,
false);
8957 m_reporter->sectionEnded(testCaseSectionStats);
8959 auto const& testInfo = m_activeTestCase->getTestCaseInfo();
8962 deltaTotals.testCases.failed = 1;
8963 deltaTotals.assertions.failed = 1;
8964 m_reporter->testCaseEnded(TestCaseStats(testInfo,
8969 m_totals.testCases.failed++;
8971 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals,
false));
8974 bool RunContext::lastAssertionPassed() {
8975 return m_lastAssertionPassed;
8978 void RunContext::assertionPassed() {
8979 m_lastAssertionPassed =
true;
8980 ++m_totals.assertions.passed;
8981 resetAssertionInfo();
8984 bool RunContext::aborting()
const {
8985 return m_totals.assertions.failed ==
static_cast<std::size_t
>(m_config->abortAfter());
8989 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
8990 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
8991 m_reporter->sectionStarting(testCaseSection);
8992 Counts prevAssertions = m_totals.assertions;
8993 double duration = 0;
8994 m_shouldReportUnexpected =
true;
9001 if (m_reporter->getPreferences().shouldRedirectStdOut) {
9002#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
9003 RedirectedStdOut redirectedStdOut;
9004 RedirectedStdErr redirectedStdErr;
9007 invokeActiveTestCase();
9008 redirectedCout += redirectedStdOut.str();
9009 redirectedCerr += redirectedStdErr.str();
9011 OutputRedirect r(redirectedCout, redirectedCerr);
9013 invokeActiveTestCase();
9017 invokeActiveTestCase();
9019 duration = timer.getElapsedSeconds();
9020 }
catch (TestFailureException&) {
9025 if( m_shouldReportUnexpected ) {
9026 AssertionReaction dummyReaction;
9030 Counts assertions = m_totals.assertions - prevAssertions;
9031 bool missingAssertions = testForMissingAssertions(assertions);
9033 m_testCaseTracker->close();
9034 handleUnfinishedSections();
9037 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
9038 m_reporter->sectionEnded(testCaseSectionStats);
9041 void RunContext::invokeActiveTestCase() {
9042 FatalConditionHandler fatalConditionHandler;
9043 m_activeTestCase->invoke();
9044 fatalConditionHandler.reset();
9047 void RunContext::handleUnfinishedSections() {
9050 for (
auto it = m_unfinishedSections.rbegin(),
9051 itEnd = m_unfinishedSections.rend();
9055 m_unfinishedSections.clear();
9058 void RunContext::handleExpr(
9059 AssertionInfo
const& info,
9060 ITransientExpression
const& expr,
9061 AssertionReaction& reaction
9063 m_reporter->assertionStarting( info );
9065 bool negated =
isFalseTest( info.resultDisposition );
9066 bool result = expr.getResult() != negated;
9069 if (!m_includeSuccessfulResults) {
9078 populateReaction( reaction );
9081 void RunContext::reportExpr(
9082 AssertionInfo
const &info,
9084 ITransientExpression
const *expr,
9087 m_lastAssertionInfo = info;
9088 AssertionResultData
data( resultType, LazyExpression( negated ) );
9090 AssertionResult assertionResult{ info,
data };
9091 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
9093 assertionEnded( assertionResult );
9096 void RunContext::handleMessage(
9097 AssertionInfo
const& info,
9099 StringRef
const& message,
9100 AssertionReaction& reaction
9102 m_reporter->assertionStarting( info );
9104 m_lastAssertionInfo = info;
9106 AssertionResultData
data( resultType, LazyExpression(
false ) );
9107 data.message = message;
9108 AssertionResult assertionResult{ m_lastAssertionInfo,
data };
9109 assertionEnded( assertionResult );
9110 if( !assertionResult.isOk() )
9111 populateReaction( reaction );
9113 void RunContext::handleUnexpectedExceptionNotThrown(
9114 AssertionInfo
const& info,
9115 AssertionReaction& reaction
9120 void RunContext::handleUnexpectedInflightException(
9121 AssertionInfo
const& info,
9123 AssertionReaction& reaction
9125 m_lastAssertionInfo = info;
9128 data.message = message;
9129 AssertionResult assertionResult{ info,
data };
9130 assertionEnded( assertionResult );
9131 populateReaction( reaction );
9134 void RunContext::populateReaction( AssertionReaction& reaction ) {
9135 reaction.shouldDebugBreak = m_config->shouldDebugBreak();
9139 void RunContext::handleIncomplete(
9140 AssertionInfo
const& info
9142 m_lastAssertionInfo = info;
9145 data.message =
"Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
9146 AssertionResult assertionResult{ info,
data };
9147 assertionEnded( assertionResult );
9149 void RunContext::handleNonExpr(
9150 AssertionInfo
const &info,
9152 AssertionReaction &reaction
9154 m_lastAssertionInfo = info;
9156 AssertionResultData
data( resultType, LazyExpression(
false ) );
9157 AssertionResult assertionResult{ info,
data };
9158 assertionEnded( assertionResult );
9160 if( !assertionResult.isOk() )
9161 populateReaction( reaction );
9168 CATCH_INTERNAL_ERROR(
"No result capture instance");
9178 m_sectionIncluded(
getResultCapture().sectionStarted( m_info, m_assertions ) )
9184 if( m_sectionIncluded ) {
9186 if( uncaught_exceptions() )
9194 Section::operator
bool()
const {
9195 return m_sectionIncluded;
9205 ( SourceLineInfo
const& _lineInfo,
9209 description( _description ),
9210 lineInfo( _lineInfo )
9214 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
9227 class Session : NonCopyable {
9231 ~Session()
override;
9233 void showHelp()
const;
9236 int applyCommandLine(
int argc,
char const *
const * argv );
9238 void useConfigData( ConfigData
const& configData );
9240 int run(
int argc,
char* argv[] );
9241 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
9242 int run(
int argc,
wchar_t*
const argv[] );
9246 clara::Parser
const& cli()
const;
9247 void cli( clara::Parser
const& newParser );
9248 ConfigData& configData();
9253 clara::Parser m_cli;
9254 ConfigData m_configData;
9255 std::shared_ptr<Config> m_config;
9256 bool m_startupExceptions =
false;
9270 Version( Version
const& ) =
delete;
9271 Version& operator=( Version
const& ) =
delete;
9272 Version(
unsigned int _majorVersion,
9273 unsigned int _minorVersion,
9274 unsigned int _patchNumber,
9275 char const *
const _branchName,
9276 unsigned int _buildNumber );
9278 unsigned int const majorVersion;
9279 unsigned int const minorVersion;
9280 unsigned int const patchNumber;
9283 char const *
const branchName;
9284 unsigned int const buildNumber;
9289 Version
const& libraryVersion();
9299 const int MaxExitCode = 255;
9301 IStreamingReporterPtr createReporter(
std::string const& reporterName, IConfigPtr
const& config) {
9303 CATCH_ENFORCE(reporter,
"No reporter registered with name: '" << reporterName <<
"'");
9308 IStreamingReporterPtr makeReporter(std::shared_ptr<Config>
const& config) {
9310 return createReporter(config->getReporterName(), config);
9313 auto multi = std::unique_ptr<ListeningReporter>(
new ListeningReporter);
9316 for (
auto const& listener : listeners) {
9317 multi->addListener(listener->create(Catch::ReporterConfig(config)));
9319 multi->addReporter(createReporter(config->getReporterName(), config));
9320 return std::move(multi);
9323 Catch::Totals runTests(std::shared_ptr<Config>
const& config) {
9326 auto reporter = makeReporter(config);
9328 RunContext context(config, std::move(reporter));
9332 context.testGroupStarting(config->name(), 1, 1);
9334 TestSpec testSpec = config->testSpec();
9337 for (
auto const& testCase : allTestCases) {
9338 if (!context.aborting() &&
matchTest(testCase, testSpec, *config))
9339 totals += context.runTest(testCase);
9341 context.reporter().skipTest(testCase);
9344 if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
9345 ReusableStringStream testConfig;
9348 for (
const auto& input : config->getTestsOrTags()) {
9349 if (!first) { testConfig <<
' '; }
9351 testConfig << input;
9354 context.reporter().noMatchingTestCases(testConfig.str());
9358 context.testGroupEnded(config->name(), totals, 1, 1);
9362 void applyFilenamesAsTags(Catch::IConfig
const& config) {
9364 for (
auto& testCase : tests) {
9365 auto tags = testCase.tags;
9368 auto lastSlash = filename.find_last_of(
"\\/");
9369 if (lastSlash != std::string::npos) {
9370 filename.erase(0, lastSlash);
9374 auto lastDot = filename.find_last_of(
'.');
9375 if (lastDot != std::string::npos) {
9376 filename.erase(lastDot);
9379 tags.push_back(std::move(filename));
9380 setTags(testCase, tags);
9386 Session::Session() {
9387 static bool alreadyInstantiated =
false;
9388 if( alreadyInstantiated ) {
9389 try { CATCH_INTERNAL_ERROR(
"Only one instance of Catch::Session can ever be used" ); }
9394 if ( !exceptions.empty() ) {
9395 m_startupExceptions =
true;
9396 Colour colourGuard( Colour::Red );
9397 Catch::cerr() <<
"Errors occurred during startup!" <<
'\n';
9399 for (
const auto& ex_ptr : exceptions ) {
9401 std::rethrow_exception(ex_ptr);
9402 }
catch ( std::exception
const& ex ) {
9403 Catch::cerr() << Column( ex.what() ).indent(2) <<
'\n';
9408 alreadyInstantiated =
true;
9409 m_cli = makeCommandLineParser( m_configData );
9411 Session::~Session() {
9415 void Session::showHelp()
const {
9417 <<
"\nCatch v" << libraryVersion() <<
"\n"
9418 << m_cli << std::endl
9419 <<
"For more detailed usage please see the project docs\n" << std::endl;
9421 void Session::libIdentify() {
9423 << std::left << std::setw(16) <<
"description: " <<
"A Catch test executable\n"
9424 << std::left << std::setw(16) <<
"category: " <<
"testframework\n"
9425 << std::left << std::setw(16) <<
"framework: " <<
"Catch Test\n"
9426 << std::left << std::setw(16) <<
"version: " << libraryVersion() << std::endl;
9429 int Session::applyCommandLine(
int argc,
char const *
const * argv ) {
9430 if( m_startupExceptions )
9433 auto result = m_cli.parse( clara::Args( argc, argv ) );
9436 << Colour( Colour::Red )
9437 <<
"\nError(s) in input:\n"
9438 << Column( result.errorMessage() ).indent( 2 )
9440 Catch::cerr() <<
"Run with -? for usage\n" << std::endl;
9444 if( m_configData.showHelp )
9446 if( m_configData.libIdentify )
9452 void Session::useConfigData( ConfigData
const& configData ) {
9453 m_configData = configData;
9457 int Session::run(
int argc,
char* argv[] ) {
9458 if( m_startupExceptions )
9460 int returnCode = applyCommandLine( argc, argv );
9461 if( returnCode == 0 )
9466#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
9467 int Session::run(
int argc,
wchar_t*
const argv[] ) {
9469 char **utf8Argv =
new char *[ argc ];
9471 for (
int i = 0; i < argc; ++i ) {
9472 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
9474 utf8Argv[ i ] =
new char[ bufSize ];
9476 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
9479 int returnCode = run( argc, utf8Argv );
9481 for (
int i = 0; i < argc; ++i )
9482 delete [] utf8Argv[ i ];
9489 int Session::run() {
9490 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
9491 Catch::cout() <<
"...waiting for enter/ return before starting" << std::endl;
9492 static_cast<void>(std::getchar());
9494 int exitCode = runInternal();
9495 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
9496 Catch::cout() <<
"...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
9497 static_cast<void>(std::getchar());
9502 clara::Parser
const& Session::cli()
const {
9505 void Session::cli( clara::Parser
const& newParser ) {
9508 ConfigData& Session::configData() {
9509 return m_configData;
9511 Config& Session::config() {
9513 m_config = std::make_shared<Config>( m_configData );
9517 int Session::runInternal() {
9518 if( m_startupExceptions )
9521 if( m_configData.showHelp || m_configData.libIdentify )
9528 seedRng( *m_config );
9530 if( m_configData.filenamesAsTags )
9531 applyFilenamesAsTags( *m_config );
9534 if( Option<std::size_t> listed = list( config() ) )
9535 return static_cast<int>( *listed );
9537 auto totals = runTests( m_config );
9541 return (
std::min) (MaxExitCode, (
std::max) (totals.error,
static_cast<int>(totals.assertions.failed)));
9543 catch( std::exception& ex ) {
9554 void StartupExceptionRegistry::add( std::exception_ptr
const& exception )
noexcept {
9556 m_exceptions.push_back(exception);
9564 std::vector<std::exception_ptr>
const& StartupExceptionRegistry::getExceptions() const noexcept {
9565 return m_exceptions;
9579#if defined(__clang__)
9580# pragma clang diagnostic push
9581# pragma clang diagnostic ignored "-Wexit-time-destructors"
9588 namespace detail {
namespace {
9589 template<
typename WriterF, std::
size_t bufferSize=256>
9590 class StreamBufImpl :
public std::streambuf {
9591 char data[bufferSize];
9599 ~StreamBufImpl() noexcept {
9600 StreamBufImpl::sync();
9604 int overflow(
int c )
override {
9608 if( pbase() == epptr() )
9609 m_writer(
std::string( 1,
static_cast<char>( c ) ) );
9611 sputc(
static_cast<char>( c ) );
9616 int sync()
override {
9617 if( pbase() != pptr() ) {
9618 m_writer(
std::string( pbase(),
static_cast<std::string::size_type
>( pptr() - pbase() ) ) );
9619 setp( pbase(), epptr() );
9627 struct OutputDebugWriter {
9630 writeToDebugConsole( str );
9636 class FileStream :
public IStream {
9637 mutable std::ofstream m_ofs;
9639 FileStream( StringRef filename ) {
9640 m_ofs.open( filename.c_str() );
9641 CATCH_ENFORCE( !m_ofs.fail(),
"Unable to open file: '" << filename <<
"'" );
9643 ~FileStream()
override =
default;
9645 std::ostream& stream()
const override {
9652 class CoutStream :
public IStream {
9653 mutable std::ostream m_os;
9657 CoutStream() : m_os(
Catch::
cout().rdbuf() ) {}
9658 ~CoutStream()
override =
default;
9661 std::ostream& stream()
const override {
return m_os; }
9666 class DebugOutStream :
public IStream {
9667 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
9668 mutable std::ostream m_os;
9671 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
9672 m_os( m_streamBuf.
get() )
9675 ~DebugOutStream()
override =
default;
9678 std::ostream& stream()
const override {
return m_os; }
9685 auto makeStream( StringRef
const &filename ) -> IStream
const* {
9686 if( filename.empty() )
9687 return new detail::CoutStream();
9688 else if( filename[0] ==
'%' ) {
9689 if( filename ==
"%debug" )
9690 return new detail::DebugOutStream();
9692 CATCH_ERROR(
"Unrecognised stream: '" << filename <<
"'" );
9695 return new detail::FileStream( filename );
9699 struct StringStreams {
9700 std::vector<std::unique_ptr<std::ostringstream>> m_streams;
9701 std::vector<std::size_t> m_unused;
9702 std::ostringstream m_referenceStream;
9703 static StringStreams* s_instance;
9705 auto add() -> std::size_t {
9706 if( m_unused.empty() ) {
9707 m_streams.push_back( std::unique_ptr<std::ostringstream>(
new std::ostringstream ) );
9708 return m_streams.size()-1;
9711 auto index = m_unused.back();
9712 m_unused.pop_back();
9717 void release( std::size_t
index ) {
9718 m_streams[index]->copyfmt( m_referenceStream );
9719 m_unused.push_back(
index);
9723 static auto instance() -> StringStreams& {
9725 s_instance =
new StringStreams();
9728 static void cleanup() {
9730 s_instance =
nullptr;
9734 StringStreams* StringStreams::s_instance =
nullptr;
9737 StringStreams::cleanup();
9741 : m_index( StringStreams::instance().add() ),
9742 m_oss( StringStreams::instance().m_streams[m_index].
get() )
9746 static_cast<std::ostringstream*
>( m_oss )->
str(
"");
9748 StringStreams::instance().release( m_index );
9752 return static_cast<std::ostringstream*
>( m_oss )->
str();
9757#ifndef CATCH_CONFIG_NOSTDOUT
9764#if defined(__clang__)
9765# pragma clang diagnostic pop
9778 return s.size() >= prefix.size() &&
std::equal(prefix.begin(), prefix.end(), s.begin());
9781 return !s.empty() && s[0] == prefix;
9784 return s.size() >= suffix.size() &&
std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
9787 return !s.empty() && s[s.size()-1] == suffix;
9790 return s.find( infix ) != std::string::npos;
9792 char toLowerCh(
char c) {
9793 return static_cast<char>( std::tolower( c ) );
9796 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
9804 static char const* whitespaceChars =
"\n\r\t ";
9805 std::string::size_type start = str.find_first_not_of( whitespaceChars );
9806 std::string::size_type
end = str.find_last_not_of( whitespaceChars );
9808 return start != std::string::npos ? str.substr( start, 1+
end-start ) :
std::string();
9812 bool replaced =
false;
9813 std::size_t i = str.find( replaceThis );
9814 while( i != std::string::npos ) {
9816 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
9817 if( i < str.size()-withThis.size() )
9818 i = str.find( replaceThis, i+withThis.size() );
9820 i = std::string::npos;
9830 std::ostream&
operator << ( std::ostream& os, pluralise
const& pluraliser ) {
9831 os << pluraliser.m_count <<
' ' << pluraliser.m_label;
9832 if( pluraliser.m_count != 1 )
9841#if defined(__clang__)
9842# pragma clang diagnostic push
9843# pragma clang diagnostic ignored "-Wexit-time-destructors"
9851 const uint32_t byte_2_lead = 0xC0;
9852 const uint32_t byte_3_lead = 0xE0;
9853 const uint32_t byte_4_lead = 0xF0;
9866 std::swap( m_start, other.m_start );
9867 std::swap( m_size, other.m_size );
9868 std::swap( m_data, other.m_data );
9873 const_cast<StringRef*
>( this )->takeOwnership();
9880 auto StringRef::isOwned() const noexcept ->
bool {
9881 return m_data !=
nullptr;
9883 auto StringRef::isSubstring() const noexcept ->
bool {
9884 return m_start[m_size] !=
'\0';
9887 void StringRef::takeOwnership() {
9889 m_data =
new char[m_size+1];
9890 memcpy( m_data, m_start, m_size );
9891 m_data[m_size] =
'\0';
9895 auto StringRef::substr( size_type start, size_type size )
const noexcept -> StringRef {
9896 if( start < m_size )
9897 return StringRef( m_start+start, size );
9903 size() == other.size() &&
9904 (std::strncmp( m_start, other.m_start, size() ) == 0);
9911 return m_start[index];
9918 char c = m_start[i];
9919 if( ( c & byte_2_lead ) == byte_2_lead ) {
9921 if (( c & byte_3_lead ) == byte_3_lead )
9923 if( ( c & byte_4_lead ) == byte_4_lead )
9932 str.reserve( lhs.size() + rhs.size() );
9944 auto operator << ( std::ostream& os, StringRef
const& str ) -> std::ostream& {
9945 return os.write(str.currentData(), str.size());
9949 lhs.append(rhs.currentData(), rhs.size());
9955#if defined(__clang__)
9956# pragma clang diagnostic pop
9962 TagAlias::TagAlias(
std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
9986 TagAliasRegistry::~TagAliasRegistry() {}
9988 TagAlias
const* TagAliasRegistry::find(
std::string const& alias )
const {
9989 auto it = m_registry.find( alias );
9990 if( it != m_registry.end() )
9991 return &(it->second);
9997 std::string expandedTestSpec = unexpandedTestSpec;
9998 for(
auto const& registryKvp : m_registry ) {
9999 std::size_t pos = expandedTestSpec.find( registryKvp.first );
10000 if( pos != std::string::npos ) {
10001 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
10002 registryKvp.
second.tag +
10003 expandedTestSpec.substr( pos + registryKvp.first.size() );
10006 return expandedTestSpec;
10009 void TagAliasRegistry::add(
std::string const& alias,
std::string const& tag, SourceLineInfo
const& lineInfo ) {
10011 "error: tag alias, '" << alias <<
"' is not of the form [@alias name].\n" << lineInfo );
10013 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).
second,
10014 "error: tag alias, '" << alias <<
"' already registered.\n"
10015 <<
"\tFirst seen at: " << find(alias)->lineInfo <<
"\n"
10016 <<
"\tRedefined at: " << lineInfo );
10019 ITagAliasRegistry::~ITagAliasRegistry() {}
10030#include <exception>
10031#include <algorithm>
10040 else if( tag ==
"!throws" )
10042 else if( tag ==
"!shouldfail" )
10044 else if( tag ==
"!mayfail" )
10046 else if( tag ==
"!nonportable" )
10048 else if( tag ==
"!benchmark" )
10054 return parseSpecialTag( tag ) ==
TestCaseInfo::None && tag.size() > 0 && !std::isalnum(
static_cast<unsigned char>(tag[0]) );
10056 void enforceNotReservedTag(
std::string const& tag, SourceLineInfo
const& _lineInfo ) {
10057 CATCH_ENFORCE( !isReservedTag(tag),
10058 "Tag name: [" << tag <<
"] is not allowed.\n"
10059 <<
"Tag names starting with non alpha-numeric characters are reserved\n"
10065 NameAndTags
const& nameAndTags,
10066 SourceLineInfo
const& _lineInfo )
10068 bool isHidden =
false;
10071 std::vector<std::string> tags;
10073 bool inTag =
false;
10075 for (
char c : _descOrTags) {
10088 enforceNotReservedTag( tag, _lineInfo );
10090 tags.push_back( tag );
10099 tags.push_back(
"." );
10102 TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
10103 return TestCase( _testCase, std::move(info) );
10106 void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
10107 std::sort(
begin(tags),
end(tags));
10108 tags.erase(std::unique(
begin(tags),
end(tags)),
end(tags));
10109 testCaseInfo.lcaseTags.clear();
10111 for(
auto const& tag : tags ) {
10114 testCaseInfo.lcaseTags.push_back( lcaseTag );
10116 testCaseInfo.tags = std::move(tags);
10122 std::vector<std::string>
const& _tags,
10123 SourceLineInfo
const& _lineInfo )
10125 className( _className ),
10126 description( _description ),
10127 lineInfo( _lineInfo ),
10130 setTags( *
this, _tags );
10149 std::size_t full_size = 2 *
tags.size();
10150 for (
const auto& tag :
tags) {
10151 full_size += tag.size();
10153 ret.reserve(full_size);
10154 for (
const auto& tag :
tags) {
10155 ret.push_back(
'[');
10157 ret.push_back(
']');
10163 TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}
10167 other.name = _newName;
10176 return test.get() == other.test.get() &&
10177 name == other.name &&
10182 return name < other.name;
10198 std::vector<TestCase> sortTests( IConfig
const& config, std::vector<TestCase>
const& unsortedTestCases ) {
10200 std::vector<TestCase> sorted = unsortedTestCases;
10202 switch( config.runOrder() ) {
10203 case RunTests::InLexicographicalOrder:
10204 std::sort( sorted.begin(), sorted.end() );
10206 case RunTests::InRandomOrder:
10208 RandomNumberGenerator::shuffle( sorted );
10210 case RunTests::InDeclarationOrder:
10216 bool matchTest( TestCase
const& testCase, TestSpec
const& testSpec, IConfig
const& config ) {
10217 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
10220 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions ) {
10221 std::set<TestCase> seenFunctions;
10222 for(
auto const&
function : functions ) {
10223 auto prev = seenFunctions.insert(
function );
10224 CATCH_ENFORCE( prev.second,
10225 "error: TEST_CASE( \"" <<
function.name <<
"\" ) already defined.\n"
10226 <<
"\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo <<
"\n"
10227 <<
"\tRedefined at " <<
function.getTestCaseInfo().lineInfo );
10231 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config ) {
10232 std::vector<TestCase> filtered;
10233 filtered.reserve( testCases.size() );
10234 for(
auto const& testCase : testCases )
10235 if(
matchTest( testCase, testSpec, config ) )
10236 filtered.push_back( testCase );
10243 void TestRegistry::registerTest( TestCase
const& testCase ) {
10245 if(
name.empty() ) {
10246 ReusableStringStream rss;
10247 rss <<
"Anonymous test case " << ++m_unnamedCount;
10248 return registerTest( testCase.withName( rss.str() ) );
10250 m_functions.push_back( testCase );
10253 std::vector<TestCase>
const& TestRegistry::getAllTests()
const {
10254 return m_functions;
10256 std::vector<TestCase>
const& TestRegistry::getAllTestsSorted( IConfig
const& config )
const {
10257 if( m_sortedFunctions.empty() )
10258 enforceNoDuplicateTestCases( m_functions );
10260 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
10261 m_sortedFunctions = sortTests( config, m_functions );
10262 m_currentSortOrder = config.runOrder();
10264 return m_sortedFunctions;
10268 TestInvokerAsFunction::TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
10270 void TestInvokerAsFunction::invoke()
const {
10271 m_testAsFunction();
10274 std::string extractClassName( StringRef
const& classOrQualifiedMethodName ) {
10275 std::string className = classOrQualifiedMethodName;
10278 std::size_t lastColons = className.rfind(
"::" );
10279 std::size_t penultimateColons = className.rfind(
"::", lastColons-1 );
10280 if( penultimateColons == std::string::npos )
10281 penultimateColons = 1;
10282 className = className.substr( penultimateColons, lastColons-penultimateColons );
10291#include <algorithm>
10293#include <stdexcept>
10297#if defined(__clang__)
10298# pragma clang diagnostic push
10299# pragma clang diagnostic ignored "-Wexit-time-destructors"
10303namespace TestCaseTracking {
10305 NameAndLocation::NameAndLocation(
std::string const& _name, SourceLineInfo
const& _location )
10307 location( _location )
10310 ITracker::~ITracker() =
default;
10312 TrackerContext& TrackerContext::instance() {
10313 static TrackerContext s_instance;
10317 ITracker& TrackerContext::startRun() {
10318 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation(
"{root}",
CATCH_INTERNAL_LINEINFO ), *
this,
nullptr );
10319 m_currentTracker =
nullptr;
10320 m_runState = Executing;
10321 return *m_rootTracker;
10324 void TrackerContext::endRun() {
10325 m_rootTracker.reset();
10326 m_currentTracker =
nullptr;
10327 m_runState = NotStarted;
10330 void TrackerContext::startCycle() {
10331 m_currentTracker = m_rootTracker.get();
10332 m_runState = Executing;
10334 void TrackerContext::completeCycle() {
10335 m_runState = CompletedCycle;
10338 bool TrackerContext::completedCycle()
const {
10339 return m_runState == CompletedCycle;
10341 ITracker& TrackerContext::currentTracker() {
10342 return *m_currentTracker;
10344 void TrackerContext::setCurrentTracker( ITracker* tracker ) {
10345 m_currentTracker = tracker;
10348 TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation
const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
10349 bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr
const& tracker )
const {
10351 tracker->nameAndLocation().name == m_nameAndLocation.name &&
10352 tracker->nameAndLocation().location == m_nameAndLocation.location;
10355 TrackerBase::TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
10356 : m_nameAndLocation( nameAndLocation ),
10361 NameAndLocation
const& TrackerBase::nameAndLocation()
const {
10362 return m_nameAndLocation;
10364 bool TrackerBase::isComplete()
const {
10365 return m_runState == CompletedSuccessfully || m_runState == Failed;
10367 bool TrackerBase::isSuccessfullyCompleted()
const {
10368 return m_runState == CompletedSuccessfully;
10370 bool TrackerBase::isOpen()
const {
10371 return m_runState != NotStarted && !isComplete();
10373 bool TrackerBase::hasChildren()
const {
10374 return !m_children.empty();
10377 void TrackerBase::addChild( ITrackerPtr
const& child ) {
10378 m_children.push_back( child );
10381 ITrackerPtr TrackerBase::findChild( NameAndLocation
const& nameAndLocation ) {
10382 auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
10383 return( it != m_children.end() )
10387 ITracker& TrackerBase::parent() {
10388 assert( m_parent );
10392 void TrackerBase::openChild() {
10393 if( m_runState != ExecutingChildren ) {
10394 m_runState = ExecutingChildren;
10396 m_parent->openChild();
10400 bool TrackerBase::isSectionTracker()
const {
return false; }
10401 bool TrackerBase::isIndexTracker()
const {
return false; }
10403 void TrackerBase::open() {
10404 m_runState = Executing;
10407 m_parent->openChild();
10410 void TrackerBase::close() {
10413 while( &m_ctx.currentTracker() !=
this )
10414 m_ctx.currentTracker().close();
10416 switch( m_runState ) {
10417 case NeedsAnotherRun:
10421 m_runState = CompletedSuccessfully;
10423 case ExecutingChildren:
10424 if( m_children.empty() || m_children.back()->isComplete() )
10425 m_runState = CompletedSuccessfully;
10429 case CompletedSuccessfully:
10431 CATCH_INTERNAL_ERROR(
"Illogical state: " << m_runState );
10434 CATCH_INTERNAL_ERROR(
"Unknown state: " << m_runState );
10437 m_ctx.completeCycle();
10439 void TrackerBase::fail() {
10440 m_runState = Failed;
10442 m_parent->markAsNeedingAnotherRun();
10444 m_ctx.completeCycle();
10446 void TrackerBase::markAsNeedingAnotherRun() {
10447 m_runState = NeedsAnotherRun;
10450 void TrackerBase::moveToParent() {
10451 assert( m_parent );
10452 m_ctx.setCurrentTracker( m_parent );
10454 void TrackerBase::moveToThis() {
10455 m_ctx.setCurrentTracker(
this );
10458 SectionTracker::SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
10459 : TrackerBase( nameAndLocation, ctx, parent )
10462 while( !parent->isSectionTracker() )
10463 parent = &parent->parent();
10465 SectionTracker& parentSection =
static_cast<SectionTracker&
>( *parent );
10466 addNextFilters( parentSection.m_filters );
10470 bool SectionTracker::isSectionTracker()
const {
return true; }
10472 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation ) {
10473 std::shared_ptr<SectionTracker> section;
10475 ITracker& currentTracker = ctx.currentTracker();
10476 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
10477 assert( childTracker );
10478 assert( childTracker->isSectionTracker() );
10479 section = std::static_pointer_cast<SectionTracker>( childTracker );
10482 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker );
10483 currentTracker.addChild( section );
10485 if( !ctx.completedCycle() )
10486 section->tryOpen();
10490 void SectionTracker::tryOpen() {
10491 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
10495 void SectionTracker::addInitialFilters( std::vector<std::string>
const& filters ) {
10496 if( !filters.empty() ) {
10497 m_filters.push_back(
"");
10498 m_filters.push_back(
"");
10499 m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
10502 void SectionTracker::addNextFilters( std::vector<std::string>
const& filters ) {
10503 if( filters.size() > 1 )
10504 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
10507 IndexTracker::IndexTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent,
int size )
10508 : TrackerBase( nameAndLocation, ctx, parent ),
10512 bool IndexTracker::isIndexTracker()
const {
return true; }
10514 IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation,
int size ) {
10515 std::shared_ptr<IndexTracker> tracker;
10517 ITracker& currentTracker = ctx.currentTracker();
10518 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
10519 assert( childTracker );
10520 assert( childTracker->isIndexTracker() );
10521 tracker = std::static_pointer_cast<IndexTracker>( childTracker );
10524 tracker = std::make_shared<IndexTracker>( nameAndLocation, ctx, ¤tTracker, size );
10525 currentTracker.addChild( tracker );
10528 if( !ctx.completedCycle() && !tracker->isComplete() ) {
10529 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
10530 tracker->moveNext();
10539 void IndexTracker::moveNext() {
10541 m_children.clear();
10544 void IndexTracker::close() {
10545 TrackerBase::close();
10546 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
10547 m_runState = Executing;
10552using TestCaseTracking::ITracker;
10553using TestCaseTracking::TrackerContext;
10554using TestCaseTracking::SectionTracker;
10555using TestCaseTracking::IndexTracker;
10559#if defined(__clang__)
10560# pragma clang diagnostic pop
10567 auto makeTestInvoker(
void(*testAsFunction)() ) noexcept -> ITestInvoker* {
10568 return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
10573 AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo
const& lineInfo, StringRef
const& classOrMethod, NameAndTags
const& nameAndTags )
noexcept {
10579 extractClassName( classOrMethod ),
10593#include <algorithm>
10600 TestSpec::Pattern::~Pattern() =
default;
10601 TestSpec::NamePattern::~NamePattern() =
default;
10602 TestSpec::TagPattern::~TagPattern() =
default;
10603 TestSpec::ExcludedPattern::~ExcludedPattern() =
default;
10606 : m_wildcardPattern(
toLower(
name ), CaseSensitive::No )
10608 bool TestSpec::NamePattern::matches( TestCaseInfo
const& testCase )
const {
10609 return m_wildcardPattern.matches(
toLower( testCase.name ) );
10612 TestSpec::TagPattern::TagPattern(
std::string const& tag ) : m_tag(
toLower( tag ) ) {}
10613 bool TestSpec::TagPattern::matches( TestCaseInfo
const& testCase )
const {
10614 return std::find(
begin(testCase.lcaseTags),
10615 end(testCase.lcaseTags),
10616 m_tag) !=
end(testCase.lcaseTags);
10619 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr
const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
10620 bool TestSpec::ExcludedPattern::matches( TestCaseInfo
const& testCase )
const {
return !m_underlyingPattern->matches( testCase ); }
10622 bool TestSpec::Filter::matches( TestCaseInfo
const& testCase )
const {
10624 for(
auto const& pattern : m_patterns ) {
10625 if( !pattern->matches( testCase ) )
10631 bool TestSpec::hasFilters()
const {
10632 return !m_filters.empty();
10634 bool TestSpec::matches( TestCaseInfo
const& testCase )
const {
10636 for(
auto const& filter : m_filters )
10637 if( filter.matches( testCase ) )
10647 TestSpecParser::TestSpecParser( ITagAliasRegistry
const& tagAliases ) : m_tagAliases( &tagAliases ) {}
10649 TestSpecParser& TestSpecParser::parse(
std::string const& arg ) {
10651 m_exclusion =
false;
10652 m_start = std::string::npos;
10653 m_arg = m_tagAliases->expandAliases( arg );
10654 m_escapeChars.clear();
10655 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
10656 visitChar( m_arg[m_pos] );
10657 if( m_mode == Name )
10658 addPattern<TestSpec::NamePattern>();
10661 TestSpec TestSpecParser::testSpec() {
10666 void TestSpecParser::visitChar(
char c ) {
10667 if( m_mode == None ) {
10670 case '~': m_exclusion =
true;
return;
10671 case '[':
return startNewMode( Tag, ++m_pos );
10672 case '"':
return startNewMode( QuotedName, ++m_pos );
10673 case '\\':
return escape();
10674 default: startNewMode( Name, m_pos );
break;
10677 if( m_mode == Name ) {
10679 addPattern<TestSpec::NamePattern>();
10682 else if( c ==
'[' ) {
10683 if( subString() ==
"exclude:" )
10684 m_exclusion =
true;
10686 addPattern<TestSpec::NamePattern>();
10687 startNewMode( Tag, ++m_pos );
10689 else if( c ==
'\\' )
10692 else if( m_mode == EscapedName )
10694 else if( m_mode == QuotedName && c ==
'"' )
10695 addPattern<TestSpec::NamePattern>();
10696 else if( m_mode == Tag && c ==
']' )
10697 addPattern<TestSpec::TagPattern>();
10699 void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
10703 void TestSpecParser::escape() {
10704 if( m_mode == None )
10706 m_mode = EscapedName;
10707 m_escapeChars.push_back( m_pos );
10709 std::string TestSpecParser::subString()
const {
return m_arg.substr( m_start, m_pos - m_start ); }
10711 void TestSpecParser::addFilter() {
10712 if( !m_currentFilter.m_patterns.empty() ) {
10713 m_testSpec.m_filters.push_back( m_currentFilter );
10714 m_currentFilter = TestSpec::Filter();
10718 TestSpec parseTestSpec(
std::string const& arg ) {
10728static const uint64_t nanosecondsInSecond = 1000000000;
10736 auto estimateClockResolution() -> uint64_t {
10738 static const uint64_t iterations = 1000000;
10742 for( std::size_t i = 0; i < iterations; ++i ) {
10748 }
while( ticks == baseTicks );
10750 auto delta = ticks - baseTicks;
10756 if (ticks > startTime + 3 * nanosecondsInSecond) {
10763 return sum/iterations;
10766 static auto s_resolution = estimateClockResolution();
10767 return s_resolution;
10770 void Timer::start() {
10773 auto Timer::getElapsedNanoseconds() const -> uint64_t {
10776 auto Timer::getElapsedMicroseconds() const -> uint64_t {
10777 return getElapsedNanoseconds()/1000;
10779 auto Timer::getElapsedMilliseconds() const ->
unsigned int {
10780 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
10782 auto Timer::getElapsedSeconds() const ->
double {
10783 return getElapsedMicroseconds()/1000000.0;
10790#if defined(__clang__)
10791# pragma clang diagnostic push
10792# pragma clang diagnostic ignored "-Wexit-time-destructors"
10793# pragma clang diagnostic ignored "-Wglobal-constructors"
10797#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
10798#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
10811 const int hexThreshold = 255;
10813 struct Endianness {
10814 enum Arch { Big, Little };
10816 static Arch
which() {
10819 char asChar[sizeof (int)];
10823 return ( u.asChar[
sizeof(
int)-1] == 1 ) ? Big : Little;
10830 int i = 0,
end =
static_cast<int>( size ), inc = 1;
10836 unsigned char const *bytes =
static_cast<unsigned char const *
>(object);
10837 ReusableStringStream rss;
10838 rss <<
"0x" << std::setfill(
'0') << std::hex;
10839 for( ; i !=
end; i += inc )
10840 rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
10845template<
typename T>
10847 if (std::isnan(
value)) {
10851 ReusableStringStream rss;
10852 rss << std::setprecision( precision )
10856 std::size_t i = d.find_last_not_of(
'0' );
10857 if( i != std::string::npos && i != d.size()-1 ) {
10860 d = d.substr( 0, i+1 );
10872 if (!getCurrentContext().getConfig()->showInvisibles()) {
10873 return '"' + str + '"';
10877 for (
char c : str) {
10894#ifdef CATCH_CONFIG_WCHAR
10897 s.reserve(wstr.size());
10898 for (
auto c : wstr) {
10899 s += (c <= 0xff) ? static_cast<char>(c) : '?';
10909 return{
"{null string}" };
10916 return{
"{null string}" };
10919#ifdef CATCH_CONFIG_WCHAR
10924 return{
"{null string}" };
10931 return{
"{null string}" };
10943 ReusableStringStream rss;
10945 if (
value > Detail::hexThreshold) {
10946 rss <<
" (0x" << std::hex <<
value <<
')';
10958 ReusableStringStream rss;
10960 if (
value > Detail::hexThreshold) {
10961 rss <<
" (0x" << std::hex <<
value <<
')';
10967 return b ?
"true" :
"false";
10971 if (
value ==
'\r') {
10973 }
else if (
value ==
'\f') {
10975 }
else if (
value ==
'\n') {
10977 }
else if (
value ==
'\t') {
10982 char chstr[] =
"' '";
10999 return fpToString(
value, 5) + 'f';
11002 return fpToString(
value, 10);
11005std::string ratio_string<std::atto>::symbol() {
return "a"; }
11006std::string ratio_string<std::femto>::symbol() {
return "f"; }
11007std::string ratio_string<std::pico>::symbol() {
return "p"; }
11008std::string ratio_string<std::nano>::symbol() {
return "n"; }
11009std::string ratio_string<std::micro>::symbol() {
return "u"; }
11010std::string ratio_string<std::milli>::symbol() {
return "m"; }
11014#if defined(__clang__)
11015# pragma clang diagnostic pop
11062 Totals diff = *
this - prevTotals;
11063 if( diff.assertions.failed > 0 )
11065 else if( diff.assertions.failedButOk > 0 )
11076#include <exception>
11079 bool uncaught_exceptions() {
11080#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
11081 return std::uncaught_exceptions() > 0;
11083 return std::uncaught_exception();
11095 (
unsigned int _majorVersion,
11096 unsigned int _minorVersion,
11097 unsigned int _patchNumber,
11098 char const *
const _branchName,
11099 unsigned int _buildNumber )
11100 : majorVersion( _majorVersion ),
11101 minorVersion( _minorVersion ),
11102 patchNumber( _patchNumber ),
11103 branchName( _branchName ),
11104 buildNumber( _buildNumber )
11108 os <<
version.majorVersion <<
'.'
11109 <<
version.minorVersion <<
'.'
11113 os <<
'-' <<
version.branchName
11114 <<
'.' <<
version.buildNumber;
11119 Version
const& libraryVersion() {
11120 static Version
version( 2, 2, 3,
"", 0 );
11132 WildcardPattern::WildcardPattern(
std::string const& pattern,
11134 : m_caseSensitivity( caseSensitivity ),
11135 m_pattern( adjustCase( pattern ) )
11138 m_pattern = m_pattern.substr( 1 );
11139 m_wildcard = WildcardAtStart;
11141 if(
endsWith( m_pattern,
'*' ) ) {
11142 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
11143 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
11147 bool WildcardPattern::matches(
std::string const& str )
const {
11148 switch( m_wildcard ) {
11150 return m_pattern == adjustCase( str );
11151 case WildcardAtStart:
11152 return endsWith( adjustCase( str ), m_pattern );
11153 case WildcardAtEnd:
11154 return startsWith( adjustCase( str ), m_pattern );
11155 case WildcardAtBothEnds:
11156 return contains( adjustCase( str ), m_pattern );
11158 CATCH_INTERNAL_ERROR(
"Unknown enum" );
11171using uchar =
unsigned char;
11177 size_t trailingBytes(
unsigned char c) {
11178 if ((c & 0xE0) == 0xC0) {
11181 if ((c & 0xF0) == 0xE0) {
11184 if ((c & 0xF8) == 0xF0) {
11187 CATCH_INTERNAL_ERROR(
"Invalid multibyte utf-8 start byte encountered");
11190 uint32_t headerValue(
unsigned char c) {
11191 if ((c & 0xE0) == 0xC0) {
11194 if ((c & 0xF0) == 0xE0) {
11197 if ((c & 0xF8) == 0xF0) {
11200 CATCH_INTERNAL_ERROR(
"Invalid multibyte utf-8 start byte encountered");
11203 void hexEscapeChar(std::ostream& os,
unsigned char c) {
11205 <<
std::uppercase << std::hex << std::setfill(
'0') << std::setw(2)
11206 <<
static_cast<int>(c);
11211 XmlEncode::XmlEncode(
std::string const& str, ForWhat forWhat )
11213 m_forWhat( forWhat )
11216 void XmlEncode::encodeTo( std::ostream& os )
const {
11220 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
11221 uchar c = m_str[idx];
11223 case '<': os <<
"<";
break;
11224 case '&': os <<
"&";
break;
11228 if (idx > 2 && m_str[idx - 1] ==
']' && m_str[idx - 2] ==
']')
11235 if (m_forWhat == ForAttributes)
11246 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
11247 hexEscapeChar(os, c);
11265 hexEscapeChar(os, c);
11269 auto encBytes = trailingBytes(c);
11271 if (idx + encBytes - 1 >= m_str.size()) {
11272 hexEscapeChar(os, c);
11279 uint32_t
value = headerValue(c);
11280 for (std::size_t n = 1; n < encBytes; ++n) {
11281 uchar nc = m_str[idx + n];
11282 valid &= ((nc & 0xC0) == 0x80);
11291 (0x80 <=
value && value < 0x800 && encBytes > 2) ||
11292 (0x800 <
value && value < 0x10000 && encBytes > 3) ||
11294 (
value >= 0x110000)
11296 hexEscapeChar(os, c);
11301 for (std::size_t n = 0; n < encBytes; ++n) {
11302 os << m_str[idx + n];
11304 idx += encBytes - 1;
11310 std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode ) {
11311 xmlEncode.encodeTo( os );
11315 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
11316 : m_writer( writer )
11319 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
11320 : m_writer( other.m_writer ){
11321 other.m_writer =
nullptr;
11323 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other )
noexcept {
11325 m_writer->endElement();
11327 m_writer = other.m_writer;
11328 other.m_writer =
nullptr;
11332 XmlWriter::ScopedElement::~ScopedElement() {
11334 m_writer->endElement();
11337 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText(
std::string const& text,
bool indent ) {
11338 m_writer->writeText( text, indent );
11342 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
11344 writeDeclaration();
11347 XmlWriter::~XmlWriter() {
11348 while( !m_tags.empty() )
11354 newlineIfNecessary();
11355 m_os << m_indent <<
'<' <<
name;
11356 m_tags.push_back(
name );
11358 m_tagIsOpen =
true;
11362 XmlWriter::ScopedElement XmlWriter::scopedElement(
std::string const&
name ) {
11363 ScopedElement scoped(
this );
11364 startElement(
name );
11368 XmlWriter& XmlWriter::endElement() {
11369 newlineIfNecessary();
11370 m_indent = m_indent.substr( 0, m_indent.size()-2 );
11371 if( m_tagIsOpen ) {
11373 m_tagIsOpen =
false;
11376 m_os << m_indent <<
"</" << m_tags.back() <<
">";
11384 if( !
name.empty() && !attribute.empty() )
11385 m_os <<
' ' <<
name <<
"=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) <<
'"';
11389 XmlWriter& XmlWriter::writeAttribute(
std::string const&
name,
bool attribute ) {
11390 m_os <<
' ' <<
name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
'"';
11394 XmlWriter& XmlWriter::writeText(
std::string const& text,
bool indent ) {
11395 if( !text.empty() ){
11396 bool tagWasOpen = m_tagIsOpen;
11398 if( tagWasOpen && indent )
11400 m_os << XmlEncode( text );
11401 m_needsNewline =
true;
11406 XmlWriter& XmlWriter::writeComment(
std::string const& text ) {
11408 m_os << m_indent <<
"<!--" << text <<
"-->";
11409 m_needsNewline =
true;
11413 void XmlWriter::writeStylesheetRef(
std::string const& url ) {
11414 m_os <<
"<?xml-stylesheet type=\"text/xsl\" href=\"" << url <<
"\"?>\n";
11417 XmlWriter& XmlWriter::writeBlankLine() {
11423 void XmlWriter::ensureTagClosed() {
11424 if( m_tagIsOpen ) {
11425 m_os <<
">" << std::endl;
11426 m_tagIsOpen =
false;
11430 void XmlWriter::writeDeclaration() {
11431 m_os <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
11434 void XmlWriter::newlineIfNecessary() {
11435 if( m_needsNewline ) {
11437 m_needsNewline =
false;
11451 void prepareExpandedExpression(AssertionResult& result) {
11452 result.getExpandedExpression();
11457 std::string getFormattedDuration(
double duration ) {
11462 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
11463 char buffer[maxDoubleSize];
11468 sprintf_s(
buffer,
"%.3f", duration);
11470 sprintf(
buffer,
"%.3f", duration);
11475 TestEventListenerBase::TestEventListenerBase(ReporterConfig
const & _config)
11476 :StreamingReporterBase(_config) {}
11478 void TestEventListenerBase::assertionStarting(AssertionInfo
const &) {}
11480 bool TestEventListenerBase::assertionEnded(AssertionStats
const &) {
11490#ifdef CATCH_PLATFORM_MAC
11491 const char* failedString() {
return "FAILED"; }
11492 const char* passedString() {
return "PASSED"; }
11494 const char* failedString() {
return "failed"; }
11495 const char* passedString() {
return "passed"; }
11499 Catch::Colour::Code dimColour() {
return Catch::Colour::FileName; }
11503 count == 2 ?
"both " :
"all " ;
11516void printTotals(std::ostream& out,
const Totals& totals) {
11517 if (totals.testCases.total() == 0) {
11518 out <<
"No tests ran.";
11519 }
else if (totals.testCases.failed == totals.testCases.total()) {
11520 Colour colour(Colour::ResultError);
11522 totals.assertions.failed == totals.assertions.total() ?
11523 bothOrAll(totals.assertions.failed) : std::
string();
11525 "Failed " << bothOrAll(totals.testCases.failed)
11526 << pluralise(totals.testCases.failed,
"test case") <<
", "
11527 "failed " << qualify_assertions_failed <<
11528 pluralise(totals.assertions.failed,
"assertion") <<
'.';
11529 }
else if (totals.assertions.total() == 0) {
11531 "Passed " << bothOrAll(totals.testCases.total())
11532 << pluralise(totals.testCases.total(),
"test case")
11533 <<
" (no assertions).";
11534 }
else if (totals.assertions.failed) {
11535 Colour colour(Colour::ResultError);
11537 "Failed " << pluralise(totals.testCases.failed,
"test case") <<
", "
11538 "failed " << pluralise(totals.assertions.failed,
"assertion") <<
'.';
11540 Colour colour(Colour::ResultSuccess);
11542 "Passed " << bothOrAll(totals.testCases.passed)
11543 << pluralise(totals.testCases.passed,
"test case") <<
11544 " with " << pluralise(totals.assertions.passed,
"assertion") <<
'.';
11549class AssertionPrinter {
11551 AssertionPrinter& operator= (AssertionPrinter
const&) =
delete;
11552 AssertionPrinter(AssertionPrinter
const&) =
delete;
11553 AssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
11555 , result(_stats.assertionResult)
11556 , messages(_stats.infoMessages)
11557 , itMessage(_stats.infoMessages.
begin())
11558 , printInfoMessages(_printInfoMessages) {}
11563 itMessage = messages.begin();
11565 switch (result.getResultType()) {
11567 printResultType(Colour::ResultSuccess, passedString());
11568 printOriginalExpression();
11569 printReconstructedExpression();
11570 if (!result.hasExpression())
11571 printRemainingMessages(Colour::None);
11573 printRemainingMessages();
11577 printResultType(Colour::ResultSuccess, failedString() +
std::string(
" - but was ok"));
11580 printOriginalExpression();
11581 printReconstructedExpression();
11582 printRemainingMessages();
11586 printIssue(
"unexpected exception with message:");
11588 printExpressionWas();
11589 printRemainingMessages();
11593 printIssue(
"fatal error condition with message:");
11595 printExpressionWas();
11596 printRemainingMessages();
11600 printIssue(
"expected exception, got none");
11601 printExpressionWas();
11602 printRemainingMessages();
11605 printResultType(Colour::None,
"info");
11607 printRemainingMessages();
11610 printResultType(Colour::None,
"warning");
11612 printRemainingMessages();
11616 printIssue(
"explicitly");
11617 printRemainingMessages(Colour::None);
11629 void printSourceInfo()
const {
11630 Colour colourGuard(Colour::FileName);
11631 stream << result.getSourceInfo() <<
':';
11634 void printResultType(Colour::Code colour,
std::string const& passOrFail)
const {
11635 if (!passOrFail.empty()) {
11637 Colour colourGuard(colour);
11638 stream <<
' ' << passOrFail;
11644 void printIssue(
std::string const& issue)
const {
11645 stream <<
' ' << issue;
11648 void printExpressionWas() {
11649 if (result.hasExpression()) {
11652 Colour colour(dimColour());
11653 stream <<
" expression was:";
11655 printOriginalExpression();
11659 void printOriginalExpression()
const {
11660 if (result.hasExpression()) {
11661 stream <<
' ' << result.getExpression();
11665 void printReconstructedExpression()
const {
11666 if (result.hasExpandedExpression()) {
11668 Colour colour(dimColour());
11669 stream <<
" for: ";
11671 stream << result.getExpandedExpression();
11675 void printMessage() {
11676 if (itMessage != messages.end()) {
11677 stream <<
" '" << itMessage->message <<
'\'';
11682 void printRemainingMessages(Colour::Code colour = dimColour()) {
11683 if (itMessage == messages.end())
11687 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
11688 const std::size_t N =
static_cast<std::size_t
>(std::distance(itMessage, itEnd));
11691 Colour colourGuard(colour);
11692 stream <<
" with " << pluralise(N,
"message") <<
':';
11695 for (; itMessage != itEnd; ) {
11698 stream <<
" '" << itMessage->message <<
'\'';
11699 if (++itMessage != itEnd) {
11700 Colour colourGuard(dimColour());
11708 std::ostream& stream;
11709 AssertionResult
const& result;
11710 std::vector<MessageInfo> messages;
11711 std::vector<MessageInfo>::const_iterator itMessage;
11712 bool printInfoMessages;
11718 return "Reports test results on a single line, suitable for IDEs";
11721 ReporterPreferences CompactReporter::getPreferences()
const {
11722 ReporterPreferences prefs;
11723 prefs.shouldRedirectStdOut =
false;
11727 void CompactReporter::noMatchingTestCases(
std::string const& spec ) {
11728 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
11731 void CompactReporter::assertionStarting( AssertionInfo
const& ) {}
11733 bool CompactReporter::assertionEnded( AssertionStats
const& _assertionStats ) {
11734 AssertionResult
const& result = _assertionStats.assertionResult;
11736 bool printInfoMessages =
true;
11739 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
11742 printInfoMessages =
false;
11745 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
11748 stream << std::endl;
11752 void CompactReporter::sectionEnded(SectionStats
const& _sectionStats) {
11753 if (m_config->showDurations() == ShowDurations::Always) {
11754 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name << std::endl;
11758 void CompactReporter::testRunEnded( TestRunStats
const& _testRunStats ) {
11759 printTotals( stream, _testRunStats.totals );
11760 stream <<
'\n' << std::endl;
11761 StreamingReporterBase::testRunEnded( _testRunStats );
11764 CompactReporter::~CompactReporter() {}
11766 CATCH_REGISTER_REPORTER(
"compact", CompactReporter )
11775#if defined(_MSC_VER)
11776#pragma warning(push)
11777#pragma warning(disable:4061)
11787class ConsoleAssertionPrinter {
11789 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter
const&) =
delete;
11790 ConsoleAssertionPrinter(ConsoleAssertionPrinter
const&) =
delete;
11791 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
11794 result(_stats.assertionResult),
11795 colour(Colour::None),
11796 message(result.getMessage()),
11797 messages(_stats.infoMessages),
11798 printInfoMessages(_printInfoMessages) {
11799 switch (result.getResultType()) {
11801 colour = Colour::Success;
11802 passOrFail =
"PASSED";
11804 if (_stats.infoMessages.size() == 1)
11805 messageLabel =
"with message";
11806 if (_stats.infoMessages.size() > 1)
11807 messageLabel =
"with messages";
11810 if (result.isOk()) {
11811 colour = Colour::Success;
11812 passOrFail =
"FAILED - but was ok";
11815 passOrFail =
"FAILED";
11817 if (_stats.infoMessages.size() == 1)
11818 messageLabel =
"with message";
11819 if (_stats.infoMessages.size() > 1)
11820 messageLabel =
"with messages";
11824 passOrFail =
"FAILED";
11825 messageLabel =
"due to unexpected exception with ";
11826 if (_stats.infoMessages.size() == 1)
11827 messageLabel += "message";
11828 if (_stats.infoMessages.size() > 1)
11829 messageLabel += "messages";
11833 passOrFail =
"FAILED";
11834 messageLabel =
"due to a fatal error condition";
11838 passOrFail =
"FAILED";
11839 messageLabel =
"because no exception was thrown where one was expected";
11842 messageLabel =
"info";
11845 messageLabel =
"warning";
11848 passOrFail =
"FAILED";
11850 if (_stats.infoMessages.size() == 1)
11851 messageLabel =
"explicitly with message";
11852 if (_stats.infoMessages.size() > 1)
11853 messageLabel =
"explicitly with messages";
11859 passOrFail =
"** internal error **";
11865 void print()
const {
11867 if (stats.totals.assertions.total() > 0) {
11871 printOriginalExpression();
11872 printReconstructedExpression();
11880 void printResultType()
const {
11881 if (!passOrFail.empty()) {
11882 Colour colourGuard(colour);
11883 stream << passOrFail <<
":\n";
11886 void printOriginalExpression()
const {
11887 if (result.hasExpression()) {
11888 Colour colourGuard(Colour::OriginalExpression);
11890 stream << result.getExpressionInMacro();
11894 void printReconstructedExpression()
const {
11895 if (result.hasExpandedExpression()) {
11896 stream <<
"with expansion:\n";
11897 Colour colourGuard(Colour::ReconstructedExpression);
11898 stream << Column(result.getExpandedExpression()).indent(2) <<
'\n';
11901 void printMessage()
const {
11902 if (!messageLabel.empty())
11903 stream << messageLabel <<
':' <<
'\n';
11904 for (
auto const& msg : messages) {
11907 stream << Column(msg.message).indent(2) <<
'\n';
11910 void printSourceInfo()
const {
11911 Colour colourGuard(Colour::FileName);
11912 stream << result.getSourceInfo() <<
": ";
11915 std::ostream& stream;
11916 AssertionStats
const& stats;
11917 AssertionResult
const& result;
11918 Colour::Code colour;
11922 std::vector<MessageInfo> messages;
11923 bool printInfoMessages;
11926std::size_t makeRatio(std::size_t number, std::size_t total) {
11927 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH *
number / total : 0;
11928 return (ratio == 0 && number > 0) ? 1 : ratio;
11931std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {
11932 if (i > j && i > k)
11941 enum Justification { Left, Right };
11944 Justification justification;
11946struct ColumnBreak {};
11958 static const uint64_t s_nanosecondsInAMicrosecond = 1000;
11959 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
11960 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
11961 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
11963 uint64_t m_inNanoseconds;
11967 explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
11968 : m_inNanoseconds(inNanoseconds),
11970 if (m_units == Unit::Auto) {
11971 if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
11972 m_units = Unit::Nanoseconds;
11973 else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
11974 m_units = Unit::Microseconds;
11975 else if (m_inNanoseconds < s_nanosecondsInASecond)
11976 m_units = Unit::Milliseconds;
11977 else if (m_inNanoseconds < s_nanosecondsInAMinute)
11978 m_units = Unit::Seconds;
11980 m_units = Unit::Minutes;
11985 auto value() const ->
double {
11987 case Unit::Microseconds:
11988 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMicrosecond);
11989 case Unit::Milliseconds:
11990 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMillisecond);
11991 case Unit::Seconds:
11992 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInASecond);
11993 case Unit::Minutes:
11994 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMinute);
11996 return static_cast<double>(m_inNanoseconds);
11999 auto unitsAsString() const -> std::
string {
12001 case Unit::Nanoseconds:
12003 case Unit::Microseconds:
12005 case Unit::Milliseconds:
12007 case Unit::Seconds:
12009 case Unit::Minutes:
12012 return "** internal error **";
12016 friend auto operator << (std::ostream& os, Duration
const& duration) -> std::ostream& {
12017 return os << duration.value() <<
" " << duration.unitsAsString();
12022class TablePrinter {
12023 std::ostream& m_os;
12024 std::vector<ColumnInfo> m_columnInfos;
12025 std::ostringstream m_oss;
12026 int m_currentColumn = -1;
12027 bool m_isOpen =
false;
12030 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
12032 m_columnInfos( std::move( columnInfos ) ) {}
12034 auto columnInfos() const -> std::vector<ColumnInfo> const& {
12035 return m_columnInfos;
12041 *
this << RowBreak();
12042 for (
auto const& info : m_columnInfos)
12043 *
this << info.name << ColumnBreak();
12044 *
this << RowBreak();
12045 m_os << Catch::getLineOfChars<
'-'>() <<
"\n";
12050 *
this << RowBreak();
12056 template<
typename T>
12062 friend TablePrinter&
operator << (TablePrinter& tp, ColumnBreak) {
12063 auto colStr = tp.m_oss.str();
12068 if (tp.m_currentColumn ==
static_cast<int>(tp.m_columnInfos.size() - 1)) {
12069 tp.m_currentColumn = -1;
12072 tp.m_currentColumn++;
12074 auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
12075 auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width))
12076 ? std::string(colInfo.width - (strSize + 2), ' ')
12078 if (colInfo.justification == ColumnInfo::Left)
12079 tp.m_os << colStr << padding <<
" ";
12081 tp.m_os << padding << colStr <<
" ";
12085 friend TablePrinter&
operator << (TablePrinter& tp, RowBreak) {
12086 if (tp.m_currentColumn > 0) {
12088 tp.m_currentColumn = -1;
12094ConsoleReporter::ConsoleReporter(ReporterConfig
const& config)
12095 : StreamingReporterBase(config),
12096 m_tablePrinter(new TablePrinter(config.stream(),
12098 {
"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
12099 {
"iters", 8, ColumnInfo::Right },
12100 {
"elapsed ns", 14, ColumnInfo::Right },
12101 {
"average", 14, ColumnInfo::Right }
12103ConsoleReporter::~ConsoleReporter() =
default;
12106 return "Reports test results as plain lines of text";
12109void ConsoleReporter::noMatchingTestCases(
std::string const& spec) {
12110 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
12113void ConsoleReporter::assertionStarting(AssertionInfo
const&) {}
12115bool ConsoleReporter::assertionEnded(AssertionStats
const& _assertionStats) {
12116 AssertionResult
const& result = _assertionStats.assertionResult;
12118 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
12126 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
12128 stream << std::endl;
12132void ConsoleReporter::sectionStarting(SectionInfo
const& _sectionInfo) {
12133 m_headerPrinted =
false;
12134 StreamingReporterBase::sectionStarting(_sectionInfo);
12136void ConsoleReporter::sectionEnded(SectionStats
const& _sectionStats) {
12137 m_tablePrinter->close();
12138 if (_sectionStats.missingAssertions) {
12140 Colour colour(Colour::ResultError);
12141 if (m_sectionStack.size() > 1)
12142 stream <<
"\nNo assertions in section";
12144 stream <<
"\nNo assertions in test case";
12145 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" << std::endl;
12147 if (m_config->showDurations() == ShowDurations::Always) {
12148 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name << std::endl;
12150 if (m_headerPrinted) {
12151 m_headerPrinted =
false;
12153 StreamingReporterBase::sectionEnded(_sectionStats);
12156void ConsoleReporter::benchmarkStarting(BenchmarkInfo
const& info) {
12157 lazyPrintWithoutClosingBenchmarkTable();
12159 auto nameCol = Column( info.name ).width(
static_cast<std::size_t
>( m_tablePrinter->columnInfos()[0].width - 2 ) );
12161 bool firstLine =
true;
12162 for (
auto line : nameCol) {
12164 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
12168 (*m_tablePrinter) << line << ColumnBreak();
12171void ConsoleReporter::benchmarkEnded(BenchmarkStats
const& stats) {
12172 Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
12174 << stats.iterations << ColumnBreak()
12175 << stats.elapsedTimeInNanoseconds << ColumnBreak()
12176 << average << ColumnBreak();
12179void ConsoleReporter::testCaseEnded(TestCaseStats
const& _testCaseStats) {
12180 m_tablePrinter->close();
12181 StreamingReporterBase::testCaseEnded(_testCaseStats);
12182 m_headerPrinted =
false;
12184void ConsoleReporter::testGroupEnded(TestGroupStats
const& _testGroupStats) {
12185 if (currentGroupInfo.used) {
12186 printSummaryDivider();
12187 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
12188 printTotals(_testGroupStats.totals);
12189 stream <<
'\n' << std::endl;
12191 StreamingReporterBase::testGroupEnded(_testGroupStats);
12193void ConsoleReporter::testRunEnded(TestRunStats
const& _testRunStats) {
12194 printTotalsDivider(_testRunStats.totals);
12195 printTotals(_testRunStats.totals);
12196 stream << std::endl;
12197 StreamingReporterBase::testRunEnded(_testRunStats);
12200void ConsoleReporter::lazyPrint() {
12202 m_tablePrinter->close();
12203 lazyPrintWithoutClosingBenchmarkTable();
12206void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
12208 if (!currentTestRunInfo.used)
12209 lazyPrintRunInfo();
12210 if (!currentGroupInfo.used)
12211 lazyPrintGroupInfo();
12213 if (!m_headerPrinted) {
12214 printTestCaseAndSectionHeader();
12215 m_headerPrinted =
true;
12218void ConsoleReporter::lazyPrintRunInfo() {
12219 stream << '\n' << getLineOfChars<'~'>() <<
'\n';
12220 Colour colour(Colour::SecondaryText);
12221 stream << currentTestRunInfo->name
12222 <<
" is a Catch v" << libraryVersion() <<
" host application.\n"
12223 <<
"Run with -? for options\n\n";
12225 if (m_config->rngSeed() != 0)
12226 stream <<
"Randomness seeded to: " << m_config->rngSeed() <<
"\n\n";
12228 currentTestRunInfo.used =
true;
12230void ConsoleReporter::lazyPrintGroupInfo() {
12231 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
12232 printClosedHeader(
"Group: " + currentGroupInfo->name);
12233 currentGroupInfo.used =
true;
12236void ConsoleReporter::printTestCaseAndSectionHeader() {
12237 assert(!m_sectionStack.empty());
12238 printOpenHeader(currentTestCaseInfo->name);
12240 if (m_sectionStack.size() > 1) {
12241 Colour colourGuard(Colour::Headers);
12244 it = m_sectionStack.begin() + 1,
12245 itEnd = m_sectionStack.
end();
12246 for (; it != itEnd; ++it)
12247 printHeaderString(it->
name, 2);
12250 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
12252 if (!lineInfo.empty()) {
12253 stream << getLineOfChars<
'-'>() <<
'\n';
12254 Colour colourGuard(Colour::FileName);
12255 stream << lineInfo <<
'\n';
12257 stream << getLineOfChars<'.'>() <<
'\n' << std::endl;
12260void ConsoleReporter::printClosedHeader(
std::string const& _name) {
12261 printOpenHeader(_name);
12262 stream << getLineOfChars<
'.'>() <<
'\n';
12264void ConsoleReporter::printOpenHeader(
std::string const& _name) {
12265 stream << getLineOfChars<
'-'>() <<
'\n';
12267 Colour colourGuard(Colour::Headers);
12268 printHeaderString(_name);
12274void ConsoleReporter::printHeaderString(
std::string const& _string, std::size_t indent) {
12275 std::size_t i = _string.find(
": ");
12276 if (i != std::string::npos)
12280 stream << Column(_string).indent(indent + i).initialIndent(indent) <<
'\n';
12283struct SummaryColumn {
12285 SummaryColumn(
std::string _label, Colour::Code _colour )
12286 : label( std::move( _label ) ),
12287 colour( _colour ) {}
12288 SummaryColumn addRow( std::size_t
count ) {
12289 ReusableStringStream rss;
12292 for (
auto& oldRow : rows) {
12293 while (oldRow.size() < row.size())
12294 oldRow =
' ' + oldRow;
12295 while (oldRow.size() > row.size())
12298 rows.push_back(row);
12303 Colour::Code colour;
12304 std::vector<std::string> rows;
12308void ConsoleReporter::printTotals( Totals
const& totals ) {
12309 if (totals.testCases.total() == 0) {
12311 }
else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {
12312 stream << Colour(Colour::ResultSuccess) <<
"All tests passed";
12314 << pluralise(totals.assertions.passed,
"assertion") <<
" in "
12315 << pluralise(totals.testCases.passed,
"test case") <<
')'
12319 std::vector<SummaryColumn> columns;
12320 columns.push_back(SummaryColumn(
"", Colour::None)
12321 .addRow(totals.testCases.total())
12322 .addRow(totals.assertions.total()));
12323 columns.push_back(SummaryColumn(
"passed", Colour::Success)
12324 .addRow(totals.testCases.passed)
12325 .addRow(totals.assertions.passed));
12326 columns.push_back(SummaryColumn(
"failed", Colour::ResultError)
12327 .addRow(totals.testCases.failed)
12328 .addRow(totals.assertions.failed));
12329 columns.push_back(SummaryColumn(
"failed as expected", Colour::ResultExpectedFailure)
12330 .addRow(totals.testCases.failedButOk)
12331 .addRow(totals.assertions.failedButOk));
12333 printSummaryRow(
"test cases", columns, 0);
12334 printSummaryRow(
"assertions", columns, 1);
12337void ConsoleReporter::printSummaryRow(
std::string const& label, std::vector<SummaryColumn>
const& cols, std::size_t row) {
12338 for (
auto col : cols) {
12340 if (col.label.empty()) {
12341 stream << label <<
": ";
12346 }
else if (
value !=
"0") {
12347 stream << Colour(Colour::LightGrey) <<
" | ";
12348 stream << Colour(col.colour)
12349 <<
value <<
' ' << col.label;
12355void ConsoleReporter::printTotalsDivider(Totals
const& totals) {
12356 if (totals.testCases.total() > 0) {
12357 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
12358 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
12359 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
12360 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
12361 findMax(failedRatio, failedButOkRatio, passedRatio)++;
12362 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
12363 findMax(failedRatio, failedButOkRatio, passedRatio)--;
12366 stream << Colour(Colour::ResultExpectedFailure) <<
std::string(failedButOkRatio,
'=');
12367 if (totals.testCases.allPassed())
12368 stream << Colour(Colour::ResultSuccess) <<
std::string(passedRatio,
'=');
12370 stream << Colour(Colour::Success) <<
std::string(passedRatio,
'=');
12376void ConsoleReporter::printSummaryDivider() {
12377 stream << getLineOfChars<
'-'>() <<
'\n';
12380CATCH_REGISTER_REPORTER(
"console", ConsoleReporter)
12384#if defined(_MSC_VER)
12385#pragma warning(pop)
12393#include <algorithm>
12402 std::time(&rawtime);
12403 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
12406 std::tm timeInfo = {};
12407 gmtime_s(&timeInfo, &rawtime);
12410 timeInfo = std::gmtime(&rawtime);
12413 char timeStamp[timeStampSize];
12414 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
12417 std::strftime(timeStamp, timeStampSize,
fmt, &timeInfo);
12419 std::strftime(timeStamp, timeStampSize,
fmt, timeInfo);
12424 std::string fileNameTag(
const std::vector<std::string> &tags) {
12425 auto it = std::find_if(
begin(tags),
12427 [] (
std::string const& tag) {
return tag.front() ==
'#'; });
12428 if (it != tags.end())
12429 return it->substr(1);
12434 JunitReporter::JunitReporter( ReporterConfig
const& _config )
12435 : CumulativeReporterBase( _config ),
12436 xml( _config.stream() )
12438 m_reporterPrefs.shouldRedirectStdOut =
true;
12441 JunitReporter::~JunitReporter() {}
12444 return "Reports test results in an XML format that looks like Ant's junitreport target";
12447 void JunitReporter::noMatchingTestCases(
std::string const& ) {}
12449 void JunitReporter::testRunStarting( TestRunInfo
const& runInfo ) {
12450 CumulativeReporterBase::testRunStarting( runInfo );
12451 xml.startElement(
"testsuites" );
12454 void JunitReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
12455 suiteTimer.start();
12456 stdOutForSuite.clear();
12457 stdErrForSuite.clear();
12458 unexpectedExceptions = 0;
12459 CumulativeReporterBase::testGroupStarting( groupInfo );
12462 void JunitReporter::testCaseStarting( TestCaseInfo
const& testCaseInfo ) {
12463 m_okToFail = testCaseInfo.okToFail();
12466 bool JunitReporter::assertionEnded( AssertionStats
const& assertionStats ) {
12468 unexpectedExceptions++;
12469 return CumulativeReporterBase::assertionEnded( assertionStats );
12472 void JunitReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
12473 stdOutForSuite += testCaseStats.stdOut;
12474 stdErrForSuite += testCaseStats.stdErr;
12475 CumulativeReporterBase::testCaseEnded( testCaseStats );
12478 void JunitReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
12479 double suiteTime = suiteTimer.getElapsedSeconds();
12480 CumulativeReporterBase::testGroupEnded( testGroupStats );
12481 writeGroup( *m_testGroups.back(), suiteTime );
12484 void JunitReporter::testRunEndedCumulative() {
12488 void JunitReporter::writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
12489 XmlWriter::ScopedElement
e = xml.scopedElement(
"testsuite" );
12490 TestGroupStats
const& stats = groupNode.value;
12491 xml.writeAttribute(
"name", stats.groupInfo.name );
12492 xml.writeAttribute(
"errors", unexpectedExceptions );
12493 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
12494 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
12495 xml.writeAttribute(
"hostname",
"tbd" );
12496 if( m_config->showDurations() == ShowDurations::Never )
12497 xml.writeAttribute(
"time",
"" );
12499 xml.writeAttribute(
"time", suiteTime );
12500 xml.writeAttribute(
"timestamp", getCurrentTimestamp() );
12503 for(
auto const& child : groupNode.children )
12504 writeTestCase( *child );
12506 xml.scopedElement(
"system-out" ).writeText(
trim( stdOutForSuite ),
false );
12507 xml.scopedElement(
"system-err" ).writeText(
trim( stdErrForSuite ),
false );
12510 void JunitReporter::writeTestCase( TestCaseNode
const& testCaseNode ) {
12511 TestCaseStats
const& stats = testCaseNode.value;
12515 assert( testCaseNode.children.size() == 1 );
12516 SectionNode
const& rootSection = *testCaseNode.children.front();
12518 std::string className = stats.testInfo.className;
12520 if( className.empty() ) {
12521 className = fileNameTag(stats.testInfo.tags);
12522 if ( className.empty() )
12523 className =
"global";
12526 if ( !m_config->name().empty() )
12527 className = m_config->name() + "." + className;
12529 writeSection( className,
"", rootSection );
12532 void JunitReporter::writeSection(
std::string const& className,
12534 SectionNode
const& sectionNode ) {
12536 if( !rootName.empty() )
12539 if( !sectionNode.assertions.empty() ||
12540 !sectionNode.stdOut.empty() ||
12541 !sectionNode.stdErr.empty() ) {
12542 XmlWriter::ScopedElement
e = xml.scopedElement(
"testcase" );
12543 if( className.empty() ) {
12544 xml.writeAttribute(
"classname",
name );
12545 xml.writeAttribute(
"name",
"root" );
12548 xml.writeAttribute(
"classname", className );
12549 xml.writeAttribute(
"name",
name );
12553 writeAssertions( sectionNode );
12555 if( !sectionNode.stdOut.empty() )
12556 xml.scopedElement(
"system-out" ).writeText(
trim( sectionNode.stdOut ),
false );
12557 if( !sectionNode.stdErr.empty() )
12558 xml.scopedElement(
"system-err" ).writeText(
trim( sectionNode.stdErr ),
false );
12560 for(
auto const& childNode : sectionNode.childSections )
12561 if( className.empty() )
12562 writeSection(
name,
"", *childNode );
12564 writeSection( className,
name, *childNode );
12567 void JunitReporter::writeAssertions( SectionNode
const& sectionNode ) {
12568 for(
auto const& assertion : sectionNode.assertions )
12569 writeAssertion( assertion );
12572 void JunitReporter::writeAssertion( AssertionStats
const& stats ) {
12573 AssertionResult
const& result = stats.assertionResult;
12574 if( !result.isOk() ) {
12576 switch( result.getResultType() ) {
12579 elementName =
"error";
12582 elementName =
"failure";
12585 elementName =
"failure";
12588 elementName =
"failure";
12598 elementName =
"internalError";
12602 XmlWriter::ScopedElement
e = xml.scopedElement( elementName );
12604 xml.writeAttribute(
"message", result.getExpandedExpression() );
12605 xml.writeAttribute(
"type", result.getTestMacroName() );
12607 ReusableStringStream rss;
12608 if( !result.getMessage().empty() )
12609 rss << result.getMessage() <<
'\n';
12610 for(
auto const& msg : stats.infoMessages )
12612 rss << msg.message <<
'\n';
12614 rss <<
"at " << result.getSourceInfo();
12615 xml.writeText( rss.str(),
false );
12619 CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
12629 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
12630 m_listeners.push_back( std::move( listener ) );
12633 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
12634 assert(!m_reporter &&
"Listening reporter can wrap only 1 real reporter");
12635 m_reporter = std::move( reporter );
12638 ReporterPreferences ListeningReporter::getPreferences()
const {
12639 return m_reporter->getPreferences();
12642 std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
12643 return std::set<Verbosity>{ };
12646 void ListeningReporter::noMatchingTestCases(
std::string const& spec ) {
12647 for (
auto const& listener : m_listeners ) {
12648 listener->noMatchingTestCases( spec );
12650 m_reporter->noMatchingTestCases( spec );
12653 void ListeningReporter::benchmarkStarting( BenchmarkInfo
const& benchmarkInfo ) {
12654 for (
auto const& listener : m_listeners ) {
12655 listener->benchmarkStarting( benchmarkInfo );
12657 m_reporter->benchmarkStarting( benchmarkInfo );
12659 void ListeningReporter::benchmarkEnded( BenchmarkStats
const& benchmarkStats ) {
12660 for (
auto const& listener : m_listeners ) {
12661 listener->benchmarkEnded( benchmarkStats );
12663 m_reporter->benchmarkEnded( benchmarkStats );
12666 void ListeningReporter::testRunStarting( TestRunInfo
const& testRunInfo ) {
12667 for (
auto const& listener : m_listeners ) {
12668 listener->testRunStarting( testRunInfo );
12670 m_reporter->testRunStarting( testRunInfo );
12673 void ListeningReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
12674 for (
auto const& listener : m_listeners ) {
12675 listener->testGroupStarting( groupInfo );
12677 m_reporter->testGroupStarting( groupInfo );
12680 void ListeningReporter::testCaseStarting( TestCaseInfo
const& testInfo ) {
12681 for (
auto const& listener : m_listeners ) {
12682 listener->testCaseStarting( testInfo );
12684 m_reporter->testCaseStarting( testInfo );
12687 void ListeningReporter::sectionStarting( SectionInfo
const& sectionInfo ) {
12688 for (
auto const& listener : m_listeners ) {
12689 listener->sectionStarting( sectionInfo );
12691 m_reporter->sectionStarting( sectionInfo );
12694 void ListeningReporter::assertionStarting( AssertionInfo
const& assertionInfo ) {
12695 for (
auto const& listener : m_listeners ) {
12696 listener->assertionStarting( assertionInfo );
12698 m_reporter->assertionStarting( assertionInfo );
12702 bool ListeningReporter::assertionEnded( AssertionStats
const& assertionStats ) {
12703 for(
auto const& listener : m_listeners ) {
12704 static_cast<void>( listener->assertionEnded( assertionStats ) );
12706 return m_reporter->assertionEnded( assertionStats );
12709 void ListeningReporter::sectionEnded( SectionStats
const& sectionStats ) {
12710 for (
auto const& listener : m_listeners ) {
12711 listener->sectionEnded( sectionStats );
12713 m_reporter->sectionEnded( sectionStats );
12716 void ListeningReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
12717 for (
auto const& listener : m_listeners ) {
12718 listener->testCaseEnded( testCaseStats );
12720 m_reporter->testCaseEnded( testCaseStats );
12723 void ListeningReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
12724 for (
auto const& listener : m_listeners ) {
12725 listener->testGroupEnded( testGroupStats );
12727 m_reporter->testGroupEnded( testGroupStats );
12730 void ListeningReporter::testRunEnded( TestRunStats
const& testRunStats ) {
12731 for (
auto const& listener : m_listeners ) {
12732 listener->testRunEnded( testRunStats );
12734 m_reporter->testRunEnded( testRunStats );
12737 void ListeningReporter::skipTest( TestCaseInfo
const& testInfo ) {
12738 for (
auto const& listener : m_listeners ) {
12739 listener->skipTest( testInfo );
12741 m_reporter->skipTest( testInfo );
12744 bool ListeningReporter::isMulti()
const {
12752#if defined(_MSC_VER)
12753#pragma warning(push)
12754#pragma warning(disable:4061)
12760 XmlReporter::XmlReporter( ReporterConfig
const& _config )
12761 : StreamingReporterBase( _config ),
12762 m_xml(_config.stream())
12764 m_reporterPrefs.shouldRedirectStdOut =
true;
12767 XmlReporter::~XmlReporter() =
default;
12770 return "Reports test results as an XML document";
12773 std::string XmlReporter::getStylesheetRef()
const {
12777 void XmlReporter::writeSourceInfo( SourceLineInfo
const& sourceInfo ) {
12779 .writeAttribute(
"filename", sourceInfo.file )
12780 .writeAttribute(
"line", sourceInfo.line );
12783 void XmlReporter::noMatchingTestCases(
std::string const& s ) {
12784 StreamingReporterBase::noMatchingTestCases( s );
12787 void XmlReporter::testRunStarting( TestRunInfo
const& testInfo ) {
12788 StreamingReporterBase::testRunStarting( testInfo );
12790 if( !stylesheetRef.empty() )
12791 m_xml.writeStylesheetRef( stylesheetRef );
12792 m_xml.startElement(
"Catch" );
12793 if( !m_config->name().empty() )
12794 m_xml.writeAttribute(
"name", m_config->name() );
12797 void XmlReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
12798 StreamingReporterBase::testGroupStarting( groupInfo );
12799 m_xml.startElement(
"Group" )
12800 .writeAttribute(
"name", groupInfo.name );
12803 void XmlReporter::testCaseStarting( TestCaseInfo
const& testInfo ) {
12804 StreamingReporterBase::testCaseStarting(testInfo);
12805 m_xml.startElement(
"TestCase" )
12806 .writeAttribute(
"name",
trim( testInfo.name ) )
12807 .writeAttribute(
"description", testInfo.description )
12808 .writeAttribute(
"tags", testInfo.tagsAsString() );
12810 writeSourceInfo( testInfo.lineInfo );
12812 if ( m_config->showDurations() == ShowDurations::Always )
12813 m_testCaseTimer.start();
12814 m_xml.ensureTagClosed();
12817 void XmlReporter::sectionStarting( SectionInfo
const& sectionInfo ) {
12818 StreamingReporterBase::sectionStarting( sectionInfo );
12819 if( m_sectionDepth++ > 0 ) {
12820 m_xml.startElement(
"Section" )
12821 .writeAttribute(
"name",
trim( sectionInfo.name ) )
12822 .writeAttribute(
"description", sectionInfo.description );
12823 writeSourceInfo( sectionInfo.lineInfo );
12824 m_xml.ensureTagClosed();
12828 void XmlReporter::assertionStarting( AssertionInfo
const& ) { }
12830 bool XmlReporter::assertionEnded( AssertionStats
const& assertionStats ) {
12832 AssertionResult
const& result = assertionStats.assertionResult;
12834 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
12838 for(
auto const& msg : assertionStats.infoMessages ) {
12840 m_xml.scopedElement(
"Info" )
12841 .writeText( msg.message );
12843 m_xml.scopedElement(
"Warning" )
12844 .writeText( msg.message );
12854 if( result.hasExpression() ) {
12855 m_xml.startElement(
"Expression" )
12856 .writeAttribute(
"success", result.succeeded() )
12857 .writeAttribute(
"type", result.getTestMacroName() );
12859 writeSourceInfo( result.getSourceInfo() );
12861 m_xml.scopedElement(
"Original" )
12862 .writeText( result.getExpression() );
12863 m_xml.scopedElement(
"Expanded" )
12864 .writeText( result.getExpandedExpression() );
12868 switch( result.getResultType() ) {
12870 m_xml.startElement(
"Exception" );
12871 writeSourceInfo( result.getSourceInfo() );
12872 m_xml.writeText( result.getMessage() );
12873 m_xml.endElement();
12876 m_xml.startElement(
"FatalErrorCondition" );
12877 writeSourceInfo( result.getSourceInfo() );
12878 m_xml.writeText( result.getMessage() );
12879 m_xml.endElement();
12882 m_xml.scopedElement(
"Info" )
12883 .writeText( result.getMessage() );
12889 m_xml.startElement(
"Failure" );
12890 writeSourceInfo( result.getSourceInfo() );
12891 m_xml.writeText( result.getMessage() );
12892 m_xml.endElement();
12898 if( result.hasExpression() )
12899 m_xml.endElement();
12904 void XmlReporter::sectionEnded( SectionStats
const& sectionStats ) {
12905 StreamingReporterBase::sectionEnded( sectionStats );
12906 if( --m_sectionDepth > 0 ) {
12907 XmlWriter::ScopedElement
e = m_xml.scopedElement(
"OverallResults" );
12908 e.writeAttribute(
"successes", sectionStats.assertions.passed );
12909 e.writeAttribute(
"failures", sectionStats.assertions.failed );
12910 e.writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
12912 if ( m_config->showDurations() == ShowDurations::Always )
12913 e.writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
12915 m_xml.endElement();
12919 void XmlReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
12920 StreamingReporterBase::testCaseEnded( testCaseStats );
12921 XmlWriter::ScopedElement
e = m_xml.scopedElement(
"OverallResult" );
12922 e.writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
12924 if ( m_config->showDurations() == ShowDurations::Always )
12925 e.writeAttribute(
"durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
12927 if( !testCaseStats.stdOut.empty() )
12928 m_xml.scopedElement(
"StdOut" ).writeText(
trim( testCaseStats.stdOut ),
false );
12929 if( !testCaseStats.stdErr.empty() )
12930 m_xml.scopedElement(
"StdErr" ).writeText(
trim( testCaseStats.stdErr ),
false );
12932 m_xml.endElement();
12935 void XmlReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
12936 StreamingReporterBase::testGroupEnded( testGroupStats );
12938 m_xml.scopedElement(
"OverallResults" )
12939 .writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
12940 .writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
12941 .writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
12942 m_xml.endElement();
12945 void XmlReporter::testRunEnded( TestRunStats
const& testRunStats ) {
12946 StreamingReporterBase::testRunEnded( testRunStats );
12947 m_xml.scopedElement(
"OverallResults" )
12948 .writeAttribute(
"successes", testRunStats.totals.assertions.passed )
12949 .writeAttribute(
"failures", testRunStats.totals.assertions.failed )
12950 .writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
12951 m_xml.endElement();
12954 CATCH_REGISTER_REPORTER(
"xml", XmlReporter )
12958#if defined(_MSC_VER)
12959#pragma warning(pop)
12964 LeakDetector leakDetector;
12968#pragma clang diagnostic pop
12974#ifdef CATCH_CONFIG_MAIN
12979#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
12981extern "C" int wmain (
int argc,
wchar_t * argv[],
wchar_t * []) {
12984int main (
int argc,
char * argv[]) {
12987 return Catch::Session().run( argc, argv );
12993int main (
int argc,
char *
const argv[]) {
12994#if !CATCH_ARC_ENABLED
12995 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
12998 Catch::registerTestMethods();
12999 int result = Catch::Session().run( argc, (
char**)argv );
13001#if !CATCH_ARC_ENABLED
13013#if !defined(CATCH_CONFIG_IMPL_ONLY)
13015#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
13016# undef CLARA_CONFIG_MAIN
13019#if !defined(CATCH_CONFIG_DISABLE)
13022#ifdef CATCH_CONFIG_PREFIX_ALL
13024#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
13025#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
13027#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ )
13028#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
13029#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
13030#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13031#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
13033#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
13035#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13036#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
13037#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13038#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13039#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
13041#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ )
13042#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
13043#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
13044#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13045#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
13047#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13049#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13050#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
13052#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
13055#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
13056#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
13057#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
13059#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
13060#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
13061#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
13062#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
13063#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
13064#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
13065#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13066#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13068#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
13071#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
13072#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
13073#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc )
13074#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc )
13075#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
13076#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc )
13077#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
13082#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
13083#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
13085#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
13086#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
13087#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
13088#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13089#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
13091#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
13093#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13094#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
13095#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13096#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13097#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
13099#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13100#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
13101#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
13102#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13103#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
13105#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13107#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13108#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
13110#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
13113#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
13114#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
13115#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
13117#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
13118#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
13119#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
13120#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
13121#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
13122#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
13123#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13124#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13125#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
13129#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
13132#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
13133#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
13135#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc )
13136#define WHEN( desc ) SECTION( std::string(" When: ") + desc )
13137#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc )
13138#define THEN( desc ) SECTION( std::string(" Then: ") + desc )
13139#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc )
13146#ifdef CATCH_CONFIG_PREFIX_ALL
13148#define CATCH_REQUIRE( ... ) (void)(0)
13149#define CATCH_REQUIRE_FALSE( ... ) (void)(0)
13151#define CATCH_REQUIRE_THROWS( ... ) (void)(0)
13152#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
13153#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
13154#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13155#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
13157#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
13159#define CATCH_CHECK( ... ) (void)(0)
13160#define CATCH_CHECK_FALSE( ... ) (void)(0)
13161#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__)
13162#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
13163#define CATCH_CHECK_NOFAIL( ... ) (void)(0)
13165#define CATCH_CHECK_THROWS( ... ) (void)(0)
13166#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
13167#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0)
13168#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13169#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
13171#define CATCH_CHECK_NOTHROW( ... ) (void)(0)
13173#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13174#define CATCH_CHECK_THAT( arg, matcher ) (void)(0)
13176#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
13179#define CATCH_INFO( msg ) (void)(0)
13180#define CATCH_WARN( msg ) (void)(0)
13181#define CATCH_CAPTURE( msg ) (void)(0)
13183#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13184#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13185#define CATCH_METHOD_AS_TEST_CASE( method, ... )
13186#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
13187#define CATCH_SECTION( ... )
13188#define CATCH_FAIL( ... ) (void)(0)
13189#define CATCH_FAIL_CHECK( ... ) (void)(0)
13190#define CATCH_SUCCEED( ... ) (void)(0)
13192#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13195#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13196#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 )
13197#define CATCH_GIVEN( desc )
13198#define CATCH_WHEN( desc )
13199#define CATCH_AND_WHEN( desc )
13200#define CATCH_THEN( desc )
13201#define CATCH_AND_THEN( desc )
13206#define REQUIRE( ... ) (void)(0)
13207#define REQUIRE_FALSE( ... ) (void)(0)
13209#define REQUIRE_THROWS( ... ) (void)(0)
13210#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
13211#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
13212#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13213#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
13215#define REQUIRE_NOTHROW( ... ) (void)(0)
13217#define CHECK( ... ) (void)(0)
13218#define CHECK_FALSE( ... ) (void)(0)
13219#define CHECKED_IF( ... ) if (__VA_ARGS__)
13220#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
13221#define CHECK_NOFAIL( ... ) (void)(0)
13223#define CHECK_THROWS( ... ) (void)(0)
13224#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
13225#define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
13226#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13227#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
13229#define CHECK_NOTHROW( ... ) (void)(0)
13231#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13232#define CHECK_THAT( arg, matcher ) (void)(0)
13234#define REQUIRE_THAT( arg, matcher ) (void)(0)
13237#define INFO( msg ) (void)(0)
13238#define WARN( msg ) (void)(0)
13239#define CAPTURE( msg ) (void)(0)
13241#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13242#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13243#define METHOD_AS_TEST_CASE( method, ... )
13244#define REGISTER_TEST_CASE( Function, ... ) (void)(0)
13245#define SECTION( ... )
13246#define FAIL( ... ) (void)(0)
13247#define FAIL_CHECK( ... ) (void)(0)
13248#define SUCCEED( ... ) (void)(0)
13249#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13253#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
13256#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )
13257#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
13259#define GIVEN( desc )
13260#define WHEN( desc )
13261#define AND_WHEN( desc )
13262#define THEN( desc )
13263#define AND_THEN( desc )
13276# pragma warning(pop)
13278# pragma clang diagnostic pop
13280#elif defined __GNUC__
13281# pragma GCC diagnostic pop
const char *const const double number
Definition: cJSON.h:262
char const int length
Definition: cJSON.h:161
const cJSON *const b
Definition: cJSON.h:251
const char *const name
Definition: cJSON.h:258
int index
Definition: cJSON.h:168
int which
Definition: cJSON.h:230
int cJSON_bool fmt
Definition: cJSON.h:158
cJSON * item
Definition: cJSON.h:218
int count
Definition: cJSON.h:212
const char *const string
Definition: cJSON.h:170
char * buffer
Definition: cJSON.h:161
std::ostream & operator<<(std::ostream &, Catch_global_namespace_dummy)
#define CATCH_INTERNAL_LINEINFO
Definition: catch.hpp:324
Definition: catch.hpp:1574
auto allowThrows() const -> bool
~AssertionHandler()
Definition: catch.hpp:1586
void handleExpr(ExprLhs< T > const &expr)
Definition: catch.hpp:1593
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)
Definition: catch.hpp:1928
void increment()
Definition: catch.hpp:1953
auto needsMoreIterations() -> bool
BenchmarkLooper(StringRef name)
Definition: catch.hpp:1939
Definition: catch.hpp:1348
BinaryExpr(bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs)
Definition: catch.hpp:1359
Definition: catch.hpp:2096
Approx & epsilon(T const &newEpsilon)
Definition: catch.hpp:2160
Approx & margin(T const &newMargin)
Definition: catch.hpp:2173
Approx & scale(T const &newScale)
Definition: catch.hpp:2187
std::string toString() const
Approx(T const &value)
Definition: catch.hpp:2115
Approx operator()(T const &value)
Definition: catch.hpp:2106
Definition: catch.hpp:778
static const bool value
Definition: catch.hpp:787
Definition: catch.hpp:2043
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
Definition: catch.hpp:2070
Definition: catch.hpp:1406
auto operator!=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1420
auto operator>=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1436
auto operator>(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1428
auto operator<=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1440
auto makeUnaryExpr() const -> UnaryExpr< LhsT >
Definition: catch.hpp:1444
ExprLhs(LhsT lhs)
Definition: catch.hpp:1409
auto operator==(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1412
auto operator<(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1432
Definition: catch.hpp:1552
LazyExpression & operator=(LazyExpression const &)=delete
LazyExpression(bool isNegated)
friend struct AssertionStats
Definition: catch.hpp:1554
friend auto operator<<(std::ostream &os, LazyExpression const &lazyExpr) -> std::ostream &
LazyExpression(LazyExpression const &other)
friend class RunContext
Definition: catch.hpp:1555
Definition: catch.hpp:2724
MatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef matcherString)
Definition: catch.hpp:2729
void streamReconstructedExpression(std::ostream &os) const override
Definition: catch.hpp:2736
Definition: catch.hpp:2445
bool match(T const &item) const override
Definition: catch.hpp:2455
PredicateMatcher(std::function< bool(T const &)> const &elem, std::string const &descr)
Definition: catch.hpp:2450
std::string describe() const override
Definition: catch.hpp:2459
Definition: catch.hpp:2254
std::string toString() const
virtual ~MatcherUntypedBase()
virtual std::string describe() const =0
std::string m_cachedToString
Definition: catch.hpp:2264
MatcherUntypedBase(MatcherUntypedBase const &)=default
MatcherUntypedBase()=default
Definition: catch.hpp:277
Definition: catch.hpp:685
auto str() const -> std::string
auto get() -> std::ostream &
Definition: catch.hpp:699
Definition: catch.hpp:1666
ScopedMessage(MessageBuilder const &builder)
MessageInfo m_info
Definition: catch.hpp:1671
Definition: catch.hpp:1898
Section(SectionInfo const &info)
Definition: catch.hpp:393
std::size_t size_type
Definition: catch.hpp:395
auto operator=(StringRef const &other) noexcept -> StringRef &
Definition: catch.hpp:443
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:414
StringRef(char const *rawChars, size_type size) noexcept
Definition: catch.hpp:429
~StringRef() noexcept
Definition: catch.hpp:439
StringRef(StringRef &&other) noexcept
Definition: catch.hpp:419
friend struct StringRefTestAccess
Definition: catch.hpp:398
auto operator[](size_type index) const noexcept -> char
auto numberOfCharacters() const noexcept -> size_type
StringRef(std::string const &stdString) noexcept
Definition: catch.hpp:434
void swap(StringRef &other) noexcept
StringRef() noexcept
Definition: catch.hpp:410
auto operator!=(StringRef const &other) const noexcept -> bool
auto operator==(StringRef const &other) const noexcept -> bool
auto empty() const noexcept -> bool
Definition: catch.hpp:462
auto size() const noexcept -> size_type
Definition: catch.hpp:465
StringRef(char const *rawChars) noexcept
auto currentData() const noexcept -> char const *
Definition: catch.hpp:2842
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)
Definition: catch.hpp:501
TestInvokerAsMethod(void(C::*testAsMethod)()) noexcept
Definition: catch.hpp:504
void invoke() const override
Definition: catch.hpp:506
Definition: catch.hpp:1881
auto getElapsedSeconds() const -> double
auto getElapsedNanoseconds() const -> uint64_t
Definition: catch.hpp:1368
UnaryExpr(LhsT lhs)
Definition: catch.hpp:1376
#define true
Definition: msvc_stdbool.h:18
#define false
Definition: msvc_stdbool.h:19
char bool
Definition: msvc_stdbool.h:17
std::string convertUnknownEnumToString(E e)
Definition: catch.hpp:863
std::string rawMemoryToString(const T &object)
Definition: catch.hpp:773
const std::string unprintableString
std::string rangeToString(InputIterator first, InputIterator last)
Definition: catch.hpp:1021
std::enable_if<!std::is_enum< T >::value &&!std::is_base_of< std::exception, T >::value, std::string >::type convertUnstreamable(T const &)
Definition: catch.hpp:796
std::string rawMemoryToString(const void *object, std::size_t size)
std::string stringify(const T &e)
Definition: catch.hpp:858
std::string finalizeDescription(const std::string &desc)
bool contains(InputIterator first, InputIterator last, T const &item)
Definition: catch.hpp:2568
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:2471
StdString::RegexMatcher Matches(std::string const ®ex, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Vector::EqualsMatcher< T > Equals(std::vector< T > const &comparator)
Definition: catch.hpp:2708
Vector::ContainsElementMatcher< T > VectorContains(T const &comparator)
Definition: catch.hpp:2703
Vector::ContainsMatcher< T > Contains(std::vector< T > const &comparator)
Definition: catch.hpp:2698
StdString::StartsWithMatcher StartsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff)
Vector::UnorderedEqualsMatcher< T > UnorderedEquals(std::vector< T > const &target)
Definition: catch.hpp:2713
StdString::EndsWithMatcher EndsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
StdString::EqualsMatcher Equals(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
T const & operator+(T const &value, StreamEndStop)
Definition: catch.hpp:319
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:2751
std::vector< TestCase > filterTests(std::vector< TestCase > const &testCases, TestSpec const &testSpec, IConfig const &config)
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)
IRegistryHub & getRegistryHub()
auto operator+(char const *lhs, StringRef const &rhs) -> std::string
std::vector< std::unique_ptr< IExceptionTranslator const > > ExceptionTranslators
Definition: catch.hpp:2030
bool shouldContinueOnFailure(int flags)
auto compareNotEqual(LhsT const &lhs, RhsT &&rhs) -> bool
Definition: catch.hpp:1395
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
bool isFalseTest(int flags)
Definition: catch.hpp:633
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)
Matchers::Impl::MatcherBase< std::string > StringMatcher
Definition: catch.hpp:2746
std::string toLower(std::string const &s)
auto getEstimatedClockResolution() -> uint64_t
std::shared_ptr< IReporterFactory > IReporterFactoryPtr
Definition: catch.hpp:1985
bool endsWith(std::string const &s, std::string const &suffix)
std::string translateActiveException()
std::string rangeToString(std::vector< bool, Allocator > const &v)
Definition: catch.hpp:1161
std::string(*)() exceptionTranslateFunction
Definition: catch.hpp:2027
std::string rangeToString(Range const &range)
Definition: catch.hpp:1155
auto makeStream(StringRef const &filename) -> IStream const *
IResultCapture & getResultCapture()
auto compareEqual(LhsT const &lhs, RhsT const &rhs) -> bool
Definition: catch.hpp:1384
std::shared_ptr< ITestInvoker > ITestCasePtr
Definition: catch.hpp:358
bool replaceInPlace(std::string &str, std::string const &replaceThis, std::string const &withThis)
const std::string none
Definition: LogUtil.hpp:48
const int64_t Error
Definition: LogUtil.hpp:36
const int64_t Warning
Definition: LogUtil.hpp:35
function get(const std::string &func, double alpha, double beta)
std::function< double(double, double)> function
Definition: Operate.hpp:28
std::time_t to_time_t(const time_point &tp)
constexpr const double micro
Definition: custom-opm-common/opm-common/opm/parser/eclipse/Units/Units.hpp:60
constexpr const double milli
Definition: custom-opm-common/opm-common/opm/parser/eclipse/Units/Units.hpp:61
constexpr const double second
Definition: custom-opm-common/opm-common/opm/parser/eclipse/Units/Units.hpp:104
bool operator==(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
UDQScalar operator-(const UDQScalar &lhs, const UDQScalar &rhs)
std::chrono::time_point< std::chrono::system_clock, std::chrono::duration< int64_t, std::ratio< 1, 1000 > > > time_point
Definition: TimeService.hpp:31
bool operator<(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
bool operator<=(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
Definition: SummaryConfig.hpp:101
UDQScalar operator*(const UDQScalar &lhs, const UDQScalar &rhs)
TokenType
Definition: ActionValue.hpp:7
@ end
Definition: ActionValue.hpp:20
bool operator>=(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
Definition: SummaryConfig.hpp:111
bool operator!=(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
Definition: SummaryConfig.hpp:96
U & uppercase(const T &src, U &dst)
Definition: String.hpp:13
static const double e
Definition: exprtk.hpp:758
T min(const T v0, const T v1)
Definition: exprtk.hpp:1400
T equal(const T v0, const T v1)
Definition: exprtk.hpp:1414
T max(const T v0, const T v1)
Definition: exprtk.hpp:1407
T value(details::expression_node< T > *n)
Definition: exprtk.hpp:12955
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t t(t+t)") define_sfop3(16
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t x(y+z)
FloatingPoint< float > Float
Definition: gtest.h:6756
FloatingPoint< double > Double
Definition: gtest.h:6757
internal::ParamGenerator< T > Range(T start, T end, IncrementT step)
Definition: gtest.h:11204
Definition: catch.hpp:642
SourceLineInfo lineInfo
Definition: catch.hpp:644
ResultDisposition::Flags resultDisposition
Definition: catch.hpp:646
StringRef macroName
Definition: catch.hpp:643
StringRef capturedExpression
Definition: catch.hpp:645
Definition: catch.hpp:1569
bool shouldThrow
Definition: catch.hpp:1571
bool shouldDebugBreak
Definition: catch.hpp:1570
Definition: catch.hpp:525
AutoReg(ITestInvoker *invoker, SourceLineInfo const &lineInfo, StringRef const &classOrMethod, NameAndTags const &nameAndTags) noexcept
Definition: catch.hpp:272
Choice
Definition: catch.hpp:272
@ No
Definition: catch.hpp:274
@ Yes
Definition: catch.hpp:273
Definition: catch.hpp:1819
Counts & operator+=(Counts const &other)
std::size_t failed
Definition: catch.hpp:1828
std::size_t total() const
Counts operator-(Counts const &other) const
std::size_t failedButOk
Definition: catch.hpp:1829
std::size_t passed
Definition: catch.hpp:1827
Definition: catch.hpp:1456
auto operator<=(T const &lhs) -> ExprLhs< T const & >
Definition: catch.hpp:1458
Definition: catch.hpp:2032
virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const =0
virtual ~IExceptionTranslator()
Definition: catch.hpp:2037
virtual ~IExceptionTranslatorRegistry()
virtual std::string translateActiveException() const =0
Definition: catch.hpp:1999
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:1987
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:1492
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:2875
virtual bool aborting() const =0
Definition: catch.hpp:678
virtual std::ostream & stream() const =0
Definition: catch.hpp:363
virtual std::vector< TestCase > const & getAllTestsSorted(IConfig const &config) const =0
virtual std::vector< TestCase > const & getAllTests() const =0
virtual ~ITestCaseRegistry()
Definition: catch.hpp:353
virtual void invoke() const =0
Definition: catch.hpp:1326
auto getResult() const -> bool
Definition: catch.hpp:1328
auto isBinaryExpression() const -> bool
Definition: catch.hpp:1327
bool m_result
Definition: catch.hpp:1341
bool m_isBinaryExpression
Definition: catch.hpp:1340
virtual void streamReconstructedExpression(std::ostream &os) const =0
ITransientExpression(bool isBinaryExpression, bool result)
Definition: catch.hpp:1331
virtual ~ITransientExpression()
Definition: catch.hpp:2400
std::string describe() const override
WithinAbsMatcher(double target, double margin)
bool match(double const &matchee) const override
Definition: catch.hpp:2409
WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
bool match(double const &matchee) const override
std::string describe() const override
Definition: catch.hpp:2285
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:2317
std::vector< MatcherBase< ArgT > const * > m_matchers
Definition: catch.hpp:2347
std::string describe() const override
Definition: catch.hpp:2326
bool match(ArgT const &arg) const override
Definition: catch.hpp:2319
Definition: catch.hpp:2351
bool match(ArgT const &arg) const override
Definition: catch.hpp:2355
MatchNotOf(MatcherBase< ArgT > const &underlyingMatcher)
Definition: catch.hpp:2353
std::string describe() const override
Definition: catch.hpp:2359
MatcherBase< ArgT > const & m_underlyingMatcher
Definition: catch.hpp:2362
Definition: catch.hpp:2277
MatchNotOf< T > operator!() const
Definition: catch.hpp:2374
MatchAnyOf< T > operator||(MatcherBase const &other) const
Definition: catch.hpp:2370
MatchAllOf< T > operator&&(MatcherBase const &other) const
Definition: catch.hpp:2366
virtual bool match(PtrT *arg) const =0
Definition: catch.hpp:2268
virtual bool match(ObjectT const &arg) const =0
Definition: catch.hpp:2489
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:2495
CaseSensitive::Choice m_caseSensitivity
Definition: catch.hpp:2494
Definition: catch.hpp:2510
bool match(std::string const &source) const override
ContainsMatcher(CasedString const &comparator)
Definition: catch.hpp:2518
EndsWithMatcher(CasedString const &comparator)
bool match(std::string const &source) const override
Definition: catch.hpp:2506
bool match(std::string const &source) const override
EqualsMatcher(CasedString const &comparator)
Definition: catch.hpp:2523
std::string describe() const override
bool match(std::string const &matchee) const override
RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity)
Definition: catch.hpp:2514
StartsWithMatcher(CasedString const &comparator)
bool match(std::string const &source) const override
Definition: catch.hpp:2498
CasedString m_comparator
Definition: catch.hpp:2502
StringMatcherBase(std::string const &operation, CasedString const &comparator)
std::string describe() const override
std::string m_operation
Definition: catch.hpp:2503
Definition: catch.hpp:2579
ContainsElementMatcher(T const &comparator)
Definition: catch.hpp:2581
bool match(std::vector< T > const &v) const override
Definition: catch.hpp:2583
T const & m_comparator
Definition: catch.hpp:2596
std::string describe() const override
Definition: catch.hpp:2592
Definition: catch.hpp:2600
std::vector< T > const & m_comparator
Definition: catch.hpp:2626
std::string describe() const override
Definition: catch.hpp:2622
ContainsMatcher(std::vector< T > const &comparator)
Definition: catch.hpp:2602
bool match(std::vector< T > const &v) const override
Definition: catch.hpp:2604
Definition: catch.hpp:2630
bool match(std::vector< T > const &v) const override
Definition: catch.hpp:2634
std::string describe() const override
Definition: catch.hpp:2646
EqualsMatcher(std::vector< T > const &comparator)
Definition: catch.hpp:2632
std::vector< T > const & m_comparator
Definition: catch.hpp:2649
Definition: catch.hpp:2653
bool match(std::vector< T > const &vec) const override
Definition: catch.hpp:2655
UnorderedEqualsMatcher(std::vector< T > const &target)
Definition: catch.hpp:2654
std::string describe() const override
Definition: catch.hpp:2685
Definition: catch.hpp:1652
MessageInfo m_info
Definition: catch.hpp:1663
MessageBuilder(std::string const ¯oName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
Definition: catch.hpp:1624
std::string macroName
Definition: catch.hpp:1629
MessageInfo(std::string const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
unsigned int sequence
Definition: catch.hpp:1633
bool operator<(MessageInfo const &other) const
SourceLineInfo lineInfo
Definition: catch.hpp:1631
std::string message
Definition: catch.hpp:1630
ResultWas::OfType type
Definition: catch.hpp:1632
bool operator==(MessageInfo const &other) const
Definition: catch.hpp:1641
ReusableStringStream m_stream
Definition: catch.hpp:1649
Definition: catch.hpp:330
RegistrarForTagAliases(char const *alias, char const *tag, SourceLineInfo const &lineInfo)
Definition: catch.hpp:622
Flags
Definition: catch.hpp:622
@ SuppressFail
Definition: catch.hpp:627
@ FalseTest
Definition: catch.hpp:626
@ ContinueOnFailure
Definition: catch.hpp:625
@ Normal
Definition: catch.hpp:623
Definition: catch.hpp:598
OfType
Definition: catch.hpp:598
@ FailureBit
Definition: catch.hpp:604
@ Info
Definition: catch.hpp:601
@ ThrewException
Definition: catch.hpp:611
@ ExpressionFailed
Definition: catch.hpp:606
@ Unknown
Definition: catch.hpp:599
@ Warning
Definition: catch.hpp:602
@ FatalErrorCondition
Definition: catch.hpp:614
@ DidntThrowException
Definition: catch.hpp:612
@ Exception
Definition: catch.hpp:609
@ ExplicitFailure
Definition: catch.hpp:607
@ Ok
Definition: catch.hpp:600
Definition: catch.hpp:1861
SectionInfo sectionInfo
Definition: catch.hpp:1864
double durationInSeconds
Definition: catch.hpp:1866
SectionEndInfo(SectionInfo const &_sectionInfo, Counts const &_prevAssertions, double _durationInSeconds)
Counts prevAssertions
Definition: catch.hpp:1865
Definition: catch.hpp:1850
std::string description
Definition: catch.hpp:1857
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name, std::string const &_description=std::string())
std::string name
Definition: catch.hpp:1856
SourceLineInfo lineInfo
Definition: catch.hpp:1858
Definition: catch.hpp:288
bool empty() const noexcept
SourceLineInfo(char const *_file, std::size_t _line) noexcept
Definition: catch.hpp:291
SourceLineInfo(SourceLineInfo &&)=default
SourceLineInfo(SourceLineInfo const &other)=default
std::size_t line
Definition: catch.hpp:306
SourceLineInfo & operator=(SourceLineInfo const &)=default
char const * file
Definition: catch.hpp:305
bool operator==(SourceLineInfo const &other) const noexcept
bool operator<(SourceLineInfo const &other) const noexcept
Definition: catch.hpp:315
std::string operator+() const
static std::string convert(Catch::Detail::Approx const &value)
static std::string convert(R const &range)
Definition: catch.hpp:1178
static std::string convert(R C::*p)
Definition: catch.hpp:1001
static std::string convert(U *p)
Definition: catch.hpp:990
static std::string convert(T const(&arr)[SZ])
Definition: catch.hpp:1185
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:913
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:919
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:925
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)
Definition: catch.hpp:829
static std::enable_if<::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
Definition: catch.hpp:833
static std::enable_if<!::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
Definition: catch.hpp:844
Definition: catch.hpp:2807
friend void setTags(TestCaseInfo &testCaseInfo, std::vector< std::string > tags)
std::vector< std::string > tags
Definition: catch.hpp:2836
std::string tagsAsString() const
std::string className
Definition: catch.hpp:2834
std::string description
Definition: catch.hpp:2835
SpecialProperties
Definition: catch.hpp:2808
@ NonPortable
Definition: catch.hpp:2814
@ Throws
Definition: catch.hpp:2813
@ Benchmark
Definition: catch.hpp:2815
@ MayFail
Definition: catch.hpp:2812
@ IsHidden
Definition: catch.hpp:2810
@ ShouldFail
Definition: catch.hpp:2811
@ None
Definition: catch.hpp:2809
std::string name
Definition: catch.hpp:2833
std::vector< std::string > lcaseTags
Definition: catch.hpp:2837
SourceLineInfo lineInfo
Definition: catch.hpp:2838
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:2839
Definition: catch.hpp:1547
Definition: catch.hpp:1832
Totals delta(Totals const &prevTotals) const
Counts assertions
Definition: catch.hpp:1840
Totals operator-(Totals const &other) const
Totals & operator+=(Totals const &other)
Counts testCases
Definition: catch.hpp:1841
Definition: catch.hpp:1141
static const bool value
Definition: catch.hpp:1142
Definition: catch.hpp:1131
Definition: catch.hpp:2227
std::size_t m_count
Definition: catch.hpp:2232
pluralise(std::size_t count, std::string const &label)
std::string m_label
Definition: catch.hpp:2233
Definition: catch.hpp:759