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 4 18 #define CATCH_VERSION_PATCH 2 21 # pragma clang system_header 22 #elif defined __GNUC__ 23 # pragma GCC system_header 29 # ifdef __ICC // icpc defines the __clang__ macro 30 # pragma warning(push) 31 # pragma warning(disable: 161 1682) 33 # pragma clang diagnostic push 34 # pragma clang diagnostic ignored "-Wpadded" 35 # pragma clang diagnostic ignored "-Wswitch-enum" 36 # pragma clang diagnostic ignored "-Wcovered-switch-default" 38 #elif defined __GNUC__ 42 # pragma GCC diagnostic ignored "-Wparentheses" 43 # pragma GCC diagnostic push 44 # pragma GCC diagnostic ignored "-Wunused-variable" 45 # pragma GCC diagnostic ignored "-Wpadded" 48 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) 50 # define CATCH_CONFIG_ALL_PARTS 55 #if defined(CATCH_CONFIG_ALL_PARTS) 56 # define CATCH_CONFIG_EXTERNAL_INTERFACES 57 # if defined(CATCH_CONFIG_DISABLE_MATCHERS) 58 # undef CATCH_CONFIG_DISABLE_MATCHERS 60 # if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 61 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 65 #if !defined(CATCH_CONFIG_IMPL_ONLY) 69 # include <TargetConditionals.h> 70 # if TARGET_OS_OSX == 1 71 # define CATCH_PLATFORM_MAC 72 # elif TARGET_OS_IPHONE == 1 73 # define CATCH_PLATFORM_IPHONE 76 #elif defined(linux) || defined(__linux) || defined(__linux__) 77 # define CATCH_PLATFORM_LINUX 79 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) 80 # define CATCH_PLATFORM_WINDOWS 86 # ifndef CLARA_CONFIG_MAIN 87 # define CLARA_CONFIG_MAIN_NOT_DEFINED 88 # define CLARA_CONFIG_MAIN 124 # if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) 125 # define CATCH_CPP14_OR_GREATER 128 # if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) 129 # define CATCH_CPP17_OR_GREATER 134 #if defined(CATCH_CPP17_OR_GREATER) 135 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 140 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 141 _Pragma( "clang diagnostic push" ) \ 142 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ 143 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") 144 # define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 145 _Pragma( "clang diagnostic pop" ) 147 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 148 _Pragma( "clang diagnostic push" ) \ 149 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 150 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 151 _Pragma( "clang diagnostic pop" ) 153 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 154 _Pragma( "clang diagnostic push" ) \ 155 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) 156 # define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \ 157 _Pragma( "clang diagnostic pop" ) 163 #if !defined(CATCH_PLATFORM_WINDOWS) 164 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS 169 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) 170 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 174 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 175 # define CATCH_CONFIG_COLOUR_NONE 180 #if defined(__ANDROID__) 181 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 186 #if defined(__MINGW32__) 187 # define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 192 #if defined(__ORBIS__) 193 # define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE 205 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ 206 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) 208 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 217 # if _MSC_VER >= 1900 // Visual Studio 2015 or newer 218 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 223 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 224 # define CATCH_CONFIG_COLOUR_NONE 226 # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 233 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) 234 # define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED 240 # define CATCH_INTERNAL_CONFIG_NO_WCHAR 250 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) 251 #define CATCH_INTERNAL_CONFIG_COUNTER 257 #if defined(__has_include) 258 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER) 259 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW 265 #if defined(__has_include) 266 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 267 # if defined(__clang__) && (__clang_major__ < 8) 271 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 272 # define CATCH_CONFIG_NO_CPP17_VARIANT 274 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 275 # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 276 # endif // defined(__clang__) && (__clang_major__ < 8) 277 # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 278 #endif // __has_include 280 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) 281 # define CATCH_CONFIG_COUNTER 283 #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) 284 # define CATCH_CONFIG_WINDOWS_SEH 287 #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) 288 # define CATCH_CONFIG_POSIX_SIGNALS 291 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) 292 # define CATCH_CONFIG_WCHAR 295 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) 296 # define CATCH_CONFIG_CPP11_TO_STRING 299 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 300 # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 303 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) 304 # define CATCH_CONFIG_CPP17_STRING_VIEW 307 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) 308 # define CATCH_CONFIG_CPP17_VARIANT 311 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 312 # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE 315 #if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) 316 # define CATCH_CONFIG_NEW_CAPTURE 319 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 320 # define CATCH_CONFIG_DISABLE_EXCEPTIONS 323 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) 324 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 325 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS 327 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) 328 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 329 # define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 331 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) 332 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS 333 # define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS 336 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 337 #define CATCH_TRY if ((true)) 338 #define CATCH_CATCH_ALL if ((false)) 339 #define CATCH_CATCH_ANON(type) if ((false)) 341 #define CATCH_TRY try 342 #define CATCH_CATCH_ALL catch (...) 343 #define CATCH_CATCH_ANON(type) catch (type) 347 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 348 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 349 #ifdef CATCH_CONFIG_COUNTER 350 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 352 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 394 bool empty()
const noexcept;
422 #define CATCH_INTERNAL_LINEINFO \ 423 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 434 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ 435 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 436 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ 437 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 452 virtual void invoke ()
const = 0;
463 virtual std::vector<TestCase>
const& getAllTests()
const = 0;
464 virtual std::vector<TestCase>
const& getAllTestsSorted( IConfig
const& config )
const = 0;
467 bool matchTest(
TestCase const& testCase, TestSpec
const& testSpec, IConfig
const& config );
468 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config );
496 friend struct StringRefTestAccess;
501 char* m_data =
nullptr;
503 void takeOwnership();
505 static constexpr
char const*
const s_empty =
"";
513 : m_start( other.m_start ),
514 m_size( other.m_size )
518 : m_start( other.m_start ),
519 m_size( other.m_size ),
520 m_data( other.m_data )
522 other.m_data =
nullptr;
525 StringRef(
char const* rawChars ) noexcept;
528 : m_start( rawChars ),
533 : m_start( stdString.c_str() ),
534 m_size( stdString.size() )
545 m_size = other.m_size;
549 operator std::string()
const;
554 auto operator == (
StringRef const& other )
const noexcept -> bool;
555 auto operator != (
StringRef const& other )
const noexcept -> bool;
557 auto operator[] (
size_type index )
const noexcept -> char;
560 auto empty() const noexcept ->
bool {
567 auto numberOfCharacters()
const noexcept ->
size_type;
568 auto c_str()
const ->
char const*;
575 auto currentData()
const noexcept ->
char const*;
578 auto isOwned()
const noexcept -> bool;
579 auto isSubstring()
const noexcept -> bool;
589 inline auto operator "" _sr(
char const* rawChars, std::size_t size ) noexcept ->
StringRef {
595 inline auto operator "" _catch_sr(
char const* rawChars, std::size_t size ) noexcept ->
Catch::StringRef {
604 void (C::*m_testAsMethod)();
610 (obj.*m_testAsMethod)();
634 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) 635 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ 636 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ 637 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 639 #if defined(CATCH_CONFIG_DISABLE) 640 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ 641 static void TestName() 642 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 644 struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \ 648 void TestName::test() 653 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ 654 static void TestName(); \ 655 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 656 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } \ 657 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 658 static void TestName() 659 #define INTERNAL_CATCH_TESTCASE( ... ) \ 660 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) 663 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ 664 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 665 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } \ 666 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 669 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ 670 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 672 struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \ 675 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); \ 677 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 678 void TestName::test() 679 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ 680 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) 683 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ 684 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 685 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); \ 686 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 708 ExpressionFailed = FailureBit | 1,
709 ExplicitFailure = FailureBit | 2,
711 Exception = 0x100 | FailureBit,
713 ThrewException = Exception | 1,
714 DidntThrowException = Exception | 2,
716 FatalErrorCondition = 0x200 | FailureBit
727 ContinueOnFailure = 0x02,
764 #include <type_traits> 774 std::ostream&
cout();
775 std::ostream&
cerr();
776 std::ostream&
clog();
782 virtual std::ostream& stream()
const = 0;
794 auto str() const ->
std::
string;
801 auto get() -> std::ostream& {
return *m_oss; }
807 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 808 #include <string_view> 814 #import <Foundation/Foundation.h> 817 #define CATCH_ARC_ENABLED __has_feature(objc_arc) 819 #define CATCH_ARC_ENABLED 0 822 void arcSafeRelease( NSObject* obj );
823 id performOptionalSelector(
id obj,
SEL sel );
825 #if !CATCH_ARC_ENABLED 826 inline void arcSafeRelease( NSObject* obj ) {
829 inline id performOptionalSelector(
id obj,
SEL sel ) {
830 if( [obj respondsToSelector: sel] )
831 return [obj performSelector: sel];
834 #define CATCH_UNSAFE_UNRETAINED 835 #define CATCH_ARC_STRONG 837 inline void arcSafeRelease( NSObject* ){}
838 inline id performOptionalSelector(
id obj,
SEL sel ) {
840 #pragma clang diagnostic push 841 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 843 if( [obj respondsToSelector: sel] )
844 return [obj performSelector: sel];
846 #pragma clang diagnostic pop 850 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 851 #define CATCH_ARC_STRONG __strong 858 #pragma warning(push) 859 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless 876 template<
typename SS,
typename TT>
877 static auto test(
int)
878 -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
880 template<
typename,
typename>
881 static auto test(...)->std::false_type;
884 static const bool value = decltype(test<std::ostream, const T&>(0))::value;
891 typename std::enable_if<
897 typename std::enable_if<
904 typename std::enable_if<
910 #if defined(_MANAGED) 913 std::string clrReferenceToString( T^ ref ) {
915 return std::string(
"null");
916 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
917 cli::pin_ptr<System::Byte> p = &bytes[0];
918 return std::string(reinterpret_cast<char const *>(p), bytes->Length);
925 template <
typename T,
typename =
void>
927 template <
typename Fake = T>
934 rss.operator<<(
value);
938 template <
typename Fake = T>
942 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) 945 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
954 template <
typename T>
956 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e);
964 #if defined(_MANAGED) 965 template <
typename T>
967 return ::Catch::StringMaker<T^>::convert(e);
977 static std::string convert(
const std::string& str);
980 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 983 static std::string convert(std::string_view str);
989 static std::string convert(
char const * str);
993 static std::string convert(
char * str);
996 #ifdef CATCH_CONFIG_WCHAR 999 static std::string convert(
const std::wstring& wstr);
1002 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1005 static std::string convert(std::wstring_view str);
1011 static std::string convert(
wchar_t const * str);
1015 static std::string convert(
wchar_t * str);
1029 static std::string
convert(
signed char const* str) {
1035 static std::string
convert(
unsigned char const* str) {
1042 static std::string convert(
int value);
1046 static std::string convert(
long value);
1050 static std::string convert(
long long value);
1054 static std::string convert(
unsigned int value);
1058 static std::string convert(
unsigned long value);
1062 static std::string convert(
unsigned long long value);
1067 static std::string convert(
bool b);
1072 static std::string convert(
char c);
1076 static std::string convert(
signed char c);
1080 static std::string convert(
unsigned char c);
1085 static std::string convert(std::nullptr_t);
1090 static std::string convert(
float value);
1094 static std::string convert(
double value);
1097 template <
typename T>
1099 template <
typename U>
1109 template <
typename R,
typename C>
1120 #if defined(_MANAGED) 1121 template <
typename T>
1123 static std::string convert( T^ ref ) {
1124 return ::Catch::Detail::clrReferenceToString(ref);
1130 template<
typename InputIterator>
1134 if (first != last) {
1136 for (++first; first != last; ++first)
1147 static std::string convert(NSString * nsstring) {
1150 return std::string(
"@") + [nsstring UTF8String];
1155 static std::string convert(NSObject* nsObject) {
1161 inline std::string
stringify( NSString* nsstring ) {
1174 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) 1175 # define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1176 # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1177 # define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1178 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1182 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) 1185 template<
typename T1,
typename T2>
1187 static std::string convert(
const std::pair<T1, T2>& pair) {
1198 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1201 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) 1210 struct TupleElementPrinter {
1211 static void print(
const Tuple& tuple, std::ostream& os) {
1212 os << (N ?
", " :
" ")
1214 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
1222 struct TupleElementPrinter<Tuple, N, false> {
1223 static void print(
const Tuple&, std::ostream&) {}
1228 template<
typename ...Types>
1230 static std::string convert(
const std::tuple<Types...>& tuple) {
1233 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.
get());
1239 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1241 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT) 1246 static std::string convert(
const std::monostate&) {
1251 template<
typename... Elements>
1253 static std::string convert(
const std::variant<Elements...>& variant) {
1254 if (variant.valueless_by_exception()) {
1255 return "{valueless variant}";
1258 [](
const auto&
value) {
1267 #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1279 template <
typename T>
1286 #if defined(_MANAGED) // Managed types are never ranges 1287 template <
typename T>
1289 static const bool value =
false;
1293 template<
typename Range>
1299 template<
typename Allocator>
1315 template<
typename R>
1316 struct StringMaker<R, typename
std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
1322 template <
typename T,
int SZ>
1332 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 1339 template <
class Ratio>
1340 struct ratio_string {
1341 static std::string symbol();
1344 template <
class Ratio>
1345 std::string ratio_string<Ratio>::symbol() {
1347 rss <<
'[' << Ratio::num <<
'/' 1348 << Ratio::den <<
']';
1352 struct ratio_string<std::atto> {
1353 static std::string symbol();
1356 struct ratio_string<std::femto> {
1357 static std::string symbol();
1360 struct ratio_string<std::pico> {
1361 static std::string symbol();
1364 struct ratio_string<std::nano> {
1365 static std::string symbol();
1368 struct ratio_string<std::micro> {
1369 static std::string symbol();
1372 struct ratio_string<std::milli> {
1373 static std::string symbol();
1378 template<
typename Value,
typename Ratio>
1379 struct StringMaker<std::chrono::duration<Value, Ratio>> {
1380 static std::string convert(std::chrono::duration<Value, Ratio>
const& duration) {
1382 rss << duration.count() <<
' ' << ratio_string<Ratio>::symbol() <<
's';
1386 template<
typename Value>
1387 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
1388 static std::string convert(std::chrono::duration<Value, std::ratio<1>>
const& duration) {
1390 rss << duration.count() <<
" s";
1394 template<
typename Value>
1395 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
1396 static std::string convert(std::chrono::duration<Value, std::ratio<60>>
const& duration) {
1398 rss << duration.count() <<
" m";
1402 template<
typename Value>
1403 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
1404 static std::string convert(std::chrono::duration<Value, std::ratio<3600>>
const& duration) {
1406 rss << duration.count() <<
" h";
1414 template<
typename Clock,
typename Duration>
1415 struct StringMaker<std::chrono::time_point<Clock, Duration>> {
1416 static std::string convert(std::chrono::time_point<Clock, Duration>
const& time_point) {
1421 template<
typename Duration>
1422 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
1423 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration>
const& time_point) {
1424 auto converted = std::chrono::system_clock::to_time_t(time_point);
1427 std::tm timeInfo = {};
1428 gmtime_s(&timeInfo, &converted);
1430 std::tm* timeInfo = std::gmtime(&converted);
1433 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
1435 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
1438 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
1440 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
1442 return std::string(timeStamp);
1446 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1449 #pragma warning(pop) 1456 #pragma warning(push) 1457 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch 1458 #pragma warning(disable:4018) // more "signed/unsigned mismatch" 1459 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 1460 #pragma warning(disable:4180) // qualifier applied to function type has no meaning 1468 virtual void streamReconstructedExpression( std::ostream &os )
const = 0;
1471 : m_isBinaryExpression( isBinaryExpression ),
1486 template<
typename LhsT,
typename RhsT>
1506 template<
typename LhsT>
1522 template<
typename LhsT,
typename RhsT>
1523 auto compareEqual( LhsT
const& lhs, RhsT
const& rhs ) ->
bool {
return static_cast<bool>(lhs == rhs); }
1524 template<
typename T>
1525 auto compareEqual( T*
const& lhs,
int rhs ) ->
bool {
return lhs ==
reinterpret_cast<void const*
>( rhs ); }
1526 template<
typename T>
1527 auto compareEqual( T*
const& lhs,
long rhs ) ->
bool {
return lhs ==
reinterpret_cast<void const*
>( rhs ); }
1528 template<
typename T>
1529 auto compareEqual(
int lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) == rhs; }
1530 template<
typename T>
1531 auto compareEqual(
long lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) == rhs; }
1533 template<
typename LhsT,
typename RhsT>
1534 auto compareNotEqual( LhsT
const& lhs, RhsT&& rhs ) ->
bool {
return static_cast<bool>(lhs != rhs); }
1535 template<
typename T>
1536 auto compareNotEqual( T*
const& lhs,
int rhs ) ->
bool {
return lhs !=
reinterpret_cast<void const*
>( rhs ); }
1537 template<
typename T>
1538 auto compareNotEqual( T*
const& lhs,
long rhs ) ->
bool {
return lhs !=
reinterpret_cast<void const*
>( rhs ); }
1539 template<
typename T>
1540 auto compareNotEqual(
int lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) != rhs; }
1541 template<
typename T>
1542 auto compareNotEqual(
long lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) != rhs; }
1544 template<
typename LhsT>
1550 template<
typename RhsT>
1552 return {
compareEqual( m_lhs, rhs ), m_lhs,
"==", rhs };
1555 return { m_lhs == rhs, m_lhs,
"==", rhs };
1558 template<
typename RhsT>
1563 return { m_lhs != rhs, m_lhs,
"!=", rhs };
1566 template<
typename RhsT>
1568 return {
static_cast<bool>(m_lhs > rhs), m_lhs,
">", rhs };
1570 template<
typename RhsT>
1572 return {
static_cast<bool>(m_lhs < rhs), m_lhs,
"<", rhs };
1574 template<
typename RhsT>
1576 return {
static_cast<bool>(m_lhs >= rhs), m_lhs,
">=", rhs };
1578 template<
typename RhsT>
1580 return {
static_cast<bool>(m_lhs <= rhs), m_lhs,
"<=", rhs };
1590 template<
typename T>
1596 template<
typename T>
1609 #pragma warning(pop) 1619 class AssertionResult;
1625 struct BenchmarkInfo;
1626 struct BenchmarkStats;
1637 virtual bool sectionStarted(
SectionInfo const& sectionInfo,
1638 Counts& assertions ) = 0;
1640 virtual void sectionEndedEarly(
SectionEndInfo const& endInfo ) = 0;
1644 virtual void benchmarkStarting( BenchmarkInfo
const& info ) = 0;
1645 virtual void benchmarkEnded( BenchmarkStats
const& stats ) = 0;
1647 virtual void pushScopedMessage(
MessageInfo const& message ) = 0;
1648 virtual void popScopedMessage(
MessageInfo const& message ) = 0;
1650 virtual void handleFatalErrorCondition(
StringRef message ) = 0;
1652 virtual void handleExpr
1656 virtual void handleMessage
1661 virtual void handleUnexpectedExceptionNotThrown
1664 virtual void handleUnexpectedInflightException
1666 std::string
const& message,
1668 virtual void handleIncomplete
1670 virtual void handleNonExpr
1675 virtual bool lastAssertionPassed() = 0;
1676 virtual void assertionPassed() = 0;
1679 virtual std::string getCurrentTestName()
const = 0;
1680 virtual const AssertionResult* getLastResult()
const = 0;
1681 virtual void exceptionEarlyReported() = 0;
1691 struct AssertionResultData;
1697 friend struct AssertionStats;
1698 friend class RunContext;
1707 explicit operator bool()
const;
1713 bool shouldDebugBreak =
false;
1714 bool shouldThrow =
false;
1720 bool m_completed =
false;
1730 if ( !m_completed ) {
1735 template<
typename T>
1743 void handleExceptionThrownAsExpected();
1744 void handleUnexpectedExceptionNotThrown();
1745 void handleExceptionNotThrownAsExpected();
1746 void handleThrowingCallSkipped();
1747 void handleUnexpectedInflightException();
1750 void setCompleted();
1753 auto allowThrows()
const -> bool;
1779 bool operator == (
MessageInfo const& other )
const;
1780 bool operator < (
MessageInfo const& other )
const;
1787 template<
typename T>
1801 template<
typename T>
1821 size_t m_captured = 0;
1828 template<
typename T>
1833 template<
typename T,
typename... Ts>
1835 captureValues( index,
value );
1836 captureValues( index+1,
values... );
1843 #if !defined(CATCH_CONFIG_DISABLE) 1845 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) 1846 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ 1848 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" 1851 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 1856 #define INTERNAL_CATCH_TRY 1857 #define INTERNAL_CATCH_CATCH( capturer ) 1859 #else // CATCH_CONFIG_FAST_COMPILE 1861 #define INTERNAL_CATCH_TRY try 1862 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); } 1866 #define INTERNAL_CATCH_REACT( handler ) handler.complete(); 1869 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ 1871 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 1872 INTERNAL_CATCH_TRY { \ 1873 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 1874 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ 1875 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 1876 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 1877 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1878 } while( (void)0, false && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look 1882 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ 1883 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 1884 if( Catch::getResultCapture().lastAssertionPassed() ) 1887 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ 1888 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 1889 if( !Catch::getResultCapture().lastAssertionPassed() ) 1892 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ 1894 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 1896 static_cast<void>(__VA_ARGS__); \ 1897 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ 1900 catchAssertionHandler.handleUnexpectedInflightException(); \ 1902 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1906 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ 1908 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ 1909 if( catchAssertionHandler.allowThrows() ) \ 1911 static_cast<void>(__VA_ARGS__); \ 1912 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 1915 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 1918 catchAssertionHandler.handleThrowingCallSkipped(); \ 1919 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1923 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 1925 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 1926 if( catchAssertionHandler.allowThrows() ) \ 1928 static_cast<void>(expr); \ 1929 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 1931 catch( exceptionType const& ) { \ 1932 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 1935 catchAssertionHandler.handleUnexpectedInflightException(); \ 1938 catchAssertionHandler.handleThrowingCallSkipped(); \ 1939 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1943 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 1945 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ 1946 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 1947 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1951 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ 1952 auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ 1953 varName.captureValues( 0, __VA_ARGS__ ) 1956 #define INTERNAL_CATCH_INFO( macroName, log ) \ 1957 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); 1961 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ 1963 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 1964 if( catchAssertionHandler.allowThrows() ) \ 1966 static_cast<void>(__VA_ARGS__); \ 1967 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 1970 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \ 1973 catchAssertionHandler.handleThrowingCallSkipped(); \ 1974 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 1977 #endif // CATCH_CONFIG_DISABLE 1994 std::size_t total()
const;
1995 bool allPassed()
const;
1998 std::size_t passed = 0;
1999 std::size_t failed = 0;
2000 std::size_t failedButOk = 0;
2024 std::string
const& _name );
2029 std::string
const& _name,
2030 std::string
const& ) :
SectionInfo( _lineInfo, _name ) {}
2056 uint64_t m_nanoseconds = 0;
2059 auto getElapsedNanoseconds() const -> uint64_t;
2060 auto getElapsedMicroseconds() const -> uint64_t;
2061 auto getElapsedMilliseconds() const ->
unsigned int;
2062 auto getElapsedSeconds() const ->
double;
2078 explicit operator bool()
const;
2091 #define INTERNAL_CATCH_SECTION( ... ) \ 2092 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2093 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ 2094 CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS 2096 #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ 2097 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2098 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ 2099 CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS 2112 std::size_t m_count = 0;
2113 std::size_t m_iterationsToRun = 1;
2117 static auto getResolution() -> uint64_t;
2122 m_resolution( getResolution() )
2128 explicit operator bool() {
2129 if( m_count < m_iterationsToRun )
2131 return needsMoreIterations();
2139 auto needsMoreIterations() -> bool;
2144 #define BENCHMARK( name ) \ 2145 for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() ) 2158 struct ITestCaseRegistry;
2159 struct IExceptionTranslatorRegistry;
2160 struct IExceptionTranslator;
2161 struct IReporterRegistry;
2162 struct IReporterFactory;
2163 struct ITagAliasRegistry;
2164 class StartupExceptionRegistry;
2171 virtual IReporterRegistry
const& getReporterRegistry()
const = 0;
2173 virtual ITagAliasRegistry
const& getTagAliasRegistry()
const = 0;
2177 virtual StartupExceptionRegistry
const& getStartupExceptionRegistry()
const = 0;
2182 virtual void registerReporter( std::string
const& name,
IReporterFactoryPtr const& factory ) = 0;
2184 virtual void registerTest(
TestCase const& testInfo ) = 0;
2186 virtual void registerTagAlias( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo ) = 0;
2187 virtual void registerStartupException() noexcept = 0;
2198 #if defined(CATCH_CONFIG_DISABLE) 2199 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ 2200 static std::string translatorName( signature ) 2203 #include <exception> 2215 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const = 0;
2225 template<
typename T>
2230 : m_translateFunction( translateFunction )
2233 std::string
translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const override {
2236 std::rethrow_exception(std::current_exception());
2238 return (*it)->translate( it+1, itEnd );
2241 return m_translateFunction( ex );
2246 std::string(*m_translateFunction)( T& );
2250 template<
typename T>
2259 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ 2260 static std::string translatorName( signature ); \ 2261 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 2262 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ 2263 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 2264 static std::string translatorName( signature ) 2266 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 2271 #include <type_traits> 2278 bool equalityComparisonImpl(
double other)
const;
2281 void setMargin(
double margin);
2284 void setEpsilon(
double epsilon);
2291 Approx operator-()
const;
2295 Approx approx( static_cast<double>(value) );
2307 friend bool operator == (
const T& lhs,
Approx const& rhs ) {
2308 auto lhs_v =
static_cast<double>(lhs);
2313 friend bool operator == (
Approx const& lhs,
const T& rhs ) {
2314 return operator==( rhs, lhs );
2318 friend bool operator != ( T
const& lhs,
Approx const& rhs ) {
2319 return !operator==( lhs, rhs );
2323 friend bool operator != (
Approx const& lhs, T
const& rhs ) {
2324 return !operator==( rhs, lhs );
2328 friend bool operator <= ( T
const& lhs,
Approx const& rhs ) {
2329 return static_cast<double>(lhs) < rhs.
m_value || lhs == rhs;
2333 friend bool operator <= (
Approx const& lhs, T
const& rhs ) {
2334 return lhs.
m_value <
static_cast<double>(rhs) || lhs == rhs;
2338 friend bool operator >= ( T
const& lhs,
Approx const& rhs ) {
2339 return static_cast<double>(lhs) > rhs.
m_value || lhs == rhs;
2343 friend bool operator >= (
Approx const& lhs, T
const& rhs ) {
2344 return lhs.
m_value >
static_cast<double>(rhs) || lhs == rhs;
2349 double epsilonAsDouble =
static_cast<double>(newEpsilon);
2350 setEpsilon(epsilonAsDouble);
2356 double marginAsDouble =
static_cast<double>(newMargin);
2357 setMargin(marginAsDouble);
2363 m_scale =
static_cast<double>(newScale);
2367 std::string toString()
const;
2377 namespace literals {
2397 bool startsWith( std::string
const&
s, std::string
const& prefix );
2398 bool startsWith( std::string
const& s,
char prefix );
2399 bool endsWith( std::string
const& s, std::string
const& suffix );
2400 bool endsWith( std::string
const& s,
char suffix );
2401 bool contains( std::string
const& s, std::string
const& infix );
2403 std::string
toLower( std::string
const& s );
2404 std::string
trim( std::string
const& str );
2405 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis );
2418 #ifndef CATCH_CONFIG_DISABLE_MATCHERS 2427 namespace Matchers {
2439 std::string toString()
const;
2443 virtual std::string describe()
const = 0;
2448 # pragma clang diagnostic push 2449 # pragma clang diagnostic ignored "-Wnon-virtual-dtor" 2452 template<
typename ObjectT>
2454 virtual bool match( ObjectT
const& arg )
const = 0;
2456 template<
typename PtrT>
2458 virtual bool match( PtrT* arg )
const = 0;
2462 # pragma clang diagnostic pop 2465 template<
typename T>
2473 template<
typename ArgT>
2475 bool match( ArgT
const& arg )
const override {
2476 for(
auto matcher : m_matchers ) {
2477 if (!matcher->match(arg))
2483 std::string description;
2484 description.reserve( 4 + m_matchers.size()*32 );
2485 description +=
"( ";
2487 for(
auto matcher : m_matchers ) {
2491 description +=
" and ";
2492 description += matcher->toString();
2494 description +=
" )";
2499 m_matchers.push_back( &other );
2505 template<
typename ArgT>
2508 bool match( ArgT
const& arg )
const override {
2509 for(
auto matcher : m_matchers ) {
2510 if (matcher->match(arg))
2516 std::string description;
2517 description.reserve( 4 + m_matchers.size()*32 );
2518 description +=
"( ";
2520 for(
auto matcher : m_matchers ) {
2524 description +=
" or ";
2525 description += matcher->toString();
2527 description +=
" )";
2532 m_matchers.push_back( &other );
2539 template<
typename ArgT>
2544 bool match( ArgT
const& arg )
const override {
2545 return !m_underlyingMatcher.match( arg );
2549 return "not " + m_underlyingMatcher.toString();
2554 template<
typename T>
2558 template<
typename T>
2562 template<
typename T>
2571 using namespace Matchers;
2579 #include <type_traits> 2583 namespace Matchers {
2585 namespace Floating {
2587 enum class FloatingPointKind : uint8_t;
2591 bool match(
double const& matchee)
const override;
2592 std::string describe()
const override;
2600 bool match(
double const& matchee)
const override;
2601 std::string describe()
const override;
2622 #include <functional> 2626 namespace Matchers {
2633 template <
typename T>
2640 :m_predicate(
std::move(elem)),
2644 bool match( T
const& item )
const override {
2645 return m_predicate(item);
2649 return m_description;
2659 template<
typename T>
2673 namespace Matchers {
2675 namespace StdString {
2680 std::string adjustString( std::string
const& str )
const;
2681 std::string caseSensitivitySuffix()
const;
2689 std::string describe()
const override;
2697 bool match( std::string
const& source )
const override;
2701 bool match( std::string
const& source )
const override;
2705 bool match( std::string
const& source )
const override;
2709 bool match( std::string
const& source )
const override;
2714 bool match( std::string
const& matchee )
const override;
2715 std::string describe()
const override;
2739 #include <algorithm> 2742 namespace Matchers {
2746 template <
typename InputIterator,
typename T>
2747 size_t count(InputIterator first, InputIterator last, T
const& item) {
2749 for (; first != last; ++first) {
2750 if (*first == item) {
2756 template <
typename InputIterator,
typename T>
2757 bool contains(InputIterator first, InputIterator last, T
const& item) {
2758 for (; first != last; ++first) {
2759 if (*first == item) {
2767 template<
typename T>
2772 bool match(std::vector<T>
const &v)
const override {
2773 for (
auto const& el : v) {
2774 if (el == m_comparator) {
2788 template<
typename T>
2793 bool match(std::vector<T>
const &v)
const override {
2795 if (m_comparator.size() > v.size())
2797 for (
auto const& comparator : m_comparator) {
2798 auto present =
false;
2799 for (
const auto& el : v) {
2800 if (el == comparator) {
2818 template<
typename T>
2823 bool match(std::vector<T>
const &v)
const override {
2828 if (m_comparator.size() != v.size())
2830 for (std::size_t i = 0; i < v.size(); ++i)
2831 if (m_comparator[i] != v[i])
2841 template<
typename T>
2844 bool match(std::vector<T>
const& vec)
const override {
2847 if (m_target.size() != vec.size()) {
2850 auto lfirst = m_target.begin(), llast = m_target.end();
2851 auto rfirst = vec.begin(), rlast = vec.end();
2853 while (lfirst != llast && *lfirst == *rfirst) {
2856 if (lfirst == llast) {
2860 for (
auto mid = lfirst; mid != llast; ++mid) {
2866 if (num_vec == 0 ||
Detail::count(lfirst, llast, *mid) != num_vec) {
2886 template<
typename T>
2891 template<
typename T>
2896 template<
typename T>
2901 template<
typename T>
2912 template<
typename ArgT,
typename MatcherT>
2921 m_matcher( matcher ),
2922 m_matcherString( matcherString )
2926 auto matcherAsString = m_matcher.toString();
2929 os << m_matcherString;
2931 os << matcherAsString;
2939 template<
typename ArgT,
typename MatcherT>
2947 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 2949 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2950 INTERNAL_CATCH_TRY { \ 2951 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ 2952 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 2953 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2957 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 2959 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2960 if( catchAssertionHandler.allowThrows() ) \ 2962 static_cast<void>(__VA_ARGS__ ); \ 2963 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2965 catch( exceptionType const& ex ) { \ 2966 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ 2969 catchAssertionHandler.handleUnexpectedInflightException(); \ 2972 catchAssertionHandler.handleThrowingCallSkipped(); \ 2973 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2995 auto size() const ->
size_t {
return m_size; }
3003 virtual auto hasGenerator()
const ->
bool = 0;
3006 virtual auto getIndex()
const -> std::size_t = 0;
3014 #include <stdexcept> 3017 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 3018 template <
typename Ex>
3023 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 3029 #define CATCH_PREPARE_EXCEPTION( type, msg ) \ 3030 type( ( Catch::ReusableStringStream() << msg ).str() ) 3031 #define CATCH_INTERNAL_ERROR( msg ) \ 3032 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg)) 3033 #define CATCH_ERROR( msg ) \ 3034 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg )) 3035 #define CATCH_RUNTIME_ERROR( msg ) \ 3036 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg )) 3037 #define CATCH_ENFORCE( condition, msg ) \ 3038 do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) 3048 namespace Generators {
3052 template<
typename T,
typename... Args>
3054 return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
3058 template<
typename T>
3061 virtual auto get(
size_t index )
const -> T = 0;
3064 template<
typename T>
3070 auto get( size_t )
const -> T
override {
3075 template<
typename T>
3082 auto get(
size_t index )
const -> T
override {
3083 return m_values[index];
3087 template<
typename T>
3094 assert( m_last > m_first );
3097 auto get(
size_t index )
const -> T
override {
3099 return static_cast<T
>(m_first+index);
3103 template<
typename T>
3105 auto get( size_t )
const -> T
override {
3110 template<
typename T>
3117 : m_generator(
std::move( generator ) ),
3121 auto size() const ->
size_t {
return m_size; }
3123 assert( index < m_size );
3124 return m_generator->get( index );
3128 std::vector<size_t>
randomiseIndices(
size_t selectionSize,
size_t sourceSize );
3130 template<
typename T>
3137 : m_baseGenerator(
std::move( baseGenerator ) ),
3138 m_indices( randomiseIndices( numberOfItems, m_baseGenerator.size() ) )
3141 auto get(
size_t index )
const -> T
override {
3142 return m_baseGenerator[m_indices[index]];
3146 template<
typename T>
3149 template<
typename T>
3155 template<
typename T>
3160 template<
typename T>
3162 auto gen =
range( first, last );
3163 auto size = gen.size();
3165 return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( std::move( gen ), size ) );
3167 template<
typename T>
3169 return Generator<T>( size, pf::make_unique<GeneratorRandomiser<T>>( all<T>(), size ) );
3172 template<
typename T>
3176 template<
typename T>
3178 return Generator<T>( 1, pf::make_unique<SingleValueGenerator<T>>( val ) );
3181 template<
typename T>
3183 return Generator<T>( 0, pf::make_unique<NullGenerator<T>>() );
3186 template<
typename... Ts>
3187 auto table( std::initializer_list<std::tuple<Ts...>>&& tuples ) ->
Generator<std::tuple<Ts...>> {
3188 return values<std::tuple<Ts...>>( std::forward<std::initializer_list<std::tuple<Ts...>>>( tuples ) );
3191 template<
typename T>
3201 m_generators.emplace_back(
value( std::move( val ) ) );
3203 template<
typename U>
3205 populate( T( std::move( val ) ) );
3208 m_size += generator.size();
3209 m_generators.emplace_back( std::move( generator ) );
3212 template<
typename U,
typename... Gs>
3213 void populate( U&& valueOrGenerator, Gs... moreGenerators ) {
3214 populate( std::forward<U>( valueOrGenerator ) );
3215 populate( std::forward<Gs>( moreGenerators )... );
3220 for(
auto const& gen : m_generators ) {
3221 auto localIndex = index-sizes;
3222 sizes += gen.size();
3224 return gen[localIndex];
3230 template<
typename T,
typename... Gs>
3233 generators.m_generators.reserve( 1+
sizeof...(Gs) );
3234 generators.populate( std::move( generator ), std::forward<Gs>( moreGenerators )... );
3237 template<
typename T>
3240 generators.populate( std::move( generator ) );
3243 template<
typename T,
typename... Gs>
3245 return makeGenerators(
value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
3247 template<
typename T,
typename U,
typename... Gs>
3249 return makeGenerators(
value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
3254 template<
typename L>
3258 auto generate(
SourceLineInfo const& lineInfo, L
const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>()[0]) {
3259 using UnderlyingType =
typename decltype(generatorExpression())::type;
3266 return generator[tracker.
getIndex()];
3272 #define GENERATE( ... ) \ 3273 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 3286 #pragma clang diagnostic push 3287 #pragma clang diagnostic ignored "-Wpadded" 3292 struct ITestInvoker;
3298 ShouldFail = 1 << 2,
3301 NonPortable = 1 << 5,
3306 std::string
const& _className,
3307 std::string
const& _description,
3308 std::vector<std::string>
const& _tags,
3311 friend void setTags(
TestCaseInfo& testCaseInfo, std::vector<std::string> tags );
3313 bool isHidden()
const;
3314 bool throws()
const;
3315 bool okToFail()
const;
3316 bool expectedToFail()
const;
3318 std::string tagsAsString()
const;
3334 TestCase withName( std::string
const& _newName )
const;
3336 void invoke()
const;
3340 bool operator == (
TestCase const& other )
const;
3341 bool operator < (
TestCase const& other )
const;
3344 std::shared_ptr<ITestInvoker>
test;
3348 std::string
const& className,
3354 #pragma clang diagnostic pop 3364 virtual bool aborting()
const = 0;
3373 #import <objc/runtime.h> 3398 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
3400 virtual void invoke()
const {
3401 id obj = [[m_cls alloc] init];
3403 performOptionalSelector( obj,
@selector(setUp) );
3404 performOptionalSelector( obj, m_sel );
3405 performOptionalSelector( obj,
@selector(tearDown) );
3407 arcSafeRelease( obj );
3410 virtual ~OcMethod() {}
3418 inline std::string getAnnotation( Class cls,
3419 std::string
const& annotationName,
3420 std::string
const& testCaseName ) {
3421 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3422 SEL sel = NSSelectorFromString( selStr );
3423 arcSafeRelease( selStr );
3424 id value = performOptionalSelector( cls, sel );
3426 return [(NSString*)value UTF8String];
3431 inline std::size_t registerTestMethods() {
3432 std::size_t noTestMethods = 0;
3433 int noClasses = objc_getClassList(
nullptr, 0 );
3435 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc(
sizeof(Class) * noClasses);
3436 objc_getClassList( classes, noClasses );
3438 for(
int c = 0; c < noClasses; c++ ) {
3439 Class cls = classes[c];
3442 Method* methods = class_copyMethodList( cls, &count );
3443 for( u_int m = 0; m <
count ; m++ ) {
3444 SEL selector = method_getName(methods[m]);
3445 std::string methodName = sel_getName(selector);
3446 if(
startsWith( methodName,
"Catch_TestCase_" ) ) {
3447 std::string testCaseName = methodName.substr( 15 );
3448 std::string name = Detail::getAnnotation( cls,
"Name", testCaseName );
3449 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
3450 const char* className = class_getName( cls );
3459 return noTestMethods;
3462 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 3464 namespace Matchers {
3466 namespace NSStringMatchers {
3468 struct StringHolder : MatcherBase<NSString*>{
3469 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
3470 StringHolder( StringHolder
const& other ) : m_substr( [other.m_substr copy] ){}
3472 arcSafeRelease( m_substr );
3475 bool match( NSString* arg )
const override {
3479 NSString* CATCH_ARC_STRONG m_substr;
3482 struct Equals : StringHolder {
3483 Equals( NSString* substr ) : StringHolder( substr ){}
3485 bool match( NSString* str )
const override {
3486 return (str != nil || m_substr == nil ) &&
3487 [str isEqualToString:m_substr];
3490 std::string describe()
const override {
3496 Contains( NSString* substr ) : StringHolder( substr ){}
3498 bool match( NSString* str )
const {
3499 return (str != nil || m_substr == nil ) &&
3500 [str rangeOfString:m_substr].location != NSNotFound;
3503 std::string describe()
const override {
3509 StartsWith( NSString* substr ) : StringHolder( substr ){}
3511 bool match( NSString* str )
const override {
3512 return (str != nil || m_substr == nil ) &&
3513 [str rangeOfString:m_substr].location == 0;
3516 std::string describe()
const override {
3521 EndsWith( NSString* substr ) : StringHolder( substr ){}
3523 bool match( NSString* str )
const override {
3524 return (str != nil || m_substr == nil ) &&
3525 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
3528 std::string describe()
const override {
3550 using namespace Matchers;
3552 #endif // CATCH_CONFIG_DISABLE_MATCHERS 3557 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix 3558 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ 3559 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ 3563 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ 3567 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) 3569 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) 3574 #ifdef CATCH_CONFIG_EXTERNAL_INTERFACES 3586 #pragma clang diagnostic push 3587 #pragma clang diagnostic ignored "-Wpadded" 3593 #pragma clang diagnostic push 3594 #pragma clang diagnostic ignored "-Wpadded" 3601 class WildcardPattern {
3602 enum WildcardPosition {
3604 WildcardAtStart = 1,
3606 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3612 virtual ~WildcardPattern() =
default;
3613 virtual bool matches( std::string
const& str )
const;
3616 std::string adjustCase( std::string
const& str )
const;
3618 WildcardPosition m_wildcard = NoWildcard;
3619 std::string m_pattern;
3633 virtual bool matches(
TestCaseInfo const& testCase )
const = 0;
3635 using PatternPtr = std::shared_ptr<Pattern>;
3637 class NamePattern :
public Pattern {
3639 NamePattern( std::string
const& name );
3640 virtual ~NamePattern();
3641 virtual bool matches(
TestCaseInfo const& testCase )
const override;
3643 WildcardPattern m_wildcardPattern;
3646 class TagPattern :
public Pattern {
3648 TagPattern( std::string
const& tag );
3649 virtual ~TagPattern();
3650 virtual bool matches(
TestCaseInfo const& testCase )
const override;
3655 class ExcludedPattern :
public Pattern {
3657 ExcludedPattern( PatternPtr
const& underlyingPattern );
3658 virtual ~ExcludedPattern();
3659 virtual bool matches(
TestCaseInfo const& testCase )
const override;
3661 PatternPtr m_underlyingPattern;
3665 std::vector<PatternPtr> m_patterns;
3671 bool hasFilters()
const;
3675 std::vector<Filter> m_filters;
3677 friend class TestSpecParser;
3682 #pragma clang diagnostic pop 3694 struct ITagAliasRegistry {
3695 virtual ~ITagAliasRegistry();
3697 virtual TagAlias
const* find( std::string
const& alias )
const = 0;
3698 virtual std::string expandAliases( std::string
const& unexpandedTestSpec )
const = 0;
3700 static ITagAliasRegistry
const&
get();
3708 class TestSpecParser {
3709 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
3711 bool m_exclusion =
false;
3712 std::size_t m_start = std::string::npos, m_pos = 0;
3714 std::vector<std::size_t> m_escapeChars;
3715 TestSpec::Filter m_currentFilter;
3716 TestSpec m_testSpec;
3717 ITagAliasRegistry
const* m_tagAliases =
nullptr;
3720 TestSpecParser( ITagAliasRegistry
const& tagAliases );
3722 TestSpecParser& parse( std::string
const& arg );
3723 TestSpec testSpec();
3726 void visitChar(
char c );
3727 void startNewMode( Mode mode, std::size_t
start );
3729 std::string subString()
const;
3731 template<
typename T>
3733 std::string token = subString();
3734 for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
3735 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
3736 m_escapeChars.clear();
3739 token = token.substr( 8 );
3741 if( !token.empty() ) {
3742 TestSpec::PatternPtr pattern = std::make_shared<T>( token );
3744 pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
3745 m_currentFilter.m_patterns.push_back( pattern );
3747 m_exclusion =
false;
3753 TestSpec parseTestSpec( std::string
const& arg );
3758 #pragma clang diagnostic pop 3771 enum class Verbosity {
3777 struct WarnAbout {
enum What {
3779 NoAssertions = 0x01,
3783 struct ShowDurations {
enum OrNot {
3788 struct RunTests {
enum InWhatOrder {
3790 InLexicographicalOrder,
3793 struct UseColour {
enum YesOrNo {
3798 struct WaitForKeypress {
enum When {
3802 BeforeStartAndExit = BeforeStart | BeforeExit
3811 virtual bool allowThrows()
const = 0;
3812 virtual std::ostream& stream()
const = 0;
3813 virtual std::string name()
const = 0;
3814 virtual bool includeSuccessfulResults()
const = 0;
3815 virtual bool shouldDebugBreak()
const = 0;
3816 virtual bool warnAboutMissingAssertions()
const = 0;
3817 virtual bool warnAboutNoTests()
const = 0;
3818 virtual int abortAfter()
const = 0;
3819 virtual bool showInvisibles()
const = 0;
3820 virtual ShowDurations::OrNot showDurations()
const = 0;
3821 virtual TestSpec
const& testSpec()
const = 0;
3822 virtual bool hasTestFilters()
const = 0;
3823 virtual RunTests::InWhatOrder runOrder()
const = 0;
3824 virtual unsigned int rngSeed()
const = 0;
3825 virtual int benchmarkResolutionMultiple()
const = 0;
3826 virtual UseColour::YesOrNo useColour()
const = 0;
3827 virtual std::vector<std::string>
const& getSectionsToRun()
const = 0;
3828 virtual Verbosity verbosity()
const = 0;
3831 using IConfigPtr = std::shared_ptr<IConfig const>;
3841 #ifndef CATCH_CONFIG_CONSOLE_WIDTH 3842 #define CATCH_CONFIG_CONSOLE_WIDTH 80 3850 bool listTests =
false;
3851 bool listTags =
false;
3852 bool listReporters =
false;
3853 bool listTestNamesOnly =
false;
3855 bool showSuccessfulTests =
false;
3856 bool shouldDebugBreak =
false;
3857 bool noThrow =
false;
3858 bool showHelp =
false;
3859 bool showInvisibles =
false;
3860 bool filenamesAsTags =
false;
3861 bool libIdentify =
false;
3863 int abortAfter = -1;
3865 int benchmarkResolutionMultiple = 100;
3867 Verbosity verbosity = Verbosity::Normal;
3868 WarnAbout::What warnings = WarnAbout::Nothing;
3869 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
3870 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
3871 UseColour::YesOrNo useColour = UseColour::Auto;
3872 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
3874 std::string outputFilename;
3876 std::string processName;
3877 #ifndef CATCH_CONFIG_DEFAULT_REPORTER 3878 #define CATCH_CONFIG_DEFAULT_REPORTER "console" 3880 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
3881 #undef CATCH_CONFIG_DEFAULT_REPORTER 3883 std::vector<std::string> testsOrTags;
3884 std::vector<std::string> sectionsToRun;
3887 class Config :
public IConfig {
3891 Config( ConfigData
const& data );
3892 virtual ~Config() =
default;
3894 std::string
const& getFilename()
const;
3896 bool listTests()
const;
3897 bool listTestNamesOnly()
const;
3898 bool listTags()
const;
3899 bool listReporters()
const;
3901 std::string getProcessName()
const;
3902 std::string
const& getReporterName()
const;
3904 std::vector<std::string>
const& getTestsOrTags()
const;
3905 std::vector<std::string>
const& getSectionsToRun()
const override;
3907 virtual TestSpec
const& testSpec()
const override;
3908 bool hasTestFilters()
const override;
3910 bool showHelp()
const;
3913 bool allowThrows()
const override;
3914 std::ostream& stream()
const override;
3915 std::string name()
const override;
3916 bool includeSuccessfulResults()
const override;
3917 bool warnAboutMissingAssertions()
const override;
3918 bool warnAboutNoTests()
const override;
3919 ShowDurations::OrNot showDurations()
const override;
3920 RunTests::InWhatOrder runOrder()
const override;
3921 unsigned int rngSeed()
const override;
3922 int benchmarkResolutionMultiple()
const override;
3923 UseColour::YesOrNo useColour()
const override;
3924 bool shouldDebugBreak()
const override;
3925 int abortAfter()
const override;
3926 bool showInvisibles()
const override;
3927 Verbosity verbosity()
const override;
3934 std::unique_ptr<IStream const> m_stream;
3935 TestSpec m_testSpec;
3936 bool m_hasTestFilters =
false;
3948 struct AssertionResultData
3950 AssertionResultData() =
delete;
3954 std::string message;
3955 mutable std::string reconstructedExpression;
3959 std::string reconstructExpression()
const;
3962 class AssertionResult {
3964 AssertionResult() =
delete;
3965 AssertionResult(
AssertionInfo const& info, AssertionResultData
const& data );
3968 bool succeeded()
const;
3970 bool hasExpression()
const;
3971 bool hasMessage()
const;
3972 std::string getExpression()
const;
3973 std::string getExpressionInMacro()
const;
3974 bool hasExpandedExpression()
const;
3975 std::string getExpandedExpression()
const;
3976 std::string getMessage()
const;
3982 AssertionResultData m_resultData;
3993 template<
typename T>
3996 Option() : nullableValue(
nullptr ) {}
3997 Option( T
const& _value )
3998 : nullableValue(
new( storage ) T( _value ) )
4000 Option( Option
const& _other )
4001 : nullableValue( _other ?
new( storage ) T( *_other ) :
nullptr )
4008 Option& operator= ( Option
const& _other ) {
4009 if( &_other !=
this ) {
4012 nullableValue =
new( storage ) T( *_other );
4016 Option& operator = ( T
const& _value ) {
4018 nullableValue =
new( storage ) T( _value );
4024 nullableValue->~T();
4025 nullableValue =
nullptr;
4028 T& operator*() {
return *nullableValue; }
4029 T
const& operator*()
const {
return *nullableValue; }
4030 T* operator->() {
return nullableValue; }
4031 const T* operator->()
const {
return nullableValue; }
4033 T valueOr( T
const& defaultValue )
const {
4034 return nullableValue ? *nullableValue : defaultValue;
4037 bool some()
const {
return nullableValue !=
nullptr; }
4038 bool none()
const {
return nullableValue ==
nullptr; }
4040 bool operator !()
const {
return nullableValue ==
nullptr; }
4041 explicit operator bool()
const {
4047 alignas(
alignof(T))
char storage[sizeof(T)];
4061 struct ReporterConfig {
4062 explicit ReporterConfig( IConfigPtr
const& _fullConfig );
4064 ReporterConfig( IConfigPtr
const& _fullConfig, std::ostream& _stream );
4066 std::ostream& stream()
const;
4067 IConfigPtr fullConfig()
const;
4070 std::ostream* m_stream;
4071 IConfigPtr m_fullConfig;
4074 struct ReporterPreferences {
4075 bool shouldRedirectStdOut =
false;
4076 bool shouldReportAllAssertions =
false;
4079 template<
typename T>
4080 struct LazyStat : Option<T> {
4081 LazyStat& operator=( T
const& _value ) {
4082 Option<T>::operator=( _value );
4093 struct TestRunInfo {
4094 TestRunInfo( std::string
const& _name );
4098 GroupInfo( std::string
const& _name,
4099 std::size_t _groupIndex,
4100 std::size_t _groupsCount );
4103 std::size_t groupIndex;
4104 std::size_t groupsCounts;
4107 struct AssertionStats {
4108 AssertionStats( AssertionResult
const& _assertionResult,
4109 std::vector<MessageInfo>
const& _infoMessages,
4112 AssertionStats( AssertionStats
const& ) =
default;
4113 AssertionStats( AssertionStats && ) =
default;
4114 AssertionStats& operator = ( AssertionStats
const& ) =
default;
4115 AssertionStats& operator = ( AssertionStats && ) =
default;
4116 virtual ~AssertionStats();
4118 AssertionResult assertionResult;
4119 std::vector<MessageInfo> infoMessages;
4123 struct SectionStats {
4125 Counts const& _assertions,
4126 double _durationInSeconds,
4127 bool _missingAssertions );
4128 SectionStats( SectionStats
const& ) =
default;
4129 SectionStats( SectionStats && ) =
default;
4130 SectionStats& operator = ( SectionStats
const& ) =
default;
4131 SectionStats& operator = ( SectionStats && ) =
default;
4132 virtual ~SectionStats();
4136 double durationInSeconds;
4137 bool missingAssertions;
4140 struct TestCaseStats {
4143 std::string
const& _stdOut,
4144 std::string
const& _stdErr,
4147 TestCaseStats( TestCaseStats
const& ) =
default;
4148 TestCaseStats( TestCaseStats && ) =
default;
4149 TestCaseStats& operator = ( TestCaseStats
const& ) =
default;
4150 TestCaseStats& operator = ( TestCaseStats && ) =
default;
4151 virtual ~TestCaseStats();
4160 struct TestGroupStats {
4161 TestGroupStats( GroupInfo
const& _groupInfo,
4164 TestGroupStats( GroupInfo
const& _groupInfo );
4166 TestGroupStats( TestGroupStats
const& ) =
default;
4167 TestGroupStats( TestGroupStats && ) =
default;
4168 TestGroupStats& operator = ( TestGroupStats
const& ) =
default;
4169 TestGroupStats& operator = ( TestGroupStats && ) =
default;
4170 virtual ~TestGroupStats();
4172 GroupInfo groupInfo;
4177 struct TestRunStats {
4178 TestRunStats( TestRunInfo
const& _runInfo,
4182 TestRunStats( TestRunStats
const& ) =
default;
4183 TestRunStats( TestRunStats && ) =
default;
4184 TestRunStats& operator = ( TestRunStats
const& ) =
default;
4185 TestRunStats& operator = ( TestRunStats && ) =
default;
4186 virtual ~TestRunStats();
4188 TestRunInfo runInfo;
4193 struct BenchmarkInfo {
4196 struct BenchmarkStats {
4198 std::size_t iterations;
4199 uint64_t elapsedTimeInNanoseconds;
4202 struct IStreamingReporter {
4203 virtual ~IStreamingReporter() =
default;
4209 virtual ReporterPreferences getPreferences()
const = 0;
4211 virtual void noMatchingTestCases( std::string
const& spec ) = 0;
4213 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
4214 virtual void testGroupStarting( GroupInfo
const& groupInfo ) = 0;
4216 virtual void testCaseStarting(
TestCaseInfo const& testInfo ) = 0;
4217 virtual void sectionStarting(
SectionInfo const& sectionInfo ) = 0;
4220 virtual void benchmarkStarting( BenchmarkInfo
const& ) {}
4222 virtual void assertionStarting(
AssertionInfo const& assertionInfo ) = 0;
4225 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
4228 virtual void benchmarkEnded( BenchmarkStats
const& ) {}
4230 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
4231 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
4232 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
4233 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
4235 virtual void skipTest(
TestCaseInfo const& testInfo ) = 0;
4238 virtual void fatalErrorEncountered(
StringRef name );
4240 virtual bool isMulti()
const;
4242 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
4244 struct IReporterFactory {
4245 virtual ~IReporterFactory();
4246 virtual IStreamingReporterPtr create( ReporterConfig
const& config )
const = 0;
4247 virtual std::string getDescription()
const = 0;
4251 struct IReporterRegistry {
4252 using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
4253 using Listeners = std::vector<IReporterFactoryPtr>;
4255 virtual ~IReporterRegistry();
4256 virtual IStreamingReporterPtr create( std::string
const& name, IConfigPtr
const& config )
const = 0;
4257 virtual FactoryMap
const& getFactories()
const = 0;
4258 virtual Listeners
const& getListeners()
const = 0;
4264 #include <algorithm> 4273 void prepareExpandedExpression(AssertionResult& result);
4276 std::string getFormattedDuration(
double duration );
4278 template<
typename DerivedT>
4279 struct StreamingReporterBase : IStreamingReporter {
4281 StreamingReporterBase( ReporterConfig
const& _config )
4282 : m_config( _config.fullConfig() ),
4283 stream( _config.stream() )
4285 m_reporterPrefs.shouldRedirectStdOut =
false;
4286 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
4287 CATCH_ERROR(
"Verbosity level not supported by this reporter" );
4290 ReporterPreferences getPreferences()
const override {
4291 return m_reporterPrefs;
4294 static std::set<Verbosity> getSupportedVerbosities() {
4295 return { Verbosity::Normal };
4298 ~StreamingReporterBase()
override =
default;
4300 void noMatchingTestCases(std::string
const&)
override {}
4302 void testRunStarting(TestRunInfo
const& _testRunInfo)
override {
4303 currentTestRunInfo = _testRunInfo;
4305 void testGroupStarting(GroupInfo
const& _groupInfo)
override {
4306 currentGroupInfo = _groupInfo;
4309 void testCaseStarting(
TestCaseInfo const& _testInfo)
override {
4310 currentTestCaseInfo = _testInfo;
4312 void sectionStarting(
SectionInfo const& _sectionInfo)
override {
4313 m_sectionStack.push_back(_sectionInfo);
4316 void sectionEnded(SectionStats
const& )
override {
4317 m_sectionStack.pop_back();
4319 void testCaseEnded(TestCaseStats
const& )
override {
4320 currentTestCaseInfo.reset();
4322 void testGroupEnded(TestGroupStats
const& )
override {
4323 currentGroupInfo.reset();
4325 void testRunEnded(TestRunStats
const& )
override {
4326 currentTestCaseInfo.reset();
4327 currentGroupInfo.reset();
4328 currentTestRunInfo.reset();
4336 IConfigPtr m_config;
4337 std::ostream& stream;
4339 LazyStat<TestRunInfo> currentTestRunInfo;
4340 LazyStat<GroupInfo> currentGroupInfo;
4341 LazyStat<TestCaseInfo> currentTestCaseInfo;
4343 std::vector<SectionInfo> m_sectionStack;
4344 ReporterPreferences m_reporterPrefs;
4347 template<
typename DerivedT>
4348 struct CumulativeReporterBase : IStreamingReporter {
4349 template<
typename T,
typename ChildNodeT>
4351 explicit Node( T
const& _value ) :
value( _value ) {}
4354 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
4356 ChildNodes children;
4358 struct SectionNode {
4359 explicit SectionNode(SectionStats
const& _stats) : stats(_stats) {}
4360 virtual ~SectionNode() =
default;
4362 bool operator == (SectionNode
const& other)
const {
4363 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
4365 bool operator == (std::shared_ptr<SectionNode>
const& other)
const {
4366 return operator==(*other);
4370 using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
4371 using Assertions = std::vector<AssertionStats>;
4372 ChildSections childSections;
4373 Assertions assertions;
4378 struct BySectionInfo {
4379 BySectionInfo(
SectionInfo const& other ) : m_other( other ) {}
4380 BySectionInfo( BySectionInfo
const& other ) : m_other( other.m_other ) {}
4381 bool operator() (std::shared_ptr<SectionNode>
const& node)
const {
4382 return ((node->stats.sectionInfo.name == m_other.name) &&
4383 (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
4385 void operator=(BySectionInfo
const&) =
delete;
4391 using TestCaseNode = Node<TestCaseStats, SectionNode>;
4392 using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
4393 using TestRunNode = Node<TestRunStats, TestGroupNode>;
4395 CumulativeReporterBase( ReporterConfig
const& _config )
4396 : m_config( _config.fullConfig() ),
4397 stream( _config.stream() )
4399 m_reporterPrefs.shouldRedirectStdOut =
false;
4400 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
4401 CATCH_ERROR(
"Verbosity level not supported by this reporter" );
4403 ~CumulativeReporterBase()
override =
default;
4405 ReporterPreferences getPreferences()
const override {
4406 return m_reporterPrefs;
4409 static std::set<Verbosity> getSupportedVerbosities() {
4410 return { Verbosity::Normal };
4413 void testRunStarting( TestRunInfo
const& )
override {}
4414 void testGroupStarting( GroupInfo
const& )
override {}
4416 void testCaseStarting(
TestCaseInfo const& )
override {}
4418 void sectionStarting(
SectionInfo const& sectionInfo )
override {
4419 SectionStats incompleteStats( sectionInfo,
Counts(), 0,
false );
4420 std::shared_ptr<SectionNode> node;
4421 if( m_sectionStack.empty() ) {
4422 if( !m_rootSection )
4423 m_rootSection = std::make_shared<SectionNode>( incompleteStats );
4424 node = m_rootSection;
4427 SectionNode& parentNode = *m_sectionStack.back();
4429 std::find_if( parentNode.childSections.begin(),
4430 parentNode.childSections.end(),
4431 BySectionInfo( sectionInfo ) );
4432 if( it == parentNode.childSections.end() ) {
4433 node = std::make_shared<SectionNode>( incompleteStats );
4434 parentNode.childSections.push_back( node );
4439 m_sectionStack.push_back( node );
4440 m_deepestSection = std::move(node);
4445 bool assertionEnded(AssertionStats
const& assertionStats)
override {
4446 assert(!m_sectionStack.empty());
4452 prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );
4453 SectionNode& sectionNode = *m_sectionStack.back();
4454 sectionNode.assertions.push_back(assertionStats);
4457 void sectionEnded(SectionStats
const& sectionStats)
override {
4458 assert(!m_sectionStack.empty());
4459 SectionNode& node = *m_sectionStack.back();
4460 node.stats = sectionStats;
4461 m_sectionStack.pop_back();
4463 void testCaseEnded(TestCaseStats
const& testCaseStats)
override {
4464 auto node = std::make_shared<TestCaseNode>(testCaseStats);
4465 assert(m_sectionStack.size() == 0);
4466 node->children.push_back(m_rootSection);
4467 m_testCases.push_back(node);
4468 m_rootSection.reset();
4470 assert(m_deepestSection);
4471 m_deepestSection->stdOut = testCaseStats.stdOut;
4472 m_deepestSection->stdErr = testCaseStats.stdErr;
4474 void testGroupEnded(TestGroupStats
const& testGroupStats)
override {
4475 auto node = std::make_shared<TestGroupNode>(testGroupStats);
4476 node->children.swap(m_testCases);
4477 m_testGroups.push_back(node);
4479 void testRunEnded(TestRunStats
const& testRunStats)
override {
4480 auto node = std::make_shared<TestRunNode>(testRunStats);
4481 node->children.swap(m_testGroups);
4482 m_testRuns.push_back(node);
4483 testRunEndedCumulative();
4485 virtual void testRunEndedCumulative() = 0;
4489 IConfigPtr m_config;
4490 std::ostream& stream;
4491 std::vector<AssertionStats> m_assertions;
4492 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
4493 std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
4494 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
4496 std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
4498 std::shared_ptr<SectionNode> m_rootSection;
4499 std::shared_ptr<SectionNode> m_deepestSection;
4500 std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
4501 ReporterPreferences m_reporterPrefs;
4505 char const* getLineOfChars() {
4506 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
4508 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
4509 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
4514 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
4515 TestEventListenerBase( ReporterConfig
const& _config );
4518 bool assertionEnded(AssertionStats
const&)
override;
4542 BrightRed = Bright | Red,
4543 BrightGreen = Bright | Green,
4544 LightGrey = Bright | Grey,
4545 BrightWhite = Bright | White,
4546 BrightYellow = Bright | Yellow,
4549 FileName = LightGrey,
4550 Warning = BrightYellow,
4551 ResultError = BrightRed,
4552 ResultSuccess = BrightGreen,
4553 ResultExpectedFailure = Warning,
4558 OriginalExpression = Cyan,
4559 ReconstructedExpression = BrightYellow,
4561 SecondaryText = LightGrey,
4566 Colour( Code _colourCode );
4567 Colour( Colour&& other ) noexcept;
4568 Colour& operator=( Colour&& other ) noexcept;
4572 static void use( Code _colourCode );
4575 bool m_moved =
false;
4578 std::ostream&
operator << ( std::ostream& os, Colour
const& );
4588 template<
typename T>
4589 class ReporterRegistrar {
4591 class ReporterFactory :
public IReporterFactory {
4593 virtual IStreamingReporterPtr create( ReporterConfig
const& config )
const override {
4594 return std::unique_ptr<T>(
new T( config ) );
4597 virtual std::string getDescription()
const override {
4598 return T::getDescription();
4604 explicit ReporterRegistrar( std::string
const& name ) {
4609 template<
typename T>
4610 class ListenerRegistrar {
4612 class ListenerFactory :
public IReporterFactory {
4614 virtual IStreamingReporterPtr create( ReporterConfig
const& config )
const override {
4615 return std::unique_ptr<T>(
new T( config ) );
4617 virtual std::string getDescription()
const override {
4618 return std::string();
4624 ListenerRegistrar() {
4630 #if !defined(CATCH_CONFIG_DISABLE) 4632 #define CATCH_REGISTER_REPORTER( name, reporterType ) \ 4633 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 4634 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ 4635 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 4637 #define CATCH_REGISTER_LISTENER( listenerType ) \ 4638 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 4639 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ 4640 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 4641 #else // CATCH_CONFIG_DISABLE 4643 #define CATCH_REGISTER_REPORTER(name, reporterType) 4644 #define CATCH_REGISTER_LISTENER(listenerType) 4646 #endif // CATCH_CONFIG_DISABLE 4654 struct CompactReporter : StreamingReporterBase<CompactReporter> {
4656 using StreamingReporterBase::StreamingReporterBase;
4658 ~CompactReporter()
override;
4660 static std::string getDescription();
4662 ReporterPreferences getPreferences()
const override;
4664 void noMatchingTestCases(std::string
const& spec)
override;
4668 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
4670 void sectionEnded(SectionStats
const& _sectionStats)
override;
4672 void testRunEnded(TestRunStats
const& _testRunStats)
override;
4681 #if defined(_MSC_VER) 4682 #pragma warning(push) 4683 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 4690 struct SummaryColumn;
4693 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
4694 std::unique_ptr<TablePrinter> m_tablePrinter;
4696 ConsoleReporter(ReporterConfig
const& config);
4697 ~ConsoleReporter()
override;
4698 static std::string getDescription();
4700 void noMatchingTestCases(std::string
const& spec)
override;
4704 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
4706 void sectionStarting(
SectionInfo const& _sectionInfo)
override;
4707 void sectionEnded(SectionStats
const& _sectionStats)
override;
4709 void benchmarkStarting(BenchmarkInfo
const& info)
override;
4710 void benchmarkEnded(BenchmarkStats
const& stats)
override;
4712 void testCaseEnded(TestCaseStats
const& _testCaseStats)
override;
4713 void testGroupEnded(TestGroupStats
const& _testGroupStats)
override;
4714 void testRunEnded(TestRunStats
const& _testRunStats)
override;
4720 void lazyPrintWithoutClosingBenchmarkTable();
4721 void lazyPrintRunInfo();
4722 void lazyPrintGroupInfo();
4723 void printTestCaseAndSectionHeader();
4725 void printClosedHeader(std::string
const& _name);
4726 void printOpenHeader(std::string
const& _name);
4730 void printHeaderString(std::string
const& _string, std::size_t indent = 0);
4732 void printTotals(
Totals const& totals);
4733 void printSummaryRow(std::string
const& label, std::vector<SummaryColumn>
const& cols, std::size_t row);
4735 void printTotalsDivider(
Totals const& totals);
4736 void printSummaryDivider();
4739 bool m_headerPrinted =
false;
4744 #if defined(_MSC_VER) 4745 #pragma warning(pop) 4759 enum ForWhat { ForTextNodes, ForAttributes };
4761 XmlEncode( std::string
const& str, ForWhat forWhat = ForTextNodes );
4763 void encodeTo( std::ostream& os )
const;
4765 friend std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode );
4775 class ScopedElement {
4777 ScopedElement( XmlWriter* writer );
4779 ScopedElement( ScopedElement&& other ) noexcept;
4780 ScopedElement& operator=( ScopedElement&& other ) noexcept;
4784 ScopedElement& writeText( std::string
const& text,
bool indent =
true );
4786 template<
typename T>
4787 ScopedElement& writeAttribute( std::string
const& name, T
const& attribute ) {
4788 m_writer->writeAttribute( name, attribute );
4793 mutable XmlWriter* m_writer =
nullptr;
4799 XmlWriter( XmlWriter
const& ) =
delete;
4800 XmlWriter& operator=( XmlWriter
const& ) =
delete;
4802 XmlWriter& startElement( std::string
const& name );
4804 ScopedElement scopedElement( std::string
const& name );
4806 XmlWriter& endElement();
4808 XmlWriter& writeAttribute( std::string
const& name, std::string
const& attribute );
4810 XmlWriter& writeAttribute( std::string
const& name,
bool attribute );
4812 template<
typename T>
4813 XmlWriter& writeAttribute( std::string
const& name, T
const& attribute ) {
4816 return writeAttribute( name, rss.
str() );
4819 XmlWriter& writeText( std::string
const& text,
bool indent =
true );
4821 XmlWriter& writeComment( std::string
const& text );
4823 void writeStylesheetRef( std::string
const& url );
4825 XmlWriter& writeBlankLine();
4827 void ensureTagClosed();
4831 void writeDeclaration();
4833 void newlineIfNecessary();
4835 bool m_tagIsOpen =
false;
4836 bool m_needsNewline =
false;
4837 std::vector<std::string> m_tags;
4838 std::string m_indent;
4847 class JunitReporter :
public CumulativeReporterBase<JunitReporter> {
4849 JunitReporter(ReporterConfig
const& _config);
4851 ~JunitReporter()
override;
4853 static std::string getDescription();
4855 void noMatchingTestCases(std::string
const& )
override;
4857 void testRunStarting(TestRunInfo
const& runInfo)
override;
4859 void testGroupStarting(GroupInfo
const& groupInfo)
override;
4861 void testCaseStarting(
TestCaseInfo const& testCaseInfo)
override;
4862 bool assertionEnded(AssertionStats
const& assertionStats)
override;
4864 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
4866 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
4868 void testRunEndedCumulative()
override;
4870 void writeGroup(TestGroupNode
const& groupNode,
double suiteTime);
4872 void writeTestCase(TestCaseNode
const& testCaseNode);
4874 void writeSection(std::string
const& className,
4875 std::string
const& rootName,
4876 SectionNode
const& sectionNode);
4878 void writeAssertions(SectionNode
const& sectionNode);
4879 void writeAssertion(AssertionStats
const& stats);
4883 std::string stdOutForSuite;
4884 std::string stdErrForSuite;
4885 unsigned int unexpectedExceptions = 0;
4886 bool m_okToFail =
false;
4895 class XmlReporter :
public StreamingReporterBase<XmlReporter> {
4897 XmlReporter(ReporterConfig
const& _config);
4899 ~XmlReporter()
override;
4901 static std::string getDescription();
4903 virtual std::string getStylesheetRef()
const;
4909 void noMatchingTestCases(std::string
const&
s)
override;
4911 void testRunStarting(TestRunInfo
const& testInfo)
override;
4913 void testGroupStarting(GroupInfo
const& groupInfo)
override;
4915 void testCaseStarting(
TestCaseInfo const& testInfo)
override;
4917 void sectionStarting(
SectionInfo const& sectionInfo)
override;
4921 bool assertionEnded(AssertionStats
const& assertionStats)
override;
4923 void sectionEnded(SectionStats
const& sectionStats)
override;
4925 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
4927 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
4929 void testRunEnded(TestRunStats
const& testRunStats)
override;
4932 Timer m_testCaseTimer;
4934 int m_sectionDepth = 0;
4944 #endif // ! CATCH_CONFIG_IMPL_ONLY 4950 #pragma clang diagnostic push 4951 #pragma clang diagnostic ignored "-Wweak-vtables" 4962 namespace TestCaseTracking {
4964 struct NameAndLocation {
4968 NameAndLocation( std::string
const& _name,
SourceLineInfo const& _location );
4973 using ITrackerPtr = std::shared_ptr<ITracker>;
4976 virtual ~ITracker();
4979 virtual NameAndLocation
const& nameAndLocation()
const = 0;
4982 virtual bool isComplete()
const = 0;
4983 virtual bool isSuccessfullyCompleted()
const = 0;
4984 virtual bool isOpen()
const = 0;
4985 virtual bool hasChildren()
const = 0;
4987 virtual ITracker& parent() = 0;
4990 virtual void close() = 0;
4991 virtual void fail() = 0;
4992 virtual void markAsNeedingAnotherRun() = 0;
4994 virtual void addChild( ITrackerPtr
const& child ) = 0;
4995 virtual ITrackerPtr findChild( NameAndLocation
const& nameAndLocation ) = 0;
4996 virtual void openChild() = 0;
4999 virtual bool isSectionTracker()
const = 0;
5000 virtual bool isIndexTracker()
const = 0;
5003 class TrackerContext {
5011 ITrackerPtr m_rootTracker;
5012 ITracker* m_currentTracker =
nullptr;
5013 RunState m_runState = NotStarted;
5017 static TrackerContext& instance();
5019 ITracker& startRun();
5023 void completeCycle();
5025 bool completedCycle()
const;
5026 ITracker& currentTracker();
5027 void setCurrentTracker( ITracker* tracker );
5030 class TrackerBase :
public ITracker {
5037 CompletedSuccessfully,
5041 using Children = std::vector<ITrackerPtr>;
5042 NameAndLocation m_nameAndLocation;
5043 TrackerContext& m_ctx;
5045 Children m_children;
5046 CycleState m_runState = NotStarted;
5049 TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
5051 NameAndLocation
const& nameAndLocation()
const override;
5052 bool isComplete()
const override;
5053 bool isSuccessfullyCompleted()
const override;
5054 bool isOpen()
const override;
5055 bool hasChildren()
const override;
5057 void addChild( ITrackerPtr
const& child )
override;
5059 ITrackerPtr findChild( NameAndLocation
const& nameAndLocation )
override;
5060 ITracker& parent()
override;
5062 void openChild()
override;
5064 bool isSectionTracker()
const override;
5065 bool isIndexTracker()
const override;
5069 void close()
override;
5070 void fail()
override;
5071 void markAsNeedingAnotherRun()
override;
5074 void moveToParent();
5078 class SectionTracker :
public TrackerBase {
5079 std::vector<std::string> m_filters;
5081 SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
5083 bool isSectionTracker()
const override;
5085 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation );
5089 void addInitialFilters( std::vector<std::string>
const& filters );
5090 void addNextFilters( std::vector<std::string>
const& filters );
5093 class IndexTracker :
public TrackerBase {
5097 IndexTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent,
int size );
5099 bool isIndexTracker()
const override;
5100 void close()
override;
5102 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation,
int size );
5111 using TestCaseTracking::ITracker;
5112 using TestCaseTracking::TrackerContext;
5113 using TestCaseTracking::SectionTracker;
5114 using TestCaseTracking::IndexTracker;
5124 struct LeakDetector {
5141 bool marginComparison(
double lhs,
double rhs,
double margin) {
5142 return (lhs + margin >= rhs) && (rhs + margin >= lhs);
5150 Approx::Approx (
double value )
5151 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
5157 Approx Approx::custom() {
5161 Approx Approx::operator-()
const {
5163 temp.m_value = -temp.m_value;
5167 std::string Approx::toString()
const {
5173 bool Approx::equalityComparisonImpl(
const double other)
const {
5176 return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
5179 void Approx::setMargin(
double margin) {
5181 "Invalid Approx::margin: " << margin <<
'.' 5182 <<
" Approx::Margin has to be non-negative.");
5186 void Approx::setEpsilon(
double epsilon) {
5188 "Invalid Approx::epsilon: " << epsilon <<
'.' 5189 <<
" Approx::epsilon has to be in [0, 1]");
5190 m_epsilon = epsilon;
5195 namespace literals {
5221 struct IMutableContext;
5223 using IConfigPtr = std::shared_ptr<IConfig const>;
5227 virtual ~IContext();
5230 virtual IRunner* getRunner() = 0;
5231 virtual IConfigPtr
const& getConfig()
const = 0;
5234 struct IMutableContext : IContext
5236 virtual ~IMutableContext();
5237 virtual void setResultCapture(
IResultCapture* resultCapture ) = 0;
5238 virtual void setRunner(
IRunner* runner ) = 0;
5239 virtual void setConfig( IConfigPtr
const& config ) = 0;
5242 static IMutableContext *currentContext;
5243 friend IMutableContext& getCurrentMutableContext();
5244 friend void cleanUpContext();
5245 static void createContext();
5248 inline IMutableContext& getCurrentMutableContext()
5250 if( !IMutableContext::currentContext )
5251 IMutableContext::createContext();
5252 return *IMutableContext::currentContext;
5255 inline IContext& getCurrentContext()
5257 return getCurrentMutableContext();
5260 void cleanUpContext();
5267 bool isDebuggerActive();
5270 #ifdef CATCH_PLATFORM_MAC 5272 #define CATCH_TRAP() __asm__("int $3\n" : : ) 5274 #elif defined(CATCH_PLATFORM_LINUX) 5278 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) 5279 #define CATCH_TRAP() asm volatile ("int $3") 5280 #else // Fall back to the generic way. 5283 #define CATCH_TRAP() raise(SIGTRAP) 5285 #elif defined(_MSC_VER) 5286 #define CATCH_TRAP() __debugbreak() 5287 #elif defined(__MINGW32__) 5288 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
5289 #define CATCH_TRAP() DebugBreak() 5293 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } 5296 inline void doNothing() {}
5298 #define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing() 5309 #if defined(CATCH_PLATFORM_WINDOWS) 5311 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) 5312 # define CATCH_DEFINED_NOMINMAX 5315 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) 5316 # define CATCH_DEFINED_WIN32_LEAN_AND_MEAN 5317 # define WIN32_LEAN_AND_MEAN 5323 #include <windows.h> 5326 #ifdef CATCH_DEFINED_NOMINMAX 5329 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN 5330 # undef WIN32_LEAN_AND_MEAN 5333 #endif // defined(CATCH_PLATFORM_WINDOWS) 5336 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 5340 struct FatalConditionHandler {
5342 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
5343 FatalConditionHandler();
5344 static void reset();
5345 ~FatalConditionHandler();
5349 static ULONG guaranteeSize;
5350 static PVOID exceptionHandlerHandle;
5355 #elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) 5361 struct FatalConditionHandler {
5364 static struct sigaction oldSigActions[];
5365 static stack_t oldSigStack;
5366 static char altStackMem[];
5368 static void handleSignal(
int sig );
5370 FatalConditionHandler();
5371 ~FatalConditionHandler();
5372 static void reset();
5380 struct FatalConditionHandler {
5392 struct IMutableContext;
5399 RunContext( RunContext
const& ) =
delete;
5400 RunContext& operator =( RunContext
const& ) =
delete;
5402 explicit RunContext( IConfigPtr
const& _config, IStreamingReporterPtr&& reporter );
5404 ~RunContext()
override;
5406 void testGroupStarting( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
5407 void testGroupEnded( std::string
const& testSpec,
Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );
5411 IConfigPtr config()
const;
5412 IStreamingReporter& reporter()
const;
5426 void handleUnexpectedExceptionNotThrown
5429 void handleUnexpectedInflightException
5431 std::string
const& message,
5433 void handleIncomplete
5440 bool sectionStarted(
SectionInfo const& sectionInfo,
Counts& assertions )
override;
5443 void sectionEndedEarly(
SectionEndInfo const& endInfo )
override;
5447 void benchmarkStarting( BenchmarkInfo
const& info )
override;
5448 void benchmarkEnded( BenchmarkStats
const& stats )
override;
5450 void pushScopedMessage(
MessageInfo const& message )
override;
5451 void popScopedMessage(
MessageInfo const& message )
override;
5453 std::string getCurrentTestName()
const override;
5455 const AssertionResult* getLastResult()
const override;
5457 void exceptionEarlyReported()
override;
5459 void handleFatalErrorCondition(
StringRef message )
override;
5461 bool lastAssertionPassed()
override;
5463 void assertionPassed()
override;
5467 bool aborting()
const final;
5471 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );
5472 void invokeActiveTestCase();
5474 void resetAssertionInfo();
5475 bool testForMissingAssertions(
Counts& assertions );
5477 void assertionEnded( AssertionResult
const& result );
5488 void handleUnfinishedSections();
5490 TestRunInfo m_runInfo;
5491 IMutableContext& m_context;
5492 TestCase const* m_activeTestCase =
nullptr;
5493 ITracker* m_testCaseTracker;
5494 Option<AssertionResult> m_lastResult;
5496 IConfigPtr m_config;
5498 IStreamingReporterPtr m_reporter;
5499 std::vector<MessageInfo> m_messages;
5501 std::vector<SectionEndInfo> m_unfinishedSections;
5502 std::vector<ITracker*> m_activeSections;
5503 TrackerContext m_trackerContext;
5504 bool m_lastAssertionPassed =
false;
5505 bool m_shouldReportUnexpected =
true;
5506 bool m_includeSuccessfulResults;
5522 : m_isNegated( isNegated )
5527 LazyExpression::operator bool()
const {
5528 return m_transientExpression !=
nullptr;
5542 os <<
"{** error - unchecked empty expression requested **}";
5552 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
5557 m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
5560 m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
5564 return getCurrentContext().getConfig()->allowThrows();
5569 if( m_reaction.shouldDebugBreak ) {
5575 CATCH_BREAK_INTO_DEBUGGER();
5577 if (m_reaction.shouldThrow) {
5578 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 5581 CATCH_ERROR(
"Test failure requires aborting test!" );
5594 m_resultCapture.handleNonExpr(m_assertionInfo,
ResultWas::Ok, m_reaction);
5597 m_resultCapture.handleNonExpr(m_assertionInfo,
ResultWas::Ok, m_reaction);
5601 m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
5605 m_resultCapture.handleNonExpr(m_assertionInfo,
ResultWas::Ok, m_reaction);
5620 lazyExpression(_lazyExpression),
5621 resultType(_resultType) {}
5623 std::string AssertionResultData::reconstructExpression()
const {
5625 if( reconstructedExpression.empty() ) {
5626 if( lazyExpression ) {
5628 rss << lazyExpression;
5629 reconstructedExpression = rss.
str();
5632 return reconstructedExpression;
5635 AssertionResult::AssertionResult(
AssertionInfo const& info, AssertionResultData
const& data )
5637 m_resultData( data )
5641 bool AssertionResult::succeeded()
const {
5651 return m_resultData.resultType;
5654 bool AssertionResult::hasExpression()
const {
5655 return m_info.capturedExpression[0] != 0;
5658 bool AssertionResult::hasMessage()
const {
5659 return !m_resultData.message.empty();
5662 std::string AssertionResult::getExpression()
const {
5664 return "!(" + m_info.capturedExpression +
")";
5666 return m_info.capturedExpression;
5669 std::string AssertionResult::getExpressionInMacro()
const {
5671 if( m_info.macroName[0] == 0 )
5672 expr = m_info.capturedExpression;
5674 expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
5675 expr += m_info.macroName;
5677 expr += m_info.capturedExpression;
5683 bool AssertionResult::hasExpandedExpression()
const {
5684 return hasExpression() && getExpandedExpression() != getExpression();
5687 std::string AssertionResult::getExpandedExpression()
const {
5688 std::string expr = m_resultData.reconstructExpression();
5694 std::string AssertionResult::getMessage()
const {
5695 return m_resultData.message;
5698 return m_info.lineInfo;
5701 StringRef AssertionResult::getTestMacroName()
const {
5702 return m_info.macroName;
5719 auto elapsed = m_timer.getElapsedNanoseconds();
5722 if( elapsed < m_resolution ) {
5723 m_iterationsToRun *= 10;
5757 #ifdef CLARA_CONFIG_CONSOLE_WIDTH 5758 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 5759 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 5761 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 5764 #pragma clang diagnostic push 5765 #pragma clang diagnostic ignored "-Wweak-vtables" 5766 #pragma clang diagnostic ignored "-Wexit-time-destructors" 5767 #pragma clang diagnostic ignored "-Wshadow" 5781 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH 5782 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 5785 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 5786 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH 5789 #ifndef CLARA_CONFIG_OPTIONAL_TYPE 5790 #ifdef __has_include 5791 #if __has_include(<optional>) && __cplusplus >= 201703L 5793 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional 5815 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 5816 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 5821 namespace TextFlow {
5823 inline auto isWhitespace(
char c) ->
bool {
5824 static std::string chars =
" \t\n\r";
5825 return chars.find(c) != std::string::npos;
5827 inline auto isBreakableBefore(
char c) ->
bool {
5828 static std::string chars =
"[({<|";
5829 return chars.find(c) != std::string::npos;
5831 inline auto isBreakableAfter(
char c) ->
bool {
5832 static std::string chars =
"])}>.,:;*+-=&/\\";
5833 return chars.find(c) != std::string::npos;
5839 std::vector<std::string> m_strings;
5840 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
5841 size_t m_indent = 0;
5842 size_t m_initialIndent = std::string::npos;
5848 Column
const& m_column;
5849 size_t m_stringIndex = 0;
5854 bool m_suffix =
false;
5856 iterator(Column
const& column,
size_t stringIndex)
5858 m_stringIndex(stringIndex) {}
5860 auto line()
const -> std::string
const& {
return m_column.m_strings[m_stringIndex]; }
5862 auto isBoundary(
size_t at)
const ->
bool {
5864 assert(at <= line().size());
5866 return at == line().size() ||
5867 (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
5868 isBreakableBefore(line()[at]) ||
5869 isBreakableAfter(line()[at - 1]);
5873 assert(m_stringIndex < m_column.m_strings.size());
5876 auto width = m_column.m_width - indent();
5878 while (m_end < line().size() && line()[m_end] !=
'\n')
5881 if (m_end < m_pos + width) {
5882 m_len = m_end - m_pos;
5885 while (len > 0 && !isBoundary(m_pos + len))
5887 while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
5899 auto indent()
const ->
size_t {
5900 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
5901 return initial == std::string::npos ? m_column.m_indent : initial;
5904 auto addIndentAndSuffix(std::string
const &plain)
const -> std::string {
5905 return std::string(indent(),
' ') + (m_suffix ? plain +
"-" : plain);
5909 using difference_type = std::ptrdiff_t;
5910 using value_type = std::string;
5911 using pointer = value_type * ;
5912 using reference = value_type & ;
5913 using iterator_category = std::forward_iterator_tag;
5915 explicit iterator(Column
const& column) : m_column(column) {
5916 assert(m_column.m_width > m_column.m_indent);
5917 assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
5923 auto operator *()
const -> std::string {
5924 assert(m_stringIndex < m_column.m_strings.size());
5925 assert(m_pos <= m_end);
5926 return addIndentAndSuffix(line().substr(m_pos, m_len));
5929 auto operator ++() -> iterator& {
5931 if (m_pos < line().size() && line()[m_pos] ==
'\n')
5934 while (m_pos < line().size() && isWhitespace(line()[m_pos]))
5937 if (m_pos == line().size()) {
5941 if (m_stringIndex < m_column.m_strings.size())
5945 auto operator ++(
int) -> iterator {
5946 iterator prev(*
this);
5951 auto operator ==(iterator
const& other)
const ->
bool {
5953 m_pos == other.m_pos &&
5954 m_stringIndex == other.m_stringIndex &&
5955 &m_column == &other.m_column;
5957 auto operator !=(iterator
const& other)
const ->
bool {
5958 return !operator==(other);
5961 using const_iterator = iterator;
5963 explicit Column(std::string
const& text) { m_strings.push_back(text); }
5965 auto width(
size_t newWidth) -> Column& {
5966 assert(newWidth > 0);
5970 auto indent(
size_t newIndent) -> Column& {
5971 m_indent = newIndent;
5974 auto initialIndent(
size_t newIndent) -> Column& {
5975 m_initialIndent = newIndent;
5979 auto width()
const ->
size_t {
return m_width; }
5980 auto begin()
const -> iterator {
return iterator(*
this); }
5981 auto end()
const -> iterator {
return { *
this, m_strings.size() }; }
5983 inline friend std::ostream&
operator << (std::ostream& os, Column
const& col) {
5985 for (
auto line : col) {
5995 auto operator + (Column
const& other)->Columns;
5997 auto toString()
const -> std::string {
5998 std::ostringstream oss;
6004 class Spacer :
public Column {
6007 explicit Spacer(
size_t spaceWidth) : Column(
"") {
6013 std::vector<Column> m_columns;
6021 std::vector<Column>
const& m_columns;
6022 std::vector<Column::iterator> m_iterators;
6023 size_t m_activeIterators;
6025 iterator(Columns
const& columns, EndTag)
6026 : m_columns(columns.m_columns),
6027 m_activeIterators(0) {
6028 m_iterators.reserve(m_columns.size());
6030 for (
auto const& col : m_columns)
6031 m_iterators.push_back(col.end());
6035 using difference_type = std::ptrdiff_t;
6036 using value_type = std::string;
6037 using pointer = value_type * ;
6038 using reference = value_type & ;
6039 using iterator_category = std::forward_iterator_tag;
6041 explicit iterator(Columns
const& columns)
6042 : m_columns(columns.m_columns),
6043 m_activeIterators(m_columns.size()) {
6044 m_iterators.reserve(m_columns.size());
6046 for (
auto const& col : m_columns)
6047 m_iterators.push_back(col.begin());
6050 auto operator ==(iterator
const& other)
const ->
bool {
6051 return m_iterators == other.m_iterators;
6053 auto operator !=(iterator
const& other)
const ->
bool {
6054 return m_iterators != other.m_iterators;
6056 auto operator *()
const -> std::string {
6057 std::string row, padding;
6059 for (
size_t i = 0; i < m_columns.size(); ++i) {
6060 auto width = m_columns[i].width();
6061 if (m_iterators[i] != m_columns[i].
end()) {
6062 std::string col = *m_iterators[i];
6063 row += padding + col;
6064 if (col.size() < width)
6065 padding = std::string(width - col.size(),
' ');
6069 padding += std::string(width,
' ');
6074 auto operator ++() -> iterator& {
6075 for (
size_t i = 0; i < m_columns.size(); ++i) {
6076 if (m_iterators[i] != m_columns[i].
end())
6081 auto operator ++(
int) -> iterator {
6082 iterator prev(*
this);
6087 using const_iterator = iterator;
6089 auto begin()
const -> iterator {
return iterator(*
this); }
6090 auto end()
const -> iterator {
return { *
this, iterator::EndTag() }; }
6092 auto operator += (Column
const& col) -> Columns& {
6093 m_columns.push_back(col);
6096 auto operator + (Column
const& col) -> Columns {
6097 Columns combined = *
this;
6102 inline friend std::ostream&
operator << (std::ostream& os, Columns
const& cols) {
6105 for (
auto line : cols) {
6115 auto toString()
const -> std::string {
6116 std::ostringstream oss;
6139 #include <algorithm> 6141 #if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) 6142 #define CATCH_PLATFORM_WINDOWS 6145 namespace Catch {
namespace clara {
6149 template<
typename L>
6150 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
6152 template<
typename ClassT,
typename ReturnT,
typename... Args>
6153 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
6154 static const bool isValid =
false;
6157 template<
typename ClassT,
typename ReturnT,
typename ArgT>
6158 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
6159 static const bool isValid =
true;
6160 using ArgType =
typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
6161 using ReturnType = ReturnT;
6169 std::string m_exeName;
6170 std::vector<std::string> m_args;
6173 Args(
int argc,
char const*
const* argv )
6174 : m_exeName(argv[0]),
6175 m_args(argv + 1, argv + argc) {}
6177 Args( std::initializer_list<std::string> args )
6178 : m_exeName( *args.begin() ),
6179 m_args( args.begin()+1, args.end() )
6182 auto exeName()
const -> std::string {
6189 enum class TokenType {
6197 inline auto isOptPrefix(
char c ) ->
bool {
6199 #ifdef CATCH_PLATFORM_WINDOWS 6207 using Iterator = std::vector<std::string>::const_iterator;
6210 std::vector<Token> m_tokenBuffer;
6213 m_tokenBuffer.resize( 0 );
6216 while( it != itEnd && it->empty() )
6220 auto const &next = *it;
6221 if( isOptPrefix( next[0] ) ) {
6222 auto delimiterPos = next.find_first_of(
" :=" );
6223 if( delimiterPos != std::string::npos ) {
6224 m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
6225 m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
6227 if( next[1] !=
'-' && next.size() > 2 ) {
6228 std::string opt =
"- ";
6229 for(
size_t i = 1; i < next.size(); ++i ) {
6231 m_tokenBuffer.push_back( { TokenType::Option, opt } );
6234 m_tokenBuffer.push_back( { TokenType::Option, next } );
6238 m_tokenBuffer.push_back( { TokenType::Argument, next } );
6244 explicit TokenStream( Args
const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
6246 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
6250 explicit operator bool()
const {
6251 return !m_tokenBuffer.empty() || it != itEnd;
6254 auto count()
const ->
size_t {
return m_tokenBuffer.size() + (itEnd - it); }
6256 auto operator*()
const -> Token {
6257 assert( !m_tokenBuffer.empty() );
6258 return m_tokenBuffer.front();
6261 auto operator->()
const -> Token
const * {
6262 assert( !m_tokenBuffer.empty() );
6263 return &m_tokenBuffer.front();
6266 auto operator++() -> TokenStream & {
6267 if( m_tokenBuffer.size() >= 2 ) {
6268 m_tokenBuffer.erase( m_tokenBuffer.begin() );
6281 Ok, LogicError, RuntimeError
6285 ResultBase( Type type ) : m_type( type ) {}
6286 virtual ~ResultBase() =
default;
6288 virtual void enforceOk()
const = 0;
6293 template<
typename T>
6294 class ResultValueBase :
public ResultBase {
6296 auto value()
const -> T
const & {
6302 ResultValueBase( Type type ) : ResultBase( type ) {}
6304 ResultValueBase( ResultValueBase
const &other ) : ResultBase( other ) {
6305 if( m_type == ResultBase::Ok )
6306 new( &m_value ) T( other.m_value );
6309 ResultValueBase( Type, T
const &
value ) : ResultBase( Ok ) {
6310 new( &m_value ) T( value );
6313 auto operator=( ResultValueBase
const &other ) -> ResultValueBase & {
6314 if( m_type == ResultBase::Ok )
6316 ResultBase::operator=(other);
6317 if( m_type == ResultBase::Ok )
6318 new( &m_value ) T( other.m_value );
6322 ~ResultValueBase()
override {
6333 class ResultValueBase<void> :
public ResultBase {
6335 using ResultBase::ResultBase;
6338 template<
typename T =
void>
6339 class BasicResult :
public ResultValueBase<T> {
6341 template<
typename U>
6342 explicit BasicResult( BasicResult<U>
const &other )
6343 : ResultValueBase<T>( other.type() ),
6344 m_errorMessage( other.errorMessage() )
6346 assert( type() != ResultBase::Ok );
6349 template<
typename U>
6350 static auto ok( U
const &
value ) -> BasicResult {
return { ResultBase::Ok, value }; }
6351 static auto ok() -> BasicResult {
return { ResultBase::Ok }; }
6352 static auto logicError( std::string
const &message ) -> BasicResult {
return { ResultBase::LogicError, message }; }
6353 static auto runtimeError( std::string
const &message ) -> BasicResult {
return { ResultBase::RuntimeError, message }; }
6355 explicit operator bool()
const {
return m_type == ResultBase::Ok; }
6356 auto type()
const -> ResultBase::Type {
return m_type; }
6357 auto errorMessage()
const -> std::string {
return m_errorMessage; }
6360 void enforceOk()
const override {
6364 assert( m_type != ResultBase::LogicError );
6365 assert( m_type != ResultBase::RuntimeError );
6366 if( m_type != ResultBase::Ok )
6370 std::string m_errorMessage;
6372 BasicResult( ResultBase::Type type, std::string
const &message )
6373 : ResultValueBase<T>(type),
6374 m_errorMessage(message)
6376 assert( m_type != ResultBase::Ok );
6379 using ResultValueBase<T>::ResultValueBase;
6380 using ResultBase::m_type;
6383 enum class ParseResultType {
6384 Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
6390 ParseState( ParseResultType type, TokenStream
const &remainingTokens )
6392 m_remainingTokens( remainingTokens )
6395 auto type()
const -> ParseResultType {
return m_type; }
6396 auto remainingTokens()
const -> TokenStream {
return m_remainingTokens; }
6399 ParseResultType m_type;
6400 TokenStream m_remainingTokens;
6403 using Result = BasicResult<void>;
6404 using ParserResult = BasicResult<ParseResultType>;
6405 using InternalParseResult = BasicResult<ParseState>;
6407 struct HelpColumns {
6412 template<
typename T>
6413 inline auto convertInto( std::string
const &source, T& target ) -> ParserResult {
6414 std::stringstream ss;
6418 return ParserResult::runtimeError(
"Unable to convert '" + source +
"' to destination type" );
6420 return ParserResult::ok( ParseResultType::Matched );
6422 inline auto convertInto( std::string
const &source, std::string& target ) -> ParserResult {
6424 return ParserResult::ok( ParseResultType::Matched );
6426 inline auto convertInto( std::string
const &source,
bool &target ) -> ParserResult {
6427 std::string srcLC = source;
6428 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), [](
char c ) {
return static_cast<char>( ::tolower(c) ); } );
6429 if (srcLC ==
"y" || srcLC ==
"1" || srcLC ==
"true" || srcLC ==
"yes" || srcLC ==
"on")
6431 else if (srcLC ==
"n" || srcLC ==
"0" || srcLC ==
"false" || srcLC ==
"no" || srcLC ==
"off")
6434 return ParserResult::runtimeError(
"Expected a boolean value but did not recognise: '" + source +
"'" );
6435 return ParserResult::ok( ParseResultType::Matched );
6437 #ifdef CLARA_CONFIG_OPTIONAL_TYPE 6438 template<
typename T>
6439 inline auto convertInto( std::string
const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
6441 auto result = convertInto( source, temp );
6443 target = std::move(temp);
6446 #endif // CLARA_CONFIG_OPTIONAL_TYPE 6457 virtual ~BoundRef() =
default;
6458 virtual auto isContainer()
const ->
bool {
return false; }
6459 virtual auto isFlag()
const ->
bool {
return false; }
6461 struct BoundValueRefBase : BoundRef {
6462 virtual auto setValue( std::string
const &arg ) -> ParserResult = 0;
6464 struct BoundFlagRefBase : BoundRef {
6465 virtual auto setFlag(
bool flag ) -> ParserResult = 0;
6466 virtual auto isFlag()
const ->
bool {
return true; }
6469 template<
typename T>
6470 struct BoundValueRef : BoundValueRefBase {
6473 explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
6475 auto setValue( std::string
const &arg ) -> ParserResult
override {
6476 return convertInto( arg, m_ref );
6480 template<
typename T>
6481 struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
6482 std::vector<T> &m_ref;
6484 explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
6486 auto isContainer()
const ->
bool override {
return true; }
6488 auto setValue( std::string
const &arg ) -> ParserResult
override {
6490 auto result = convertInto( arg, temp );
6492 m_ref.push_back( temp );
6497 struct BoundFlagRef : BoundFlagRefBase {
6500 explicit BoundFlagRef(
bool &ref ) : m_ref( ref ) {}
6502 auto setFlag(
bool flag ) -> ParserResult
override {
6504 return ParserResult::ok( ParseResultType::Matched );
6508 template<
typename ReturnType>
6509 struct LambdaInvoker {
6512 template<
typename L,
typename ArgType>
6513 static auto invoke( L
const &lambda, ArgType
const &arg ) -> ParserResult {
6514 return lambda( arg );
6519 struct LambdaInvoker<void> {
6520 template<
typename L,
typename ArgType>
6521 static auto invoke( L
const &lambda, ArgType
const &arg ) -> ParserResult {
6523 return ParserResult::ok( ParseResultType::Matched );
6527 template<
typename ArgType,
typename L>
6528 inline auto invokeLambda( L
const &lambda, std::string
const &arg ) -> ParserResult {
6530 auto result = convertInto( arg, temp );
6533 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
6536 template<
typename L>
6537 struct BoundLambda : BoundValueRefBase {
6540 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
6541 explicit BoundLambda( L
const &lambda ) : m_lambda( lambda ) {}
6543 auto setValue( std::string
const &arg ) -> ParserResult
override {
6544 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
6548 template<
typename L>
6549 struct BoundFlagLambda : BoundFlagRefBase {
6552 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
6553 static_assert( std::is_same<
typename UnaryLambdaTraits<L>::ArgType,
bool>::
value,
"flags must be boolean" );
6555 explicit BoundFlagLambda( L
const &lambda ) : m_lambda( lambda ) {}
6557 auto setFlag(
bool flag ) -> ParserResult
override {
6558 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
6562 enum class Optionality { Optional, Required };
6568 virtual ~ParserBase() =
default;
6569 virtual auto validate()
const -> Result {
return Result::ok(); }
6570 virtual auto parse( std::string
const& exeName, TokenStream
const &tokens)
const -> InternalParseResult = 0;
6571 virtual auto cardinality()
const ->
size_t {
return 1; }
6573 auto parse( Args
const &args )
const -> InternalParseResult {
6574 return parse( args.exeName(), TokenStream( args ) );
6578 template<
typename DerivedT>
6579 class ComposableParserImpl :
public ParserBase {
6581 template<
typename T>
6582 auto operator|( T
const &other )
const -> Parser;
6584 template<
typename T>
6585 auto operator+( T
const &other )
const -> Parser;
6589 template<
typename DerivedT>
6590 class ParserRefImpl :
public ComposableParserImpl<DerivedT> {
6592 Optionality m_optionality = Optionality::Optional;
6593 std::shared_ptr<BoundRef> m_ref;
6595 std::string m_description;
6597 explicit ParserRefImpl( std::shared_ptr<BoundRef>
const &ref ) : m_ref( ref ) {}
6600 template<
typename T>
6601 ParserRefImpl( T &ref, std::string
const &hint )
6602 : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
6606 template<
typename LambdaT>
6607 ParserRefImpl( LambdaT
const &ref, std::string
const &hint )
6608 : m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
6612 auto operator()( std::string
const &description ) -> DerivedT & {
6613 m_description = description;
6614 return static_cast<DerivedT &
>( *this );
6617 auto optional() -> DerivedT & {
6618 m_optionality = Optionality::Optional;
6619 return static_cast<DerivedT &
>( *this );
6622 auto required() -> DerivedT & {
6623 m_optionality = Optionality::Required;
6624 return static_cast<DerivedT &
>( *this );
6627 auto isOptional()
const ->
bool {
6628 return m_optionality == Optionality::Optional;
6631 auto cardinality()
const ->
size_t override {
6632 if( m_ref->isContainer() )
6638 auto hint()
const -> std::string {
return m_hint; }
6641 class ExeName :
public ComposableParserImpl<ExeName> {
6642 std::shared_ptr<std::string> m_name;
6643 std::shared_ptr<BoundValueRefBase> m_ref;
6645 template<
typename LambdaT>
6646 static auto makeRef(LambdaT
const &lambda) -> std::shared_ptr<BoundValueRefBase> {
6647 return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
6651 ExeName() : m_name( std::make_shared<std::string>(
"<executable>" ) ) {}
6653 explicit ExeName( std::string &ref ) : ExeName() {
6654 m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
6657 template<
typename LambdaT>
6658 explicit ExeName( LambdaT
const& lambda ) : ExeName() {
6659 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );
6663 auto parse( std::string
const&, TokenStream
const &tokens )
const -> InternalParseResult
override {
6664 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
6667 auto name()
const -> std::string {
return *m_name; }
6668 auto set( std::string
const& newName ) -> ParserResult {
6670 auto lastSlash = newName.find_last_of(
"\\/" );
6671 auto filename = ( lastSlash == std::string::npos )
6673 : newName.substr( lastSlash+1 );
6677 return m_ref->setValue( filename );
6679 return ParserResult::ok( ParseResultType::Matched );
6683 class Arg :
public ParserRefImpl<Arg> {
6685 using ParserRefImpl::ParserRefImpl;
6687 auto parse( std::string
const &, TokenStream
const &tokens )
const -> InternalParseResult
override {
6688 auto validationResult =
validate();
6689 if( !validationResult )
6690 return InternalParseResult( validationResult );
6692 auto remainingTokens = tokens;
6693 auto const &token = *remainingTokens;
6694 if( token.type != TokenType::Argument )
6695 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
6697 assert( !m_ref->isFlag() );
6698 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.get() );
6700 auto result = valueRef->setValue( remainingTokens->token );
6702 return InternalParseResult( result );
6704 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
6708 inline auto normaliseOpt( std::string
const &optName ) -> std::string {
6709 #ifdef CATCH_PLATFORM_WINDOWS 6710 if( optName[0] ==
'/' )
6711 return "-" + optName.substr( 1 );
6717 class Opt :
public ParserRefImpl<Opt> {
6719 std::vector<std::string> m_optNames;
6722 template<
typename LambdaT>
6723 explicit Opt( LambdaT
const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
6725 explicit Opt(
bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}
6727 template<
typename LambdaT>
6728 Opt( LambdaT
const &ref, std::string
const &hint ) : ParserRefImpl( ref, hint ) {}
6730 template<
typename T>
6731 Opt( T &ref, std::string
const &hint ) : ParserRefImpl( ref, hint ) {}
6733 auto operator[]( std::string
const &optName ) -> Opt & {
6734 m_optNames.push_back( optName );
6738 auto getHelpColumns()
const -> std::vector<HelpColumns> {
6739 std::ostringstream oss;
6741 for(
auto const &opt : m_optNames ) {
6748 if( !m_hint.empty() )
6749 oss <<
" <" << m_hint <<
">";
6750 return { { oss.str(), m_description } };
6753 auto isMatch( std::string
const &optToken )
const ->
bool {
6754 auto normalisedToken = normaliseOpt( optToken );
6755 for(
auto const &name : m_optNames ) {
6756 if( normaliseOpt( name ) == normalisedToken )
6762 using ParserBase::parse;
6764 auto parse( std::string
const&, TokenStream
const &tokens )
const -> InternalParseResult
override {
6765 auto validationResult =
validate();
6766 if( !validationResult )
6767 return InternalParseResult( validationResult );
6769 auto remainingTokens = tokens;
6770 if( remainingTokens && remainingTokens->type == TokenType::Option ) {
6771 auto const &token = *remainingTokens;
6772 if( isMatch(token.token ) ) {
6773 if( m_ref->isFlag() ) {
6774 auto flagRef =
static_cast<detail::BoundFlagRefBase*
>( m_ref.get() );
6775 auto result = flagRef->setFlag(
true );
6777 return InternalParseResult( result );
6778 if( result.value() == ParseResultType::ShortCircuitAll )
6779 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
6781 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.get() );
6783 if( !remainingTokens )
6784 return InternalParseResult::runtimeError(
"Expected argument following " + token.token );
6785 auto const &argToken = *remainingTokens;
6786 if( argToken.type != TokenType::Argument )
6787 return InternalParseResult::runtimeError(
"Expected argument following " + token.token );
6788 auto result = valueRef->setValue( argToken.token );
6790 return InternalParseResult( result );
6791 if( result.value() == ParseResultType::ShortCircuitAll )
6792 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
6794 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
6797 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
6800 auto validate()
const -> Result
override {
6801 if( m_optNames.empty() )
6802 return Result::logicError(
"No options supplied to Opt" );
6803 for(
auto const &name : m_optNames ) {
6805 return Result::logicError(
"Option name cannot be empty" );
6806 #ifdef CATCH_PLATFORM_WINDOWS 6807 if( name[0] !=
'-' && name[0] !=
'/' )
6808 return Result::logicError(
"Option name must begin with '-' or '/'" );
6810 if( name[0] !=
'-' )
6811 return Result::logicError(
"Option name must begin with '-'" );
6814 return ParserRefImpl::validate();
6819 Help(
bool &showHelpFlag )
6820 : Opt([&](
bool flag ) {
6821 showHelpFlag = flag;
6822 return ParserResult::ok( ParseResultType::ShortCircuitAll );
6825 static_cast<Opt &
>( *this )
6826 (
"display usage information")
6827 [
"-?"][
"-h"][
"--help"]
6832 struct Parser : ParserBase {
6834 mutable ExeName m_exeName;
6835 std::vector<Opt> m_options;
6836 std::vector<Arg> m_args;
6838 auto operator|=( ExeName
const &exeName ) -> Parser & {
6839 m_exeName = exeName;
6843 auto operator|=( Arg
const &arg ) -> Parser & {
6844 m_args.push_back(arg);
6848 auto operator|=( Opt
const &opt ) -> Parser & {
6849 m_options.push_back(opt);
6853 auto operator|=( Parser
const &other ) -> Parser & {
6854 m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
6855 m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
6859 template<
typename T>
6860 auto operator|( T
const &other )
const -> Parser {
6861 return Parser( *
this ) |= other;
6865 template<
typename T>
6866 auto operator+=( T
const &other ) -> Parser & {
return operator|=( other ); }
6867 template<
typename T>
6870 auto getHelpColumns()
const -> std::vector<HelpColumns> {
6871 std::vector<HelpColumns> cols;
6872 for (
auto const &o : m_options) {
6873 auto childCols = o.getHelpColumns();
6874 cols.insert( cols.end(), childCols.begin(), childCols.end() );
6879 void writeToStream( std::ostream &os )
const {
6880 if (!m_exeName.name().empty()) {
6881 os <<
"usage:\n" <<
" " << m_exeName.name() <<
" ";
6882 bool required =
true, first =
true;
6883 for(
auto const &arg : m_args ) {
6888 if( arg.isOptional() && required ) {
6892 os <<
"<" << arg.hint() <<
">";
6893 if( arg.cardinality() == 0 )
6898 if( !m_options.empty() )
6900 os <<
"\n\nwhere options are:" << std::endl;
6903 auto rows = getHelpColumns();
6904 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
6905 size_t optWidth = 0;
6906 for(
auto const &cols : rows )
6907 optWidth = (std::max)(optWidth, cols.left.size() + 2);
6909 optWidth = (std::min)(optWidth, consoleWidth/2);
6911 for(
auto const &cols : rows ) {
6913 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
6914 TextFlow::Spacer(4) +
6915 TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
6916 os << row << std::endl;
6920 friend auto operator<<( std::ostream &os, Parser
const &parser ) -> std::ostream& {
6921 parser.writeToStream( os );
6925 auto validate()
const -> Result
override {
6926 for(
auto const &opt : m_options ) {
6927 auto result = opt.validate();
6931 for(
auto const &arg : m_args ) {
6932 auto result = arg.validate();
6936 return Result::ok();
6939 using ParserBase::parse;
6941 auto parse( std::string
const& exeName, TokenStream
const &tokens )
const -> InternalParseResult
override {
6944 ParserBase
const* parser =
nullptr;
6947 const size_t totalParsers = m_options.size() + m_args.size();
6948 assert( totalParsers < 512 );
6950 ParserInfo parseInfos[512];
6954 for (
auto const &opt : m_options) parseInfos[i++].parser = &opt;
6955 for (
auto const &arg : m_args) parseInfos[i++].parser = &arg;
6958 m_exeName.set( exeName );
6960 auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
6961 while( result.value().remainingTokens() ) {
6962 bool tokenParsed =
false;
6964 for(
size_t i = 0; i < totalParsers; ++i ) {
6965 auto& parseInfo = parseInfos[i];
6966 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
6967 result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
6970 if (result.value().type() != ParseResultType::NoMatch) {
6978 if( result.value().type() == ParseResultType::ShortCircuitAll )
6981 return InternalParseResult::runtimeError(
"Unrecognised token: " + result.value().remainingTokens()->token );
6988 template<
typename DerivedT>
6989 template<
typename T>
6991 return Parser() |
static_cast<DerivedT
const &
>( *this ) | other;
6996 using detail::Parser;
7008 using detail::ExeName;
7014 using detail::ParseResultType;
7017 using detail::ParserResult;
7023 #pragma clang diagnostic pop 7027 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 7028 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 7029 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 7035 clara::Parser makeCommandLineParser( ConfigData& config );
7045 clara::Parser makeCommandLineParser( ConfigData& config ) {
7047 using namespace clara;
7049 auto const setWarning = [&]( std::string
const& warning ) {
7050 auto warningSet = [&]() {
7051 if( warning ==
"NoAssertions" )
7052 return WarnAbout::NoAssertions;
7054 if ( warning ==
"NoTests" )
7055 return WarnAbout::NoTests;
7057 return WarnAbout::Nothing;
7060 if (warningSet == WarnAbout::Nothing)
7061 return ParserResult::runtimeError(
"Unrecognised warning: '" + warning +
"'" );
7062 config.warnings =
static_cast<WarnAbout::What
>( config.warnings | warningSet );
7063 return ParserResult::ok( ParseResultType::Matched );
7065 auto const loadTestNamesFromFile = [&]( std::string
const& filename ) {
7066 std::ifstream
f( filename.c_str() );
7068 return ParserResult::runtimeError(
"Unable to load input file: '" + filename +
"'" );
7071 while( std::getline(
f, line ) ) {
7073 if( !line.empty() && !
startsWith( line,
'#' ) ) {
7075 line =
'"' + line +
'"';
7076 config.testsOrTags.push_back( line +
',' );
7079 return ParserResult::ok( ParseResultType::Matched );
7081 auto const setTestOrder = [&]( std::string
const& order ) {
7083 config.runOrder = RunTests::InDeclarationOrder;
7085 config.runOrder = RunTests::InLexicographicalOrder;
7087 config.runOrder = RunTests::InRandomOrder;
7089 return clara::ParserResult::runtimeError(
"Unrecognised ordering: '" + order +
"'" );
7090 return ParserResult::ok( ParseResultType::Matched );
7092 auto const setRngSeed = [&]( std::string
const& seed ) {
7093 if( seed !=
"time" )
7094 return clara::detail::convertInto( seed, config.rngSeed );
7095 config.rngSeed =
static_cast<unsigned int>( std::time(
nullptr) );
7096 return ParserResult::ok( ParseResultType::Matched );
7098 auto const setColourUsage = [&]( std::string
const& useColour ) {
7099 auto mode =
toLower( useColour );
7102 config.useColour = UseColour::Yes;
7103 else if( mode ==
"no" )
7104 config.useColour = UseColour::No;
7105 else if( mode ==
"auto" )
7106 config.useColour = UseColour::Auto;
7108 return ParserResult::runtimeError(
"colour mode must be one of: auto, yes or no. '" + useColour +
"' not recognised" );
7109 return ParserResult::ok( ParseResultType::Matched );
7111 auto const setWaitForKeypress = [&]( std::string
const& keypress ) {
7112 auto keypressLc =
toLower( keypress );
7113 if( keypressLc ==
"start" )
7114 config.waitForKeypress = WaitForKeypress::BeforeStart;
7115 else if( keypressLc ==
"exit" )
7116 config.waitForKeypress = WaitForKeypress::BeforeExit;
7117 else if( keypressLc ==
"both" )
7118 config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
7120 return ParserResult::runtimeError(
"keypress argument must be one of: start, exit or both. '" + keypress +
"' not recognised" );
7121 return ParserResult::ok( ParseResultType::Matched );
7123 auto const setVerbosity = [&]( std::string
const& verbosity ) {
7124 auto lcVerbosity =
toLower( verbosity );
7125 if( lcVerbosity ==
"quiet" )
7126 config.verbosity = Verbosity::Quiet;
7127 else if( lcVerbosity ==
"normal" )
7128 config.verbosity = Verbosity::Normal;
7129 else if( lcVerbosity ==
"high" )
7130 config.verbosity = Verbosity::High;
7132 return ParserResult::runtimeError(
"Unrecognised verbosity, '" + verbosity +
"'" );
7133 return ParserResult::ok( ParseResultType::Matched );
7135 auto const setReporter = [&]( std::string
const& reporter ) {
7138 auto lcReporter =
toLower( reporter );
7139 auto result = factories.find( lcReporter );
7141 if( factories.end() != result )
7142 config.reporterName = lcReporter;
7144 return ParserResult::runtimeError(
"Unrecognized reporter, '" + reporter +
"'. Check available with --list-reporters" );
7145 return ParserResult::ok( ParseResultType::Matched );
7149 = ExeName( config.processName )
7150 | Help( config.showHelp )
7151 | Opt( config.listTests )
7152 ["-l"]["--list-tests"]
7153 (
"list all/matching test cases" )
7154 | Opt( config.listTags )
7155 ["-t"]["--list-tags"]
7156 (
"list all/matching tags" )
7157 | Opt( config.showSuccessfulTests )
7159 (
"include successful tests in output" )
7160 | Opt( config.shouldDebugBreak )
7162 (
"break into debugger on failure" )
7163 | Opt( config.noThrow )
7165 (
"skip exception tests" )
7166 | Opt( config.showInvisibles )
7167 ["-i"]["--invisibles"]
7168 (
"show invisibles (tabs, newlines)" )
7169 | Opt( config.outputFilename,
"filename" )
7171 (
"output filename" )
7172 | Opt( setReporter,
"name" )
7173 ["-r"]["--reporter"]
7174 (
"reporter to use (defaults to console)" )
7175 | Opt( config.name,
"name" )
7178 | Opt( [&](
bool ){ config.abortAfter = 1; } )
7180 (
"abort at first failure" )
7181 | Opt( [&](
int x ){ config.abortAfter = x; },
"no. failures" )
7183 (
"abort after x failures" )
7184 | Opt( setWarning,
"warning name" )
7186 (
"enable warnings" )
7187 | Opt( [&](
bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; },
"yes|no" )
7188 [
"-d"][
"--durations"]
7189 (
"show test durations" )
7190 | Opt( loadTestNamesFromFile,
"filename" )
7191 ["-f"]["--input-file"]
7192 (
"load test names to run from a file" )
7193 | Opt( config.filenamesAsTags )
7194 ["-#"]["--filenames-as-tags"]
7195 (
"adds a tag for the filename" )
7196 | Opt( config.sectionsToRun,
"section name" )
7198 (
"specify section to run" )
7200 ["-v"]["--verbosity"]
7201 (
"set output verbosity" )
7202 | Opt( config.listTestNamesOnly )
7203 ["--list-test-names-only"]
7204 (
"list all/matching test cases names only" )
7205 | Opt( config.listReporters )
7206 ["--list-reporters"]
7207 (
"list all reporters" )
7208 | Opt( setTestOrder,
"decl|lex|rand" )
7210 (
"test case order (defaults to decl)" )
7211 | Opt( setRngSeed,
"'time'|number" )
7213 (
"set a specific seed for random numbers" )
7214 | Opt( setColourUsage,
"yes|no" )
7216 (
"should output be colourised" )
7217 | Opt( config.libIdentify )
7219 (
"report name and version according to libidentify standard" )
7220 | Opt( setWaitForKeypress,
"start|exit|both" )
7221 ["--wait-for-keypress"]
7222 (
"waits for a keypress before exiting" )
7223 | Opt( config.benchmarkResolutionMultiple,
"multiplier" )
7224 ["--benchmark-resolution-multiple"]
7225 (
"multiple of clock resolution to run benchmarks" )
7227 | Arg( config.testsOrTags,
"test name|pattern|tags" )
7228 (
"which test or tests to use" );
7243 return file[0] ==
'\0';
7246 return line == other.
line && (file == other.
file || std::strcmp(file, other.
file) == 0);
7251 return line < other.
line || ( line == other.
line && file != other.
file && (std::strcmp(file, other.
file) < 0));
7256 os << info.
file <<
'(' << info.
line <<
')';
7258 os << info.
file <<
':' << info.
line;
7264 return std::string();
7276 Config::Config( ConfigData
const& data )
7278 m_stream( openStream() )
7280 TestSpecParser parser(ITagAliasRegistry::get());
7281 if (data.testsOrTags.empty()) {
7282 parser.parse(
"~[.]");
7285 m_hasTestFilters =
true;
7286 for(
auto const& testOrTags : data.testsOrTags )
7287 parser.parse( testOrTags );
7289 m_testSpec = parser.testSpec();
7292 std::string
const& Config::getFilename()
const {
7293 return m_data.outputFilename ;
7296 bool Config::listTests()
const {
return m_data.listTests; }
7297 bool Config::listTestNamesOnly()
const {
return m_data.listTestNamesOnly; }
7298 bool Config::listTags()
const {
return m_data.listTags; }
7299 bool Config::listReporters()
const {
return m_data.listReporters; }
7301 std::string Config::getProcessName()
const {
return m_data.processName; }
7302 std::string
const& Config::getReporterName()
const {
return m_data.reporterName; }
7304 std::vector<std::string>
const& Config::getTestsOrTags()
const {
return m_data.testsOrTags; }
7305 std::vector<std::string>
const& Config::getSectionsToRun()
const {
return m_data.sectionsToRun; }
7307 TestSpec
const& Config::testSpec()
const {
return m_testSpec; }
7308 bool Config::hasTestFilters()
const {
return m_hasTestFilters; }
7310 bool Config::showHelp()
const {
return m_data.showHelp; }
7313 bool Config::allowThrows()
const {
return !m_data.noThrow; }
7314 std::ostream& Config::stream()
const {
return m_stream->stream(); }
7315 std::string Config::name()
const {
return m_data.name.empty() ? m_data.processName : m_data.name; }
7316 bool Config::includeSuccessfulResults()
const {
return m_data.showSuccessfulTests; }
7317 bool Config::warnAboutMissingAssertions()
const {
return !!(m_data.warnings & WarnAbout::NoAssertions); }
7318 bool Config::warnAboutNoTests()
const {
return !!(m_data.warnings & WarnAbout::NoTests); }
7319 ShowDurations::OrNot Config::showDurations()
const {
return m_data.showDurations; }
7320 RunTests::InWhatOrder Config::runOrder()
const {
return m_data.runOrder; }
7322 int Config::benchmarkResolutionMultiple()
const {
return m_data.benchmarkResolutionMultiple; }
7323 UseColour::YesOrNo Config::useColour()
const {
return m_data.useColour; }
7324 bool Config::shouldDebugBreak()
const {
return m_data.shouldDebugBreak; }
7325 int Config::abortAfter()
const {
return m_data.abortAfter; }
7326 bool Config::showInvisibles()
const {
return m_data.showInvisibles; }
7327 Verbosity Config::verbosity()
const {
return m_data.verbosity; }
7329 IStream const* Config::openStream() {
7337 #if defined(__clang__) 7338 # pragma clang diagnostic push 7339 # pragma clang diagnostic ignored "-Wexit-time-destructors" 7362 struct IColourImpl {
7363 virtual ~IColourImpl() =
default;
7364 virtual void use( Colour::Code _colourCode ) = 0;
7367 struct NoColourImpl : IColourImpl {
7368 void use( Colour::Code ) {}
7370 static IColourImpl* instance() {
7371 static NoColourImpl s_instance;
7379 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) 7380 # ifdef CATCH_PLATFORM_WINDOWS 7381 # define CATCH_CONFIG_COLOUR_WINDOWS 7383 # define CATCH_CONFIG_COLOUR_ANSI 7387 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) 7392 class Win32ColourImpl :
public IColourImpl {
7394 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
7396 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7397 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
7398 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
7399 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
7402 virtual void use( Colour::Code _colourCode )
override {
7403 switch( _colourCode ) {
7404 case Colour::None:
return setTextAttribute( originalForegroundAttributes );
7405 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7406 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
7407 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
7408 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
7409 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
7410 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
7411 case Colour::Grey:
return setTextAttribute( 0 );
7413 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
7414 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
7415 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
7416 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7417 case Colour::BrightYellow:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
7427 void setTextAttribute( WORD _textAttribute ) {
7428 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
7430 HANDLE stdoutHandle;
7431 WORD originalForegroundAttributes;
7432 WORD originalBackgroundAttributes;
7435 IColourImpl* platformColourInstance() {
7436 static Win32ColourImpl s_instance;
7438 IConfigPtr config = getCurrentContext().getConfig();
7439 UseColour::YesOrNo colourMode = config
7440 ? config->useColour()
7442 if( colourMode == UseColour::Auto )
7443 colourMode = UseColour::Yes;
7444 return colourMode == UseColour::Yes
7446 : NoColourImpl::instance();
7452 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) 7463 class PosixColourImpl :
public IColourImpl {
7465 virtual void use( Colour::Code _colourCode )
override {
7466 switch( _colourCode ) {
7468 case Colour::White:
return setColour(
"[0m" );
7469 case Colour::Red:
return setColour(
"[0;31m" );
7470 case Colour::Green:
return setColour(
"[0;32m" );
7471 case Colour::Blue:
return setColour(
"[0;34m" );
7472 case Colour::Cyan:
return setColour(
"[0;36m" );
7473 case Colour::Yellow:
return setColour(
"[0;33m" );
7474 case Colour::Grey:
return setColour(
"[1;30m" );
7476 case Colour::LightGrey:
return setColour(
"[0;37m" );
7477 case Colour::BrightRed:
return setColour(
"[1;31m" );
7478 case Colour::BrightGreen:
return setColour(
"[1;32m" );
7479 case Colour::BrightWhite:
return setColour(
"[1;37m" );
7480 case Colour::BrightYellow:
return setColour(
"[1;33m" );
7486 static IColourImpl* instance() {
7487 static PosixColourImpl s_instance;
7492 void setColour(
const char* _escapeCode ) {
7497 bool useColourOnPlatform() {
7499 #ifdef CATCH_PLATFORM_MAC 7500 !isDebuggerActive() &&
7502 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) 7503 isatty(STDOUT_FILENO)
7509 IColourImpl* platformColourInstance() {
7511 IConfigPtr config = getCurrentContext().getConfig();
7512 UseColour::YesOrNo colourMode = config
7513 ? config->useColour()
7515 if( colourMode == UseColour::Auto )
7516 colourMode = useColourOnPlatform()
7519 return colourMode == UseColour::Yes
7520 ? PosixColourImpl::instance()
7521 : NoColourImpl::instance();
7527 #else // not Windows or ANSI 7531 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
7535 #endif // Windows/ ANSI/ None 7539 Colour::Colour( Code _colourCode ) { use( _colourCode ); }
7540 Colour::Colour( Colour&& rhs ) noexcept {
7541 m_moved = rhs.m_moved;
7544 Colour& Colour::operator=( Colour&& rhs ) noexcept {
7545 m_moved = rhs.m_moved;
7550 Colour::~Colour(){
if( !m_moved ) use( None ); }
7552 void Colour::use( Code _colourCode ) {
7553 static IColourImpl* impl = platformColourInstance();
7554 impl->use( _colourCode );
7557 std::ostream&
operator << ( std::ostream& os, Colour
const& ) {
7563 #if defined(__clang__) 7564 # pragma clang diagnostic pop 7572 class Context :
public IMutableContext,
NonCopyable {
7576 return m_resultCapture;
7578 virtual IRunner* getRunner()
override {
7582 virtual IConfigPtr
const& getConfig()
const override {
7586 virtual ~Context()
override;
7589 virtual void setResultCapture(
IResultCapture* resultCapture )
override {
7590 m_resultCapture = resultCapture;
7592 virtual void setRunner(
IRunner* runner )
override {
7595 virtual void setConfig( IConfigPtr
const& config )
override {
7599 friend IMutableContext& getCurrentMutableContext();
7602 IConfigPtr m_config;
7607 IMutableContext *IMutableContext::currentContext =
nullptr;
7609 void IMutableContext::createContext()
7611 currentContext =
new Context();
7614 void cleanUpContext() {
7615 delete IMutableContext::currentContext;
7616 IMutableContext::currentContext =
nullptr;
7618 IContext::~IContext() =
default;
7619 IMutableContext::~IMutableContext() =
default;
7620 Context::~Context() =
default;
7630 void writeToDebugConsole( std::string
const& text );
7634 #ifdef CATCH_PLATFORM_WINDOWS 7637 void writeToDebugConsole( std::string
const& text ) {
7638 ::OutputDebugStringA( text.c_str() );
7645 void writeToDebugConsole( std::string
const& text ) {
7655 #ifdef CATCH_PLATFORM_MAC 7658 # include <stdbool.h> 7659 # include <sys/types.h> 7660 # include <unistd.h> 7661 # include <sys/sysctl.h> 7672 bool isDebuggerActive(){
7675 struct kinfo_proc info;
7681 info.kp_proc.p_flag = 0;
7688 mib[2] = KERN_PROC_PID;
7693 size =
sizeof(info);
7694 if( sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size,
nullptr, 0) != 0 ) {
7695 Catch::cerr() <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
7701 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
7705 #elif defined(CATCH_PLATFORM_LINUX) 7717 bool isDebuggerActive(){
7721 std::ifstream in(
"/proc/self/status");
7722 for( std::string line; std::getline(in, line); ) {
7723 static const int PREFIX_LEN = 11;
7724 if( line.compare(0, PREFIX_LEN,
"TracerPid:\t") == 0 ) {
7728 return line.length() > PREFIX_LEN && line[PREFIX_LEN] !=
'0';
7735 #elif defined(_MSC_VER) 7736 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7738 bool isDebuggerActive() {
7739 return IsDebuggerPresent() != 0;
7742 #elif defined(__MINGW32__) 7743 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
7745 bool isDebuggerActive() {
7746 return IsDebuggerPresent() != 0;
7751 bool isDebuggerActive() {
return false; }
7762 if( lhs.size() + rhs.size() < 40 &&
7763 lhs.find(
'\n') == std::string::npos &&
7764 rhs.find(
'\n') == std::string::npos )
7765 os << lhs <<
" " << op <<
" " << rhs;
7767 os << lhs <<
"\n" << op <<
"\n" << rhs;
7774 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) 7777 Catch::cerr() <<
"Catch will terminate because it needed to throw an exception.\n" 7778 <<
"The message was: " << e.what() <<
'\n';
7789 ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
7790 ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
7805 ~ExceptionTranslatorRegistry();
7808 std::string tryTranslators()
const;
7811 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
7817 #import "Foundation/Foundation.h" 7822 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
7825 void ExceptionTranslatorRegistry::registerTranslator(
const IExceptionTranslator* translator ) {
7826 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
7829 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 7835 return tryTranslators();
7837 @catch (NSException *exception) {
7849 if (std::current_exception() ==
nullptr) {
7850 return "Non C++ exception. Possibly a CLR exception.";
7852 return tryTranslators();
7856 std::rethrow_exception(std::current_exception());
7858 catch( std::exception& ex ) {
7861 catch( std::string& msg ) {
7864 catch(
const char* msg ) {
7868 return "Unknown exception";
7872 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 7874 CATCH_INTERNAL_ERROR(
"Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
7878 std::string ExceptionTranslatorRegistry::tryTranslators()
const {
7879 if( m_translators.empty() )
7880 std::rethrow_exception(std::current_exception());
7882 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
7888 #if defined(__GNUC__) 7889 # pragma GCC diagnostic push 7890 # pragma GCC diagnostic ignored "-Wmissing-field-initializers" 7893 #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) 7897 void reportFatal(
char const *
const message ) {
7898 Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
7902 #endif // signals/SEH handling 7904 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 7907 struct SignalDefs { DWORD id;
const char* name; };
7912 static SignalDefs signalDefs[] = {
7913 { EXCEPTION_ILLEGAL_INSTRUCTION,
"SIGILL - Illegal instruction signal" },
7914 { EXCEPTION_STACK_OVERFLOW,
"SIGSEGV - Stack overflow" },
7915 { EXCEPTION_ACCESS_VIOLATION,
"SIGSEGV - Segmentation violation signal" },
7916 { EXCEPTION_INT_DIVIDE_BY_ZERO,
"Divide by zero error" },
7919 LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
7920 for (
auto const& def : signalDefs) {
7921 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
7922 reportFatal(def.name);
7927 return EXCEPTION_CONTINUE_SEARCH;
7930 FatalConditionHandler::FatalConditionHandler() {
7934 guaranteeSize = 32 * 1024;
7935 exceptionHandlerHandle =
nullptr;
7937 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
7939 SetThreadStackGuarantee(&guaranteeSize);
7942 void FatalConditionHandler::reset() {
7944 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
7945 SetThreadStackGuarantee(&guaranteeSize);
7946 exceptionHandlerHandle =
nullptr;
7951 FatalConditionHandler::~FatalConditionHandler() {
7955 bool FatalConditionHandler::isSet =
false;
7956 ULONG FatalConditionHandler::guaranteeSize = 0;
7957 PVOID FatalConditionHandler::exceptionHandlerHandle =
nullptr;
7961 #elif defined( CATCH_CONFIG_POSIX_SIGNALS ) 7972 constexpr
static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
7974 static SignalDefs signalDefs[] = {
7975 { SIGINT,
"SIGINT - Terminal interrupt signal" },
7976 { SIGILL,
"SIGILL - Illegal instruction signal" },
7977 { SIGFPE,
"SIGFPE - Floating point error signal" },
7978 { SIGSEGV,
"SIGSEGV - Segmentation violation signal" },
7979 { SIGTERM,
"SIGTERM - Termination request signal" },
7980 { SIGABRT,
"SIGABRT - Abort (abnormal termination) signal" }
7983 void FatalConditionHandler::handleSignal(
int sig ) {
7984 char const * name =
"<unknown signal>";
7985 for (
auto const& def : signalDefs) {
7986 if (sig == def.id) {
7996 FatalConditionHandler::FatalConditionHandler() {
7999 sigStack.ss_sp = altStackMem;
8000 sigStack.ss_size = sigStackSize;
8001 sigStack.ss_flags = 0;
8002 sigaltstack(&sigStack, &oldSigStack);
8003 struct sigaction sa = { };
8005 sa.sa_handler = handleSignal;
8006 sa.sa_flags = SA_ONSTACK;
8007 for (std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i) {
8008 sigaction(signalDefs[i].
id, &sa, &oldSigActions[i]);
8012 FatalConditionHandler::~FatalConditionHandler() {
8016 void FatalConditionHandler::reset() {
8019 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i ) {
8020 sigaction(signalDefs[i].
id, &oldSigActions[i],
nullptr);
8023 sigaltstack(&oldSigStack,
nullptr);
8028 bool FatalConditionHandler::isSet =
false;
8029 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
8030 stack_t FatalConditionHandler::oldSigStack = {};
8031 char FatalConditionHandler::altStackMem[sigStackSize] = {};
8038 void FatalConditionHandler::reset() {}
8041 #endif // signals/SEH handling 8043 #if defined(__GNUC__) 8044 # pragma GCC diagnostic pop 8051 #include <algorithm> 8058 std::mt19937& rng();
8059 void seedRng( IConfig
const& config );
8072 namespace Generators {
8074 GeneratorBase::~GeneratorBase() {}
8076 std::vector<size_t>
randomiseIndices(
size_t selectionSize,
size_t sourceSize ) {
8078 assert( selectionSize <= sourceSize );
8079 std::vector<size_t> indices;
8080 indices.reserve( selectionSize );
8081 std::uniform_int_distribution<size_t> uid( 0, sourceSize-1 );
8083 std::set<size_t> seen;
8085 while( indices.size() < selectionSize ) {
8086 auto index = uid( rng() );
8087 if( seen.insert( index ).second )
8088 indices.push_back( index );
8098 auto all<int>() -> Generator<int> {
8099 return range( std::numeric_limits<int>::min(), std::numeric_limits<int>::max() );
8114 IConfig::~IConfig() =
default;
8137 class ListeningReporter :
public IStreamingReporter {
8138 using Reporters = std::vector<IStreamingReporterPtr>;
8139 Reporters m_listeners;
8140 IStreamingReporterPtr m_reporter =
nullptr;
8141 ReporterPreferences m_preferences;
8144 ListeningReporter();
8146 void addListener( IStreamingReporterPtr&& listener );
8147 void addReporter( IStreamingReporterPtr&& reporter );
8151 ReporterPreferences getPreferences()
const override;
8153 void noMatchingTestCases( std::string
const& spec )
override;
8155 static std::set<Verbosity> getSupportedVerbosities();
8157 void benchmarkStarting( BenchmarkInfo
const& benchmarkInfo )
override;
8158 void benchmarkEnded( BenchmarkStats
const& benchmarkStats )
override;
8160 void testRunStarting( TestRunInfo
const& testRunInfo )
override;
8161 void testGroupStarting( GroupInfo
const& groupInfo )
override;
8162 void testCaseStarting(
TestCaseInfo const& testInfo )
override;
8163 void sectionStarting(
SectionInfo const& sectionInfo )
override;
8164 void assertionStarting(
AssertionInfo const& assertionInfo )
override;
8167 bool assertionEnded( AssertionStats
const& assertionStats )
override;
8168 void sectionEnded( SectionStats
const& sectionStats )
override;
8169 void testCaseEnded( TestCaseStats
const& testCaseStats )
override;
8170 void testGroupEnded( TestGroupStats
const& testGroupStats )
override;
8171 void testRunEnded( TestRunStats
const& testRunStats )
override;
8173 void skipTest(
TestCaseInfo const& testInfo )
override;
8174 bool isMulti()
const override;
8183 ReporterConfig::ReporterConfig( IConfigPtr
const& _fullConfig )
8184 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
8186 ReporterConfig::ReporterConfig( IConfigPtr
const& _fullConfig, std::ostream& _stream )
8187 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
8189 std::ostream& ReporterConfig::stream()
const {
return *m_stream; }
8190 IConfigPtr ReporterConfig::fullConfig()
const {
return m_fullConfig; }
8192 TestRunInfo::TestRunInfo( std::string
const& _name ) : name( _name ) {}
8194 GroupInfo::GroupInfo( std::string
const& _name,
8195 std::size_t _groupIndex,
8196 std::size_t _groupsCount )
8198 groupIndex( _groupIndex ),
8199 groupsCounts( _groupsCount )
8202 AssertionStats::AssertionStats( AssertionResult
const& _assertionResult,
8203 std::vector<MessageInfo>
const& _infoMessages,
8205 : assertionResult( _assertionResult ),
8206 infoMessages( _infoMessages ),
8209 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
8211 if( assertionResult.hasMessage() ) {
8214 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
8215 builder << assertionResult.getMessage();
8218 infoMessages.push_back( builder.m_info );
8222 AssertionStats::~AssertionStats() =
default;
8224 SectionStats::SectionStats(
SectionInfo const& _sectionInfo,
8225 Counts const& _assertions,
8226 double _durationInSeconds,
8227 bool _missingAssertions )
8228 : sectionInfo( _sectionInfo ),
8229 assertions( _assertions ),
8230 durationInSeconds( _durationInSeconds ),
8231 missingAssertions( _missingAssertions )
8234 SectionStats::~SectionStats() =
default;
8236 TestCaseStats::TestCaseStats(
TestCaseInfo const& _testInfo,
8238 std::string
const& _stdOut,
8239 std::string
const& _stdErr,
8241 : testInfo( _testInfo ),
8245 aborting( _aborting )
8248 TestCaseStats::~TestCaseStats() =
default;
8250 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo,
8253 : groupInfo( _groupInfo ),
8255 aborting( _aborting )
8258 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo )
8259 : groupInfo( _groupInfo ),
8263 TestGroupStats::~TestGroupStats() =
default;
8265 TestRunStats::TestRunStats( TestRunInfo
const& _runInfo,
8268 : runInfo( _runInfo ),
8270 aborting( _aborting )
8273 TestRunStats::~TestRunStats() =
default;
8275 void IStreamingReporter::fatalErrorEncountered(
StringRef ) {}
8276 bool IStreamingReporter::isMulti()
const {
return false; }
8278 IReporterFactory::~IReporterFactory() =
default;
8279 IReporterRegistry::~IReporterRegistry() =
default;
8298 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG 8303 LeakDetector::LeakDetector() {
8304 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
8305 flag |= _CRTDBG_LEAK_CHECK_DF;
8306 flag |= _CRTDBG_ALLOC_MEM_DF;
8307 _CrtSetDbgFlag(flag);
8308 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
8309 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
8311 _CrtSetBreakAlloc(-1);
8317 Catch::LeakDetector::LeakDetector() {}
8321 Catch::LeakDetector::~LeakDetector() {
8333 std::size_t listTests( Config
const& config );
8335 std::size_t listTestsNamesOnly( Config
const& config );
8338 void add( std::string
const& spelling );
8339 std::string
all()
const;
8341 std::set<std::string> spellings;
8342 std::size_t
count = 0;
8345 std::size_t listTags( Config
const& config );
8347 std::size_t listReporters();
8349 Option<std::size_t> list( Config
const& config );
8357 using namespace clara::TextFlow;
8362 #include <algorithm> 8367 std::size_t listTests( Config
const& config ) {
8368 TestSpec testSpec = config.testSpec();
8369 if( config.hasTestFilters() )
8376 for(
auto const& testCaseInfo : matchedTestCases ) {
8377 Colour::Code colour = testCaseInfo.isHidden()
8378 ? Colour::SecondaryText
8380 Colour colourGuard( colour );
8382 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) <<
"\n";
8383 if( config.verbosity() >= Verbosity::High ) {
8385 std::string description = testCaseInfo.description;
8386 if( description.empty() )
8387 description =
"(NO DESCRIPTION)";
8388 Catch::cout() << Column( description ).indent(4) << std::endl;
8390 if( !testCaseInfo.tags.empty() )
8391 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) <<
"\n";
8394 if( !config.hasTestFilters() )
8397 Catch::cout() <<
pluralise( matchedTestCases.size(),
"matching test case" ) <<
'\n' << std::endl;
8398 return matchedTestCases.size();
8401 std::size_t listTestsNamesOnly( Config
const& config ) {
8402 TestSpec testSpec = config.testSpec();
8403 std::size_t matchedTests = 0;
8405 for(
auto const& testCaseInfo : matchedTestCases ) {
8411 if ( config.verbosity() >= Verbosity::High )
8415 return matchedTests;
8418 void TagInfo::add( std::string
const& spelling ) {
8420 spellings.insert( spelling );
8425 for(
auto const& spelling : spellings )
8426 out +=
"[" + spelling +
"]";
8430 std::size_t listTags( Config
const& config ) {
8431 TestSpec testSpec = config.testSpec();
8432 if( config.hasTestFilters() )
8433 Catch::cout() <<
"Tags for matching test cases:\n";
8438 std::map<std::string, TagInfo> tagCounts;
8441 for(
auto const& testCase : matchedTestCases ) {
8442 for(
auto const& tagName : testCase.getTestCaseInfo().tags ) {
8443 std::string lcaseTagName =
toLower( tagName );
8444 auto countIt = tagCounts.find( lcaseTagName );
8445 if( countIt == tagCounts.end() )
8446 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
8447 countIt->second.add( tagName );
8451 for(
auto const& tagCount : tagCounts ) {
8453 rss <<
" " << std::setw(2) << tagCount.second.count <<
" ";
8454 auto str = rss.
str();
8455 auto wrapper = Column( tagCount.second.all() )
8457 .indent( str.size() )
8458 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
8462 return tagCounts.size();
8465 std::size_t listReporters() {
8468 std::size_t maxNameLen = 0;
8469 for(
auto const& factoryKvp : factories )
8470 maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );
8472 for(
auto const& factoryKvp : factories ) {
8474 << Column( factoryKvp.first +
":" )
8476 .width( 5+maxNameLen )
8477 + Column( factoryKvp.second->getDescription() )
8480 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
8484 return factories.size();
8487 Option<std::size_t> list( Config
const& config ) {
8488 Option<std::size_t> listedCount;
8489 if( config.listTests() )
8490 listedCount = listedCount.valueOr(0) + listTests( config );
8491 if( config.listTestNamesOnly() )
8492 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
8493 if( config.listTags() )
8494 listedCount = listedCount.valueOr(0) + listTags( config );
8495 if( config.listReporters() )
8496 listedCount = listedCount.valueOr(0) + listReporters();
8505 namespace Matchers {
8508 std::string MatcherUntypedBase::toString()
const {
8509 if( m_cachedToString.empty() )
8510 m_cachedToString = describe();
8511 return m_cachedToString;
8514 MatcherUntypedBase::~MatcherUntypedBase() =
default;
8519 using namespace Matchers;
8531 template <
typename T>
8532 std::string to_string(T
const& t) {
8533 #if defined(CATCH_CONFIG_CPP11_TO_STRING) 8534 return std::to_string(t);
8549 namespace Matchers {
8550 namespace Floating {
8551 enum class FloatingPointKind : uint8_t {
8561 template <
typename T>
8565 struct Converter<float> {
8566 static_assert(
sizeof(
float) ==
sizeof(int32_t),
"Important ULP matcher assumption violated");
8567 Converter(
float f) {
8568 std::memcpy(&i, &f,
sizeof(f));
8574 struct Converter<double> {
8575 static_assert(
sizeof(
double) ==
sizeof(int64_t),
"Important ULP matcher assumption violated");
8576 Converter(
double d) {
8577 std::memcpy(&i, &d,
sizeof(d));
8582 template <
typename T>
8583 auto convert(T t) -> Converter<T> {
8584 return Converter<T>(t);
8587 template <
typename FP>
8588 bool almostEqualUlps(FP lhs, FP rhs,
int maxUlpDiff) {
8591 if (std::isnan(lhs) || std::isnan(rhs)) {
8595 auto lc = convert(lhs);
8596 auto rc = convert(rhs);
8598 if ((lc.i < 0) != (rc.i < 0)) {
8603 auto ulpDiff = std::abs(lc.i - rc.i);
8604 return ulpDiff <= maxUlpDiff;
8610 namespace Matchers {
8611 namespace Floating {
8612 WithinAbsMatcher::WithinAbsMatcher(
double target,
double margin)
8613 :m_target{ target }, m_margin{ margin } {
8614 CATCH_ENFORCE(margin >= 0,
"Invalid margin: " << margin <<
'.' 8615 <<
" Margin has to be non-negative.");
8620 bool WithinAbsMatcher::match(
double const& matchee)
const {
8621 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
8624 std::string WithinAbsMatcher::describe()
const {
8628 WithinUlpsMatcher::WithinUlpsMatcher(
double target,
int ulps, FloatingPointKind baseType)
8629 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
8630 CATCH_ENFORCE(ulps >= 0,
"Invalid ULP setting: " << ulps <<
'.' 8631 <<
" ULPs have to be non-negative.");
8634 #if defined(__clang__) 8635 #pragma clang diagnostic push 8637 #pragma clang diagnostic ignored "-Wunreachable-code" 8640 bool WithinUlpsMatcher::match(
double const& matchee)
const {
8642 case FloatingPointKind::Float:
8643 return almostEqualUlps<float>(
static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
8644 case FloatingPointKind::Double:
8645 return almostEqualUlps<double>(matchee, m_target, m_ulps);
8651 #if defined(__clang__) 8652 #pragma clang diagnostic pop 8655 std::string WithinUlpsMatcher::describe()
const {
8656 return "is within " + Catch::to_string(m_ulps) +
" ULPs of " +
::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)?
"f" :
"");
8681 return "matches undescribed predicate";
8683 return "matches predicate: \"" + desc +
'"';
8692 namespace Matchers {
8694 namespace StdString {
8697 : m_caseSensitivity( caseSensitivity ),
8698 m_str( adjustString( str ) )
8700 std::string CasedString::adjustString( std::string
const& str )
const {
8705 std::string CasedString::caseSensitivitySuffix()
const {
8707 ?
" (case insensitive)" 8711 StringMatcherBase::StringMatcherBase( std::string
const& operation, CasedString
const& comparator )
8712 : m_comparator( comparator ),
8713 m_operation( operation ) {
8716 std::string StringMatcherBase::describe()
const {
8717 std::string description;
8718 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
8719 m_comparator.caseSensitivitySuffix().size());
8720 description += m_operation;
8721 description +=
": \"";
8722 description += m_comparator.m_str;
8723 description +=
"\"";
8724 description += m_comparator.caseSensitivitySuffix();
8728 EqualsMatcher::EqualsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"equals", comparator ) {}
8730 bool EqualsMatcher::match( std::string
const& source )
const {
8731 return m_comparator.adjustString( source ) == m_comparator.m_str;
8734 ContainsMatcher::ContainsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"contains", comparator ) {}
8736 bool ContainsMatcher::match( std::string
const& source )
const {
8737 return contains( m_comparator.adjustString( source ), m_comparator.m_str );
8740 StartsWithMatcher::StartsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"starts with", comparator ) {}
8742 bool StartsWithMatcher::match( std::string
const& source )
const {
8743 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8746 EndsWithMatcher::EndsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"ends with", comparator ) {}
8748 bool EndsWithMatcher::match( std::string
const& source )
const {
8749 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8752 RegexMatcher::RegexMatcher(std::string regex,
CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}
8754 bool RegexMatcher::match(std::string
const& matchee)
const {
8755 auto flags = std::regex::ECMAScript;
8756 if (m_caseSensitivity == CaseSensitive::Choice::No) {
8757 flags |= std::regex::icase;
8759 auto reg = std::regex(m_regex, flags);
8760 return std::regex_match(matchee, reg);
8763 std::string RegexMatcher::describe()
const {
8764 return "matches " +
::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)?
" case sensitively" :
" case insensitively");
8794 bool uncaught_exceptions();
8805 : macroName( _macroName ),
8806 lineInfo( _lineInfo ),
8808 sequence( ++globalCount )
8827 :m_info(macroName, lineInfo, type) {}
8832 : m_info( builder.
m_info )
8839 if ( !uncaught_exceptions() ){
8845 auto start = std::string::npos;
8846 for(
size_t pos = 0; pos <= names.
size(); ++pos ) {
8847 char c = names[pos];
8848 if( pos == names.
size() || c ==
' ' || c ==
'\t' || c ==
',' || c ==
']' ) {
8849 if(
start != std::string::npos ) {
8850 m_messages.push_back(
MessageInfo( macroName, lineInfo, resultType ) );
8852 start = std::string::npos;
8855 else if( c !=
'[' && c !=
']' &&
start == std::string::npos )
8860 if ( !uncaught_exceptions() ){
8861 assert( m_captured == m_messages.size() );
8862 for(
size_t i = 0; i < m_captured; ++i )
8863 m_resultCapture.popScopedMessage( m_messages[i] );
8868 assert( index < m_messages.size() );
8869 m_messages[index].message +=
value;
8870 m_resultCapture.pushScopedMessage( m_messages[index] );
8879 #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 8880 #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 8888 class RedirectedStream {
8889 std::ostream& m_originalStream;
8890 std::ostream& m_redirectionStream;
8891 std::streambuf* m_prevBuf;
8894 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
8895 ~RedirectedStream();
8898 class RedirectedStdOut {
8900 RedirectedStream m_cout;
8903 auto str()
const -> std::string;
8909 class RedirectedStdErr {
8911 RedirectedStream m_cerr;
8912 RedirectedStream m_clog;
8915 auto str()
const -> std::string;
8918 #if defined(CATCH_CONFIG_NEW_CAPTURE) 8926 TempFile(TempFile
const&) =
delete;
8927 TempFile& operator=(TempFile
const&) =
delete;
8928 TempFile(TempFile&&) =
delete;
8929 TempFile& operator=(TempFile&&) =
delete;
8934 std::FILE* getFile();
8935 std::string getContents();
8938 std::FILE* m_file =
nullptr;
8939 #if defined(_MSC_VER) 8940 char m_buffer[L_tmpnam] = { 0 };
8944 class OutputRedirect {
8946 OutputRedirect(OutputRedirect
const&) =
delete;
8947 OutputRedirect& operator=(OutputRedirect
const&) =
delete;
8948 OutputRedirect(OutputRedirect&&) =
delete;
8949 OutputRedirect& operator=(OutputRedirect&&) =
delete;
8951 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
8955 int m_originalStdout = -1;
8956 int m_originalStderr = -1;
8957 TempFile m_stdoutFile;
8958 TempFile m_stderrFile;
8959 std::string& m_stdoutDest;
8960 std::string& m_stderrDest;
8967 #endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 8973 #include <stdexcept> 8975 #if defined(CATCH_CONFIG_NEW_CAPTURE) 8976 #if defined(_MSC_VER) 8980 #define fileno _fileno 8988 RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
8989 : m_originalStream( originalStream ),
8990 m_redirectionStream( redirectionStream ),
8991 m_prevBuf( m_originalStream.rdbuf() )
8993 m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
8996 RedirectedStream::~RedirectedStream() {
8997 m_originalStream.rdbuf( m_prevBuf );
9000 RedirectedStdOut::RedirectedStdOut() : m_cout(
Catch::cout(), m_rss.get() ) {}
9001 auto RedirectedStdOut::str()
const -> std::string {
return m_rss.str(); }
9003 RedirectedStdErr::RedirectedStdErr()
9007 auto RedirectedStdErr::str()
const -> std::string {
return m_rss.str(); }
9009 #if defined(CATCH_CONFIG_NEW_CAPTURE) 9011 #if defined(_MSC_VER) 9012 TempFile::TempFile() {
9013 if (tmpnam_s(m_buffer)) {
9016 if (fopen_s(&m_file, m_buffer,
"w")) {
9018 if (strerror_s(buffer, errno)) {
9021 CATCH_RUNTIME_ERROR(
"Coul dnot open the temp file: '" << m_buffer <<
"' because: " << buffer);
9025 TempFile::TempFile() {
9026 m_file = std::tmpfile();
9034 TempFile::~TempFile() {
9036 std::fclose(m_file);
9039 #if defined(_MSC_VER) 9040 std::remove(m_buffer);
9044 FILE* TempFile::getFile() {
9048 std::string TempFile::getContents() {
9049 std::stringstream sstr;
9050 char buffer[100] = {};
9051 std::rewind(m_file);
9052 while (std::fgets(buffer,
sizeof(buffer), m_file)) {
9058 OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
9059 m_originalStdout(dup(1)),
9060 m_originalStderr(dup(2)),
9061 m_stdoutDest(stdout_dest),
9062 m_stderrDest(stderr_dest) {
9063 dup2(fileno(m_stdoutFile.getFile()), 1);
9064 dup2(fileno(m_stderrFile.getFile()), 2);
9067 OutputRedirect::~OutputRedirect() {
9076 dup2(m_originalStdout, 1);
9077 dup2(m_originalStderr, 2);
9079 m_stdoutDest += m_stdoutFile.getContents();
9080 m_stderrDest += m_stderrFile.getContents();
9083 #endif // CATCH_CONFIG_NEW_CAPTURE 9087 #if defined(CATCH_CONFIG_NEW_CAPTURE) 9088 #if defined(_MSC_VER) 9099 std::mt19937& rng() {
9100 static std::mt19937 s_rng;
9104 void seedRng( IConfig
const& config ) {
9105 if( config.rngSeed() != 0 ) {
9106 std::srand( config.rngSeed() );
9107 rng().seed( config.rngSeed() );
9112 return getCurrentContext().getConfig()->rngSeed();
9122 #include <algorithm> 9130 std::vector<TestCase> sortTests( IConfig
const& config, std::vector<TestCase>
const& unsortedTestCases );
9131 bool matchTest(
TestCase const& testCase, TestSpec
const& testSpec, IConfig
const& config );
9133 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions );
9135 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config );
9140 virtual ~TestRegistry() =
default;
9142 virtual void registerTest(
TestCase const& testCase );
9144 std::vector<TestCase>
const& getAllTests()
const override;
9145 std::vector<TestCase>
const& getAllTestsSorted( IConfig
const& config )
const override;
9148 std::vector<TestCase> m_functions;
9149 mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
9150 mutable std::vector<TestCase> m_sortedFunctions;
9151 std::size_t m_unnamedCount = 0;
9152 std::ios_base::Init m_ostreamInit;
9158 void(*m_testAsFunction)();
9160 TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept;
9162 void invoke()
const override;
9165 std::string extractClassName(
StringRef const& classOrQualifiedMethodName );
9178 class ReporterRegistry :
public IReporterRegistry {
9182 ~ReporterRegistry()
override;
9184 IStreamingReporterPtr create( std::string
const& name, IConfigPtr
const& config )
const override;
9189 FactoryMap
const& getFactories()
const override;
9190 Listeners
const& getListeners()
const override;
9193 FactoryMap m_factories;
9194 Listeners m_listeners;
9221 class TagAliasRegistry :
public ITagAliasRegistry {
9223 ~TagAliasRegistry()
override;
9224 TagAlias
const* find( std::string
const& alias )
const override;
9225 std::string expandAliases( std::string
const& unexpandedTestSpec )
const override;
9226 void add( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo );
9229 std::map<std::string, TagAlias> m_registry;
9238 #include <exception> 9242 class StartupExceptionRegistry {
9244 void add(std::exception_ptr
const& exception) noexcept;
9245 std::vector<std::exception_ptr>
const& getExceptions()
const noexcept;
9247 std::vector<std::exception_ptr> m_exceptions;
9258 virtual ~ISingleton();
9261 void addSingleton( ISingleton* singleton );
9262 void cleanupSingletons();
9264 template<
typename SingletonImplT,
typename InterfaceT = SingletonImplT,
typename MutableInterfaceT = InterfaceT>
9265 class Singleton : SingletonImplT,
public ISingleton {
9267 static auto getInternal() -> Singleton* {
9268 static Singleton* s_instance =
nullptr;
9270 s_instance =
new Singleton;
9271 addSingleton( s_instance );
9277 static auto get() -> InterfaceT
const& {
9278 return *getInternal();
9280 static auto getMutable() -> MutableInterfaceT& {
9281 return *getInternal();
9296 RegistryHub() =
default;
9297 IReporterRegistry
const& getReporterRegistry()
const override {
9298 return m_reporterRegistry;
9301 return m_testCaseRegistry;
9304 return m_exceptionTranslatorRegistry;
9306 ITagAliasRegistry
const& getTagAliasRegistry()
const override {
9307 return m_tagAliasRegistry;
9309 StartupExceptionRegistry
const& getStartupExceptionRegistry()
const override {
9310 return m_exceptionRegistry;
9314 void registerReporter( std::string
const& name,
IReporterFactoryPtr const& factory )
override {
9315 m_reporterRegistry.registerReporter( name, factory );
9318 m_reporterRegistry.registerListener( factory );
9320 void registerTest(
TestCase const& testInfo )
override {
9321 m_testCaseRegistry.registerTest( testInfo );
9324 m_exceptionTranslatorRegistry.registerTranslator( translator );
9326 void registerTagAlias( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo )
override {
9327 m_tagAliasRegistry.add( alias, tag, lineInfo );
9329 void registerStartupException() noexcept
override {
9330 m_exceptionRegistry.add(std::current_exception());
9334 TestRegistry m_testCaseRegistry;
9335 ReporterRegistry m_reporterRegistry;
9336 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
9337 TagAliasRegistry m_tagAliasRegistry;
9338 StartupExceptionRegistry m_exceptionRegistry;
9342 using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
9345 return RegistryHubSingleton::get();
9348 return RegistryHubSingleton::getMutable();
9351 cleanupSingletons();
9364 ReporterRegistry::~ReporterRegistry() =
default;
9366 IStreamingReporterPtr ReporterRegistry::create( std::string
const& name, IConfigPtr
const& config )
const {
9367 auto it = m_factories.find( name );
9368 if( it == m_factories.end() )
9370 return it->second->create( ReporterConfig( config ) );
9373 void ReporterRegistry::registerReporter( std::string
const& name,
IReporterFactoryPtr const& factory ) {
9374 m_factories.emplace(name, factory);
9377 m_listeners.push_back( factory );
9380 IReporterRegistry::FactoryMap
const& ReporterRegistry::getFactories()
const {
9383 IReporterRegistry::Listeners
const& ReporterRegistry::getListeners()
const {
9412 #include <algorithm> 9417 namespace Generators {
9419 size_t m_index =
static_cast<size_t>( -1 );
9422 GeneratorTracker( TestCaseTracking::NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
9423 : TrackerBase( nameAndLocation, ctx, parent )
9425 ~GeneratorTracker();
9427 static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation
const& nameAndLocation ) {
9428 std::shared_ptr<GeneratorTracker> tracker;
9430 ITracker& currentTracker = ctx.currentTracker();
9431 if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
9432 assert( childTracker );
9433 assert( childTracker->isIndexTracker() );
9434 tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
9437 tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker );
9438 currentTracker.addChild( tracker );
9441 if( !ctx.completedCycle() && !tracker->isComplete() ) {
9442 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
9443 tracker->moveNext();
9456 bool isIndexTracker()
const override {
return true; }
9457 auto hasGenerator()
const ->
bool override {
9458 return !!m_generator;
9460 void close()
override {
9461 TrackerBase::close();
9462 if( m_runState == CompletedSuccessfully && m_index < m_generator->size()-1 )
9463 m_runState = Executing;
9471 m_generator = std::move( generator );
9473 auto getIndex()
const ->
size_t override {
9477 GeneratorTracker::~GeneratorTracker() {}
9480 RunContext::RunContext(IConfigPtr
const& _config, IStreamingReporterPtr&& reporter)
9481 : m_runInfo(_config->name()),
9482 m_context(getCurrentMutableContext()),
9484 m_reporter(std::move(reporter)),
9486 m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
9488 m_context.setRunner(
this);
9489 m_context.setConfig(m_config);
9490 m_context.setResultCapture(
this);
9491 m_reporter->testRunStarting(m_runInfo);
9494 RunContext::~RunContext() {
9495 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
9498 void RunContext::testGroupStarting(std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
9499 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
9502 void RunContext::testGroupEnded(std::string
const& testSpec,
Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {
9503 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
9507 Totals prevTotals = m_totals;
9509 std::string redirectedCout;
9510 std::string redirectedCerr;
9514 m_reporter->testCaseStarting(testInfo);
9516 m_activeTestCase = &testCase;
9518 ITracker& rootTracker = m_trackerContext.startRun();
9519 assert(rootTracker.isSectionTracker());
9520 static_cast<SectionTracker&
>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
9522 m_trackerContext.startCycle();
9523 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
9524 runCurrentTest(redirectedCout, redirectedCerr);
9525 }
while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
9533 m_totals.testCases += deltaTotals.
testCases;
9534 m_reporter->testCaseEnded(TestCaseStats(testInfo,
9540 m_activeTestCase =
nullptr;
9541 m_testCaseTracker =
nullptr;
9546 IConfigPtr RunContext::config()
const {
9550 IStreamingReporter& RunContext::reporter()
const {
9554 void RunContext::assertionEnded(AssertionResult
const & result) {
9557 m_lastAssertionPassed =
true;
9558 }
else if (!result.isOk()) {
9559 m_lastAssertionPassed =
false;
9560 if( m_activeTestCase->getTestCaseInfo().okToFail() )
9561 m_totals.assertions.failedButOk++;
9563 m_totals.assertions.failed++;
9566 m_lastAssertionPassed =
true;
9571 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
9574 resetAssertionInfo();
9575 m_lastResult = result;
9577 void RunContext::resetAssertionInfo() {
9578 m_lastAssertionInfo.macroName =
StringRef();
9579 m_lastAssertionInfo.capturedExpression =
"{Unknown expression after the reported line}"_sr;
9582 bool RunContext::sectionStarted(
SectionInfo const & sectionInfo,
Counts & assertions) {
9583 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.
name, sectionInfo.
lineInfo));
9584 if (!sectionTracker.isOpen())
9586 m_activeSections.push_back(§ionTracker);
9588 m_lastAssertionInfo.lineInfo = sectionInfo.
lineInfo;
9590 m_reporter->sectionStarting(sectionInfo);
9592 assertions = m_totals.assertions;
9597 using namespace Generators;
9598 GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation(
"generator", lineInfo ) );
9599 assert( tracker.isOpen() );
9600 m_lastAssertionInfo.lineInfo = lineInfo;
9604 bool RunContext::testForMissingAssertions(
Counts& assertions) {
9605 if (assertions.
total() != 0)
9607 if (!m_config->warnAboutMissingAssertions())
9609 if (m_trackerContext.currentTracker().hasChildren())
9611 m_totals.assertions.failed++;
9618 bool missingAssertions = testForMissingAssertions(assertions);
9620 if (!m_activeSections.empty()) {
9621 m_activeSections.back()->close();
9622 m_activeSections.pop_back();
9629 void RunContext::sectionEndedEarly(
SectionEndInfo const & endInfo) {
9630 if (m_unfinishedSections.empty())
9631 m_activeSections.back()->fail();
9633 m_activeSections.back()->close();
9634 m_activeSections.pop_back();
9636 m_unfinishedSections.push_back(endInfo);
9638 void RunContext::benchmarkStarting( BenchmarkInfo
const& info ) {
9639 m_reporter->benchmarkStarting( info );
9641 void RunContext::benchmarkEnded( BenchmarkStats
const& stats ) {
9642 m_reporter->benchmarkEnded( stats );
9645 void RunContext::pushScopedMessage(
MessageInfo const & message) {
9646 m_messages.push_back(message);
9649 void RunContext::popScopedMessage(
MessageInfo const & message) {
9650 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
9653 std::string RunContext::getCurrentTestName()
const {
9654 return m_activeTestCase
9655 ? m_activeTestCase->getTestCaseInfo().name
9659 const AssertionResult * RunContext::getLastResult()
const {
9660 return &(*m_lastResult);
9663 void RunContext::exceptionEarlyReported() {
9664 m_shouldReportUnexpected =
false;
9667 void RunContext::handleFatalErrorCondition(
StringRef message ) {
9669 m_reporter->fatalErrorEncountered(message);
9674 tempResult.message = message;
9675 AssertionResult result(m_lastAssertionInfo, tempResult);
9677 assertionEnded(result);
9679 handleUnfinishedSections();
9682 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
9683 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
9687 SectionStats testCaseSectionStats(testCaseSection, assertions, 0,
false);
9688 m_reporter->sectionEnded(testCaseSectionStats);
9690 auto const& testInfo = m_activeTestCase->getTestCaseInfo();
9695 m_reporter->testCaseEnded(TestCaseStats(testInfo,
9700 m_totals.testCases.failed++;
9701 testGroupEnded(std::string(), m_totals, 1, 1);
9702 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals,
false));
9705 bool RunContext::lastAssertionPassed() {
9706 return m_lastAssertionPassed;
9709 void RunContext::assertionPassed() {
9710 m_lastAssertionPassed =
true;
9711 ++m_totals.assertions.passed;
9712 resetAssertionInfo();
9715 bool RunContext::aborting()
const {
9716 return m_totals.assertions.failed >=
static_cast<std::size_t
>(m_config->abortAfter());
9719 void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
9720 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
9721 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
9722 m_reporter->sectionStarting(testCaseSection);
9723 Counts prevAssertions = m_totals.assertions;
9724 double duration = 0;
9725 m_shouldReportUnexpected =
true;
9732 if (m_reporter->getPreferences().shouldRedirectStdOut) {
9733 #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 9734 RedirectedStdOut redirectedStdOut;
9735 RedirectedStdErr redirectedStdErr;
9738 invokeActiveTestCase();
9739 redirectedCout += redirectedStdOut.str();
9740 redirectedCerr += redirectedStdErr.str();
9742 OutputRedirect r(redirectedCout, redirectedCerr);
9744 invokeActiveTestCase();
9748 invokeActiveTestCase();
9756 if( m_shouldReportUnexpected ) {
9761 Counts assertions = m_totals.assertions - prevAssertions;
9762 bool missingAssertions = testForMissingAssertions(assertions);
9764 m_testCaseTracker->close();
9765 handleUnfinishedSections();
9768 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
9769 m_reporter->sectionEnded(testCaseSectionStats);
9772 void RunContext::invokeActiveTestCase() {
9773 FatalConditionHandler fatalConditionHandler;
9774 m_activeTestCase->invoke();
9775 fatalConditionHandler.reset();
9778 void RunContext::handleUnfinishedSections() {
9781 for (
auto it = m_unfinishedSections.rbegin(),
9782 itEnd = m_unfinishedSections.rend();
9786 m_unfinishedSections.clear();
9789 void RunContext::handleExpr(
9794 m_reporter->assertionStarting( info );
9797 bool result = expr.
getResult() != negated;
9800 if (!m_includeSuccessfulResults) {
9809 populateReaction( reaction );
9812 void RunContext::reportExpr(
9818 m_lastAssertionInfo = info;
9819 AssertionResultData data( resultType,
LazyExpression( negated ) );
9821 AssertionResult assertionResult{ info, data };
9822 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
9824 assertionEnded( assertionResult );
9827 void RunContext::handleMessage(
9833 m_reporter->assertionStarting( info );
9835 m_lastAssertionInfo = info;
9838 data.message = message;
9839 AssertionResult assertionResult{ m_lastAssertionInfo, data };
9840 assertionEnded( assertionResult );
9841 if( !assertionResult.isOk() )
9842 populateReaction( reaction );
9844 void RunContext::handleUnexpectedExceptionNotThrown(
9851 void RunContext::handleUnexpectedInflightException(
9853 std::string
const& message,
9856 m_lastAssertionInfo = info;
9859 data.message = message;
9860 AssertionResult assertionResult{ info, data };
9861 assertionEnded( assertionResult );
9862 populateReaction( reaction );
9870 void RunContext::handleIncomplete(
9873 m_lastAssertionInfo = info;
9876 data.message =
"Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
9877 AssertionResult assertionResult{ info, data };
9878 assertionEnded( assertionResult );
9880 void RunContext::handleNonExpr(
9885 m_lastAssertionInfo = info;
9888 AssertionResult assertionResult{ info, data };
9889 assertionEnded( assertionResult );
9891 if( !assertionResult.isOk() )
9892 populateReaction( reaction );
9909 m_sectionIncluded(
getResultCapture().sectionStarted( m_info, m_assertions ) )
9915 if( m_sectionIncluded ) {
9916 SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
9917 if( uncaught_exceptions() )
9925 Section::operator bool()
const {
9926 return m_sectionIncluded;
9937 std::string
const& _name )
9939 lineInfo( _lineInfo )
9956 ~Session()
override;
9958 void showHelp()
const;
9961 int applyCommandLine(
int argc,
char const *
const * argv );
9962 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) 9963 int applyCommandLine(
int argc,
wchar_t const *
const * argv );
9966 void useConfigData( ConfigData
const& configData );
9968 template<
typename CharT>
9969 int run(
int argc, CharT
const *
const argv[]) {
9970 if (m_startupExceptions)
9972 int returnCode = applyCommandLine(argc, argv);
9973 if (returnCode == 0)
9980 clara::Parser
const& cli()
const;
9981 void cli( clara::Parser
const& newParser );
9982 ConfigData& configData();
9987 clara::Parser m_cli;
9988 ConfigData m_configData;
9989 std::shared_ptr<Config> m_config;
9990 bool m_startupExceptions =
false;
10004 Version( Version
const& ) =
delete;
10005 Version& operator=( Version
const& ) =
delete;
10006 Version(
unsigned int _majorVersion,
10007 unsigned int _minorVersion,
10008 unsigned int _patchNumber,
10009 char const *
const _branchName,
10010 unsigned int _buildNumber );
10012 unsigned int const majorVersion;
10013 unsigned int const minorVersion;
10014 unsigned int const patchNumber;
10017 char const *
const branchName;
10018 unsigned int const buildNumber;
10020 friend std::ostream&
operator << ( std::ostream& os, Version
const& version );
10023 Version
const& libraryVersion();
10033 const int MaxExitCode = 255;
10035 IStreamingReporterPtr createReporter(std::string
const& reporterName, IConfigPtr
const& config) {
10037 CATCH_ENFORCE(reporter,
"No reporter registered with name: '" << reporterName <<
"'");
10042 IStreamingReporterPtr makeReporter(std::shared_ptr<Config>
const& config) {
10044 return createReporter(config->getReporterName(), config);
10047 auto multi = std::unique_ptr<ListeningReporter>(
new ListeningReporter);
10050 for (
auto const& listener : listeners) {
10051 multi->addListener(listener->create(Catch::ReporterConfig(config)));
10053 multi->addReporter(createReporter(config->getReporterName(), config));
10054 return std::move(multi);
10057 Catch::Totals runTests(std::shared_ptr<Config>
const& config) {
10060 auto reporter = makeReporter(config);
10062 RunContext context(config, std::move(reporter));
10066 context.testGroupStarting(config->name(), 1, 1);
10068 TestSpec testSpec = config->testSpec();
10071 for (
auto const& testCase : allTestCases) {
10072 if (!context.aborting() &&
matchTest(testCase, testSpec, *config))
10073 totals += context.runTest(testCase);
10075 context.reporter().skipTest(testCase);
10078 if (config->warnAboutNoTests() && totals.
testCases.
total() == 0) {
10082 for (
const auto& input : config->getTestsOrTags()) {
10083 if (!first) { testConfig <<
' '; }
10085 testConfig << input;
10088 context.reporter().noMatchingTestCases(testConfig.
str());
10092 context.testGroupEnded(config->name(), totals, 1, 1);
10096 void applyFilenamesAsTags(Catch::IConfig
const& config) {
10098 for (
auto& testCase : tests) {
10099 auto tags = testCase.tags;
10101 std::string filename = testCase.lineInfo.file;
10102 auto lastSlash = filename.find_last_of(
"\\/");
10103 if (lastSlash != std::string::npos) {
10104 filename.erase(0, lastSlash);
10108 auto lastDot = filename.find_last_of(
'.');
10109 if (lastDot != std::string::npos) {
10110 filename.erase(lastDot);
10113 tags.push_back(std::move(filename));
10114 setTags(testCase, tags);
10120 Session::Session() {
10121 static bool alreadyInstantiated =
false;
10122 if( alreadyInstantiated ) {
10128 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 10130 if ( !exceptions.empty() ) {
10131 m_startupExceptions =
true;
10132 Colour colourGuard( Colour::Red );
10133 Catch::cerr() <<
"Errors occurred during startup!" <<
'\n';
10135 for (
const auto& ex_ptr : exceptions ) {
10137 std::rethrow_exception(ex_ptr);
10138 }
catch ( std::exception
const& ex ) {
10139 Catch::cerr() << Column( ex.what() ).indent(2) <<
'\n';
10145 alreadyInstantiated =
true;
10146 m_cli = makeCommandLineParser( m_configData );
10148 Session::~Session() {
10152 void Session::showHelp()
const {
10154 <<
"\nCatch v" << libraryVersion() <<
"\n" 10155 << m_cli << std::endl
10156 <<
"For more detailed usage please see the project docs\n" << std::endl;
10158 void Session::libIdentify() {
10160 << std::left << std::setw(16) <<
"description: " <<
"A Catch test executable\n" 10161 << std::left << std::setw(16) <<
"category: " <<
"testframework\n" 10162 << std::left << std::setw(16) <<
"framework: " <<
"Catch Test\n" 10163 << std::left << std::setw(16) <<
"version: " << libraryVersion() << std::endl;
10166 int Session::applyCommandLine(
int argc,
char const *
const * argv ) {
10167 if( m_startupExceptions )
10170 auto result = m_cli.parse( clara::Args( argc, argv ) );
10173 << Colour( Colour::Red )
10174 <<
"\nError(s) in input:\n" 10175 << Column( result.errorMessage() ).indent( 2 )
10177 Catch::cerr() <<
"Run with -? for usage\n" << std::endl;
10178 return MaxExitCode;
10181 if( m_configData.showHelp )
10183 if( m_configData.libIdentify )
10189 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) 10190 int Session::applyCommandLine(
int argc,
wchar_t const *
const * argv ) {
10192 char **utf8Argv =
new char *[ argc ];
10194 for (
int i = 0; i < argc; ++i ) {
10195 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
10197 utf8Argv[ i ] =
new char[ bufSize ];
10199 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
10202 int returnCode = applyCommandLine( argc, utf8Argv );
10204 for (
int i = 0; i < argc; ++i )
10205 delete [] utf8Argv[ i ];
10207 delete [] utf8Argv;
10213 void Session::useConfigData( ConfigData
const& configData ) {
10214 m_configData = configData;
10218 int Session::run() {
10219 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
10220 Catch::cout() <<
"...waiting for enter/ return before starting" << std::endl;
10221 static_cast<void>(std::getchar());
10223 int exitCode = runInternal();
10224 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
10225 Catch::cout() <<
"...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
10226 static_cast<void>(std::getchar());
10231 clara::Parser
const& Session::cli()
const {
10234 void Session::cli( clara::Parser
const& newParser ) {
10237 ConfigData& Session::configData() {
10238 return m_configData;
10240 Config& Session::config() {
10242 m_config = std::make_shared<Config>( m_configData );
10246 int Session::runInternal() {
10247 if( m_startupExceptions )
10250 if (m_configData.showHelp || m_configData.libIdentify) {
10257 seedRng( *m_config );
10259 if( m_configData.filenamesAsTags )
10260 applyFilenamesAsTags( *m_config );
10263 if( Option<std::size_t> listed = list( config() ) )
10264 return static_cast<int>( *listed );
10266 auto totals = runTests( m_config );
10270 return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
10272 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 10273 catch( std::exception& ex ) {
10275 return MaxExitCode;
10289 static auto getSingletons() -> std::vector<ISingleton*>*& {
10290 static std::vector<ISingleton*>* g_singletons =
nullptr;
10291 if( !g_singletons )
10292 g_singletons =
new std::vector<ISingleton*>();
10293 return g_singletons;
10297 ISingleton::~ISingleton() {}
10299 void addSingleton(ISingleton* singleton ) {
10300 getSingletons()->push_back( singleton );
10302 void cleanupSingletons() {
10303 auto& singletons = getSingletons();
10304 for(
auto singleton : *singletons )
10307 singletons =
nullptr;
10315 void StartupExceptionRegistry::add( std::exception_ptr
const& exception ) noexcept {
10317 m_exceptions.push_back(exception);
10324 std::vector<std::exception_ptr>
const& StartupExceptionRegistry::getExceptions()
const noexcept {
10325 return m_exceptions;
10333 #include <iostream> 10343 namespace detail {
namespace {
10344 template<
typename WriterF, std::
size_t bufferSize=256>
10345 class StreamBufImpl :
public std::streambuf {
10346 char data[bufferSize];
10351 setp( data, data +
sizeof(data) );
10354 ~StreamBufImpl() noexcept {
10355 StreamBufImpl::sync();
10359 int overflow(
int c )
override {
10363 if( pbase() == epptr() )
10364 m_writer( std::string( 1, static_cast<char>( c ) ) );
10366 sputc( static_cast<char>( c ) );
10371 int sync()
override {
10372 if( pbase() != pptr() ) {
10373 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
10374 setp( pbase(), epptr() );
10382 struct OutputDebugWriter {
10384 void operator()( std::string
const&str ) {
10385 writeToDebugConsole( str );
10391 class FileStream :
public IStream {
10392 mutable std::ofstream m_ofs;
10395 m_ofs.open( filename.
c_str() );
10396 CATCH_ENFORCE( !m_ofs.fail(),
"Unable to open file: '" << filename <<
"'" );
10398 ~FileStream()
override =
default;
10400 std::ostream& stream()
const override {
10407 class CoutStream :
public IStream {
10408 mutable std::ostream m_os;
10413 ~CoutStream()
override =
default;
10416 std::ostream& stream()
const override {
return m_os; }
10421 class DebugOutStream :
public IStream {
10422 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
10423 mutable std::ostream m_os;
10426 : m_streamBuf(
new StreamBufImpl<OutputDebugWriter>() ),
10427 m_os( m_streamBuf.get() )
10430 ~DebugOutStream()
override =
default;
10433 std::ostream& stream()
const override {
return m_os; }
10441 if( filename.
empty() )
10442 return new detail::CoutStream();
10443 else if( filename[0] ==
'%' ) {
10444 if( filename ==
"%debug" )
10445 return new detail::DebugOutStream();
10447 CATCH_ERROR(
"Unrecognised stream: '" << filename <<
"'" );
10450 return new detail::FileStream( filename );
10454 struct StringStreams {
10455 std::vector<std::unique_ptr<std::ostringstream>> m_streams;
10456 std::vector<std::size_t> m_unused;
10457 std::ostringstream m_referenceStream;
10459 auto add() -> std::size_t {
10460 if( m_unused.empty() ) {
10461 m_streams.push_back( std::unique_ptr<std::ostringstream>(
new std::ostringstream ) );
10462 return m_streams.size()-1;
10465 auto index = m_unused.back();
10466 m_unused.pop_back();
10471 void release( std::size_t index ) {
10472 m_streams[index]->copyfmt( m_referenceStream );
10473 m_unused.push_back(index);
10478 : m_index( Singleton<StringStreams>::getMutable().add() ),
10479 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].
get() )
10483 static_cast<std::ostringstream*
>( m_oss )->str(
"");
10485 Singleton<StringStreams>::getMutable().release( m_index );
10489 return static_cast<std::ostringstream*
>( m_oss )->str();
10494 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions 10503 #include <algorithm> 10511 char toLowerCh(
char c) {
10512 return static_cast<char>( std::tolower( c ) );
10516 bool startsWith( std::string
const&
s, std::string
const& prefix ) {
10517 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
10519 bool startsWith( std::string
const& s,
char prefix ) {
10520 return !s.empty() && s[0] == prefix;
10522 bool endsWith( std::string
const& s, std::string
const& suffix ) {
10523 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
10525 bool endsWith( std::string
const& s,
char suffix ) {
10526 return !s.empty() && s[s.size()-1] == suffix;
10528 bool contains( std::string
const& s, std::string
const& infix ) {
10529 return s.find( infix ) != std::string::npos;
10532 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
10534 std::string
toLower( std::string
const& s ) {
10535 std::string lc = s;
10539 std::string
trim( std::string
const& str ) {
10540 static char const* whitespaceChars =
"\n\r\t ";
10541 std::string::size_type
start = str.find_first_not_of( whitespaceChars );
10542 std::string::size_type end = str.find_last_not_of( whitespaceChars );
10544 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
10547 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis ) {
10548 bool replaced =
false;
10549 std::size_t i = str.find( replaceThis );
10550 while( i != std::string::npos ) {
10552 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
10553 if( i < str.size()-withThis.size() )
10554 i = str.find( replaceThis, i+withThis.size() );
10556 i = std::string::npos;
10562 : m_count( count ),
10568 if( pluraliser.
m_count != 1 )
10577 #if defined(__clang__) 10578 # pragma clang diagnostic push 10579 # pragma clang diagnostic ignored "-Wexit-time-destructors" 10587 const uint32_t byte_2_lead = 0xC0;
10588 const uint32_t byte_3_lead = 0xE0;
10589 const uint32_t byte_4_lead = 0xF0;
10594 :
StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
10597 StringRef::operator std::string()
const {
10598 return std::string( m_start, m_size );
10602 std::swap( m_start, other.
m_start );
10603 std::swap( m_size, other.
m_size );
10604 std::swap( m_data, other.
m_data );
10608 if( isSubstring() )
10609 const_cast<StringRef*
>( this )->takeOwnership();
10617 return m_data !=
nullptr;
10620 return m_start[m_size] !=
'\0';
10625 m_data =
new char[m_size+1];
10626 memcpy( m_data, m_start, m_size );
10627 m_data[m_size] =
'\0';
10632 if( start < m_size )
10633 return StringRef( m_start+start, size );
10639 size() == other.
size() &&
10640 (std::strncmp( m_start, other.
m_start, size() ) == 0);
10643 return !operator==( other );
10647 return m_start[index];
10651 size_type noChars = m_size;
10653 for( size_type i=0; i < m_size; ++i ) {
10654 char c = m_start[i];
10655 if( ( c & byte_2_lead ) == byte_2_lead ) {
10657 if (( c & byte_3_lead ) == byte_3_lead )
10659 if( ( c & byte_4_lead ) == byte_4_lead )
10668 str.reserve( lhs.
size() + rhs.
size() );
10674 return std::string( lhs ) + std::string( rhs );
10677 return std::string( lhs ) + std::string( rhs );
10691 #if defined(__clang__) 10692 # pragma clang diagnostic pop 10698 TagAlias::TagAlias(std::string
const & _tag,
SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
10722 TagAliasRegistry::~TagAliasRegistry() {}
10724 TagAlias
const* TagAliasRegistry::find( std::string
const& alias )
const {
10725 auto it = m_registry.find( alias );
10726 if( it != m_registry.end() )
10727 return &(it->second);
10732 std::string TagAliasRegistry::expandAliases( std::string
const& unexpandedTestSpec )
const {
10733 std::string expandedTestSpec = unexpandedTestSpec;
10734 for(
auto const& registryKvp : m_registry ) {
10735 std::size_t pos = expandedTestSpec.find( registryKvp.first );
10736 if( pos != std::string::npos ) {
10737 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
10738 registryKvp.second.tag +
10739 expandedTestSpec.substr( pos + registryKvp.first.size() );
10742 return expandedTestSpec;
10745 void TagAliasRegistry::add( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo ) {
10747 "error: tag alias, '" << alias <<
"' is not of the form [@alias name].\n" << lineInfo );
10749 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
10750 "error: tag alias, '" << alias <<
"' already registered.\n" 10751 <<
"\tFirst seen at: " << find(alias)->lineInfo <<
"\n" 10752 <<
"\tRedefined at: " << lineInfo );
10755 ITagAliasRegistry::~ITagAliasRegistry() {}
10757 ITagAliasRegistry
const& ITagAliasRegistry::get() {
10766 #include <exception> 10767 #include <algorithm> 10777 else if( tag ==
"!throws" )
10779 else if( tag ==
"!shouldfail" )
10781 else if( tag ==
"!mayfail" )
10783 else if( tag ==
"!nonportable" )
10785 else if( tag ==
"!benchmark" )
10790 bool isReservedTag( std::string
const& tag ) {
10791 return parseSpecialTag( tag ) ==
TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
10793 void enforceNotReservedTag( std::string
const& tag,
SourceLineInfo const& _lineInfo ) {
10795 "Tag name: [" << tag <<
"] is not allowed.\n" 10796 <<
"Tag names starting with non alpha-numeric characters are reserved\n" 10802 std::string
const& _className,
10806 bool isHidden =
false;
10809 std::vector<std::string> tags;
10810 std::string desc, tag;
10811 bool inTag =
false;
10812 std::string _descOrTags = nameAndTags.
tags;
10813 for (
char c : _descOrTags) {
10826 enforceNotReservedTag( tag, _lineInfo );
10828 tags.push_back( tag );
10837 tags.push_back(
"." );
10841 return TestCase( _testCase, std::move(info) );
10844 void setTags(
TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
10845 std::sort(
begin(tags),
end(tags));
10846 tags.erase(std::unique(
begin(tags),
end(tags)),
end(tags));
10849 for(
auto const& tag : tags ) {
10850 std::string lcaseTag =
toLower( tag );
10852 testCaseInfo.
lcaseTags.push_back( lcaseTag );
10854 testCaseInfo.
tags = std::move(tags);
10858 std::string
const& _className,
10859 std::string
const& _description,
10860 std::vector<std::string>
const& _tags,
10863 className( _className ),
10864 description( _description ),
10865 lineInfo( _lineInfo ),
10868 setTags( *
this, _tags );
10872 return ( properties & IsHidden ) != 0;
10875 return ( properties & Throws ) != 0;
10878 return ( properties & (ShouldFail | MayFail ) ) != 0;
10881 return ( properties & (ShouldFail ) ) != 0;
10887 std::size_t full_size = 2 * tags.size();
10888 for (
const auto& tag : tags) {
10889 full_size += tag.size();
10891 ret.reserve(full_size);
10892 for (
const auto& tag : tags) {
10893 ret.push_back(
'[');
10895 ret.push_back(
']');
10905 other.
name = _newName;
10914 return test.get() == other.
test.get() &&
10915 name == other.
name &&
10920 return name < other.
name;
10936 std::vector<TestCase> sortTests( IConfig
const& config, std::vector<TestCase>
const& unsortedTestCases ) {
10938 std::vector<TestCase> sorted = unsortedTestCases;
10940 switch( config.runOrder() ) {
10941 case RunTests::InLexicographicalOrder:
10942 std::sort( sorted.begin(), sorted.end() );
10944 case RunTests::InRandomOrder:
10946 std::shuffle( sorted.begin(), sorted.end(), rng() );
10948 case RunTests::InDeclarationOrder:
10954 bool matchTest(
TestCase const& testCase, TestSpec
const& testSpec, IConfig
const& config ) {
10955 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.
throws() );
10958 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions ) {
10959 std::set<TestCase> seenFunctions;
10960 for(
auto const&
function : functions ) {
10961 auto prev = seenFunctions.insert(
function );
10963 "error: TEST_CASE( \"" <<
function.name <<
"\" ) already defined.\n" 10964 <<
"\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo <<
"\n" 10965 <<
"\tRedefined at " <<
function.getTestCaseInfo().lineInfo );
10969 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const& config ) {
10970 std::vector<TestCase> filtered;
10971 filtered.reserve( testCases.size() );
10972 for(
auto const& testCase : testCases )
10973 if(
matchTest( testCase, testSpec, config ) )
10974 filtered.push_back( testCase );
10981 void TestRegistry::registerTest(
TestCase const& testCase ) {
10983 if( name.empty() ) {
10985 rss <<
"Anonymous test case " << ++m_unnamedCount;
10986 return registerTest( testCase.
withName( rss.
str() ) );
10988 m_functions.push_back( testCase );
10991 std::vector<TestCase>
const& TestRegistry::getAllTests()
const {
10992 return m_functions;
10994 std::vector<TestCase>
const& TestRegistry::getAllTestsSorted( IConfig
const& config )
const {
10995 if( m_sortedFunctions.empty() )
10996 enforceNoDuplicateTestCases( m_functions );
10998 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
10999 m_sortedFunctions = sortTests( config, m_functions );
11000 m_currentSortOrder = config.runOrder();
11002 return m_sortedFunctions;
11006 TestInvokerAsFunction::TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
11008 void TestInvokerAsFunction::invoke()
const {
11009 m_testAsFunction();
11012 std::string extractClassName(
StringRef const& classOrQualifiedMethodName ) {
11013 std::string className = classOrQualifiedMethodName;
11016 std::size_t lastColons = className.rfind(
"::" );
11017 std::size_t penultimateColons = className.rfind(
"::", lastColons-1 );
11018 if( penultimateColons == std::string::npos )
11019 penultimateColons = 1;
11020 className = className.
substr( penultimateColons, lastColons-penultimateColons );
11029 #include <algorithm> 11031 #include <stdexcept> 11035 #if defined(__clang__) 11036 # pragma clang diagnostic push 11037 # pragma clang diagnostic ignored "-Wexit-time-destructors" 11041 namespace TestCaseTracking {
11043 NameAndLocation::NameAndLocation( std::string
const& _name,
SourceLineInfo const& _location )
11045 location( _location )
11048 ITracker::~ITracker() =
default;
11050 TrackerContext& TrackerContext::instance() {
11051 static TrackerContext s_instance;
11055 ITracker& TrackerContext::startRun() {
11056 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation(
"{root}",
CATCH_INTERNAL_LINEINFO ), *
this, nullptr );
11057 m_currentTracker =
nullptr;
11058 m_runState = Executing;
11059 return *m_rootTracker;
11062 void TrackerContext::endRun() {
11063 m_rootTracker.reset();
11064 m_currentTracker =
nullptr;
11065 m_runState = NotStarted;
11068 void TrackerContext::startCycle() {
11069 m_currentTracker = m_rootTracker.get();
11070 m_runState = Executing;
11072 void TrackerContext::completeCycle() {
11073 m_runState = CompletedCycle;
11076 bool TrackerContext::completedCycle()
const {
11077 return m_runState == CompletedCycle;
11079 ITracker& TrackerContext::currentTracker() {
11080 return *m_currentTracker;
11082 void TrackerContext::setCurrentTracker( ITracker* tracker ) {
11083 m_currentTracker = tracker;
11086 TrackerBase::TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
11087 : m_nameAndLocation( nameAndLocation ),
11092 NameAndLocation
const& TrackerBase::nameAndLocation()
const {
11093 return m_nameAndLocation;
11095 bool TrackerBase::isComplete()
const {
11096 return m_runState == CompletedSuccessfully || m_runState == Failed;
11098 bool TrackerBase::isSuccessfullyCompleted()
const {
11099 return m_runState == CompletedSuccessfully;
11101 bool TrackerBase::isOpen()
const {
11102 return m_runState != NotStarted && !isComplete();
11104 bool TrackerBase::hasChildren()
const {
11105 return !m_children.empty();
11108 void TrackerBase::addChild( ITrackerPtr
const& child ) {
11109 m_children.push_back( child );
11112 ITrackerPtr TrackerBase::findChild( NameAndLocation
const& nameAndLocation ) {
11113 auto it = std::find_if( m_children.begin(), m_children.end(),
11114 [&nameAndLocation]( ITrackerPtr
const& tracker ){
11116 tracker->nameAndLocation().location == nameAndLocation.location &&
11117 tracker->nameAndLocation().name == nameAndLocation.name;
11119 return( it != m_children.end() )
11123 ITracker& TrackerBase::parent() {
11124 assert( m_parent );
11128 void TrackerBase::openChild() {
11129 if( m_runState != ExecutingChildren ) {
11130 m_runState = ExecutingChildren;
11132 m_parent->openChild();
11136 bool TrackerBase::isSectionTracker()
const {
return false; }
11137 bool TrackerBase::isIndexTracker()
const {
return false; }
11139 void TrackerBase::open() {
11140 m_runState = Executing;
11143 m_parent->openChild();
11146 void TrackerBase::close() {
11149 while( &m_ctx.currentTracker() != this )
11150 m_ctx.currentTracker().close();
11152 switch( m_runState ) {
11153 case NeedsAnotherRun:
11157 m_runState = CompletedSuccessfully;
11159 case ExecutingChildren:
11160 if( m_children.empty() || m_children.back()->isComplete() )
11161 m_runState = CompletedSuccessfully;
11165 case CompletedSuccessfully:
11173 m_ctx.completeCycle();
11175 void TrackerBase::fail() {
11176 m_runState = Failed;
11178 m_parent->markAsNeedingAnotherRun();
11180 m_ctx.completeCycle();
11182 void TrackerBase::markAsNeedingAnotherRun() {
11183 m_runState = NeedsAnotherRun;
11186 void TrackerBase::moveToParent() {
11187 assert( m_parent );
11188 m_ctx.setCurrentTracker( m_parent );
11190 void TrackerBase::moveToThis() {
11191 m_ctx.setCurrentTracker(
this );
11194 SectionTracker::SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
11195 : TrackerBase( nameAndLocation, ctx, parent )
11198 while( !parent->isSectionTracker() )
11199 parent = &parent->parent();
11201 SectionTracker& parentSection =
static_cast<SectionTracker&
>( *parent );
11202 addNextFilters( parentSection.m_filters );
11206 bool SectionTracker::isSectionTracker()
const {
return true; }
11208 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation ) {
11209 std::shared_ptr<SectionTracker> section;
11211 ITracker& currentTracker = ctx.currentTracker();
11212 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
11213 assert( childTracker );
11214 assert( childTracker->isSectionTracker() );
11215 section = std::static_pointer_cast<SectionTracker>( childTracker );
11218 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker );
11219 currentTracker.addChild( section );
11221 if( !ctx.completedCycle() )
11222 section->tryOpen();
11226 void SectionTracker::tryOpen() {
11227 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
11231 void SectionTracker::addInitialFilters( std::vector<std::string>
const& filters ) {
11232 if( !filters.empty() ) {
11233 m_filters.push_back(
"");
11234 m_filters.push_back(
"");
11235 m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
11238 void SectionTracker::addNextFilters( std::vector<std::string>
const& filters ) {
11239 if( filters.size() > 1 )
11240 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
11243 IndexTracker::IndexTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent,
int size )
11244 : TrackerBase( nameAndLocation, ctx, parent ),
11248 bool IndexTracker::isIndexTracker()
const {
return true; }
11250 IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation,
int size ) {
11251 std::shared_ptr<IndexTracker> tracker;
11253 ITracker& currentTracker = ctx.currentTracker();
11254 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
11255 assert( childTracker );
11256 assert( childTracker->isIndexTracker() );
11257 tracker = std::static_pointer_cast<IndexTracker>( childTracker );
11260 tracker = std::make_shared<IndexTracker>( nameAndLocation, ctx, ¤tTracker, size );
11261 currentTracker.addChild( tracker );
11264 if( !ctx.completedCycle() && !tracker->isComplete() ) {
11265 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
11266 tracker->moveNext();
11273 int IndexTracker::index()
const {
return m_index; }
11275 void IndexTracker::moveNext() {
11277 m_children.clear();
11280 void IndexTracker::close() {
11281 TrackerBase::close();
11282 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
11283 m_runState = Executing;
11288 using TestCaseTracking::ITracker;
11289 using TestCaseTracking::TrackerContext;
11290 using TestCaseTracking::SectionTracker;
11291 using TestCaseTracking::IndexTracker;
11295 #if defined(__clang__) 11296 # pragma clang diagnostic pop 11304 return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
11315 extractClassName( classOrMethod ),
11329 #include <algorithm> 11336 TestSpec::Pattern::~Pattern() =
default;
11337 TestSpec::NamePattern::~NamePattern() =
default;
11338 TestSpec::TagPattern::~TagPattern() =
default;
11339 TestSpec::ExcludedPattern::~ExcludedPattern() =
default;
11341 TestSpec::NamePattern::NamePattern( std::string
const& name )
11344 bool TestSpec::NamePattern::matches(
TestCaseInfo const& testCase )
const {
11345 return m_wildcardPattern.matches(
toLower( testCase.
name ) );
11348 TestSpec::TagPattern::TagPattern( std::string
const& tag ) : m_tag(
toLower( tag ) ) {}
11349 bool TestSpec::TagPattern::matches(
TestCaseInfo const& testCase )
const {
11355 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr
const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
11356 bool TestSpec::ExcludedPattern::matches(
TestCaseInfo const& testCase )
const {
return !m_underlyingPattern->matches( testCase ); }
11358 bool TestSpec::Filter::matches(
TestCaseInfo const& testCase )
const {
11360 for(
auto const& pattern : m_patterns ) {
11361 if( !pattern->matches( testCase ) )
11367 bool TestSpec::hasFilters()
const {
11368 return !m_filters.empty();
11370 bool TestSpec::matches(
TestCaseInfo const& testCase )
const {
11372 for(
auto const& filter : m_filters )
11373 if( filter.matches( testCase ) )
11383 TestSpecParser::TestSpecParser( ITagAliasRegistry
const& tagAliases ) : m_tagAliases( &tagAliases ) {}
11385 TestSpecParser& TestSpecParser::parse( std::string
const& arg ) {
11387 m_exclusion =
false;
11388 m_start = std::string::npos;
11389 m_arg = m_tagAliases->expandAliases( arg );
11390 m_escapeChars.clear();
11391 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
11392 visitChar( m_arg[m_pos] );
11393 if( m_mode == Name )
11394 addPattern<TestSpec::NamePattern>();
11397 TestSpec TestSpecParser::testSpec() {
11402 void TestSpecParser::visitChar(
char c ) {
11403 if( m_mode == None ) {
11406 case '~': m_exclusion =
true;
return;
11407 case '[':
return startNewMode( Tag, ++m_pos );
11408 case '"':
return startNewMode( QuotedName, ++m_pos );
11409 case '\\':
return escape();
11410 default: startNewMode( Name, m_pos );
break;
11413 if( m_mode == Name ) {
11415 addPattern<TestSpec::NamePattern>();
11418 else if( c ==
'[' ) {
11419 if( subString() ==
"exclude:" )
11420 m_exclusion =
true;
11422 addPattern<TestSpec::NamePattern>();
11423 startNewMode( Tag, ++m_pos );
11425 else if( c ==
'\\' )
11428 else if( m_mode == EscapedName )
11430 else if( m_mode == QuotedName && c ==
'"' )
11431 addPattern<TestSpec::NamePattern>();
11432 else if( m_mode == Tag && c ==
']' )
11433 addPattern<TestSpec::TagPattern>();
11435 void TestSpecParser::startNewMode( Mode mode, std::size_t
start ) {
11439 void TestSpecParser::escape() {
11440 if( m_mode == None )
11442 m_mode = EscapedName;
11443 m_escapeChars.push_back( m_pos );
11445 std::string TestSpecParser::subString()
const {
return m_arg.substr( m_start, m_pos - m_start ); }
11447 void TestSpecParser::addFilter() {
11448 if( !m_currentFilter.m_patterns.empty() ) {
11449 m_testSpec.m_filters.push_back( m_currentFilter );
11450 m_currentFilter = TestSpec::Filter();
11454 TestSpec parseTestSpec( std::string
const& arg ) {
11455 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
11464 static const uint64_t nanosecondsInSecond = 1000000000;
11469 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).
count();
11473 auto estimateClockResolution() -> uint64_t {
11475 static const uint64_t iterations = 1000000;
11479 for( std::size_t i = 0; i < iterations; ++i ) {
11485 }
while( ticks == baseTicks );
11487 auto delta = ticks - baseTicks;
11493 if (ticks > startTime + 3 * nanosecondsInSecond) {
11500 return sum/iterations;
11504 static auto s_resolution = estimateClockResolution();
11505 return s_resolution;
11515 return getElapsedNanoseconds()/1000;
11518 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
11521 return getElapsedMicroseconds()/1000000.0;
11528 #if defined(__clang__) 11529 # pragma clang diagnostic push 11530 # pragma clang diagnostic ignored "-Wexit-time-destructors" 11531 # pragma clang diagnostic ignored "-Wglobal-constructors" 11535 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 11536 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 11546 const std::string unprintableString =
"{?}";
11549 const int hexThreshold = 255;
11551 struct Endianness {
11552 enum Arch { Big, Little };
11554 static Arch which() {
11557 char asChar[sizeof (int)];
11561 return ( u.asChar[
sizeof(
int)-1] == 1 ) ? Big : Little;
11568 int i = 0, end =
static_cast<int>( size ), inc = 1;
11569 if( Endianness::which() == Endianness::Little ) {
11574 unsigned char const *bytes =
static_cast<unsigned char const *
>(object);
11576 rss <<
"0x" << std::setfill(
'0') << std::hex;
11577 for( ; i !=
end; i += inc )
11578 rss << std::setw(2) <<
static_cast<unsigned>(bytes[i]);
11583 template<
typename T>
11584 std::string fpToString( T
value,
int precision ) {
11585 if (std::isnan(value)) {
11590 rss << std::setprecision( precision )
11593 std::string
d = rss.
str();
11594 std::size_t i = d.find_last_not_of(
'0' );
11595 if( i != std::string::npos && i != d.size()-1 ) {
11598 d = d.substr( 0, i+1 );
11610 if (!getCurrentContext().getConfig()->showInvisibles()) {
11611 return '"' + str +
'"';
11614 std::string
s(
"\"");
11615 for (
char c : str) {
11632 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 11642 return{
"{null string}" };
11649 return{
"{null string}" };
11653 #ifdef CATCH_CONFIG_WCHAR 11656 s.reserve(wstr.size());
11657 for (
auto c : wstr) {
11658 s += (c <= 0xff) ? static_cast<char>(c) :
'?';
11663 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 11673 return{
"{null string}" };
11680 return{
"{null string}" };
11694 if (value > Detail::hexThreshold) {
11695 rss <<
" (0x" << std::hex << value <<
')';
11709 if (value > Detail::hexThreshold) {
11710 rss <<
" (0x" << std::hex << value <<
')';
11716 return b ?
"true" :
"false";
11720 if (value ==
'\r') {
11722 }
else if (value ==
'\f') {
11724 }
else if (value ==
'\n') {
11726 }
else if (value ==
'\t') {
11728 }
else if (
'\0' <= value && value <
' ') {
11731 char chstr[] =
"' '";
11748 return fpToString(value, 5) +
'f';
11751 return fpToString(value, 10);
11754 std::string ratio_string<std::atto>::symbol() {
return "a"; }
11755 std::string ratio_string<std::femto>::symbol() {
return "f"; }
11756 std::string ratio_string<std::pico>::symbol() {
return "p"; }
11757 std::string ratio_string<std::nano>::symbol() {
return "n"; }
11758 std::string ratio_string<std::micro>::symbol() {
return "u"; }
11759 std::string ratio_string<std::milli>::symbol() {
return "m"; }
11763 #if defined(__clang__) 11764 # pragma clang diagnostic pop 11788 return passed + failed + failedButOk;
11791 return failed == 0 && failedButOk == 0;
11794 return failed == 0;
11811 Totals diff = *
this - prevTotals;
11825 #include <exception> 11828 bool uncaught_exceptions() {
11829 #if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 11830 return std::uncaught_exceptions() > 0;
11832 return std::uncaught_exception();
11844 (
unsigned int _majorVersion,
11845 unsigned int _minorVersion,
11846 unsigned int _patchNumber,
11847 char const *
const _branchName,
11848 unsigned int _buildNumber )
11849 : majorVersion( _majorVersion ),
11850 minorVersion( _minorVersion ),
11851 patchNumber( _patchNumber ),
11852 branchName( _branchName ),
11853 buildNumber( _buildNumber )
11856 std::ostream&
operator << ( std::ostream& os, Version
const& version ) {
11857 os << version.majorVersion <<
'.' 11858 << version.minorVersion <<
'.' 11859 << version.patchNumber;
11861 if (version.branchName[0]) {
11862 os <<
'-' << version.branchName
11863 <<
'.' << version.buildNumber;
11868 Version
const& libraryVersion() {
11869 static Version version( 2, 4, 2,
"", 0 );
11881 WildcardPattern::WildcardPattern( std::string
const& pattern,
11883 : m_caseSensitivity( caseSensitivity ),
11884 m_pattern( adjustCase( pattern ) )
11887 m_pattern = m_pattern.substr( 1 );
11888 m_wildcard = WildcardAtStart;
11890 if(
endsWith( m_pattern,
'*' ) ) {
11891 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
11892 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
11896 bool WildcardPattern::matches( std::string
const& str )
const {
11897 switch( m_wildcard ) {
11899 return m_pattern == adjustCase( str );
11900 case WildcardAtStart:
11901 return endsWith( adjustCase( str ), m_pattern );
11902 case WildcardAtEnd:
11903 return startsWith( adjustCase( str ), m_pattern );
11904 case WildcardAtBothEnds:
11905 return contains( adjustCase( str ), m_pattern );
11911 std::string WildcardPattern::adjustCase( std::string
const& str )
const {
11920 using uchar =
unsigned char;
11926 size_t trailingBytes(
unsigned char c) {
11927 if ((c & 0xE0) == 0xC0) {
11930 if ((c & 0xF0) == 0xE0) {
11933 if ((c & 0xF8) == 0xF0) {
11939 uint32_t headerValue(
unsigned char c) {
11940 if ((c & 0xE0) == 0xC0) {
11943 if ((c & 0xF0) == 0xE0) {
11946 if ((c & 0xF8) == 0xF0) {
11952 void hexEscapeChar(std::ostream& os,
unsigned char c) {
11954 << std::uppercase << std::hex << std::setfill(
'0') << std::setw(2)
11955 <<
static_cast<int>(c);
11960 XmlEncode::XmlEncode( std::string
const& str, ForWhat forWhat )
11962 m_forWhat( forWhat )
11965 void XmlEncode::encodeTo( std::ostream& os )
const {
11969 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
11970 uchar c = m_str[idx];
11972 case '<': os <<
"<";
break;
11973 case '&': os <<
"&";
break;
11977 if (idx > 2 && m_str[idx - 1] ==
']' && m_str[idx - 2] ==
']')
11984 if (m_forWhat == ForAttributes)
11995 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
11996 hexEscapeChar(os, c);
12014 hexEscapeChar(os, c);
12018 auto encBytes = trailingBytes(c);
12020 if (idx + encBytes - 1 >= m_str.size()) {
12021 hexEscapeChar(os, c);
12028 uint32_t
value = headerValue(c);
12029 for (std::size_t n = 1; n < encBytes; ++n) {
12030 uchar nc = m_str[idx + n];
12031 valid &= ((nc & 0xC0) == 0x80);
12032 value = (value << 6) | (nc & 0x3F);
12040 (0x80 <= value && value < 0x800 && encBytes > 2) ||
12041 (0x800 < value && value < 0x10000 && encBytes > 3) ||
12043 (value >= 0x110000)
12045 hexEscapeChar(os, c);
12050 for (std::size_t n = 0; n < encBytes; ++n) {
12051 os << m_str[idx + n];
12053 idx += encBytes - 1;
12059 std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode ) {
12060 xmlEncode.encodeTo( os );
12064 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
12065 : m_writer( writer )
12068 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
12069 : m_writer( other.m_writer ){
12070 other.m_writer =
nullptr;
12072 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
12074 m_writer->endElement();
12076 m_writer = other.m_writer;
12077 other.m_writer =
nullptr;
12081 XmlWriter::ScopedElement::~ScopedElement() {
12083 m_writer->endElement();
12086 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string
const& text,
bool indent ) {
12087 m_writer->writeText( text, indent );
12091 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
12093 writeDeclaration();
12096 XmlWriter::~XmlWriter() {
12097 while( !m_tags.empty() )
12101 XmlWriter& XmlWriter::startElement( std::string
const& name ) {
12103 newlineIfNecessary();
12104 m_os << m_indent <<
'<' << name;
12105 m_tags.push_back( name );
12107 m_tagIsOpen =
true;
12111 XmlWriter::ScopedElement XmlWriter::scopedElement( std::string
const& name ) {
12112 ScopedElement scoped(
this );
12113 startElement( name );
12117 XmlWriter& XmlWriter::endElement() {
12118 newlineIfNecessary();
12119 m_indent = m_indent.substr( 0, m_indent.size()-2 );
12120 if( m_tagIsOpen ) {
12122 m_tagIsOpen =
false;
12125 m_os << m_indent <<
"</" << m_tags.back() <<
">";
12132 XmlWriter& XmlWriter::writeAttribute( std::string
const& name, std::string
const& attribute ) {
12133 if( !name.empty() && !attribute.empty() )
12134 m_os <<
' ' << name <<
"=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) <<
'"';
12138 XmlWriter& XmlWriter::writeAttribute( std::string
const& name,
bool attribute ) {
12139 m_os <<
' ' << name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
'"';
12143 XmlWriter& XmlWriter::writeText( std::string
const& text,
bool indent ) {
12144 if( !text.empty() ){
12145 bool tagWasOpen = m_tagIsOpen;
12147 if( tagWasOpen && indent )
12149 m_os << XmlEncode( text );
12150 m_needsNewline =
true;
12155 XmlWriter& XmlWriter::writeComment( std::string
const& text ) {
12157 m_os << m_indent <<
"<!--" << text <<
"-->";
12158 m_needsNewline =
true;
12162 void XmlWriter::writeStylesheetRef( std::string
const& url ) {
12163 m_os <<
"<?xml-stylesheet type=\"text/xsl\" href=\"" << url <<
"\"?>\n";
12166 XmlWriter& XmlWriter::writeBlankLine() {
12172 void XmlWriter::ensureTagClosed() {
12173 if( m_tagIsOpen ) {
12174 m_os <<
">" << std::endl;
12175 m_tagIsOpen =
false;
12179 void XmlWriter::writeDeclaration() {
12180 m_os <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
12183 void XmlWriter::newlineIfNecessary() {
12184 if( m_needsNewline ) {
12186 m_needsNewline =
false;
12200 void prepareExpandedExpression(AssertionResult& result) {
12201 result.getExpandedExpression();
12206 std::string getFormattedDuration(
double duration ) {
12211 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
12212 char buffer[maxDoubleSize];
12217 sprintf_s(buffer,
"%.3f", duration);
12219 sprintf(buffer,
"%.3f", duration);
12221 return std::string(buffer);
12224 TestEventListenerBase::TestEventListenerBase(ReporterConfig
const & _config)
12225 :StreamingReporterBase(_config) {}
12227 void TestEventListenerBase::assertionStarting(
AssertionInfo const &) {}
12229 bool TestEventListenerBase::assertionEnded(AssertionStats
const &) {
12239 #ifdef CATCH_PLATFORM_MAC 12240 const char* failedString() {
return "FAILED"; }
12241 const char* passedString() {
return "PASSED"; }
12243 const char* failedString() {
return "failed"; }
12244 const char* passedString() {
return "passed"; }
12248 Catch::Colour::Code dimColour() {
return Catch::Colour::FileName; }
12250 std::string bothOrAll( std::size_t
count ) {
12251 return count == 1 ? std::string() :
12252 count == 2 ?
"both " :
"all " ;
12265 void printTotals(std::ostream& out,
const Totals& totals) {
12267 out <<
"No tests ran.";
12269 Colour colour(Colour::ResultError);
12270 const std::string qualify_assertions_failed =
12276 "failed " << qualify_assertions_failed <<
12282 <<
" (no assertions).";
12284 Colour colour(Colour::ResultError);
12289 Colour colour(Colour::ResultSuccess);
12298 class AssertionPrinter {
12300 AssertionPrinter& operator= (AssertionPrinter
const&) =
delete;
12301 AssertionPrinter(AssertionPrinter
const&) =
delete;
12302 AssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
12304 , result(_stats.assertionResult)
12305 , messages(_stats.infoMessages)
12306 , itMessage(_stats.infoMessages.begin())
12307 , printInfoMessages(_printInfoMessages) {}
12312 itMessage = messages.begin();
12314 switch (result.getResultType()) {
12316 printResultType(Colour::ResultSuccess, passedString());
12317 printOriginalExpression();
12318 printReconstructedExpression();
12319 if (!result.hasExpression())
12320 printRemainingMessages(Colour::None);
12322 printRemainingMessages();
12326 printResultType(Colour::ResultSuccess, failedString() + std::string(
" - but was ok"));
12328 printResultType(Colour::Error, failedString());
12329 printOriginalExpression();
12330 printReconstructedExpression();
12331 printRemainingMessages();
12334 printResultType(Colour::Error, failedString());
12335 printIssue(
"unexpected exception with message:");
12337 printExpressionWas();
12338 printRemainingMessages();
12341 printResultType(Colour::Error, failedString());
12342 printIssue(
"fatal error condition with message:");
12344 printExpressionWas();
12345 printRemainingMessages();
12348 printResultType(Colour::Error, failedString());
12349 printIssue(
"expected exception, got none");
12350 printExpressionWas();
12351 printRemainingMessages();
12354 printResultType(Colour::None,
"info");
12356 printRemainingMessages();
12359 printResultType(Colour::None,
"warning");
12361 printRemainingMessages();
12364 printResultType(Colour::Error, failedString());
12365 printIssue(
"explicitly");
12366 printRemainingMessages(Colour::None);
12372 printResultType(Colour::Error,
"** internal error **");
12378 void printSourceInfo()
const {
12379 Colour colourGuard(Colour::FileName);
12380 stream << result.getSourceInfo() <<
':';
12383 void printResultType(Colour::Code colour, std::string
const& passOrFail)
const {
12384 if (!passOrFail.empty()) {
12386 Colour colourGuard(colour);
12387 stream <<
' ' << passOrFail;
12393 void printIssue(std::string
const& issue)
const {
12394 stream <<
' ' << issue;
12397 void printExpressionWas() {
12398 if (result.hasExpression()) {
12401 Colour colour(dimColour());
12402 stream <<
" expression was:";
12404 printOriginalExpression();
12408 void printOriginalExpression()
const {
12409 if (result.hasExpression()) {
12410 stream <<
' ' << result.getExpression();
12414 void printReconstructedExpression()
const {
12415 if (result.hasExpandedExpression()) {
12417 Colour colour(dimColour());
12418 stream <<
" for: ";
12420 stream << result.getExpandedExpression();
12424 void printMessage() {
12425 if (itMessage != messages.end()) {
12426 stream <<
" '" << itMessage->message <<
'\'';
12431 void printRemainingMessages(Colour::Code colour = dimColour()) {
12432 if (itMessage == messages.end())
12436 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
12437 const std::size_t N =
static_cast<std::size_t
>(std::distance(itMessage, itEnd));
12440 Colour colourGuard(colour);
12441 stream <<
" with " <<
pluralise(N,
"message") <<
':';
12444 for (; itMessage != itEnd; ) {
12447 stream <<
" '" << itMessage->message <<
'\'';
12448 if (++itMessage != itEnd) {
12449 Colour colourGuard(dimColour());
12457 std::ostream& stream;
12458 AssertionResult
const& result;
12459 std::vector<MessageInfo> messages;
12460 std::vector<MessageInfo>::const_iterator itMessage;
12461 bool printInfoMessages;
12466 std::string CompactReporter::getDescription() {
12467 return "Reports test results on a single line, suitable for IDEs";
12470 ReporterPreferences CompactReporter::getPreferences()
const {
12471 return m_reporterPrefs;
12474 void CompactReporter::noMatchingTestCases( std::string
const& spec ) {
12475 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
12478 void CompactReporter::assertionStarting(
AssertionInfo const& ) {}
12480 bool CompactReporter::assertionEnded( AssertionStats
const& _assertionStats ) {
12481 AssertionResult
const& result = _assertionStats.assertionResult;
12483 bool printInfoMessages =
true;
12486 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
12489 printInfoMessages =
false;
12492 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
12495 stream << std::endl;
12499 void CompactReporter::sectionEnded(SectionStats
const& _sectionStats) {
12500 if (m_config->showDurations() == ShowDurations::Always) {
12501 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name << std::endl;
12505 void CompactReporter::testRunEnded( TestRunStats
const& _testRunStats ) {
12506 printTotals( stream, _testRunStats.totals );
12507 stream <<
'\n' << std::endl;
12508 StreamingReporterBase::testRunEnded( _testRunStats );
12511 CompactReporter::~CompactReporter() {}
12513 CATCH_REGISTER_REPORTER(
"compact", CompactReporter )
12522 #if defined(_MSC_VER) 12523 #pragma warning(push) 12524 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 12534 class ConsoleAssertionPrinter {
12536 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter
const&) =
delete;
12537 ConsoleAssertionPrinter(ConsoleAssertionPrinter
const&) =
delete;
12538 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
12541 result(_stats.assertionResult),
12542 colour(Colour::None),
12543 message(result.getMessage()),
12544 messages(_stats.infoMessages),
12545 printInfoMessages(_printInfoMessages) {
12546 switch (result.getResultType()) {
12548 colour = Colour::Success;
12549 passOrFail =
"PASSED";
12551 if (_stats.infoMessages.size() == 1)
12552 messageLabel =
"with message";
12553 if (_stats.infoMessages.size() > 1)
12554 messageLabel =
"with messages";
12557 if (result.isOk()) {
12558 colour = Colour::Success;
12559 passOrFail =
"FAILED - but was ok";
12561 colour = Colour::Error;
12562 passOrFail =
"FAILED";
12564 if (_stats.infoMessages.size() == 1)
12565 messageLabel =
"with message";
12566 if (_stats.infoMessages.size() > 1)
12567 messageLabel =
"with messages";
12570 colour = Colour::Error;
12571 passOrFail =
"FAILED";
12572 messageLabel =
"due to unexpected exception with ";
12573 if (_stats.infoMessages.size() == 1)
12574 messageLabel +=
"message";
12575 if (_stats.infoMessages.size() > 1)
12576 messageLabel +=
"messages";
12579 colour = Colour::Error;
12580 passOrFail =
"FAILED";
12581 messageLabel =
"due to a fatal error condition";
12584 colour = Colour::Error;
12585 passOrFail =
"FAILED";
12586 messageLabel =
"because no exception was thrown where one was expected";
12589 messageLabel =
"info";
12592 messageLabel =
"warning";
12595 passOrFail =
"FAILED";
12596 colour = Colour::Error;
12597 if (_stats.infoMessages.size() == 1)
12598 messageLabel =
"explicitly with message";
12599 if (_stats.infoMessages.size() > 1)
12600 messageLabel =
"explicitly with messages";
12606 passOrFail =
"** internal error **";
12607 colour = Colour::Error;
12612 void print()
const {
12614 if (stats.totals.assertions.total() > 0) {
12618 printOriginalExpression();
12619 printReconstructedExpression();
12627 void printResultType()
const {
12628 if (!passOrFail.empty()) {
12629 Colour colourGuard(colour);
12630 stream << passOrFail <<
":\n";
12633 void printOriginalExpression()
const {
12634 if (result.hasExpression()) {
12635 Colour colourGuard(Colour::OriginalExpression);
12637 stream << result.getExpressionInMacro();
12641 void printReconstructedExpression()
const {
12642 if (result.hasExpandedExpression()) {
12643 stream <<
"with expansion:\n";
12644 Colour colourGuard(Colour::ReconstructedExpression);
12645 stream << Column(result.getExpandedExpression()).indent(2) <<
'\n';
12648 void printMessage()
const {
12649 if (!messageLabel.empty())
12650 stream << messageLabel <<
':' <<
'\n';
12651 for (
auto const& msg : messages) {
12654 stream << Column(msg.message).indent(2) <<
'\n';
12657 void printSourceInfo()
const {
12658 Colour colourGuard(Colour::FileName);
12659 stream << result.getSourceInfo() <<
": ";
12662 std::ostream& stream;
12663 AssertionStats
const& stats;
12664 AssertionResult
const& result;
12665 Colour::Code colour;
12666 std::string passOrFail;
12667 std::string messageLabel;
12668 std::string message;
12669 std::vector<MessageInfo> messages;
12670 bool printInfoMessages;
12673 std::size_t makeRatio(std::size_t number, std::size_t total) {
12674 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
12675 return (ratio == 0 && number > 0) ? 1 : ratio;
12678 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {
12679 if (i > j && i > k)
12687 struct ColumnInfo {
12688 enum Justification { Left, Right };
12691 Justification justification;
12693 struct ColumnBreak {};
12694 struct RowBreak {};
12705 static const uint64_t s_nanosecondsInAMicrosecond = 1000;
12706 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
12707 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
12708 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
12710 uint64_t m_inNanoseconds;
12714 explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
12715 : m_inNanoseconds(inNanoseconds),
12717 if (m_units == Unit::Auto) {
12718 if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
12719 m_units = Unit::Nanoseconds;
12720 else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
12721 m_units = Unit::Microseconds;
12722 else if (m_inNanoseconds < s_nanosecondsInASecond)
12723 m_units = Unit::Milliseconds;
12724 else if (m_inNanoseconds < s_nanosecondsInAMinute)
12725 m_units = Unit::Seconds;
12727 m_units = Unit::Minutes;
12732 auto value()
const ->
double {
12734 case Unit::Microseconds:
12735 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMicrosecond);
12736 case Unit::Milliseconds:
12737 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMillisecond);
12738 case Unit::Seconds:
12739 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInASecond);
12740 case Unit::Minutes:
12741 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMinute);
12743 return static_cast<double>(m_inNanoseconds);
12746 auto unitsAsString()
const -> std::string {
12748 case Unit::Nanoseconds:
12750 case Unit::Microseconds:
12752 case Unit::Milliseconds:
12754 case Unit::Seconds:
12756 case Unit::Minutes:
12759 return "** internal error **";
12763 friend auto operator << (std::ostream& os, Duration
const& duration) -> std::ostream& {
12764 return os << duration.value() <<
" " << duration.unitsAsString();
12769 class TablePrinter {
12770 std::ostream& m_os;
12771 std::vector<ColumnInfo> m_columnInfos;
12772 std::ostringstream m_oss;
12773 int m_currentColumn = -1;
12774 bool m_isOpen =
false;
12777 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
12779 m_columnInfos( std::move( columnInfos ) ) {}
12781 auto columnInfos()
const -> std::vector<ColumnInfo>
const& {
12782 return m_columnInfos;
12788 *
this << RowBreak();
12789 for (
auto const& info : m_columnInfos)
12790 *
this << info.name << ColumnBreak();
12791 *
this << RowBreak();
12792 m_os << Catch::getLineOfChars<
'-'>() <<
"\n";
12797 *
this << RowBreak();
12803 template<
typename T>
12809 friend TablePrinter&
operator << (TablePrinter& tp, ColumnBreak) {
12810 auto colStr = tp.m_oss.str();
12815 if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
12816 tp.m_currentColumn = -1;
12819 tp.m_currentColumn++;
12821 auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
12822 auto padding = (strSize + 2 <
static_cast<std::size_t
>(colInfo.width))
12823 ? std::string(colInfo.width - (strSize + 2),
' ')
12825 if (colInfo.justification == ColumnInfo::Left)
12826 tp.m_os << colStr << padding <<
" ";
12828 tp.m_os << padding << colStr <<
" ";
12832 friend TablePrinter&
operator << (TablePrinter& tp, RowBreak) {
12833 if (tp.m_currentColumn > 0) {
12835 tp.m_currentColumn = -1;
12841 ConsoleReporter::ConsoleReporter(ReporterConfig
const& config)
12842 : StreamingReporterBase(config),
12843 m_tablePrinter(
new TablePrinter(config.stream(),
12845 {
"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
12846 {
"iters", 8, ColumnInfo::Right },
12847 {
"elapsed ns", 14, ColumnInfo::Right },
12848 {
"average", 14, ColumnInfo::Right }
12850 ConsoleReporter::~ConsoleReporter() =
default;
12852 std::string ConsoleReporter::getDescription() {
12853 return "Reports test results as plain lines of text";
12856 void ConsoleReporter::noMatchingTestCases(std::string
const& spec) {
12857 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
12860 void ConsoleReporter::assertionStarting(
AssertionInfo const&) {}
12862 bool ConsoleReporter::assertionEnded(AssertionStats
const& _assertionStats) {
12863 AssertionResult
const& result = _assertionStats.assertionResult;
12865 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
12873 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
12875 stream << std::endl;
12879 void ConsoleReporter::sectionStarting(
SectionInfo const& _sectionInfo) {
12880 m_headerPrinted =
false;
12881 StreamingReporterBase::sectionStarting(_sectionInfo);
12883 void ConsoleReporter::sectionEnded(SectionStats
const& _sectionStats) {
12884 m_tablePrinter->close();
12885 if (_sectionStats.missingAssertions) {
12887 Colour colour(Colour::ResultError);
12888 if (m_sectionStack.size() > 1)
12889 stream <<
"\nNo assertions in section";
12891 stream <<
"\nNo assertions in test case";
12892 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" << std::endl;
12894 if (m_config->showDurations() == ShowDurations::Always) {
12895 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name << std::endl;
12897 if (m_headerPrinted) {
12898 m_headerPrinted =
false;
12900 StreamingReporterBase::sectionEnded(_sectionStats);
12903 void ConsoleReporter::benchmarkStarting(BenchmarkInfo
const& info) {
12904 lazyPrintWithoutClosingBenchmarkTable();
12906 auto nameCol = Column( info.name ).width( static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) );
12908 bool firstLine =
true;
12909 for (
auto line : nameCol) {
12911 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
12915 (*m_tablePrinter) << line << ColumnBreak();
12918 void ConsoleReporter::benchmarkEnded(BenchmarkStats
const& stats) {
12919 Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
12921 << stats.iterations << ColumnBreak()
12922 << stats.elapsedTimeInNanoseconds << ColumnBreak()
12923 << average << ColumnBreak();
12926 void ConsoleReporter::testCaseEnded(TestCaseStats
const& _testCaseStats) {
12927 m_tablePrinter->close();
12928 StreamingReporterBase::testCaseEnded(_testCaseStats);
12929 m_headerPrinted =
false;
12931 void ConsoleReporter::testGroupEnded(TestGroupStats
const& _testGroupStats) {
12932 if (currentGroupInfo.used) {
12933 printSummaryDivider();
12934 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
12935 printTotals(_testGroupStats.totals);
12936 stream <<
'\n' << std::endl;
12938 StreamingReporterBase::testGroupEnded(_testGroupStats);
12940 void ConsoleReporter::testRunEnded(TestRunStats
const& _testRunStats) {
12941 printTotalsDivider(_testRunStats.totals);
12942 printTotals(_testRunStats.totals);
12943 stream << std::endl;
12944 StreamingReporterBase::testRunEnded(_testRunStats);
12947 void ConsoleReporter::lazyPrint() {
12949 m_tablePrinter->close();
12950 lazyPrintWithoutClosingBenchmarkTable();
12953 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
12955 if (!currentTestRunInfo.used)
12956 lazyPrintRunInfo();
12957 if (!currentGroupInfo.used)
12958 lazyPrintGroupInfo();
12960 if (!m_headerPrinted) {
12961 printTestCaseAndSectionHeader();
12962 m_headerPrinted =
true;
12965 void ConsoleReporter::lazyPrintRunInfo() {
12966 stream << '\n' << getLineOfChars<'~'>() <<
'\n';
12967 Colour colour(Colour::SecondaryText);
12968 stream << currentTestRunInfo->name
12969 <<
" is a Catch v" << libraryVersion() <<
" host application.\n" 12970 <<
"Run with -? for options\n\n";
12972 if (m_config->rngSeed() != 0)
12973 stream <<
"Randomness seeded to: " << m_config->rngSeed() <<
"\n\n";
12975 currentTestRunInfo.used =
true;
12977 void ConsoleReporter::lazyPrintGroupInfo() {
12978 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
12979 printClosedHeader(
"Group: " + currentGroupInfo->name);
12980 currentGroupInfo.used =
true;
12983 void ConsoleReporter::printTestCaseAndSectionHeader() {
12984 assert(!m_sectionStack.empty());
12985 printOpenHeader(currentTestCaseInfo->name);
12987 if (m_sectionStack.size() > 1) {
12988 Colour colourGuard(Colour::Headers);
12991 it = m_sectionStack.begin() + 1,
12992 itEnd = m_sectionStack.end();
12993 for (; it != itEnd; ++it)
12994 printHeaderString(it->name, 2);
12999 if (!lineInfo.
empty()) {
13000 stream << getLineOfChars<
'-'>() <<
'\n';
13001 Colour colourGuard(Colour::FileName);
13002 stream << lineInfo <<
'\n';
13004 stream << getLineOfChars<
'.'>() <<
'\n' << std::endl;
13007 void ConsoleReporter::printClosedHeader(std::string
const& _name) {
13008 printOpenHeader(_name);
13009 stream << getLineOfChars<
'.'>() <<
'\n';
13011 void ConsoleReporter::printOpenHeader(std::string
const& _name) {
13012 stream << getLineOfChars<
'-'>() <<
'\n';
13014 Colour colourGuard(Colour::Headers);
13015 printHeaderString(_name);
13021 void ConsoleReporter::printHeaderString(std::string
const& _string, std::size_t indent) {
13022 std::size_t i = _string.find(
": ");
13023 if (i != std::string::npos)
13027 stream << Column(_string).indent(indent + i).initialIndent(indent) <<
'\n';
13030 struct SummaryColumn {
13032 SummaryColumn( std::string _label, Colour::Code _colour )
13033 : label( std::move( _label ) ),
13034 colour( _colour ) {}
13035 SummaryColumn addRow( std::size_t
count ) {
13038 std::string row = rss.
str();
13039 for (
auto& oldRow : rows) {
13040 while (oldRow.size() < row.size())
13041 oldRow =
' ' + oldRow;
13042 while (oldRow.size() > row.size())
13045 rows.push_back(row);
13050 Colour::Code colour;
13051 std::vector<std::string> rows;
13055 void ConsoleReporter::printTotals(
Totals const& totals ) {
13057 stream << Colour(Colour::Warning) <<
"No tests ran\n";
13059 stream << Colour(Colour::ResultSuccess) <<
"All tests passed";
13066 std::vector<SummaryColumn> columns;
13067 columns.push_back(SummaryColumn(
"", Colour::None)
13070 columns.push_back(SummaryColumn(
"passed", Colour::Success)
13073 columns.push_back(SummaryColumn(
"failed", Colour::ResultError)
13076 columns.push_back(SummaryColumn(
"failed as expected", Colour::ResultExpectedFailure)
13080 printSummaryRow(
"test cases", columns, 0);
13081 printSummaryRow(
"assertions", columns, 1);
13084 void ConsoleReporter::printSummaryRow(std::string
const& label, std::vector<SummaryColumn>
const& cols, std::size_t row) {
13085 for (
auto col : cols) {
13086 std::string
value = col.rows[row];
13087 if (col.label.empty()) {
13088 stream << label <<
": ";
13092 stream << Colour(Colour::Warning) <<
"- none -";
13093 }
else if (value !=
"0") {
13094 stream << Colour(Colour::LightGrey) <<
" | ";
13095 stream << Colour(col.colour)
13096 << value <<
' ' << col.label;
13102 void ConsoleReporter::printTotalsDivider(
Totals const& totals) {
13107 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
13108 findMax(failedRatio, failedButOkRatio, passedRatio)++;
13109 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
13110 findMax(failedRatio, failedButOkRatio, passedRatio)--;
13112 stream << Colour(Colour::Error) << std::string(failedRatio,
'=');
13113 stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio,
'=');
13115 stream << Colour(Colour::ResultSuccess) << std::string(passedRatio,
'=');
13117 stream << Colour(Colour::Success) << std::string(passedRatio,
'=');
13119 stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1,
'=');
13123 void ConsoleReporter::printSummaryDivider() {
13124 stream << getLineOfChars<
'-'>() <<
'\n';
13127 CATCH_REGISTER_REPORTER(
"console", ConsoleReporter)
13131 #if defined(_MSC_VER) 13132 #pragma warning(pop) 13140 #include <algorithm> 13145 std::string getCurrentTimestamp() {
13149 std::time(&rawtime);
13150 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
13153 std::tm timeInfo = {};
13154 gmtime_s(&timeInfo, &rawtime);
13157 timeInfo = std::gmtime(&rawtime);
13161 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
13164 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
13166 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
13168 return std::string(timeStamp);
13171 std::string fileNameTag(
const std::vector<std::string> &tags) {
13172 auto it = std::find_if(
begin(tags),
13174 [] (std::string
const& tag) {
return tag.front() ==
'#'; });
13175 if (it != tags.end())
13176 return it->substr(1);
13177 return std::string();
13181 JunitReporter::JunitReporter( ReporterConfig
const& _config )
13182 : CumulativeReporterBase( _config ),
13183 xml( _config.stream() )
13185 m_reporterPrefs.shouldRedirectStdOut =
true;
13186 m_reporterPrefs.shouldReportAllAssertions =
true;
13189 JunitReporter::~JunitReporter() {}
13191 std::string JunitReporter::getDescription() {
13192 return "Reports test results in an XML format that looks like Ant's junitreport target";
13195 void JunitReporter::noMatchingTestCases( std::string
const& ) {}
13197 void JunitReporter::testRunStarting( TestRunInfo
const& runInfo ) {
13198 CumulativeReporterBase::testRunStarting( runInfo );
13199 xml.startElement(
"testsuites" );
13202 void JunitReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
13203 suiteTimer.start();
13204 stdOutForSuite.clear();
13205 stdErrForSuite.clear();
13206 unexpectedExceptions = 0;
13207 CumulativeReporterBase::testGroupStarting( groupInfo );
13210 void JunitReporter::testCaseStarting(
TestCaseInfo const& testCaseInfo ) {
13211 m_okToFail = testCaseInfo.
okToFail();
13214 bool JunitReporter::assertionEnded( AssertionStats
const& assertionStats ) {
13216 unexpectedExceptions++;
13217 return CumulativeReporterBase::assertionEnded( assertionStats );
13220 void JunitReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
13221 stdOutForSuite += testCaseStats.stdOut;
13222 stdErrForSuite += testCaseStats.stdErr;
13223 CumulativeReporterBase::testCaseEnded( testCaseStats );
13226 void JunitReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
13227 double suiteTime = suiteTimer.getElapsedSeconds();
13228 CumulativeReporterBase::testGroupEnded( testGroupStats );
13229 writeGroup( *m_testGroups.back(), suiteTime );
13232 void JunitReporter::testRunEndedCumulative() {
13236 void JunitReporter::writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
13237 XmlWriter::ScopedElement e = xml.scopedElement(
"testsuite" );
13238 TestGroupStats
const& stats = groupNode.value;
13239 xml.writeAttribute(
"name", stats.groupInfo.name );
13240 xml.writeAttribute(
"errors", unexpectedExceptions );
13241 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
13242 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
13243 xml.writeAttribute(
"hostname",
"tbd" );
13244 if( m_config->showDurations() == ShowDurations::Never )
13245 xml.writeAttribute(
"time",
"" );
13247 xml.writeAttribute(
"time", suiteTime );
13248 xml.writeAttribute(
"timestamp", getCurrentTimestamp() );
13251 for(
auto const& child : groupNode.children )
13252 writeTestCase( *child );
13254 xml.scopedElement(
"system-out" ).writeText(
trim( stdOutForSuite ),
false );
13255 xml.scopedElement(
"system-err" ).writeText(
trim( stdErrForSuite ),
false );
13258 void JunitReporter::writeTestCase( TestCaseNode
const& testCaseNode ) {
13259 TestCaseStats
const& stats = testCaseNode.value;
13263 assert( testCaseNode.children.size() == 1 );
13264 SectionNode
const& rootSection = *testCaseNode.children.front();
13266 std::string className = stats.testInfo.className;
13268 if( className.empty() ) {
13269 className = fileNameTag(stats.testInfo.tags);
13270 if ( className.empty() )
13271 className =
"global";
13274 if ( !m_config->name().empty() )
13275 className = m_config->name() +
"." + className;
13277 writeSection( className,
"", rootSection );
13280 void JunitReporter::writeSection( std::string
const& className,
13281 std::string
const& rootName,
13282 SectionNode
const& sectionNode ) {
13283 std::string name =
trim( sectionNode.stats.sectionInfo.name );
13284 if( !rootName.empty() )
13285 name = rootName +
'/' + name;
13287 if( !sectionNode.assertions.empty() ||
13288 !sectionNode.stdOut.empty() ||
13289 !sectionNode.stdErr.empty() ) {
13290 XmlWriter::ScopedElement e = xml.scopedElement(
"testcase" );
13291 if( className.empty() ) {
13292 xml.writeAttribute(
"classname", name );
13293 xml.writeAttribute(
"name",
"root" );
13296 xml.writeAttribute(
"classname", className );
13297 xml.writeAttribute(
"name", name );
13301 writeAssertions( sectionNode );
13303 if( !sectionNode.stdOut.empty() )
13304 xml.scopedElement(
"system-out" ).writeText(
trim( sectionNode.stdOut ),
false );
13305 if( !sectionNode.stdErr.empty() )
13306 xml.scopedElement(
"system-err" ).writeText(
trim( sectionNode.stdErr ),
false );
13308 for(
auto const& childNode : sectionNode.childSections )
13309 if( className.empty() )
13310 writeSection( name,
"", *childNode );
13312 writeSection( className, name, *childNode );
13315 void JunitReporter::writeAssertions( SectionNode
const& sectionNode ) {
13316 for(
auto const& assertion : sectionNode.assertions )
13317 writeAssertion( assertion );
13320 void JunitReporter::writeAssertion( AssertionStats
const& stats ) {
13321 AssertionResult
const& result = stats.assertionResult;
13322 if( !result.isOk() ) {
13323 std::string elementName;
13324 switch( result.getResultType() ) {
13327 elementName =
"error";
13330 elementName =
"failure";
13333 elementName =
"failure";
13336 elementName =
"failure";
13346 elementName =
"internalError";
13350 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
13352 xml.writeAttribute(
"message", result.getExpandedExpression() );
13353 xml.writeAttribute(
"type", result.getTestMacroName() );
13356 if( !result.getMessage().empty() )
13357 rss << result.getMessage() <<
'\n';
13358 for(
auto const& msg : stats.infoMessages )
13360 rss << msg.message <<
'\n';
13362 rss <<
"at " << result.getSourceInfo();
13363 xml.writeText( rss.
str(), false );
13367 CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
13377 ListeningReporter::ListeningReporter() {
13379 m_preferences.shouldReportAllAssertions =
true;
13382 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
13383 m_listeners.push_back( std::move( listener ) );
13386 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
13387 assert(!m_reporter &&
"Listening reporter can wrap only 1 real reporter");
13388 m_reporter = std::move( reporter );
13389 m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;
13392 ReporterPreferences ListeningReporter::getPreferences()
const {
13393 return m_preferences;
13396 std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
13397 return std::set<Verbosity>{ };
13400 void ListeningReporter::noMatchingTestCases( std::string
const& spec ) {
13401 for (
auto const& listener : m_listeners ) {
13402 listener->noMatchingTestCases( spec );
13404 m_reporter->noMatchingTestCases( spec );
13407 void ListeningReporter::benchmarkStarting( BenchmarkInfo
const& benchmarkInfo ) {
13408 for (
auto const& listener : m_listeners ) {
13409 listener->benchmarkStarting( benchmarkInfo );
13411 m_reporter->benchmarkStarting( benchmarkInfo );
13413 void ListeningReporter::benchmarkEnded( BenchmarkStats
const& benchmarkStats ) {
13414 for (
auto const& listener : m_listeners ) {
13415 listener->benchmarkEnded( benchmarkStats );
13417 m_reporter->benchmarkEnded( benchmarkStats );
13420 void ListeningReporter::testRunStarting( TestRunInfo
const& testRunInfo ) {
13421 for (
auto const& listener : m_listeners ) {
13422 listener->testRunStarting( testRunInfo );
13424 m_reporter->testRunStarting( testRunInfo );
13427 void ListeningReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
13428 for (
auto const& listener : m_listeners ) {
13429 listener->testGroupStarting( groupInfo );
13431 m_reporter->testGroupStarting( groupInfo );
13434 void ListeningReporter::testCaseStarting(
TestCaseInfo const& testInfo ) {
13435 for (
auto const& listener : m_listeners ) {
13436 listener->testCaseStarting( testInfo );
13438 m_reporter->testCaseStarting( testInfo );
13441 void ListeningReporter::sectionStarting(
SectionInfo const& sectionInfo ) {
13442 for (
auto const& listener : m_listeners ) {
13443 listener->sectionStarting( sectionInfo );
13445 m_reporter->sectionStarting( sectionInfo );
13448 void ListeningReporter::assertionStarting(
AssertionInfo const& assertionInfo ) {
13449 for (
auto const& listener : m_listeners ) {
13450 listener->assertionStarting( assertionInfo );
13452 m_reporter->assertionStarting( assertionInfo );
13456 bool ListeningReporter::assertionEnded( AssertionStats
const& assertionStats ) {
13457 for(
auto const& listener : m_listeners ) {
13458 static_cast<void>( listener->assertionEnded( assertionStats ) );
13460 return m_reporter->assertionEnded( assertionStats );
13463 void ListeningReporter::sectionEnded( SectionStats
const& sectionStats ) {
13464 for (
auto const& listener : m_listeners ) {
13465 listener->sectionEnded( sectionStats );
13467 m_reporter->sectionEnded( sectionStats );
13470 void ListeningReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
13471 for (
auto const& listener : m_listeners ) {
13472 listener->testCaseEnded( testCaseStats );
13474 m_reporter->testCaseEnded( testCaseStats );
13477 void ListeningReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
13478 for (
auto const& listener : m_listeners ) {
13479 listener->testGroupEnded( testGroupStats );
13481 m_reporter->testGroupEnded( testGroupStats );
13484 void ListeningReporter::testRunEnded( TestRunStats
const& testRunStats ) {
13485 for (
auto const& listener : m_listeners ) {
13486 listener->testRunEnded( testRunStats );
13488 m_reporter->testRunEnded( testRunStats );
13491 void ListeningReporter::skipTest(
TestCaseInfo const& testInfo ) {
13492 for (
auto const& listener : m_listeners ) {
13493 listener->skipTest( testInfo );
13495 m_reporter->skipTest( testInfo );
13498 bool ListeningReporter::isMulti()
const {
13506 #if defined(_MSC_VER) 13507 #pragma warning(push) 13508 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 13514 XmlReporter::XmlReporter( ReporterConfig
const& _config )
13515 : StreamingReporterBase( _config ),
13516 m_xml(_config.stream())
13518 m_reporterPrefs.shouldRedirectStdOut =
true;
13519 m_reporterPrefs.shouldReportAllAssertions =
true;
13522 XmlReporter::~XmlReporter() =
default;
13524 std::string XmlReporter::getDescription() {
13525 return "Reports test results as an XML document";
13528 std::string XmlReporter::getStylesheetRef()
const {
13529 return std::string();
13532 void XmlReporter::writeSourceInfo(
SourceLineInfo const& sourceInfo ) {
13534 .writeAttribute(
"filename", sourceInfo.
file )
13535 .writeAttribute(
"line", sourceInfo.
line );
13538 void XmlReporter::noMatchingTestCases( std::string
const&
s ) {
13539 StreamingReporterBase::noMatchingTestCases( s );
13542 void XmlReporter::testRunStarting( TestRunInfo
const& testInfo ) {
13543 StreamingReporterBase::testRunStarting( testInfo );
13544 std::string stylesheetRef = getStylesheetRef();
13545 if( !stylesheetRef.empty() )
13546 m_xml.writeStylesheetRef( stylesheetRef );
13547 m_xml.startElement(
"Catch" );
13548 if( !m_config->name().empty() )
13549 m_xml.writeAttribute(
"name", m_config->name() );
13550 if( m_config->rngSeed() != 0 )
13551 m_xml.scopedElement(
"Randomness" )
13552 .writeAttribute(
"seed", m_config->rngSeed() );
13555 void XmlReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
13556 StreamingReporterBase::testGroupStarting( groupInfo );
13557 m_xml.startElement(
"Group" )
13558 .writeAttribute(
"name", groupInfo.name );
13561 void XmlReporter::testCaseStarting(
TestCaseInfo const& testInfo ) {
13562 StreamingReporterBase::testCaseStarting(testInfo);
13563 m_xml.startElement(
"TestCase" )
13564 .writeAttribute(
"name",
trim( testInfo.
name ) )
13565 .writeAttribute(
"description", testInfo.
description )
13568 writeSourceInfo( testInfo.
lineInfo );
13570 if ( m_config->showDurations() == ShowDurations::Always )
13571 m_testCaseTimer.start();
13572 m_xml.ensureTagClosed();
13575 void XmlReporter::sectionStarting(
SectionInfo const& sectionInfo ) {
13576 StreamingReporterBase::sectionStarting( sectionInfo );
13577 if( m_sectionDepth++ > 0 ) {
13578 m_xml.startElement(
"Section" )
13579 .writeAttribute(
"name",
trim( sectionInfo.
name ) );
13580 writeSourceInfo( sectionInfo.
lineInfo );
13581 m_xml.ensureTagClosed();
13585 void XmlReporter::assertionStarting(
AssertionInfo const& ) { }
13587 bool XmlReporter::assertionEnded( AssertionStats
const& assertionStats ) {
13589 AssertionResult
const& result = assertionStats.assertionResult;
13591 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
13595 for(
auto const& msg : assertionStats.infoMessages ) {
13597 m_xml.scopedElement(
"Info" )
13598 .writeText( msg.message );
13600 m_xml.scopedElement(
"Warning" )
13601 .writeText( msg.message );
13611 if( result.hasExpression() ) {
13612 m_xml.startElement(
"Expression" )
13613 .writeAttribute(
"success", result.succeeded() )
13614 .writeAttribute(
"type", result.getTestMacroName() );
13616 writeSourceInfo( result.getSourceInfo() );
13618 m_xml.scopedElement(
"Original" )
13619 .writeText( result.getExpression() );
13620 m_xml.scopedElement(
"Expanded" )
13621 .writeText( result.getExpandedExpression() );
13625 switch( result.getResultType() ) {
13627 m_xml.startElement(
"Exception" );
13628 writeSourceInfo( result.getSourceInfo() );
13629 m_xml.writeText( result.getMessage() );
13630 m_xml.endElement();
13633 m_xml.startElement(
"FatalErrorCondition" );
13634 writeSourceInfo( result.getSourceInfo() );
13635 m_xml.writeText( result.getMessage() );
13636 m_xml.endElement();
13639 m_xml.scopedElement(
"Info" )
13640 .writeText( result.getMessage() );
13646 m_xml.startElement(
"Failure" );
13647 writeSourceInfo( result.getSourceInfo() );
13648 m_xml.writeText( result.getMessage() );
13649 m_xml.endElement();
13655 if( result.hasExpression() )
13656 m_xml.endElement();
13661 void XmlReporter::sectionEnded( SectionStats
const& sectionStats ) {
13662 StreamingReporterBase::sectionEnded( sectionStats );
13663 if( --m_sectionDepth > 0 ) {
13664 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResults" );
13665 e.writeAttribute(
"successes", sectionStats.assertions.passed );
13666 e.writeAttribute(
"failures", sectionStats.assertions.failed );
13667 e.writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
13669 if ( m_config->showDurations() == ShowDurations::Always )
13670 e.writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
13672 m_xml.endElement();
13676 void XmlReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
13677 StreamingReporterBase::testCaseEnded( testCaseStats );
13678 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResult" );
13679 e.writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
13681 if ( m_config->showDurations() == ShowDurations::Always )
13682 e.writeAttribute(
"durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
13684 if( !testCaseStats.stdOut.empty() )
13685 m_xml.scopedElement(
"StdOut" ).writeText(
trim( testCaseStats.stdOut ),
false );
13686 if( !testCaseStats.stdErr.empty() )
13687 m_xml.scopedElement(
"StdErr" ).writeText(
trim( testCaseStats.stdErr ),
false );
13689 m_xml.endElement();
13692 void XmlReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
13693 StreamingReporterBase::testGroupEnded( testGroupStats );
13695 m_xml.scopedElement(
"OverallResults" )
13696 .writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
13697 .writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
13698 .writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
13699 m_xml.endElement();
13702 void XmlReporter::testRunEnded( TestRunStats
const& testRunStats ) {
13703 StreamingReporterBase::testRunEnded( testRunStats );
13704 m_xml.scopedElement(
"OverallResults" )
13705 .writeAttribute(
"successes", testRunStats.totals.assertions.passed )
13706 .writeAttribute(
"failures", testRunStats.totals.assertions.failed )
13707 .writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
13708 m_xml.endElement();
13711 CATCH_REGISTER_REPORTER(
"xml", XmlReporter )
13715 #if defined(_MSC_VER) 13716 #pragma warning(pop) 13721 LeakDetector leakDetector;
13725 #pragma clang diagnostic pop 13731 #ifdef CATCH_CONFIG_MAIN 13736 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) 13738 extern "C" int wmain (
int argc,
wchar_t * argv[],
wchar_t * []) {
13741 int main (
int argc,
char * argv[]) {
13744 return Catch::Session().run( argc, argv );
13750 int main (
int argc,
char *
const argv[]) {
13751 #if !CATCH_ARC_ENABLED 13752 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
13755 Catch::registerTestMethods();
13756 int result = Catch::Session().run( argc, (
char**)argv );
13758 #if !CATCH_ARC_ENABLED 13770 #if !defined(CATCH_CONFIG_IMPL_ONLY) 13772 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED 13773 # undef CLARA_CONFIG_MAIN 13776 #if !defined(CATCH_CONFIG_DISABLE) 13779 #ifdef CATCH_CONFIG_PREFIX_ALL 13781 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 13782 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 13784 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) 13785 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 13786 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 13787 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 13788 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 13789 #endif// CATCH_CONFIG_DISABLE_MATCHERS 13790 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 13792 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13793 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 13794 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13795 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13796 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 13798 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) 13799 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 13800 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 13801 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 13802 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 13803 #endif // CATCH_CONFIG_DISABLE_MATCHERS 13804 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13806 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 13807 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 13809 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 13810 #endif // CATCH_CONFIG_DISABLE_MATCHERS 13812 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 13813 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 13814 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ ) 13816 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 13817 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 13818 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 13819 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 13820 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 13821 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 13822 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 13823 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13824 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13826 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 13828 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 13829 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) 13830 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) 13832 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ ) 13833 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) 13837 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 13838 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 13839 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 13840 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 13841 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 13842 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 13843 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 13844 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 13849 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 13850 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 13852 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 13853 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 13854 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 13855 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 13856 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 13857 #endif // CATCH_CONFIG_DISABLE_MATCHERS 13858 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 13860 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13861 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 13862 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13863 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13864 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 13866 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13867 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 13868 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 13869 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 13870 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 13871 #endif // CATCH_CONFIG_DISABLE_MATCHERS 13872 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13874 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 13875 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 13877 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 13878 #endif // CATCH_CONFIG_DISABLE_MATCHERS 13880 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 13881 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 13882 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) 13884 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 13885 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 13886 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 13887 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 13888 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 13889 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 13890 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 13891 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13892 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 13893 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 13895 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 13896 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) 13897 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) 13899 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ ) 13900 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ ) 13905 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 13908 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 13909 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 13911 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 13912 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 13913 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 13914 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 13915 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 13916 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 13920 #else // CATCH_CONFIG_DISABLE 13924 #ifdef CATCH_CONFIG_PREFIX_ALL 13926 #define CATCH_REQUIRE( ... ) (void)(0) 13927 #define CATCH_REQUIRE_FALSE( ... ) (void)(0) 13929 #define CATCH_REQUIRE_THROWS( ... ) (void)(0) 13930 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 13931 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 13932 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 13933 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 13934 #endif// CATCH_CONFIG_DISABLE_MATCHERS 13935 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) 13937 #define CATCH_CHECK( ... ) (void)(0) 13938 #define CATCH_CHECK_FALSE( ... ) (void)(0) 13939 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) 13940 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 13941 #define CATCH_CHECK_NOFAIL( ... ) (void)(0) 13943 #define CATCH_CHECK_THROWS( ... ) (void)(0) 13944 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 13945 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) 13946 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 13947 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 13948 #endif // CATCH_CONFIG_DISABLE_MATCHERS 13949 #define CATCH_CHECK_NOTHROW( ... ) (void)(0) 13951 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 13952 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0) 13954 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) 13955 #endif // CATCH_CONFIG_DISABLE_MATCHERS 13957 #define CATCH_INFO( msg ) (void)(0) 13958 #define CATCH_WARN( msg ) (void)(0) 13959 #define CATCH_CAPTURE( msg ) (void)(0) 13961 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 13962 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 13963 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) 13964 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) 13965 #define CATCH_SECTION( ... ) 13966 #define CATCH_DYNAMIC_SECTION( ... ) 13967 #define CATCH_FAIL( ... ) (void)(0) 13968 #define CATCH_FAIL_CHECK( ... ) (void)(0) 13969 #define CATCH_SUCCEED( ... ) (void)(0) 13971 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 13974 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 13975 #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 ) 13976 #define CATCH_GIVEN( desc ) 13977 #define CATCH_AND_GIVEN( desc ) 13978 #define CATCH_WHEN( desc ) 13979 #define CATCH_AND_WHEN( desc ) 13980 #define CATCH_THEN( desc ) 13981 #define CATCH_AND_THEN( desc ) 13983 #define CATCH_STATIC_REQUIRE( ... ) (void)(0) 13984 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) 13989 #define REQUIRE( ... ) (void)(0) 13990 #define REQUIRE_FALSE( ... ) (void)(0) 13992 #define REQUIRE_THROWS( ... ) (void)(0) 13993 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 13994 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 13995 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 13996 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 13997 #endif // CATCH_CONFIG_DISABLE_MATCHERS 13998 #define REQUIRE_NOTHROW( ... ) (void)(0) 14000 #define CHECK( ... ) (void)(0) 14001 #define CHECK_FALSE( ... ) (void)(0) 14002 #define CHECKED_IF( ... ) if (__VA_ARGS__) 14003 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 14004 #define CHECK_NOFAIL( ... ) (void)(0) 14006 #define CHECK_THROWS( ... ) (void)(0) 14007 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 14008 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0) 14009 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14010 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 14011 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14012 #define CHECK_NOTHROW( ... ) (void)(0) 14014 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14015 #define CHECK_THAT( arg, matcher ) (void)(0) 14017 #define REQUIRE_THAT( arg, matcher ) (void)(0) 14018 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14020 #define INFO( msg ) (void)(0) 14021 #define WARN( msg ) (void)(0) 14022 #define CAPTURE( msg ) (void)(0) 14024 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14025 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14026 #define METHOD_AS_TEST_CASE( method, ... ) 14027 #define REGISTER_TEST_CASE( Function, ... ) (void)(0) 14028 #define SECTION( ... ) 14029 #define DYNAMIC_SECTION( ... ) 14030 #define FAIL( ... ) (void)(0) 14031 #define FAIL_CHECK( ... ) (void)(0) 14032 #define SUCCEED( ... ) (void)(0) 14033 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14035 #define STATIC_REQUIRE( ... ) (void)(0) 14036 #define STATIC_REQUIRE_FALSE( ... ) (void)(0) 14040 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 14043 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) 14044 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) 14046 #define GIVEN( desc ) 14047 #define AND_GIVEN( desc ) 14048 #define WHEN( desc ) 14049 #define AND_WHEN( desc ) 14050 #define THEN( desc ) 14051 #define AND_THEN( desc ) 14057 #endif // ! CATCH_CONFIG_IMPL_ONLY 14063 # ifdef __ICC // icpc defines the __clang__ macro 14064 # pragma warning(pop) 14066 # pragma clang diagnostic pop 14068 #elif defined __GNUC__ 14069 # pragma GCC diagnostic pop 14074 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED EqualsMatcher(std::vector< T > const &comparator)
static std::string convert(T const (&arr)[SZ])
virtual void setGenerator(Generators::GeneratorBasePtr &&generator)=0
virtual ~IGeneratorTracker()
void handleExpression(ITransientExpression const &expr)
bool matchTest(TestCase const &testCase, TestSpec const &testSpec, IConfig const &config)
virtual void benchmarkEnded(BenchmarkStats const &stats)=0
auto getResult() const -> bool
Totals & operator+=(Totals const &other)
std::vector< MatcherBase< ArgT > const * > m_matchers
std::unique_ptr< T > make_unique(Args &&...args)
std::string rawMemoryToString(const T &object)
FixedValuesGenerator(std::initializer_list< T > values)
CaseSensitive::Choice m_caseSensitivity
bool isFalseTest(int flags)
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
TestCase(ITestInvoker *testCase, TestCaseInfo &&info)
std::vector< size_t > randomiseIndices(size_t selectionSize, size_t sourceSize)
bool match(std::vector< T > const &v) const override
std::string m_description
void populate(U &&valueOrGenerator, Gs...moreGenerators)
auto empty() const noexcept-> bool
bool operator<(TestCase const &other) const
static std::enable_if<!::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
#define CATCH_ENFORCE(condition, msg)
virtual void registerTest(TestCase const &testInfo)=0
SingleValueGenerator(T const &value)
std::string toString() const
auto operator[](size_type index) const noexcept-> char
void toLowerInPlace(std::string &s)
virtual StartupExceptionRegistry const & getStartupExceptionRegistry() const =0
std::shared_ptr< ITestInvoker > test
void handleMessage(ResultWas::OfType resultType, StringRef const &message)
void handleExceptionNotThrownAsExpected()
LazyExpression(bool isNegated)
auto c_str() const -> char const *
ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
TestCase makeTestCase(ITestInvoker *testCase, std::string const &className, NameAndTags const &nameAndTags, SourceLineInfo const &lineInfo)
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
virtual void registerTagAlias(std::string const &alias, std::string const &tag, SourceLineInfo const &lineInfo)=0
virtual auto acquireGeneratorTracker(SourceLineInfo const &lineInfo) -> IGeneratorTracker &=0
bool contains(std::string const &s, std::string const &infix)
StringRef(char const *rawChars, size_type size) noexcept
bool match(T const &item) const override
CaseSensitive::Choice m_caseSensitivity
PredicateMatcher(std::function< bool(T const &)> const &elem, std::string const &descr)
auto makeUnaryExpr() const -> UnaryExpr< LhsT >
int main(int argc, char **argv)
std::vector< T > const & m_target
bool expectedToFail() const
virtual void registerReporter(std::string const &name, IReporterFactoryPtr const &factory)=0
ros::Time * timeStamp(M &m)
auto compareNotEqual(LhsT const &lhs, RhsT &&rhs) -> bool
auto getCurrentNanosecondsSinceEpoch() -> uint64_t
T const & operator+(T const &value, StreamEndStop)
auto getEstimatedClockResolution() -> uint64_t
SpecialProperties properties
bool match(ArgT const &arg) const override
ContainsMatcher(std::vector< T > const &comparator)
TestInvokerAsMethod(void(C::*testAsMethod)()) noexcept
bool match(std::vector< T > const &vec) const override
SourceLineInfo(char const *_file, std::size_t _line) noexcept
virtual void popScopedMessage(MessageInfo const &message)=0
IResultCapture & getResultCapture()
std::string tagsAsString() const
Approx & epsilon(T const &newEpsilon)
Capturer(StringRef macroName, SourceLineInfo const &lineInfo, ResultWas::OfType resultType, StringRef names)
std::shared_ptr< ITestInvoker > ITestCasePtr
std::vector< std::string > lcaseTags
StdString::RegexMatcher Matches(std::string const ®ex, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
auto as() -> Generator< T >
virtual auto hasGenerator() const -> bool=0
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name)
#define CATCH_RUNTIME_ERROR(msg)
bool replaceInPlace(std::string &str, std::string const &replaceThis, std::string const &withThis)
size_t count(InputIterator first, InputIterator last, T const &item)
StringRef(StringRef const &other) noexcept
std::vector< size_t > m_indices
virtual std::vector< TestCase > const & getAllTestsSorted(IConfig const &config) const =0
std::string finalizeDescription(const std::string &desc)
bool operator==(SourceLineInfo const &other) const noexcept
Approx operator()(T const &value)
static auto getResolution() -> uint64_t
ROSCPP_DECL bool validate(const std::string &name, std::string &error)
virtual auto getGenerator() const -> Generators::GeneratorBasePtr const &=0
std::vector< std::unique_ptr< IExceptionTranslator const >> ExceptionTranslators
StringRef(std::string const &stdString) noexcept
auto size() const -> size_t
std::vector< std::string > tags
virtual auto getIndex() const -> std::size_t=0
#define CATCH_INTERNAL_ERROR(msg)
static std::string convert(signed char const *str)
IMutableRegistryHub & getMutableRegistryHub()
Counts & operator+=(Counts const &other)
std::string(*)( exceptionTranslateFunction)
Vector::ContainsMatcher< T > Contains(std::vector< T > const &comparator)
void formatReconstructedExpression(std::ostream &os, std::string const &lhs, StringRef op, std::string const &rhs)
bool empty() const noexcept
ITransientExpression(bool isBinaryExpression, bool result)
ScopedMessage(MessageBuilder const &builder)
std::string stringify(const T &e)
StdString::EqualsMatcher Equals(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
std::vector< T > const & m_comparator
Generator(size_t size, std::unique_ptr< IGenerator< T >> generator)
bool operator==(TestCase const &other) const
std::vector< Generator< T > > m_generators
static std::string convert(U *p)
virtual void registerStartupException() noexcept=0
virtual void pushScopedMessage(MessageInfo const &message)=0
virtual ~ITestCaseRegistry()
auto getElapsedSeconds() const -> double
ROSCONSOLE_DECL void print(FilterBase *filter, void *logger, Level level, const char *file, int line, const char *function, const char *fmt,...) ROSCONSOLE_PRINTF_ATTRIBUTE(7
auto operator+(char const *lhs, StringRef const &rhs) -> std::string
std::string describe() const override
ResultDisposition::Flags resultDisposition
std::vector< TestCase > const & getAllTestCasesSorted(IConfig const &config)
ExceptionTranslator(std::string(*translateFunction)(T &))
void streamReconstructedExpression(std::ostream &os) const override
bool shouldContinueOnFailure(int flags)
auto str() const -> std::string
std::string operator+() const
bool isJustInfo(int flags)
AutoReg(ITestInvoker *invoker, SourceLineInfo const &lineInfo, StringRef const &classOrMethod, NameAndTags const &nameAndTags) noexcept
auto values(std::initializer_list< T > values) -> Generator< T >
static std::string convert(R const &range)
std::vector< TestCase > filterTests(std::vector< TestCase > const &testCases, TestSpec const &testSpec, IConfig const &config)
AssertionReaction m_reaction
AssertionInfo m_assertionInfo
void handleUnexpectedInflightException()
Floating::WithinAbsMatcher WithinAbs(double target, double margin)
Approx & scale(T const &newScale)
Totals delta(Totals const &prevTotals) const
std::unique_ptr< GeneratorBase > GeneratorBasePtr
static std::string convert(R C::*p)
GeneratorRandomiser(Generator< T > &&baseGenerator, size_t numberOfItems)
StringRef m_matcherString
BinaryExpr(bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs)
auto operator!=(StringRef const &other) const noexcept-> bool
void captureValues(size_t index, T &&value)
AssertionHandler(StringRef const ¯oName, SourceLineInfo const &lineInfo, StringRef capturedExpression, ResultDisposition::Flags resultDisposition)
StringRef capturedExpression
bool shouldSuppressFailure(int flags)
std::shared_ptr< IReporterFactory > IReporterFactoryPtr
StdString::EndsWithMatcher EndsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
std::string describe() const override
UnorderedEqualsMatcher(std::vector< T > const &target)
auto random(size_t size) -> Generator< T >
virtual ~IExceptionTranslatorRegistry()
auto makeTestInvoker(void(*testAsFunction)()) noexcept-> ITestInvoker *
bool isOk(ResultWas::OfType resultType)
virtual void registerTranslator(const IExceptionTranslator *translator)=0
void setVerbosity(int level)
ReusableStringStream m_stream
virtual ~ITransientExpression()
bool operator<(SourceLineInfo const &other) const noexcept
auto size() const noexcept-> size_type
void handleThrowingCallSkipped()
RangeGenerator(T const &first, T const &last)
void handleExceptionThrownAsExpected()
Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff)
virtual std::string translateActiveException() const =0
auto needsMoreIterations() -> bool
auto all< int >() -> Generator< int >
std::string trim(std::string const &str)
bool endsWith(std::string const &s, std::string const &suffix)
#define CATCH_INTERNAL_LINEINFO
static std::string convert(char const *str)
std::string describe() const override
std::string toLower(std::string const &s)
std::string translateActiveException()
virtual void benchmarkStarting(BenchmarkInfo const &info)=0
Vector::EqualsMatcher< T > Equals(std::vector< T > const &comparator)
virtual void streamReconstructedExpression(std::ostream &os) const =0
TestCase withName(std::string const &_newName) const
std::string describe() const override
ContainsElementMatcher(T const &comparator)
bool equalityComparisonImpl(double other) const
std::enable_if< !std::is_enum< T >::value &&!std::is_base_of< std::exception, T >::value, std::string >::type convertUnstreamable(T const &)
virtual ITestCaseRegistry const & getTestCaseRegistry() const =0
void captureValues(size_t index, T &&value, Ts &&...values)
void handleExpr(ExprLhs< T > const &expr)
bool match(ArgT const &arg) const override
auto isSubstring() const noexcept-> bool
std::size_t total() const
auto makeGenerators(U &&val, Gs...moreGenerators) -> Generators< T >
StringRef(StringRef &&other) noexcept
bool match(ArgT const &arg) const override
auto operator+=(std::string &lhs, StringRef const &sr) -> std::string &
RegistrarForTagAliases(char const *alias, char const *tag, SourceLineInfo const &lineInfo)
BenchmarkLooper(StringRef name)
virtual ~IMutableRegistryHub()
MessageBuilder(StringRef const ¯oName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
IResultCapture & m_resultCapture
void throw_exception(std::exception const &e)
auto table(std::initializer_list< std::tuple< Ts... >> &&tuples) -> Generator< std::tuple< Ts... >>
static unsigned int globalCount
auto getElapsedNanoseconds() const -> uint64_t
virtual void registerListener(IReporterFactoryPtr const &factory)=0
void streamReconstructedExpression(std::ostream &os) const override
std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const override
TestCaseInfo const & getTestCaseInfo() const
auto getElapsedMicroseconds() const -> uint64_t
auto range(T const &first, T const &last) -> Generator< T >
const std::string unprintableString
static std::enable_if<::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
virtual void handleIncomplete(AssertionInfo const &info)=0
std::string rangeToString(std::vector< bool, Allocator > const &v)
auto isBinaryExpression() const -> bool
MessageInfo(StringRef const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
auto all() -> Generator< T >
std::string m_cachedToString
Section(SectionInfo const &info)
auto substr(size_type start, size_type size) const noexcept-> StringRef
virtual IReporterRegistry const & getReporterRegistry() const =0
void populate(Generator< T > &&generator)
std::vector< MatcherBase< ArgT > const * > m_matchers
auto acquireGeneratorTracker(SourceLineInfo const &lineInfo) -> IGeneratorTracker &
auto operator==(StringRef const &other) const noexcept-> bool
std::unique_ptr< IGenerator< T > > m_generator
auto makeMatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef const &matcherString) -> MatchExpr< ArgT, MatcherT >
void captureValue(size_t index, StringRef value)
StdString::StartsWithMatcher StartsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
std::enable_if< std::is_enum< T >::value, std::string >::type convertUnstreamable(T const &value)
Approx & margin(T const &newMargin)
std::string convertUnknownEnumToString(E e)
bool operator==(MessageInfo const &other) const
std::string describe() const override
std::string describe() const override
auto numberOfCharacters() const noexcept-> size_type
std::function< bool(T const &)> m_predicate
bool operator<(MessageInfo const &other) const
virtual void sectionEnded(SectionEndInfo const &endInfo)=0
auto size() const -> size_t
void handleExceptionMatchExpr(AssertionHandler &handler, std::string const &str, StringRef const &matcherString)
Totals operator-(Totals const &other) const
MatcherBase< ArgT > const & m_underlyingMatcher
bool match(std::vector< T > const &v) const override
std::vector< T > const & m_comparator
virtual IExceptionTranslatorRegistry const & getExceptionTranslatorRegistry() const =0
Generator< T > m_baseGenerator
Counts operator-(Counts const &other) const
void swap(StringRef &other) noexcept
void streamReconstructedExpression(std::ostream &os) const override
bool contains(InputIterator first, InputIterator last, T const &item)
auto generate(SourceLineInfo const &lineInfo, L const &generatorExpression) -> decltype(std::declval< decltype(generatorExpression())>()[0])
IRegistryHub const & getRegistryHub()
auto value(T const &val) -> Generator< T >
Vector::UnorderedEqualsMatcher< T > UnorderedEquals(std::vector< T > const &target)
auto operator[](size_t index) const -> T
virtual ~IExceptionTranslator()
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
void handleUnexpectedExceptionNotThrown()
auto compareEqual(LhsT const &lhs, RhsT const &rhs) -> bool
MatchNotOf(MatcherBase< ArgT > const &underlyingMatcher)
virtual void sectionEndedEarly(SectionEndInfo const &endInfo)=0
ITransientExpression const * m_transientExpression
std::vector< T > m_values
std::string describe() const override
virtual ~IResultCapture()
std::string describe() const override
bool match(std::vector< T > const &v) const override
MatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef const &matcherString)
std::string rangeToString(Range const &range)
void invoke() const override
auto makeStream(StringRef const &filename) -> IStream const *
static std::string convert(unsigned char const *str)
auto currentData() const noexcept-> char const *
auto isOwned() const noexcept-> bool
auto allowThrows() const -> bool
TestCaseInfo(std::string const &_name, std::string const &_className, std::string const &_description, std::vector< std::string > const &_tags, SourceLineInfo const &_lineInfo)
virtual ITagAliasRegistry const & getTagAliasRegistry() const =0
#define CATCH_CATCH_ANON(type)
pluralise(std::size_t count, std::string const &label)
bool m_isBinaryExpression
auto get() -> std::ostream &
std::vector< MessageInfo > m_messages
auto operator[](size_t index) const -> T
GeneratorBase(size_t size)
bool startsWith(std::string const &s, std::string const &prefix)
Vector::ContainsElementMatcher< T > VectorContains(T const &comparator)
auto getElapsedMilliseconds() const -> unsigned int