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 7 18 #define CATCH_VERSION_PATCH 0 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" // See #674 for details 44 # pragma GCC diagnostic push 45 # pragma GCC diagnostic ignored "-Wunused-variable" 46 # pragma GCC diagnostic ignored "-Wpadded" 49 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) 51 # define CATCH_CONFIG_ALL_PARTS 56 #if defined(CATCH_CONFIG_ALL_PARTS) 57 # define CATCH_CONFIG_EXTERNAL_INTERFACES 58 # if defined(CATCH_CONFIG_DISABLE_MATCHERS) 59 # undef CATCH_CONFIG_DISABLE_MATCHERS 61 # if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 62 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 66 #if !defined(CATCH_CONFIG_IMPL_ONLY) 70 # include <TargetConditionals.h> 71 # if TARGET_OS_OSX == 1 72 # define CATCH_PLATFORM_MAC 73 # elif TARGET_OS_IPHONE == 1 74 # define CATCH_PLATFORM_IPHONE 77 #elif defined(linux) || defined(__linux) || defined(__linux__) 78 # define CATCH_PLATFORM_LINUX 80 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) 81 # define CATCH_PLATFORM_WINDOWS 87 # ifndef CLARA_CONFIG_MAIN 88 # define CLARA_CONFIG_MAIN_NOT_DEFINED 89 # define CLARA_CONFIG_MAIN 125 # if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) 126 # define CATCH_CPP14_OR_GREATER 129 # if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) 130 # define CATCH_CPP17_OR_GREATER 135 #if defined(CATCH_CPP17_OR_GREATER) 136 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 141 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 142 _Pragma( "clang diagnostic push" ) \ 143 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ 144 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") 145 # define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 146 _Pragma( "clang diagnostic pop" ) 148 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 149 _Pragma( "clang diagnostic push" ) \ 150 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 151 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 152 _Pragma( "clang diagnostic pop" ) 154 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 155 _Pragma( "clang diagnostic push" ) \ 156 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) 157 # define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \ 158 _Pragma( "clang diagnostic pop" ) 164 #if !defined(CATCH_PLATFORM_WINDOWS) 165 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS 170 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) 171 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 175 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 176 # define CATCH_CONFIG_COLOUR_NONE 181 #if defined(__ANDROID__) 182 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 187 #if defined(__MINGW32__) 188 # define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH 193 #if defined(__ORBIS__) 194 # define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE 206 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ 207 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) 209 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING 218 # if _MSC_VER >= 1900 // Visual Studio 2015 or newer 219 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 224 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) 225 # define CATCH_CONFIG_COLOUR_NONE 227 # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 233 # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) 234 # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 241 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) 242 # define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED 248 # define CATCH_INTERNAL_CONFIG_NO_WCHAR 253 #if defined(__BORLANDC__) 254 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN 264 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) 265 #define CATCH_INTERNAL_CONFIG_COUNTER 271 #if defined(__has_include) 272 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER) 273 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW 279 #if defined(__has_include) 280 # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 281 # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL 282 # endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER) 283 #endif // __has_include 287 #if defined(__has_include) 288 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 289 # if defined(__clang__) && (__clang_major__ < 8) 293 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 294 # define CATCH_CONFIG_NO_CPP17_VARIANT 296 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 297 # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) 299 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT 300 # endif // defined(__clang__) && (__clang_major__ < 8) 301 # endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER) 302 #endif // __has_include 304 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) 305 # define CATCH_CONFIG_COUNTER 307 #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) 308 # define CATCH_CONFIG_WINDOWS_SEH 311 #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) 312 # define CATCH_CONFIG_POSIX_SIGNALS 315 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) 316 # define CATCH_CONFIG_WCHAR 319 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) 320 # define CATCH_CONFIG_CPP11_TO_STRING 323 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) 324 # define CATCH_CONFIG_CPP17_OPTIONAL 327 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 328 # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS 331 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) 332 # define CATCH_CONFIG_CPP17_STRING_VIEW 335 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) 336 # define CATCH_CONFIG_CPP17_VARIANT 339 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 340 # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE 343 #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) 344 # define CATCH_CONFIG_NEW_CAPTURE 347 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 348 # define CATCH_CONFIG_DISABLE_EXCEPTIONS 351 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) 352 # define CATCH_CONFIG_POLYFILL_ISNAN 355 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) 356 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 357 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS 359 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) 360 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 361 # define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 363 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) 364 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS 365 # define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS 368 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 369 #define CATCH_TRY if ((true)) 370 #define CATCH_CATCH_ALL if ((false)) 371 #define CATCH_CATCH_ANON(type) if ((false)) 373 #define CATCH_TRY try 374 #define CATCH_CATCH_ALL catch (...) 375 #define CATCH_CATCH_ANON(type) catch (type) 378 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) 379 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 383 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 384 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 385 #ifdef CATCH_CONFIG_COUNTER 386 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 388 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 430 bool empty()
const noexcept;
458 #define CATCH_INTERNAL_LINEINFO \ 459 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 470 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ 471 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 472 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ 473 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 487 virtual void invoke ()
const = 0;
496 virtual std::vector<TestCase>
const& getAllTests()
const = 0;
497 virtual std::vector<TestCase>
const& getAllTestsSorted(
IConfig const&
config )
const = 0;
501 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec,
IConfig const& config );
527 friend struct StringRefTestAccess;
532 char* m_data =
nullptr;
534 void takeOwnership();
536 static constexpr
char const*
const s_empty =
"";
544 : m_start( other.m_start ),
545 m_size( other.m_size )
549 : m_start( other.m_start ),
550 m_size( other.m_size ),
551 m_data( other.m_data )
553 other.m_data =
nullptr;
556 StringRef(
char const* rawChars ) noexcept;
559 : m_start( rawChars ),
564 : m_start( stdString.c_str() ),
565 m_size( stdString.size() )
576 m_size = other.m_size;
580 operator std::string()
const;
588 auto operator[] (
size_type index )
const noexcept -> char;
591 auto empty() const noexcept ->
bool {
598 auto numberOfCharacters()
const noexcept ->
size_type;
599 auto c_str()
const ->
char const*;
606 auto currentData()
const noexcept ->
char const*;
609 auto isOwned()
const noexcept ->
bool;
610 auto isSubstring()
const noexcept ->
bool;
620 inline auto operator "" _sr(
char const* rawChars, std::size_t size ) noexcept ->
StringRef {
626 inline auto operator "" _catch_sr(
char const* rawChars, std::size_t size ) noexcept ->
Catch::StringRef {
634 #include <type_traits> 638 #ifdef CATCH_CPP17_OR_GREATER 639 template <
typename...>
640 inline constexpr
auto is_unique = std::true_type{};
642 template <
typename T,
typename... Rest>
643 inline constexpr
auto is_unique<T, Rest...> = std::bool_constant<
644 (!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>
648 template <
typename...>
649 struct is_unique : std::true_type{};
651 template <
typename T0,
typename T1,
typename... Rest>
652 struct is_unique<T0, T1, Rest...> : std::integral_constant
654 !std::is_same<T0, T1>::value
655 && is_unique<T0, Rest...>::value
656 && is_unique<T1, Rest...>::value
666 #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ 667 #define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) 668 #define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) 669 #define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) 670 #define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) 671 #define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) 673 #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 674 #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ 676 #define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) 677 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) 679 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) 682 #define CATCH_REC_END(...) 683 #define CATCH_REC_OUT 685 #define CATCH_EMPTY() 686 #define CATCH_DEFER(id) id CATCH_EMPTY() 688 #define CATCH_REC_GET_END2() 0, CATCH_REC_END 689 #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 690 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 691 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT 692 #define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) 693 #define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) 695 #define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 696 #define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) 697 #define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) 699 #define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) 700 #define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) 701 #define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) 706 #define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 708 #define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) 710 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) 711 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ 712 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ 713 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF 714 #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) 715 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 716 #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ 717 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) 720 #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) 721 #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ 722 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) 725 #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) 727 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__) 728 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 729 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " - " #__VA_ARGS__ 730 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name,...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) 733 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " -" #__VA_ARGS__ 734 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__) 735 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) 738 #define INTERNAL_CATCH_MAKE_TYPE_LIST(types) Catch::TypeList<INTERNAL_CATCH_REMOVE_PARENS(types)> 740 #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\ 741 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types)) 747 #include <type_traits> 750 template<
typename... >
753 template<
typename... >
756 template<
template<
typename...>
class L1
758 ,
template<
typename...>
class L2
765 template<
template<
typename...>
class L1
767 ,
template<
typename...>
class L2
771 struct append< L1<E1...>, L2<E2...>, Rest...> {
775 template<
template<
typename...> class
780 template<
template<
typename...>
class Container
781 ,
template<
typename...>
class List
784 struct rewrap<Container, List<elems...>> {
788 template<
template<
typename...>
class Container
789 ,
template<
typename...>
class List
791 ,
typename...Elements>
792 struct rewrap<Container, List<Elems...>, Elements...> {
796 template<
template<
typename...>
class...Containers >
798 template<
typename...Types >
800 template<
template <
typename...>
class Final >
817 void (C::*m_testAsMethod)();
823 (obj.*m_testAsMethod)();
847 #if defined(CATCH_CONFIG_DISABLE) 848 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ 849 static void TestName() 850 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 852 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 856 void TestName::test() 857 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( TestName, ... ) \ 858 template<typename TestType> \ 859 static void TestName() 860 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ 862 template<typename TestType> \ 863 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 867 template<typename TestType> \ 868 void TestName::test() 872 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ 873 static void TestName(); \ 874 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 875 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } \ 876 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 877 static void TestName() 878 #define INTERNAL_CATCH_TESTCASE( ... ) \ 879 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) 882 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ 883 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 884 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } \ 885 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 888 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ 889 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 891 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \ 894 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); \ 896 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 897 void TestName::test() 898 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ 899 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) 902 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ 903 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 904 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); \ 905 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 908 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, ... )\ 909 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 910 template<typename TestType> \ 911 static void TestFunc();\ 913 template<typename...Types> \ 915 template<typename...Ts> \ 916 TestName(Ts...names){\ 917 CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \ 918 using expander = int[];\ 919 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ names, Tags } ), 0)... }; \ 922 INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \ 924 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 925 template<typename TestType> \ 926 static void TestFunc() 928 #if defined(CATCH_CPP17_OR_GREATER) 929 #define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>,"Duplicate type detected in declaration of template test case"); 931 #define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>::value,"Duplicate type detected in declaration of template test case"); 934 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 935 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 936 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) 938 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \ 939 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) ) 942 #define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...)\ 943 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 944 TestName<CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)>(CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME,Name, __VA_ARGS__));\ 948 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, TmplTypes, TypesList) \ 949 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 950 template<typename TestType> static void TestFuncName(); \ 952 template<typename... Types> \ 955 CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...) \ 957 using expander = int[]; \ 958 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 959 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 960 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 961 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };\ 964 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ 965 using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)> \ 966 ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestName>::type; \ 971 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 972 template<typename TestType> \ 973 static void TestFuncName() 975 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 976 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 977 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ),Name,Tags,__VA_ARGS__) 979 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\ 980 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) ) 983 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \ 984 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 986 template<typename TestType> \ 987 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 990 template<typename...Types> \ 991 struct TestNameClass{\ 992 template<typename...Ts> \ 993 TestNameClass(Ts...names){\ 994 CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \ 995 using expander = int[];\ 996 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ names, Tags } ), 0)... }; \ 999 INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__)\ 1001 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\ 1002 template<typename TestType> \ 1003 void TestName<TestType>::test() 1005 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1006 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1007 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) 1009 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \ 1010 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) ) 1013 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplTypes, TypesList)\ 1014 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 1015 template<typename TestType> \ 1016 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \ 1020 template<typename...Types>\ 1021 struct TestNameClass{\ 1023 CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\ 1025 using expander = int[];\ 1026 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\ 1027 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\ 1028 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\ 1029 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... }; \ 1032 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ 1033 using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>\ 1034 ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestNameClass>::type;\ 1039 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 1040 template<typename TestType> \ 1041 void TestName<TestType>::test() 1043 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 1044 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1045 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ ) 1047 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\ 1048 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ ) ) 1071 ExpressionFailed = FailureBit | 1,
1072 ExplicitFailure = FailureBit | 2,
1074 Exception = 0x100 | FailureBit,
1076 ThrewException = Exception | 1,
1077 DidntThrowException = Exception | 2,
1079 FatalErrorCondition = 0x200 | FailureBit
1090 ContinueOnFailure = 0x02,
1127 #include <type_traits> 1137 std::ostream&
cout();
1138 std::ostream&
cerr();
1139 std::ostream&
clog();
1145 virtual std::ostream& stream()
const = 0;
1157 auto str() const ->
std::
string;
1159 template<typename T>
1164 auto get() -> std::ostream& {
return *m_oss; }
1170 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1171 #include <string_view> 1177 #import <Foundation/Foundation.h> 1179 #ifdef __has_feature 1180 #define CATCH_ARC_ENABLED __has_feature(objc_arc) 1182 #define CATCH_ARC_ENABLED 0 1185 void arcSafeRelease( NSObject* obj );
1186 id performOptionalSelector(
id obj,
SEL sel );
1188 #if !CATCH_ARC_ENABLED 1189 inline void arcSafeRelease( NSObject* obj ) {
1192 inline id performOptionalSelector(
id obj,
SEL sel ) {
1193 if( [obj respondsToSelector: sel] )
1194 return [obj performSelector: sel];
1197 #define CATCH_UNSAFE_UNRETAINED 1198 #define CATCH_ARC_STRONG 1200 inline void arcSafeRelease( NSObject* ){}
1201 inline id performOptionalSelector(
id obj,
SEL sel ) {
1203 #pragma clang diagnostic push 1204 #pragma clang diagnostic ignored "-Warc-performSelector-leaks" 1206 if( [obj respondsToSelector: sel] )
1207 return [obj performSelector: sel];
1209 #pragma clang diagnostic pop 1213 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 1214 #define CATCH_ARC_STRONG __strong 1221 #pragma warning(push) 1222 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless 1232 template<
typename T>
1237 template<
typename T>
1239 template<
typename SS,
typename TT>
1240 static auto test(
int)
1241 -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
1243 template<
typename,
typename>
1244 static auto test(...)->std::false_type;
1247 static const bool value = decltype(test<std::ostream, const T&>(0))::value;
1250 template<
typename E>
1253 template<
typename T>
1254 typename std::enable_if<
1259 template<
typename T>
1260 typename std::enable_if<
1266 template<
typename T>
1267 typename std::enable_if<
1273 #if defined(_MANAGED) 1274 template<
typename T>
1276 std::string clrReferenceToString( T^ ref ) {
1278 return std::string(
"null");
1279 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
1280 cli::pin_ptr<System::Byte> p = &bytes[0];
1281 return std::string(reinterpret_cast<char const *>(p), bytes->Length);
1288 template <
typename T,
typename =
void>
1290 template <
typename Fake = T>
1297 rss.operator<<(
value);
1301 template <
typename Fake = T>
1305 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) 1308 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
1317 template <
typename T>
1319 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e);
1322 template<
typename E>
1327 #if defined(_MANAGED) 1328 template <
typename T>
1330 return ::Catch::StringMaker<T^>::convert(e);
1340 static std::string
convert(
const std::string& str);
1343 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1346 static std::string
convert(std::string_view str);
1352 static std::string
convert(
char const * str);
1356 static std::string
convert(
char * str);
1359 #ifdef CATCH_CONFIG_WCHAR 1362 static std::string
convert(
const std::wstring& wstr);
1365 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 1368 static std::string
convert(std::wstring_view str);
1374 static std::string
convert(
wchar_t const * str);
1378 static std::string
convert(
wchar_t * str);
1392 static std::string
convert(
signed char const* str) {
1398 static std::string
convert(
unsigned char const* str) {
1405 static std::string
convert(
int value);
1409 static std::string
convert(
long value);
1413 static std::string
convert(
long long value);
1417 static std::string
convert(
unsigned int value);
1421 static std::string
convert(
unsigned long value);
1425 static std::string
convert(
unsigned long long value);
1430 static std::string
convert(
bool b);
1435 static std::string
convert(
char c);
1439 static std::string
convert(
signed char c);
1443 static std::string
convert(
unsigned char c);
1448 static std::string
convert(std::nullptr_t);
1453 static std::string
convert(
float value);
1457 static std::string
convert(
double value);
1460 template <
typename T>
1462 template <
typename U>
1472 template <
typename R,
typename C>
1483 #if defined(_MANAGED) 1484 template <
typename T>
1486 static std::string
convert( T^ ref ) {
1487 return ::Catch::Detail::clrReferenceToString(ref);
1493 template<
typename InputIterator>
1497 if (first != last) {
1499 for (++first; first != last; ++first)
1510 static std::string
convert(NSString * nsstring) {
1513 return std::string(
"@") + [nsstring UTF8String];
1518 static std::string
convert(NSObject* nsObject) {
1524 inline std::string
stringify( NSString* nsstring ) {
1537 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) 1538 # define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1539 # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1540 # define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1541 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1542 # define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1546 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) 1549 template<
typename T1,
typename T2>
1551 static std::string
convert(
const std::pair<T1, T2>& pair) {
1562 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER 1564 #if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL) 1567 template<
typename T>
1569 static std::string
convert(
const std::optional<T>& optional) {
1571 if (optional.has_value()) {
1580 #endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER 1583 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) 1592 struct TupleElementPrinter {
1593 static void print(
const Tuple& tuple, std::ostream& os) {
1594 os << (N ?
", " :
" ")
1596 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
1604 struct TupleElementPrinter<Tuple, N, false> {
1605 static void print(
const Tuple&, std::ostream&) {}
1610 template<
typename ...Types>
1612 static std::string
convert(
const std::tuple<Types...>& tuple) {
1615 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.
get());
1621 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER 1623 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT) 1628 static std::string
convert(
const std::monostate&) {
1633 template<
typename... Elements>
1635 static std::string
convert(
const std::variant<Elements...>& variant) {
1636 if (variant.valueless_by_exception()) {
1637 return "{valueless variant}";
1640 [](
const auto&
value) {
1649 #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER 1661 template <
typename T>
1668 #if defined(_MANAGED) // Managed types are never ranges 1669 template <
typename T>
1671 static const bool value =
false;
1675 template<
typename Range>
1681 template<
typename Allocator>
1697 template<
typename R>
1698 struct StringMaker<R, typename
std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
1704 template <
typename T,
int SZ>
1714 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 1721 template <
class Ratio>
1722 struct ratio_string {
1723 static std::string symbol();
1726 template <
class Ratio>
1727 std::string ratio_string<Ratio>::symbol() {
1729 rss <<
'[' << Ratio::num <<
'/' 1730 << Ratio::den <<
']';
1734 struct ratio_string<std::atto> {
1735 static std::string symbol();
1738 struct ratio_string<std::femto> {
1739 static std::string symbol();
1742 struct ratio_string<std::pico> {
1743 static std::string symbol();
1746 struct ratio_string<std::nano> {
1747 static std::string symbol();
1750 struct ratio_string<std::micro> {
1751 static std::string symbol();
1754 struct ratio_string<std::milli> {
1755 static std::string symbol();
1760 template<
typename Value,
typename Ratio>
1761 struct StringMaker<std::chrono::duration<Value, Ratio>> {
1762 static std::string
convert(std::chrono::duration<Value, Ratio>
const& duration) {
1764 rss << duration.count() <<
' ' << ratio_string<Ratio>::symbol() <<
's';
1768 template<
typename Value>
1769 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
1770 static std::string
convert(std::chrono::duration<Value, std::ratio<1>>
const& duration) {
1772 rss << duration.count() <<
" s";
1776 template<
typename Value>
1777 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
1778 static std::string
convert(std::chrono::duration<Value, std::ratio<60>>
const& duration) {
1780 rss << duration.count() <<
" m";
1784 template<
typename Value>
1785 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
1786 static std::string
convert(std::chrono::duration<Value, std::ratio<3600>>
const& duration) {
1788 rss << duration.count() <<
" h";
1796 template<
typename Clock,
typename Duration>
1797 struct StringMaker<std::chrono::time_point<Clock, Duration>> {
1798 static std::string
convert(std::chrono::time_point<Clock, Duration>
const& time_point) {
1803 template<
typename Duration>
1804 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
1805 static std::string
convert(std::chrono::time_point<std::chrono::system_clock, Duration>
const& time_point) {
1806 auto converted = std::chrono::system_clock::to_time_t(time_point);
1809 std::tm timeInfo = {};
1810 gmtime_s(&timeInfo, &converted);
1812 std::tm* timeInfo = std::gmtime(&converted);
1815 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
1817 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
1820 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
1822 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
1824 return std::string(timeStamp);
1828 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 1831 #pragma warning(pop) 1838 #pragma warning(push) 1839 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch 1840 #pragma warning(disable:4018) // more "signed/unsigned mismatch" 1841 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 1842 #pragma warning(disable:4180) // qualifier applied to function type has no meaning 1843 #pragma warning(disable:4800) // Forcing result to true or false 1851 virtual void streamReconstructedExpression( std::ostream &os )
const = 0;
1854 : m_isBinaryExpression( isBinaryExpression ),
1869 template<
typename LhsT,
typename RhsT>
1888 template<
typename T>
1891 "chained comparisons are not supported inside assertions, " 1892 "wrap the expression inside parentheses, or decompose it");
1895 template<
typename T>
1898 "chained comparisons are not supported inside assertions, " 1899 "wrap the expression inside parentheses, or decompose it");
1902 template<
typename T>
1905 "chained comparisons are not supported inside assertions, " 1906 "wrap the expression inside parentheses, or decompose it");
1909 template<
typename T>
1912 "chained comparisons are not supported inside assertions, " 1913 "wrap the expression inside parentheses, or decompose it");
1916 template<
typename T>
1919 "chained comparisons are not supported inside assertions, " 1920 "wrap the expression inside parentheses, or decompose it");
1923 template<
typename T>
1926 "chained comparisons are not supported inside assertions, " 1927 "wrap the expression inside parentheses, or decompose it");
1930 template<
typename T>
1933 "chained comparisons are not supported inside assertions, " 1934 "wrap the expression inside parentheses, or decompose it");
1937 template<
typename T>
1940 "chained comparisons are not supported inside assertions, " 1941 "wrap the expression inside parentheses, or decompose it");
1945 template<
typename LhsT>
1961 template<
typename LhsT,
typename RhsT>
1962 auto compareEqual( LhsT
const& lhs, RhsT
const& rhs ) ->
bool {
return static_cast<bool>(lhs == rhs); }
1963 template<
typename T>
1964 auto compareEqual( T*
const& lhs,
int rhs ) ->
bool {
return lhs ==
reinterpret_cast<void const*
>( rhs ); }
1965 template<
typename T>
1966 auto compareEqual( T*
const& lhs,
long rhs ) ->
bool {
return lhs ==
reinterpret_cast<void const*
>( rhs ); }
1967 template<
typename T>
1968 auto compareEqual(
int lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) == rhs; }
1969 template<
typename T>
1970 auto compareEqual(
long lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) == rhs; }
1972 template<
typename LhsT,
typename RhsT>
1973 auto compareNotEqual( LhsT
const& lhs, RhsT&& rhs ) ->
bool {
return static_cast<bool>(lhs != rhs); }
1974 template<
typename T>
1975 auto compareNotEqual( T*
const& lhs,
int rhs ) ->
bool {
return lhs !=
reinterpret_cast<void const*
>( rhs ); }
1976 template<
typename T>
1977 auto compareNotEqual( T*
const& lhs,
long rhs ) ->
bool {
return lhs !=
reinterpret_cast<void const*
>( rhs ); }
1978 template<
typename T>
1979 auto compareNotEqual(
int lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) != rhs; }
1980 template<
typename T>
1981 auto compareNotEqual(
long lhs, T*
const& rhs ) ->
bool {
return reinterpret_cast<void const*
>( lhs ) != rhs; }
1983 template<
typename LhsT>
1989 template<
typename RhsT>
1991 return {
compareEqual( m_lhs, rhs ), m_lhs,
"==", rhs };
1994 return { m_lhs == rhs, m_lhs,
"==", rhs };
1997 template<
typename RhsT>
2002 return { m_lhs != rhs, m_lhs,
"!=", rhs };
2005 template<
typename RhsT>
2007 return {
static_cast<bool>(m_lhs > rhs), m_lhs,
">", rhs };
2009 template<
typename RhsT>
2011 return {
static_cast<bool>(m_lhs < rhs), m_lhs,
"<", rhs };
2013 template<
typename RhsT>
2015 return {
static_cast<bool>(m_lhs >= rhs), m_lhs,
">=", rhs };
2017 template<
typename RhsT>
2019 return {
static_cast<bool>(m_lhs <= rhs), m_lhs,
"<=", rhs };
2022 template<
typename RhsT>
2025 "operator&& is not supported inside assertions, " 2026 "wrap the expression inside parentheses, or decompose it");
2029 template<
typename RhsT>
2032 "operator|| is not supported inside assertions, " 2033 "wrap the expression inside parentheses, or decompose it");
2043 template<
typename T>
2049 template<
typename T>
2062 #pragma warning(pop) 2072 class AssertionResult;
2079 struct BenchmarkInfo;
2080 struct BenchmarkStats;
2091 virtual bool sectionStarted(
SectionInfo const& sectionInfo,
2092 Counts& assertions ) = 0;
2094 virtual void sectionEndedEarly(
SectionEndInfo const& endInfo ) = 0;
2098 virtual void benchmarkStarting( BenchmarkInfo
const& info ) = 0;
2099 virtual void benchmarkEnded( BenchmarkStats
const& stats ) = 0;
2101 virtual void pushScopedMessage(
MessageInfo const& message ) = 0;
2102 virtual void popScopedMessage(
MessageInfo const& message ) = 0;
2104 virtual void emplaceUnscopedMessage(
MessageBuilder const& builder ) = 0;
2106 virtual void handleFatalErrorCondition(
StringRef message ) = 0;
2108 virtual void handleExpr
2112 virtual void handleMessage
2117 virtual void handleUnexpectedExceptionNotThrown
2120 virtual void handleUnexpectedInflightException
2122 std::string
const& message,
2124 virtual void handleIncomplete
2126 virtual void handleNonExpr
2131 virtual bool lastAssertionPassed() = 0;
2132 virtual void assertionPassed() = 0;
2135 virtual std::string getCurrentTestName()
const = 0;
2136 virtual const AssertionResult* getLastResult()
const = 0;
2137 virtual void exceptionEarlyReported() = 0;
2147 struct AssertionResultData;
2153 friend struct AssertionStats;
2154 friend class RunContext;
2163 explicit operator bool()
const;
2169 bool shouldDebugBreak =
false;
2170 bool shouldThrow =
false;
2176 bool m_completed =
false;
2186 if ( !m_completed ) {
2191 template<
typename T>
2199 void handleExceptionThrownAsExpected();
2200 void handleUnexpectedExceptionNotThrown();
2201 void handleExceptionNotThrownAsExpected();
2202 void handleThrowingCallSkipped();
2203 void handleUnexpectedInflightException();
2206 void setCompleted();
2209 auto allowThrows()
const ->
bool;
2243 template<
typename T>
2257 template<
typename T>
2280 size_t m_captured = 0;
2285 void captureValue(
size_t index, std::string
const&
value );
2287 template<
typename T>
2292 template<
typename T,
typename... Ts>
2295 captureValues( index+1, values... );
2302 #if !defined(CATCH_CONFIG_DISABLE) 2304 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) 2305 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ 2307 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" 2310 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 2315 #define INTERNAL_CATCH_TRY 2316 #define INTERNAL_CATCH_CATCH( capturer ) 2318 #else // CATCH_CONFIG_FAST_COMPILE 2320 #define INTERNAL_CATCH_TRY try 2321 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); } 2325 #define INTERNAL_CATCH_REACT( handler ) handler.complete(); 2328 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ 2330 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2331 INTERNAL_CATCH_TRY { \ 2332 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 2333 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ 2334 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 2335 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 2336 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2337 } 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 2341 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ 2342 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2343 if( Catch::getResultCapture().lastAssertionPassed() ) 2346 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ 2347 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ 2348 if( !Catch::getResultCapture().lastAssertionPassed() ) 2351 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ 2353 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ 2355 static_cast<void>(__VA_ARGS__); \ 2356 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ 2359 catchAssertionHandler.handleUnexpectedInflightException(); \ 2361 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2365 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ 2367 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ 2368 if( catchAssertionHandler.allowThrows() ) \ 2370 static_cast<void>(__VA_ARGS__); \ 2371 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2374 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2377 catchAssertionHandler.handleThrowingCallSkipped(); \ 2378 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2382 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 2384 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 2385 if( catchAssertionHandler.allowThrows() ) \ 2387 static_cast<void>(expr); \ 2388 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2390 catch( exceptionType const& ) { \ 2391 catchAssertionHandler.handleExceptionThrownAsExpected(); \ 2394 catchAssertionHandler.handleUnexpectedInflightException(); \ 2397 catchAssertionHandler.handleThrowingCallSkipped(); \ 2398 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2402 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 2404 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ 2405 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 2406 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2410 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ 2411 auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ 2412 varName.captureValues( 0, __VA_ARGS__ ) 2415 #define INTERNAL_CATCH_INFO( macroName, log ) \ 2416 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); 2419 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ 2420 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 2424 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ 2426 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 2427 if( catchAssertionHandler.allowThrows() ) \ 2429 static_cast<void>(__VA_ARGS__); \ 2430 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 2433 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \ 2436 catchAssertionHandler.handleThrowingCallSkipped(); \ 2437 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 2440 #endif // CATCH_CONFIG_DISABLE 2457 std::size_t total()
const;
2458 bool allPassed()
const;
2461 std::size_t passed = 0;
2462 std::size_t failed = 0;
2463 std::size_t failedButOk = 0;
2487 std::string
const& _name );
2492 std::string
const& _name,
2493 std::string
const& ) :
SectionInfo( _lineInfo, _name ) {}
2519 uint64_t m_nanoseconds = 0;
2522 auto getElapsedNanoseconds() const -> uint64_t;
2523 auto getElapsedMicroseconds() const -> uint64_t;
2524 auto getElapsedMilliseconds() const ->
unsigned int;
2525 auto getElapsedSeconds() const ->
double;
2541 explicit operator bool()
const;
2554 #define INTERNAL_CATCH_SECTION( ... ) \ 2555 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2556 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \ 2557 CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS 2559 #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \ 2560 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ 2561 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \ 2562 CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS 2575 std::size_t m_count = 0;
2576 std::size_t m_iterationsToRun = 1;
2580 static auto getResolution() -> uint64_t;
2585 m_resolution( getResolution() )
2592 if( m_count < m_iterationsToRun )
2594 return needsMoreIterations();
2602 auto needsMoreIterations() ->
bool;
2607 #define BENCHMARK( name ) \ 2608 for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() ) 2621 struct ITestCaseRegistry;
2622 struct IExceptionTranslatorRegistry;
2623 struct IExceptionTranslator;
2624 struct IReporterRegistry;
2625 struct IReporterFactory;
2626 struct ITagAliasRegistry;
2627 class StartupExceptionRegistry;
2634 virtual IReporterRegistry
const& getReporterRegistry()
const = 0;
2636 virtual ITagAliasRegistry
const& getTagAliasRegistry()
const = 0;
2640 virtual StartupExceptionRegistry
const& getStartupExceptionRegistry()
const = 0;
2647 virtual void registerTest(
TestCase const& testInfo ) = 0;
2649 virtual void registerTagAlias( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo ) = 0;
2650 virtual void registerStartupException() noexcept = 0;
2661 #if defined(CATCH_CONFIG_DISABLE) 2662 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ 2663 static std::string translatorName( signature ) 2666 #include <exception> 2678 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const = 0;
2688 template<
typename T>
2693 : m_translateFunction( translateFunction )
2696 std::string
translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const override {
2699 std::rethrow_exception(std::current_exception());
2701 return (*it)->translate( it+1, itEnd );
2704 return m_translateFunction( ex );
2709 std::string(*m_translateFunction)( T& );
2713 template<
typename T>
2722 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ 2723 static std::string translatorName( signature ); \ 2724 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 2725 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ 2726 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ 2727 static std::string translatorName( signature ) 2729 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 2734 #include <type_traits> 2741 bool equalityComparisonImpl(
double other)
const;
2744 void setMargin(
double margin);
2747 void setEpsilon(
double epsilon);
2758 Approx approx( static_cast<double>(value) );
2771 auto lhs_v =
static_cast<double>(lhs);
2792 return static_cast<double>(lhs) < rhs.
m_value || lhs == rhs;
2797 return lhs.
m_value <
static_cast<double>(rhs) || lhs == rhs;
2802 return static_cast<double>(lhs) > rhs.
m_value || lhs == rhs;
2807 return lhs.
m_value >
static_cast<double>(rhs) || lhs == rhs;
2812 double epsilonAsDouble =
static_cast<double>(newEpsilon);
2813 setEpsilon(epsilonAsDouble);
2819 double marginAsDouble =
static_cast<double>(newMargin);
2820 setMargin(marginAsDouble);
2826 m_scale =
static_cast<double>(newScale);
2830 std::string toString()
const;
2840 namespace literals {
2860 bool startsWith( std::string
const&
s, std::string
const& prefix );
2861 bool startsWith( std::string
const& s,
char prefix );
2862 bool endsWith( std::string
const& s, std::string
const& suffix );
2863 bool endsWith( std::string
const& s,
char suffix );
2864 bool contains( std::string
const& s, std::string
const& infix );
2866 std::string
toLower( std::string
const& s );
2867 std::string
trim( std::string
const& str );
2868 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis );
2881 #ifndef CATCH_CONFIG_DISABLE_MATCHERS 2890 namespace Matchers {
2902 std::string toString()
const;
2906 virtual std::string describe()
const = 0;
2911 # pragma clang diagnostic push 2912 # pragma clang diagnostic ignored "-Wnon-virtual-dtor" 2915 template<
typename ObjectT>
2917 virtual bool match( ObjectT
const& arg )
const = 0;
2921 # pragma clang diagnostic pop 2924 template<
typename T>
2932 template<
typename ArgT>
2934 bool match( ArgT
const& arg )
const override {
2935 for(
auto matcher : m_matchers ) {
2936 if (!matcher->match(arg))
2942 std::string description;
2943 description.reserve( 4 + m_matchers.size()*32 );
2944 description +=
"( ";
2946 for(
auto matcher : m_matchers ) {
2950 description +=
" and ";
2951 description += matcher->toString();
2953 description +=
" )";
2958 m_matchers.push_back( &other );
2964 template<
typename ArgT>
2967 bool match( ArgT
const& arg )
const override {
2968 for(
auto matcher : m_matchers ) {
2969 if (matcher->match(arg))
2975 std::string description;
2976 description.reserve( 4 + m_matchers.size()*32 );
2977 description +=
"( ";
2979 for(
auto matcher : m_matchers ) {
2983 description +=
" or ";
2984 description += matcher->toString();
2986 description +=
" )";
2991 m_matchers.push_back( &other );
2998 template<
typename ArgT>
3003 bool match( ArgT
const& arg )
const override {
3004 return !m_underlyingMatcher.match( arg );
3008 return "not " + m_underlyingMatcher.toString();
3013 template<
typename T>
3017 template<
typename T>
3021 template<
typename T>
3030 using namespace Matchers;
3038 #include <type_traits> 3042 namespace Matchers {
3044 namespace Floating {
3046 enum class FloatingPointKind : uint8_t;
3050 bool match(
double const& matchee)
const override;
3051 std::string describe()
const override;
3059 bool match(
double const& matchee)
const override;
3060 std::string describe()
const override;
3081 #include <functional> 3085 namespace Matchers {
3092 template <
typename T>
3099 :m_predicate(
std::move(elem)),
3103 bool match( T
const& item )
const override {
3104 return m_predicate(item);
3108 return m_description;
3118 template<
typename T>
3132 namespace Matchers {
3134 namespace StdString {
3139 std::string adjustString( std::string
const& str )
const;
3140 std::string caseSensitivitySuffix()
const;
3148 std::string describe()
const override;
3156 bool match( std::string
const& source )
const override;
3160 bool match( std::string
const& source )
const override;
3164 bool match( std::string
const& source )
const override;
3168 bool match( std::string
const& source )
const override;
3173 bool match( std::string
const& matchee )
const override;
3174 std::string describe()
const override;
3198 #include <algorithm> 3201 namespace Matchers {
3205 template <
typename InputIterator,
typename T>
3206 size_t count(InputIterator first, InputIterator last, T
const& item) {
3208 for (; first != last; ++first) {
3209 if (*first == item) {
3215 template <
typename InputIterator,
typename T>
3216 bool contains(InputIterator first, InputIterator last, T
const& item) {
3217 for (; first != last; ++first) {
3218 if (*first == item) {
3226 template<
typename T>
3231 bool match(std::vector<T>
const &v)
const override {
3232 for (
auto const& el : v) {
3233 if (el == m_comparator) {
3247 template<
typename T>
3252 bool match(std::vector<T>
const &v)
const override {
3254 if (m_comparator.size() > v.size())
3256 for (
auto const& comparator : m_comparator) {
3257 auto present =
false;
3258 for (
const auto& el : v) {
3259 if (el == comparator) {
3277 template<
typename T>
3282 bool match(std::vector<T>
const &v)
const override {
3287 if (m_comparator.size() != v.size())
3289 for (std::size_t i = 0; i < v.size(); ++i)
3290 if (m_comparator[i] != v[i])
3300 template<
typename T>
3303 bool match(std::vector<T>
const& vec)
const override {
3306 if (m_target.size() != vec.size()) {
3309 auto lfirst = m_target.begin(), llast = m_target.end();
3310 auto rfirst = vec.begin(), rlast = vec.end();
3312 while (lfirst != llast && *lfirst == *rfirst) {
3315 if (lfirst == llast) {
3319 for (
auto mid = lfirst; mid != llast; ++mid) {
3325 if (num_vec == 0 ||
Detail::count(lfirst, llast, *mid) != num_vec) {
3345 template<
typename T>
3350 template<
typename T>
3355 template<
typename T>
3360 template<
typename T>
3371 template<
typename ArgT,
typename MatcherT>
3380 m_matcher( matcher ),
3381 m_matcherString( matcherString )
3385 auto matcherAsString = m_matcher.toString();
3388 os << m_matcherString;
3390 os << matcherAsString;
3398 template<
typename ArgT,
typename MatcherT>
3406 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 3408 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3409 INTERNAL_CATCH_TRY { \ 3410 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ 3411 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 3412 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3416 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 3418 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 3419 if( catchAssertionHandler.allowThrows() ) \ 3421 static_cast<void>(__VA_ARGS__ ); \ 3422 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 3424 catch( exceptionType const& ex ) { \ 3425 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ 3428 catchAssertionHandler.handleUnexpectedInflightException(); \ 3431 catchAssertionHandler.handleThrowingCallSkipped(); \ 3432 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 3455 virtual bool next() = 0;
3463 virtual auto hasGenerator()
const ->
bool = 0;
3473 #include <stdexcept> 3476 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 3477 template <
typename Ex>
3482 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 3488 #define CATCH_PREPARE_EXCEPTION( type, msg ) \ 3489 type( ( Catch::ReusableStringStream() << msg ).str() ) 3490 #define CATCH_INTERNAL_ERROR( msg ) \ 3491 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg)) 3492 #define CATCH_ERROR( msg ) \ 3493 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg )) 3494 #define CATCH_RUNTIME_ERROR( msg ) \ 3495 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg )) 3496 #define CATCH_ENFORCE( condition, msg ) \ 3497 do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) 3505 #include <exception> 3510 const char*
const m_msg =
"";
3517 const char* what()
const noexcept
override final;
3520 namespace Generators {
3524 template<
typename T,
typename... Args>
3526 return std::unique_ptr<T>(
new T(std::forward<Args>(
args)...));
3530 template<
typename T>
3538 virtual T
const&
get()
const = 0;
3542 template<
typename T>
3549 T
const&
get()
const override {
3557 template<
typename T>
3564 T
const&
get()
const override {
3565 return m_values[m_idx];
3569 return m_idx < m_values.size();
3573 template <
typename T>
3578 m_generator(
std::move(generator))
3580 T
const&
get()
const {
3581 return m_generator->get();
3584 return m_generator->next();
3588 template <
typename T>
3592 template <
typename T>
3597 template<
typename T>
3600 size_t m_current = 0;
3603 m_generators.emplace_back(std::move(generator));
3606 m_generators.emplace_back(
value(std::move(val)));
3608 template<
typename U>
3610 populate(T(std::move(val)));
3612 template<
typename U,
typename... Gs>
3613 void populate(U&& valueOrGenerator, Gs... moreGenerators) {
3614 populate(std::forward<U>(valueOrGenerator));
3615 populate(std::forward<Gs>(moreGenerators)...);
3619 template <
typename... Gs>
3621 m_generators.reserve(
sizeof...(Gs));
3622 populate(std::forward<Gs>(moreGenerators)...);
3625 T
const&
get()
const override {
3626 return m_generators[m_current].get();
3630 if (m_current >= m_generators.size()) {
3633 const bool current_status = m_generators[m_current].next();
3634 if (!current_status) {
3637 return m_current < m_generators.size();
3641 template<
typename... Ts>
3642 GeneratorWrapper<std::tuple<Ts...>>
table( std::initializer_list<std::tuple<
typename std::decay<Ts>::type...>> tuples ) {
3643 return values<std::tuple<Ts...>>( tuples );
3647 template <
typename T>
3650 template<
typename T,
typename... Gs>
3652 return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
3654 template<
typename T>
3658 template<
typename T,
typename... Gs>
3660 return makeGenerators(
value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
3662 template<
typename T,
typename U,
typename... Gs>
3664 return makeGenerators(
value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
3669 template<
typename L>
3673 auto generate(
SourceLineInfo const& lineInfo, L
const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().
get()) {
3674 using UnderlyingType =
typename decltype(generatorExpression())::type;
3682 return generator.
get();
3688 #define GENERATE( ... ) \ 3689 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) 3695 namespace Generators {
3697 template <
typename T>
3700 size_t m_returned = 0;
3704 m_generator(
std::move(generator)),
3707 assert(target != 0 &&
"Empty generators are not allowed");
3709 T
const&
get()
const override {
3710 return m_generator.
get();
3714 if (m_returned >= m_target) {
3718 const auto success = m_generator.
next();
3722 m_returned = m_target;
3728 template <
typename T>
3730 return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
3733 template <
typename T,
typename Predicate>
3738 template <
typename P = Predicate>
3740 m_generator(
std::move(generator)),
3741 m_predicate(
std::forward<P>(pred))
3743 if (!m_predicate(m_generator.
get())) {
3746 auto has_initial_value = next();
3747 if (!has_initial_value) {
3753 T
const&
get()
const override {
3754 return m_generator.
get();
3758 bool success = m_generator.
next();
3762 while (!m_predicate(m_generator.
get()) && (success = m_generator.
next()) ==
true);
3767 template <
typename T,
typename Predicate>
3769 return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
3772 template <
typename T>
3777 size_t m_current_repeat = 0;
3778 size_t m_repeat_index = 0;
3781 m_generator(
std::move(generator)),
3782 m_target_repeats(repeats)
3784 assert(m_target_repeats > 0 &&
"Repeat generator must repeat at least once");
3787 T
const&
get()
const override {
3788 if (m_current_repeat == 0) {
3789 m_returned.push_back(m_generator.
get());
3790 return m_returned.back();
3792 return m_returned[m_repeat_index];
3802 if (m_current_repeat == 0) {
3803 const auto success = m_generator.
next();
3807 return m_current_repeat < m_target_repeats;
3812 if (m_repeat_index == m_returned.size()) {
3816 return m_current_repeat < m_target_repeats;
3820 template <
typename T>
3822 return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
3825 template <
typename T,
typename U,
typename Func>
3833 template <
typename F2 = Func>
3835 m_generator(
std::move(generator)),
3836 m_function(
std::forward<F2>(function)),
3837 m_cache(m_function(m_generator.
get()))
3840 T
const&
get()
const override {
3844 const auto success = m_generator.
next();
3846 m_cache = m_function(m_generator.
get());
3852 template <
typename T,
typename U,
typename Func>
3855 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(
function), std::move(generator))
3858 template <
typename T,
typename Func>
3861 pf::make_unique<MapGenerator<T, T, Func>>(std::forward<Func>(
function), std::move(generator))
3865 template <
typename T>
3870 bool m_used_up =
false;
3873 m_chunk_size(size), m_generator(
std::move(generator))
3875 m_chunk.reserve(m_chunk_size);
3876 m_chunk.push_back(m_generator.
get());
3877 for (
size_t i = 1; i < m_chunk_size; ++i) {
3878 if (!m_generator.
next()) {
3881 m_chunk.push_back(m_generator.
get());
3884 std::vector<T>
const&
get()
const override {
3889 for (
size_t idx = 0; idx < m_chunk_size; ++idx) {
3890 if (!m_generator.
next()) {
3893 m_chunk.push_back(m_generator.
get());
3899 template <
typename T>
3902 pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
3930 virtual IRunner* getRunner() = 0;
3931 virtual IConfigPtr const& getConfig()
const = 0;
3937 virtual void setResultCapture(
IResultCapture* resultCapture ) = 0;
3938 virtual void setRunner(
IRunner* runner ) = 0;
3945 static void createContext();
3981 NoAssertions = 0x01,
4004 BeforeStartAndExit = BeforeStart | BeforeExit
4013 virtual bool allowThrows()
const = 0;
4014 virtual std::ostream& stream()
const = 0;
4015 virtual std::string
name()
const = 0;
4016 virtual bool includeSuccessfulResults()
const = 0;
4017 virtual bool shouldDebugBreak()
const = 0;
4018 virtual bool warnAboutMissingAssertions()
const = 0;
4019 virtual bool warnAboutNoTests()
const = 0;
4020 virtual int abortAfter()
const = 0;
4021 virtual bool showInvisibles()
const = 0;
4023 virtual TestSpec
const& testSpec()
const = 0;
4024 virtual bool hasTestFilters()
const = 0;
4026 virtual unsigned int rngSeed()
const = 0;
4027 virtual int benchmarkResolutionMultiple()
const = 0;
4029 virtual std::vector<std::string>
const& getSectionsToRun()
const = 0;
4030 virtual Verbosity verbosity()
const = 0;
4033 using IConfigPtr = std::shared_ptr<IConfig const>;
4040 namespace Generators {
4042 template <
typename Float>
4046 std::uniform_real_distribution<Float>
m_dist;
4053 static_cast<void>(next());
4056 Float
const&
get()
const override {
4057 return m_current_number;
4060 m_current_number = m_dist(m_rand);
4065 template <
typename Integer>
4068 std::uniform_int_distribution<Integer>
m_dist;
4075 static_cast<void>(next());
4078 Integer
const&
get()
const override {
4079 return m_current_number;
4082 m_current_number = m_dist(m_rand);
4089 template <
typename T>
4094 pf::make_unique<RandomIntegerGenerator<T>>(a, b)
4098 template <
typename T>
4103 pf::make_unique<RandomFloatingGenerator<T>>(a, b)
4107 template <
typename T>
4119 m_positive(m_step > T(0))
4121 assert(m_current != m_end &&
"Range start and end cannot be equal");
4122 assert(m_step != T(0) &&
"Step size cannot be zero");
4123 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) &&
"Step moves away from end");
4130 T
const&
get()
const override {
4135 m_current += m_step;
4136 return (m_positive) ? (m_current < m_end) : (m_current > m_end);
4140 template <
typename T>
4146 template <
typename T>
4166 #pragma clang diagnostic push 4167 #pragma clang diagnostic ignored "-Wpadded" 4178 ShouldFail = 1 << 2,
4181 NonPortable = 1 << 5,
4186 std::string
const& _className,
4187 std::string
const& _description,
4188 std::vector<std::string>
const& _tags,
4191 friend void setTags(
TestCaseInfo& testCaseInfo, std::vector<std::string> tags );
4193 bool isHidden()
const;
4194 bool throws()
const;
4195 bool okToFail()
const;
4196 bool expectedToFail()
const;
4198 std::string tagsAsString()
const;
4214 TestCase withName( std::string
const& _newName )
const;
4216 void invoke()
const;
4224 std::shared_ptr<ITestInvoker>
test;
4228 std::string
const& className,
4234 #pragma clang diagnostic pop 4244 virtual bool aborting()
const = 0;
4253 #import <objc/runtime.h> 4278 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
4280 virtual void invoke()
const {
4281 id obj = [[m_cls alloc] init];
4283 performOptionalSelector( obj,
@selector(setUp) );
4284 performOptionalSelector( obj, m_sel );
4285 performOptionalSelector( obj,
@selector(tearDown) );
4287 arcSafeRelease( obj );
4290 virtual ~OcMethod() {}
4298 inline std::string getAnnotation( Class cls,
4299 std::string
const& annotationName,
4300 std::string
const& testCaseName ) {
4301 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
4302 SEL sel = NSSelectorFromString( selStr );
4303 arcSafeRelease( selStr );
4304 id value = performOptionalSelector( cls, sel );
4306 return [(NSString*)value UTF8String];
4311 inline std::size_t registerTestMethods() {
4312 std::size_t noTestMethods = 0;
4313 int noClasses = objc_getClassList(
nullptr, 0 );
4315 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)
malloc(
sizeof(Class) * noClasses);
4316 objc_getClassList( classes, noClasses );
4318 for(
int c = 0; c < noClasses; c++ ) {
4319 Class cls = classes[c];
4322 Method* methods = class_copyMethodList( cls, &count );
4323 for( u_int m = 0; m <
count ; m++ ) {
4324 SEL selector = method_getName(methods[m]);
4325 std::string methodName = sel_getName(selector);
4326 if(
startsWith( methodName,
"Catch_TestCase_" ) ) {
4327 std::string testCaseName = methodName.substr( 15 );
4328 std::string
name = Detail::getAnnotation( cls,
"Name", testCaseName );
4329 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
4330 const char* className = class_getName( cls );
4339 return noTestMethods;
4342 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 4344 namespace Matchers {
4346 namespace NSStringMatchers {
4349 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
4350 StringHolder( StringHolder
const& other ) : m_substr( [other.m_substr copy] ){}
4352 arcSafeRelease( m_substr );
4355 bool match( NSString* arg )
const override {
4359 NSString* CATCH_ARC_STRONG m_substr;
4362 struct Equals : StringHolder {
4363 Equals( NSString* substr ) : StringHolder( substr ){}
4365 bool match( NSString* str )
const override {
4366 return (str != nil || m_substr == nil ) &&
4367 [str isEqualToString:m_substr];
4370 std::string describe()
const override {
4376 Contains( NSString* substr ) : StringHolder( substr ){}
4378 bool match( NSString* str )
const {
4379 return (str != nil || m_substr == nil ) &&
4380 [str rangeOfString:m_substr].location != NSNotFound;
4383 std::string describe()
const override {
4389 StartsWith( NSString* substr ) : StringHolder( substr ){}
4391 bool match( NSString* str )
const override {
4392 return (str != nil || m_substr == nil ) &&
4393 [str rangeOfString:m_substr].location == 0;
4396 std::string describe()
const override {
4401 EndsWith( NSString* substr ) : StringHolder( substr ){}
4403 bool match( NSString* str )
const override {
4404 return (str != nil || m_substr == nil ) &&
4405 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
4408 std::string describe()
const override {
4430 using namespace Matchers;
4432 #endif // CATCH_CONFIG_DISABLE_MATCHERS 4437 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix 4438 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ 4439 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ 4443 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ 4447 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) 4449 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) 4454 #ifdef CATCH_CONFIG_EXTERNAL_INTERFACES 4466 #pragma clang diagnostic push 4467 #pragma clang diagnostic ignored "-Wpadded" 4473 #pragma clang diagnostic push 4474 #pragma clang diagnostic ignored "-Wpadded" 4481 class WildcardPattern {
4482 enum WildcardPosition {
4484 WildcardAtStart = 1,
4486 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
4492 virtual ~WildcardPattern() =
default;
4493 virtual bool matches( std::string
const& str )
const;
4496 std::string adjustCase( std::string
const& str )
const;
4498 WildcardPosition m_wildcard = NoWildcard;
4499 std::string m_pattern;
4513 virtual bool matches(
TestCaseInfo const& testCase )
const = 0;
4515 using PatternPtr = std::shared_ptr<Pattern>;
4517 class NamePattern :
public Pattern {
4519 NamePattern( std::string
const&
name );
4520 virtual ~NamePattern();
4521 virtual bool matches(
TestCaseInfo const& testCase )
const override;
4523 WildcardPattern m_wildcardPattern;
4526 class TagPattern :
public Pattern {
4528 TagPattern( std::string
const& tag );
4529 virtual ~TagPattern();
4530 virtual bool matches(
TestCaseInfo const& testCase )
const override;
4535 class ExcludedPattern :
public Pattern {
4537 ExcludedPattern( PatternPtr
const& underlyingPattern );
4538 virtual ~ExcludedPattern();
4539 virtual bool matches(
TestCaseInfo const& testCase )
const override;
4541 PatternPtr m_underlyingPattern;
4545 std::vector<PatternPtr> m_patterns;
4551 bool hasFilters()
const;
4555 std::vector<Filter> m_filters;
4557 friend class TestSpecParser;
4562 #pragma clang diagnostic pop 4574 struct ITagAliasRegistry {
4575 virtual ~ITagAliasRegistry();
4577 virtual TagAlias
const* find( std::string
const& alias )
const = 0;
4578 virtual std::string expandAliases( std::string
const& unexpandedTestSpec )
const = 0;
4580 static ITagAliasRegistry
const&
get();
4588 class TestSpecParser {
4589 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
4591 bool m_exclusion =
false;
4592 std::size_t m_start = std::string::npos, m_pos = 0;
4594 std::vector<std::size_t> m_escapeChars;
4595 TestSpec::Filter m_currentFilter;
4596 TestSpec m_testSpec;
4597 ITagAliasRegistry
const* m_tagAliases =
nullptr;
4600 TestSpecParser( ITagAliasRegistry
const& tagAliases );
4602 TestSpecParser& parse( std::string
const& arg );
4603 TestSpec testSpec();
4606 void visitChar(
char c );
4607 void startNewMode( Mode mode, std::size_t
start );
4609 std::string subString()
const;
4611 template<
typename T>
4613 std::string token = subString();
4614 for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
4615 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
4616 m_escapeChars.clear();
4619 token = token.substr( 8 );
4621 if( !token.empty() ) {
4622 TestSpec::PatternPtr pattern = std::make_shared<T>( token );
4624 pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
4625 m_currentFilter.m_patterns.push_back( pattern );
4627 m_exclusion =
false;
4633 TestSpec parseTestSpec( std::string
const& arg );
4638 #pragma clang diagnostic pop 4648 #ifndef CATCH_CONFIG_CONSOLE_WIDTH 4649 #define CATCH_CONFIG_CONSOLE_WIDTH 80 4657 bool listTests =
false;
4658 bool listTags =
false;
4659 bool listReporters =
false;
4660 bool listTestNamesOnly =
false;
4662 bool showSuccessfulTests =
false;
4663 bool shouldDebugBreak =
false;
4664 bool noThrow =
false;
4665 bool showHelp =
false;
4666 bool showInvisibles =
false;
4667 bool filenamesAsTags =
false;
4668 bool libIdentify =
false;
4670 int abortAfter = -1;
4672 int benchmarkResolutionMultiple = 100;
4681 std::string outputFilename;
4683 std::string processName;
4684 #ifndef CATCH_CONFIG_DEFAULT_REPORTER 4685 #define CATCH_CONFIG_DEFAULT_REPORTER "console" 4687 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
4688 #undef CATCH_CONFIG_DEFAULT_REPORTER 4690 std::vector<std::string> testsOrTags;
4691 std::vector<std::string> sectionsToRun;
4694 class Config :
public IConfig {
4698 Config( ConfigData
const&
data );
4699 virtual ~Config() =
default;
4701 std::string
const& getFilename()
const;
4703 bool listTests()
const;
4704 bool listTestNamesOnly()
const;
4705 bool listTags()
const;
4706 bool listReporters()
const;
4708 std::string getProcessName()
const;
4709 std::string
const& getReporterName()
const;
4711 std::vector<std::string>
const& getTestsOrTags()
const;
4712 std::vector<std::string>
const& getSectionsToRun()
const override;
4714 virtual TestSpec
const& testSpec()
const override;
4715 bool hasTestFilters()
const override;
4717 bool showHelp()
const;
4720 bool allowThrows()
const override;
4721 std::ostream& stream()
const override;
4722 std::string
name()
const override;
4723 bool includeSuccessfulResults()
const override;
4724 bool warnAboutMissingAssertions()
const override;
4725 bool warnAboutNoTests()
const override;
4728 unsigned int rngSeed()
const override;
4729 int benchmarkResolutionMultiple()
const override;
4731 bool shouldDebugBreak()
const override;
4732 int abortAfter()
const override;
4733 bool showInvisibles()
const override;
4741 std::unique_ptr<IStream const> m_stream;
4742 TestSpec m_testSpec;
4743 bool m_hasTestFilters =
false;
4755 struct AssertionResultData
4757 AssertionResultData() =
delete;
4761 std::string message;
4762 mutable std::string reconstructedExpression;
4766 std::string reconstructExpression()
const;
4769 class AssertionResult {
4771 AssertionResult() =
delete;
4775 bool succeeded()
const;
4777 bool hasExpression()
const;
4778 bool hasMessage()
const;
4779 std::string getExpression()
const;
4780 std::string getExpressionInMacro()
const;
4781 bool hasExpandedExpression()
const;
4782 std::string getExpandedExpression()
const;
4783 std::string getMessage()
const;
4789 AssertionResultData m_resultData;
4800 template<
typename T>
4803 Option() : nullableValue(
nullptr ) {}
4804 Option( T
const& _value )
4805 : nullableValue(
new( storage ) T( _value ) )
4807 Option( Option
const& _other )
4808 : nullableValue( _other ?
new( storage ) T( *_other ) :
nullptr )
4815 Option& operator= ( Option
const& _other ) {
4816 if( &_other !=
this ) {
4819 nullableValue =
new( storage ) T( *_other );
4823 Option& operator = ( T
const& _value ) {
4825 nullableValue =
new( storage ) T( _value );
4831 nullableValue->~T();
4832 nullableValue =
nullptr;
4835 T&
operator*() {
return *nullableValue; }
4836 T
const&
operator*()
const {
return *nullableValue; }
4837 T* operator->() {
return nullableValue; }
4838 const T* operator->()
const {
return nullableValue; }
4840 T valueOr( T
const& defaultValue )
const {
4841 return nullableValue ? *nullableValue : defaultValue;
4844 bool some()
const {
return nullableValue !=
nullptr; }
4845 bool none()
const {
return nullableValue ==
nullptr; }
4847 bool operator !()
const {
return nullableValue ==
nullptr; }
4848 explicit operator bool()
const {
4854 alignas(
alignof(T))
char storage[sizeof(T)];
4868 struct ReporterConfig {
4869 explicit ReporterConfig(
IConfigPtr const& _fullConfig );
4871 ReporterConfig(
IConfigPtr const& _fullConfig, std::ostream& _stream );
4873 std::ostream& stream()
const;
4877 std::ostream* m_stream;
4881 struct ReporterPreferences {
4882 bool shouldRedirectStdOut =
false;
4883 bool shouldReportAllAssertions =
false;
4886 template<
typename T>
4887 struct LazyStat : Option<T> {
4888 LazyStat& operator=( T
const& _value ) {
4889 Option<T>::operator=( _value );
4900 struct TestRunInfo {
4901 TestRunInfo( std::string
const& _name );
4905 GroupInfo( std::string
const& _name,
4906 std::size_t _groupIndex,
4907 std::size_t _groupsCount );
4910 std::size_t groupIndex;
4911 std::size_t groupsCounts;
4914 struct AssertionStats {
4915 AssertionStats( AssertionResult
const& _assertionResult,
4916 std::vector<MessageInfo>
const& _infoMessages,
4919 AssertionStats( AssertionStats
const& ) =
default;
4920 AssertionStats( AssertionStats && ) =
default;
4921 AssertionStats& operator = ( AssertionStats
const& ) =
delete;
4922 AssertionStats& operator = ( AssertionStats && ) =
delete;
4923 virtual ~AssertionStats();
4925 AssertionResult assertionResult;
4926 std::vector<MessageInfo> infoMessages;
4930 struct SectionStats {
4932 Counts const& _assertions,
4933 double _durationInSeconds,
4934 bool _missingAssertions );
4935 SectionStats( SectionStats
const& ) =
default;
4936 SectionStats( SectionStats && ) =
default;
4937 SectionStats& operator = ( SectionStats
const& ) =
default;
4938 SectionStats& operator = ( SectionStats && ) =
default;
4939 virtual ~SectionStats();
4943 double durationInSeconds;
4944 bool missingAssertions;
4947 struct TestCaseStats {
4950 std::string
const& _stdOut,
4951 std::string
const& _stdErr,
4954 TestCaseStats( TestCaseStats
const& ) =
default;
4955 TestCaseStats( TestCaseStats && ) =
default;
4956 TestCaseStats& operator = ( TestCaseStats
const& ) =
default;
4957 TestCaseStats& operator = ( TestCaseStats && ) =
default;
4958 virtual ~TestCaseStats();
4967 struct TestGroupStats {
4968 TestGroupStats( GroupInfo
const& _groupInfo,
4971 TestGroupStats( GroupInfo
const& _groupInfo );
4973 TestGroupStats( TestGroupStats
const& ) =
default;
4974 TestGroupStats( TestGroupStats && ) =
default;
4975 TestGroupStats& operator = ( TestGroupStats
const& ) =
default;
4976 TestGroupStats& operator = ( TestGroupStats && ) =
default;
4977 virtual ~TestGroupStats();
4979 GroupInfo groupInfo;
4984 struct TestRunStats {
4985 TestRunStats( TestRunInfo
const& _runInfo,
4989 TestRunStats( TestRunStats
const& ) =
default;
4990 TestRunStats( TestRunStats && ) =
default;
4991 TestRunStats& operator = ( TestRunStats
const& ) =
default;
4992 TestRunStats& operator = ( TestRunStats && ) =
default;
4993 virtual ~TestRunStats();
4995 TestRunInfo runInfo;
5000 struct BenchmarkInfo {
5003 struct BenchmarkStats {
5005 std::size_t iterations;
5006 uint64_t elapsedTimeInNanoseconds;
5009 struct IStreamingReporter {
5010 virtual ~IStreamingReporter() =
default;
5016 virtual ReporterPreferences getPreferences()
const = 0;
5018 virtual void noMatchingTestCases( std::string
const& spec ) = 0;
5020 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
5021 virtual void testGroupStarting( GroupInfo
const& groupInfo ) = 0;
5023 virtual void testCaseStarting(
TestCaseInfo const& testInfo ) = 0;
5024 virtual void sectionStarting(
SectionInfo const& sectionInfo ) = 0;
5027 virtual void benchmarkStarting( BenchmarkInfo
const& ) {}
5029 virtual void assertionStarting(
AssertionInfo const& assertionInfo ) = 0;
5032 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
5035 virtual void benchmarkEnded( BenchmarkStats
const& ) {}
5037 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
5038 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
5039 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
5040 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
5042 virtual void skipTest(
TestCaseInfo const& testInfo ) = 0;
5047 virtual bool isMulti()
const;
5049 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
5051 struct IReporterFactory {
5052 virtual ~IReporterFactory();
5053 virtual IStreamingReporterPtr create( ReporterConfig
const&
config )
const = 0;
5054 virtual std::string getDescription()
const = 0;
5058 struct IReporterRegistry {
5059 using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
5060 using Listeners = std::vector<IReporterFactoryPtr>;
5062 virtual ~IReporterRegistry();
5063 virtual IStreamingReporterPtr create( std::string
const&
name,
IConfigPtr const&
config )
const = 0;
5064 virtual FactoryMap const& getFactories()
const = 0;
5065 virtual Listeners
const& getListeners()
const = 0;
5071 #include <algorithm> 5080 void prepareExpandedExpression(AssertionResult& result);
5083 std::string getFormattedDuration(
double duration );
5085 template<
typename DerivedT>
5086 struct StreamingReporterBase : IStreamingReporter {
5088 StreamingReporterBase( ReporterConfig
const& _config )
5089 : m_config( _config.fullConfig() ),
5090 stream( _config.stream() )
5092 m_reporterPrefs.shouldRedirectStdOut =
false;
5093 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
5094 CATCH_ERROR(
"Verbosity level not supported by this reporter" );
5097 ReporterPreferences getPreferences()
const override {
5098 return m_reporterPrefs;
5101 static std::set<Verbosity> getSupportedVerbosities() {
5105 ~StreamingReporterBase()
override =
default;
5107 void noMatchingTestCases(std::string
const&)
override {}
5109 void testRunStarting(TestRunInfo
const& _testRunInfo)
override {
5110 currentTestRunInfo = _testRunInfo;
5112 void testGroupStarting(GroupInfo
const& _groupInfo)
override {
5113 currentGroupInfo = _groupInfo;
5116 void testCaseStarting(
TestCaseInfo const& _testInfo)
override {
5117 currentTestCaseInfo = _testInfo;
5119 void sectionStarting(
SectionInfo const& _sectionInfo)
override {
5120 m_sectionStack.push_back(_sectionInfo);
5123 void sectionEnded(SectionStats
const& )
override {
5124 m_sectionStack.pop_back();
5126 void testCaseEnded(TestCaseStats
const& )
override {
5127 currentTestCaseInfo.reset();
5129 void testGroupEnded(TestGroupStats
const& )
override {
5130 currentGroupInfo.reset();
5132 void testRunEnded(TestRunStats
const& )
override {
5133 currentTestCaseInfo.reset();
5134 currentGroupInfo.reset();
5135 currentTestRunInfo.reset();
5144 std::ostream& stream;
5146 LazyStat<TestRunInfo> currentTestRunInfo;
5147 LazyStat<GroupInfo> currentGroupInfo;
5148 LazyStat<TestCaseInfo> currentTestCaseInfo;
5150 std::vector<SectionInfo> m_sectionStack;
5151 ReporterPreferences m_reporterPrefs;
5154 template<
typename DerivedT>
5155 struct CumulativeReporterBase : IStreamingReporter {
5156 template<
typename T,
typename ChildNodeT>
5158 explicit Node( T
const& _value ) :
value( _value ) {}
5161 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
5163 ChildNodes children;
5165 struct SectionNode {
5166 explicit SectionNode(SectionStats
const& _stats) : stats(_stats) {}
5167 virtual ~SectionNode() =
default;
5169 bool operator == (SectionNode
const& other)
const {
5170 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
5172 bool operator == (std::shared_ptr<SectionNode>
const& other)
const {
5177 using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
5178 using Assertions = std::vector<AssertionStats>;
5179 ChildSections childSections;
5180 Assertions assertions;
5185 struct BySectionInfo {
5186 BySectionInfo(
SectionInfo const& other ) : m_other( other ) {}
5187 BySectionInfo( BySectionInfo
const& other ) : m_other( other.m_other ) {}
5188 bool operator() (std::shared_ptr<SectionNode>
const& node)
const {
5189 return ((node->stats.sectionInfo.name == m_other.name) &&
5190 (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
5192 void operator=(BySectionInfo
const&) =
delete;
5198 using TestCaseNode = Node<TestCaseStats, SectionNode>;
5199 using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
5200 using TestRunNode = Node<TestRunStats, TestGroupNode>;
5202 CumulativeReporterBase( ReporterConfig
const& _config )
5203 : m_config( _config.fullConfig() ),
5204 stream( _config.stream() )
5206 m_reporterPrefs.shouldRedirectStdOut =
false;
5207 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
5208 CATCH_ERROR(
"Verbosity level not supported by this reporter" );
5210 ~CumulativeReporterBase()
override =
default;
5212 ReporterPreferences getPreferences()
const override {
5213 return m_reporterPrefs;
5216 static std::set<Verbosity> getSupportedVerbosities() {
5220 void testRunStarting( TestRunInfo
const& )
override {}
5221 void testGroupStarting( GroupInfo
const& )
override {}
5223 void testCaseStarting(
TestCaseInfo const& )
override {}
5225 void sectionStarting(
SectionInfo const& sectionInfo )
override {
5226 SectionStats incompleteStats( sectionInfo,
Counts(), 0,
false );
5227 std::shared_ptr<SectionNode> node;
5228 if( m_sectionStack.empty() ) {
5229 if( !m_rootSection )
5230 m_rootSection = std::make_shared<SectionNode>( incompleteStats );
5231 node = m_rootSection;
5234 SectionNode& parentNode = *m_sectionStack.back();
5236 std::find_if( parentNode.childSections.begin(),
5237 parentNode.childSections.end(),
5238 BySectionInfo( sectionInfo ) );
5239 if( it == parentNode.childSections.end() ) {
5240 node = std::make_shared<SectionNode>( incompleteStats );
5241 parentNode.childSections.push_back( node );
5246 m_sectionStack.push_back( node );
5247 m_deepestSection = std::move(node);
5252 bool assertionEnded(AssertionStats
const& assertionStats)
override {
5253 assert(!m_sectionStack.empty());
5259 prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );
5260 SectionNode& sectionNode = *m_sectionStack.back();
5261 sectionNode.assertions.push_back(assertionStats);
5264 void sectionEnded(SectionStats
const& sectionStats)
override {
5265 assert(!m_sectionStack.empty());
5266 SectionNode& node = *m_sectionStack.back();
5267 node.stats = sectionStats;
5268 m_sectionStack.pop_back();
5270 void testCaseEnded(TestCaseStats
const& testCaseStats)
override {
5271 auto node = std::make_shared<TestCaseNode>(testCaseStats);
5272 assert(m_sectionStack.size() == 0);
5273 node->children.push_back(m_rootSection);
5274 m_testCases.push_back(node);
5275 m_rootSection.reset();
5277 assert(m_deepestSection);
5278 m_deepestSection->stdOut = testCaseStats.stdOut;
5279 m_deepestSection->stdErr = testCaseStats.stdErr;
5281 void testGroupEnded(TestGroupStats
const& testGroupStats)
override {
5282 auto node = std::make_shared<TestGroupNode>(testGroupStats);
5283 node->children.swap(m_testCases);
5284 m_testGroups.push_back(node);
5286 void testRunEnded(TestRunStats
const& testRunStats)
override {
5287 auto node = std::make_shared<TestRunNode>(testRunStats);
5288 node->children.swap(m_testGroups);
5289 m_testRuns.push_back(node);
5290 testRunEndedCumulative();
5292 virtual void testRunEndedCumulative() = 0;
5297 std::ostream& stream;
5298 std::vector<AssertionStats> m_assertions;
5299 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
5300 std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
5301 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
5303 std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
5305 std::shared_ptr<SectionNode> m_rootSection;
5306 std::shared_ptr<SectionNode> m_deepestSection;
5307 std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
5308 ReporterPreferences m_reporterPrefs;
5312 char const* getLineOfChars() {
5313 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
5315 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
5316 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
5321 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
5322 TestEventListenerBase( ReporterConfig
const& _config );
5324 static std::set<Verbosity> getSupportedVerbosities();
5327 bool assertionEnded(AssertionStats
const&)
override;
5351 BrightRed = Bright | Red,
5352 BrightGreen = Bright | Green,
5353 LightGrey = Bright | Grey,
5354 BrightWhite = Bright | White,
5355 BrightYellow = Bright | Yellow,
5358 FileName = LightGrey,
5359 Warning = BrightYellow,
5360 ResultError = BrightRed,
5361 ResultSuccess = BrightGreen,
5362 ResultExpectedFailure = Warning,
5367 OriginalExpression = Cyan,
5368 ReconstructedExpression = BrightYellow,
5370 SecondaryText = LightGrey,
5375 Colour( Code _colourCode );
5376 Colour( Colour&& other ) noexcept;
5377 Colour& operator=( Colour&& other ) noexcept;
5381 static void use( Code _colourCode );
5384 bool m_moved =
false;
5387 std::ostream&
operator << ( std::ostream& os, Colour
const& );
5397 template<
typename T>
5398 class ReporterRegistrar {
5400 class ReporterFactory :
public IReporterFactory {
5402 virtual IStreamingReporterPtr create( ReporterConfig
const&
config )
const override {
5403 return std::unique_ptr<T>(
new T( config ) );
5406 virtual std::string getDescription()
const override {
5407 return T::getDescription();
5413 explicit ReporterRegistrar( std::string
const&
name ) {
5418 template<
typename T>
5419 class ListenerRegistrar {
5421 class ListenerFactory :
public IReporterFactory {
5423 virtual IStreamingReporterPtr create( ReporterConfig
const&
config )
const override {
5424 return std::unique_ptr<T>(
new T( config ) );
5426 virtual std::string getDescription()
const override {
5427 return std::string();
5433 ListenerRegistrar() {
5439 #if !defined(CATCH_CONFIG_DISABLE) 5441 #define CATCH_REGISTER_REPORTER( name, reporterType ) \ 5442 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 5443 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \ 5444 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS 5446 #define CATCH_REGISTER_LISTENER( listenerType ) \ 5447 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ 5448 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \ 5449 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS 5450 #else // CATCH_CONFIG_DISABLE 5452 #define CATCH_REGISTER_REPORTER(name, reporterType) 5453 #define CATCH_REGISTER_LISTENER(listenerType) 5455 #endif // CATCH_CONFIG_DISABLE 5463 struct CompactReporter : StreamingReporterBase<CompactReporter> {
5465 using StreamingReporterBase::StreamingReporterBase;
5467 ~CompactReporter()
override;
5469 static std::string getDescription();
5471 ReporterPreferences getPreferences()
const override;
5473 void noMatchingTestCases(std::string
const& spec)
override;
5477 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
5479 void sectionEnded(SectionStats
const& _sectionStats)
override;
5481 void testRunEnded(TestRunStats
const& _testRunStats)
override;
5490 #if defined(_MSC_VER) 5491 #pragma warning(push) 5492 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 5499 struct SummaryColumn;
5502 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
5503 std::unique_ptr<TablePrinter> m_tablePrinter;
5505 ConsoleReporter(ReporterConfig
const&
config);
5506 ~ConsoleReporter()
override;
5507 static std::string getDescription();
5509 void noMatchingTestCases(std::string
const& spec)
override;
5513 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
5515 void sectionStarting(
SectionInfo const& _sectionInfo)
override;
5516 void sectionEnded(SectionStats
const& _sectionStats)
override;
5518 void benchmarkStarting(BenchmarkInfo
const& info)
override;
5519 void benchmarkEnded(BenchmarkStats
const& stats)
override;
5521 void testCaseEnded(TestCaseStats
const& _testCaseStats)
override;
5522 void testGroupEnded(TestGroupStats
const& _testGroupStats)
override;
5523 void testRunEnded(TestRunStats
const& _testRunStats)
override;
5529 void lazyPrintWithoutClosingBenchmarkTable();
5530 void lazyPrintRunInfo();
5531 void lazyPrintGroupInfo();
5532 void printTestCaseAndSectionHeader();
5534 void printClosedHeader(std::string
const& _name);
5535 void printOpenHeader(std::string
const& _name);
5539 void printHeaderString(std::string
const& _string, std::size_t indent = 0);
5541 void printTotals(
Totals const& totals);
5542 void printSummaryRow(std::string
const& label, std::vector<SummaryColumn>
const& cols, std::size_t row);
5544 void printTotalsDivider(
Totals const& totals);
5545 void printSummaryDivider();
5548 bool m_headerPrinted =
false;
5553 #if defined(_MSC_VER) 5554 #pragma warning(pop) 5568 enum ForWhat { ForTextNodes, ForAttributes };
5570 XmlEncode( std::string
const& str, ForWhat forWhat = ForTextNodes );
5572 void encodeTo( std::ostream& os )
const;
5574 friend std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode );
5584 class ScopedElement {
5586 ScopedElement( XmlWriter* writer );
5588 ScopedElement( ScopedElement&& other ) noexcept;
5589 ScopedElement& operator=( ScopedElement&& other ) noexcept;
5593 ScopedElement& writeText( std::string
const& text,
bool indent =
true );
5595 template<
typename T>
5596 ScopedElement& writeAttribute( std::string
const&
name, T
const& attribute ) {
5597 m_writer->writeAttribute( name, attribute );
5602 mutable XmlWriter* m_writer =
nullptr;
5608 XmlWriter( XmlWriter
const& ) =
delete;
5609 XmlWriter& operator=( XmlWriter
const& ) =
delete;
5611 XmlWriter& startElement( std::string
const&
name );
5613 ScopedElement scopedElement( std::string
const& name );
5615 XmlWriter& endElement();
5617 XmlWriter& writeAttribute( std::string
const& name, std::string
const& attribute );
5619 XmlWriter& writeAttribute( std::string
const& name,
bool attribute );
5621 template<
typename T>
5622 XmlWriter& writeAttribute( std::string
const& name, T
const& attribute ) {
5625 return writeAttribute( name, rss.
str() );
5628 XmlWriter& writeText( std::string
const& text,
bool indent =
true );
5630 XmlWriter& writeComment( std::string
const& text );
5632 void writeStylesheetRef( std::string
const& url );
5634 XmlWriter& writeBlankLine();
5636 void ensureTagClosed();
5640 void writeDeclaration();
5642 void newlineIfNecessary();
5644 bool m_tagIsOpen =
false;
5645 bool m_needsNewline =
false;
5646 std::vector<std::string> m_tags;
5647 std::string m_indent;
5656 class JunitReporter :
public CumulativeReporterBase<JunitReporter> {
5658 JunitReporter(ReporterConfig
const& _config);
5660 ~JunitReporter()
override;
5662 static std::string getDescription();
5664 void noMatchingTestCases(std::string
const& )
override;
5666 void testRunStarting(TestRunInfo
const& runInfo)
override;
5668 void testGroupStarting(GroupInfo
const& groupInfo)
override;
5670 void testCaseStarting(
TestCaseInfo const& testCaseInfo)
override;
5671 bool assertionEnded(AssertionStats
const& assertionStats)
override;
5673 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
5675 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
5677 void testRunEndedCumulative()
override;
5679 void writeGroup(TestGroupNode
const& groupNode,
double suiteTime);
5681 void writeTestCase(TestCaseNode
const& testCaseNode);
5683 void writeSection(std::string
const& className,
5684 std::string
const& rootName,
5685 SectionNode
const& sectionNode);
5687 void writeAssertions(SectionNode
const& sectionNode);
5688 void writeAssertion(AssertionStats
const& stats);
5692 std::string stdOutForSuite;
5693 std::string stdErrForSuite;
5694 unsigned int unexpectedExceptions = 0;
5695 bool m_okToFail =
false;
5704 class XmlReporter :
public StreamingReporterBase<XmlReporter> {
5706 XmlReporter(ReporterConfig
const& _config);
5708 ~XmlReporter()
override;
5710 static std::string getDescription();
5712 virtual std::string getStylesheetRef()
const;
5718 void noMatchingTestCases(std::string
const&
s)
override;
5720 void testRunStarting(TestRunInfo
const& testInfo)
override;
5722 void testGroupStarting(GroupInfo
const& groupInfo)
override;
5724 void testCaseStarting(
TestCaseInfo const& testInfo)
override;
5726 void sectionStarting(
SectionInfo const& sectionInfo)
override;
5730 bool assertionEnded(AssertionStats
const& assertionStats)
override;
5732 void sectionEnded(SectionStats
const& sectionStats)
override;
5734 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
5736 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
5738 void testRunEnded(TestRunStats
const& testRunStats)
override;
5741 Timer m_testCaseTimer;
5743 int m_sectionDepth = 0;
5753 #endif // ! CATCH_CONFIG_IMPL_ONLY 5759 #pragma clang diagnostic push 5760 #pragma clang diagnostic ignored "-Wweak-vtables" 5771 namespace TestCaseTracking {
5773 struct NameAndLocation {
5777 NameAndLocation( std::string
const& _name,
SourceLineInfo const& _location );
5782 using ITrackerPtr = std::shared_ptr<ITracker>;
5785 virtual ~ITracker();
5788 virtual NameAndLocation
const& nameAndLocation()
const = 0;
5791 virtual bool isComplete()
const = 0;
5792 virtual bool isSuccessfullyCompleted()
const = 0;
5793 virtual bool isOpen()
const = 0;
5794 virtual bool hasChildren()
const = 0;
5796 virtual ITracker& parent() = 0;
5799 virtual void close() = 0;
5800 virtual void fail() = 0;
5801 virtual void markAsNeedingAnotherRun() = 0;
5803 virtual void addChild( ITrackerPtr
const& child ) = 0;
5804 virtual ITrackerPtr findChild( NameAndLocation
const& nameAndLocation ) = 0;
5805 virtual void openChild() = 0;
5808 virtual bool isSectionTracker()
const = 0;
5809 virtual bool isGeneratorTracker()
const = 0;
5812 class TrackerContext {
5820 ITrackerPtr m_rootTracker;
5821 ITracker* m_currentTracker =
nullptr;
5822 RunState m_runState = NotStarted;
5826 static TrackerContext& instance();
5828 ITracker& startRun();
5832 void completeCycle();
5834 bool completedCycle()
const;
5835 ITracker& currentTracker();
5836 void setCurrentTracker( ITracker* tracker );
5839 class TrackerBase :
public ITracker {
5846 CompletedSuccessfully,
5850 using Children = std::vector<ITrackerPtr>;
5851 NameAndLocation m_nameAndLocation;
5852 TrackerContext& m_ctx;
5854 Children m_children;
5855 CycleState m_runState = NotStarted;
5858 TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
5860 NameAndLocation
const& nameAndLocation()
const override;
5861 bool isComplete()
const override;
5862 bool isSuccessfullyCompleted()
const override;
5863 bool isOpen()
const override;
5864 bool hasChildren()
const override;
5866 void addChild( ITrackerPtr
const& child )
override;
5868 ITrackerPtr findChild( NameAndLocation
const& nameAndLocation )
override;
5869 ITracker& parent()
override;
5871 void openChild()
override;
5873 bool isSectionTracker()
const override;
5874 bool isGeneratorTracker()
const override;
5878 void close()
override;
5879 void fail()
override;
5880 void markAsNeedingAnotherRun()
override;
5883 void moveToParent();
5887 class SectionTracker :
public TrackerBase {
5888 std::vector<std::string> m_filters;
5890 SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
5892 bool isSectionTracker()
const override;
5894 bool isComplete()
const override;
5896 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation );
5900 void addInitialFilters( std::vector<std::string>
const& filters );
5901 void addNextFilters( std::vector<std::string>
const& filters );
5906 using TestCaseTracking::ITracker;
5907 using TestCaseTracking::TrackerContext;
5908 using TestCaseTracking::SectionTracker;
5918 struct LeakDetector {
5935 bool marginComparison(
double lhs,
double rhs,
double margin) {
5936 return (lhs + margin >= rhs) && (rhs + margin >= lhs);
5944 Approx::Approx (
double value )
5945 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
5951 Approx Approx::custom() {
5955 Approx Approx::operator-()
const {
5957 temp.m_value = -temp.m_value;
5961 std::string Approx::toString()
const {
5967 bool Approx::equalityComparisonImpl(
const double other)
const {
5970 return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
5973 void Approx::setMargin(
double margin) {
5975 "Invalid Approx::margin: " << margin <<
'.' 5976 <<
" Approx::Margin has to be non-negative.");
5980 void Approx::setEpsilon(
double epsilon) {
5982 "Invalid Approx::epsilon: " << epsilon <<
'.' 5983 <<
" Approx::epsilon has to be in [0, 1]");
5984 m_epsilon = epsilon;
5989 namespace literals {
6009 bool isDebuggerActive();
6012 #ifdef CATCH_PLATFORM_MAC 6014 #define CATCH_TRAP() __asm__("int $3\n" : : ) 6016 #elif defined(CATCH_PLATFORM_LINUX) 6020 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) 6021 #define CATCH_TRAP() asm volatile ("int $3") 6022 #else // Fall back to the generic way. 6025 #define CATCH_TRAP() raise(SIGTRAP) 6027 #elif defined(_MSC_VER) 6028 #define CATCH_TRAP() __debugbreak() 6029 #elif defined(__MINGW32__) 6030 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
6031 #define CATCH_TRAP() DebugBreak() 6035 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }() 6037 #define CATCH_BREAK_INTO_DEBUGGER() []{}() 6048 #if defined(CATCH_PLATFORM_WINDOWS) 6050 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) 6051 # define CATCH_DEFINED_NOMINMAX 6054 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) 6055 # define CATCH_DEFINED_WIN32_LEAN_AND_MEAN 6056 # define WIN32_LEAN_AND_MEAN 6062 #include <windows.h> 6065 #ifdef CATCH_DEFINED_NOMINMAX 6068 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN 6069 # undef WIN32_LEAN_AND_MEAN 6072 #endif // defined(CATCH_PLATFORM_WINDOWS) 6075 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 6079 struct FatalConditionHandler {
6081 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
6082 FatalConditionHandler();
6083 static void reset();
6084 ~FatalConditionHandler();
6088 static ULONG guaranteeSize;
6089 static PVOID exceptionHandlerHandle;
6094 #elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) 6100 struct FatalConditionHandler {
6103 static struct sigaction oldSigActions[];
6104 static stack_t oldSigStack;
6105 static char altStackMem[];
6107 static void handleSignal(
int sig );
6109 FatalConditionHandler();
6110 ~FatalConditionHandler();
6111 static void reset();
6119 struct FatalConditionHandler {
6138 RunContext( RunContext
const& ) =
delete;
6139 RunContext& operator =( RunContext
const& ) =
delete;
6141 explicit RunContext(
IConfigPtr const& _config, IStreamingReporterPtr&& reporter );
6143 ~RunContext()
override;
6145 void testGroupStarting( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
6146 void testGroupEnded( std::string
const& testSpec,
Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );
6151 IStreamingReporter& reporter()
const;
6165 void handleUnexpectedExceptionNotThrown
6168 void handleUnexpectedInflightException
6170 std::string
const& message,
6172 void handleIncomplete
6179 bool sectionStarted(
SectionInfo const& sectionInfo,
Counts& assertions )
override;
6182 void sectionEndedEarly(
SectionEndInfo const& endInfo )
override;
6186 void benchmarkStarting( BenchmarkInfo
const& info )
override;
6187 void benchmarkEnded( BenchmarkStats
const& stats )
override;
6189 void pushScopedMessage(
MessageInfo const& message )
override;
6190 void popScopedMessage(
MessageInfo const& message )
override;
6192 void emplaceUnscopedMessage(
MessageBuilder const& builder )
override;
6194 std::string getCurrentTestName()
const override;
6196 const AssertionResult* getLastResult()
const override;
6198 void exceptionEarlyReported()
override;
6200 void handleFatalErrorCondition(
StringRef message )
override;
6202 bool lastAssertionPassed()
override;
6204 void assertionPassed()
override;
6208 bool aborting()
const final;
6212 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );
6213 void invokeActiveTestCase();
6215 void resetAssertionInfo();
6216 bool testForMissingAssertions(
Counts& assertions );
6218 void assertionEnded( AssertionResult
const& result );
6229 void handleUnfinishedSections();
6231 TestRunInfo m_runInfo;
6233 TestCase const* m_activeTestCase =
nullptr;
6234 ITracker* m_testCaseTracker =
nullptr;
6235 Option<AssertionResult> m_lastResult;
6239 IStreamingReporterPtr m_reporter;
6240 std::vector<MessageInfo> m_messages;
6241 std::vector<ScopedMessage> m_messageScopes;
6243 std::vector<SectionEndInfo> m_unfinishedSections;
6244 std::vector<ITracker*> m_activeSections;
6245 TrackerContext m_trackerContext;
6246 bool m_lastAssertionPassed =
false;
6247 bool m_shouldReportUnexpected =
true;
6248 bool m_includeSuccessfulResults;
6264 : m_isNegated( isNegated )
6269 LazyExpression::operator
bool()
const {
6270 return m_transientExpression !=
nullptr;
6284 os <<
"{** error - unchecked empty expression requested **}";
6294 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
6299 m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
6302 m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
6311 if( m_reaction.shouldDebugBreak ) {
6317 CATCH_BREAK_INTO_DEBUGGER();
6319 if (m_reaction.shouldThrow) {
6320 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 6323 CATCH_ERROR(
"Test failure requires aborting test!" );
6336 m_resultCapture.handleNonExpr(m_assertionInfo,
ResultWas::Ok, m_reaction);
6339 m_resultCapture.handleNonExpr(m_assertionInfo,
ResultWas::Ok, m_reaction);
6343 m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
6347 m_resultCapture.handleNonExpr(m_assertionInfo,
ResultWas::Ok, m_reaction);
6362 lazyExpression(_lazyExpression),
6363 resultType(_resultType) {}
6365 std::string AssertionResultData::reconstructExpression()
const {
6367 if( reconstructedExpression.empty() ) {
6368 if( lazyExpression ) {
6370 rss << lazyExpression;
6371 reconstructedExpression = rss.
str();
6374 return reconstructedExpression;
6377 AssertionResult::AssertionResult(
AssertionInfo const& info, AssertionResultData
const&
data )
6379 m_resultData( data )
6383 bool AssertionResult::succeeded()
const {
6393 return m_resultData.resultType;
6396 bool AssertionResult::hasExpression()
const {
6397 return m_info.capturedExpression[0] != 0;
6400 bool AssertionResult::hasMessage()
const {
6401 return !m_resultData.message.empty();
6404 std::string AssertionResult::getExpression()
const {
6406 return "!(" + m_info.capturedExpression +
")";
6408 return m_info.capturedExpression;
6411 std::string AssertionResult::getExpressionInMacro()
const {
6413 if( m_info.macroName[0] == 0 )
6414 expr = m_info.capturedExpression;
6416 expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
6417 expr += m_info.macroName;
6419 expr += m_info.capturedExpression;
6425 bool AssertionResult::hasExpandedExpression()
const {
6426 return hasExpression() && getExpandedExpression() != getExpression();
6429 std::string AssertionResult::getExpandedExpression()
const {
6430 std::string expr = m_resultData.reconstructExpression();
6436 std::string AssertionResult::getMessage()
const {
6437 return m_resultData.message;
6440 return m_info.lineInfo;
6443 StringRef AssertionResult::getTestMacroName()
const {
6444 return m_info.macroName;
6461 auto elapsed = m_timer.getElapsedNanoseconds();
6464 if( elapsed < m_resolution ) {
6465 m_iterationsToRun *= 10;
6499 #ifdef CLARA_CONFIG_CONSOLE_WIDTH 6500 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 6501 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 6503 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 6506 #pragma clang diagnostic push 6507 #pragma clang diagnostic ignored "-Wweak-vtables" 6508 #pragma clang diagnostic ignored "-Wexit-time-destructors" 6509 #pragma clang diagnostic ignored "-Wshadow" 6523 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH 6524 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 6527 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 6528 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH 6531 #ifndef CLARA_CONFIG_OPTIONAL_TYPE 6532 #ifdef __has_include 6533 #if __has_include(<optional>) && __cplusplus >= 201703L 6535 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional 6557 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 6558 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 6563 namespace TextFlow {
6565 inline auto isWhitespace(
char c) ->
bool {
6566 static std::string chars =
" \t\n\r";
6567 return chars.find(c) != std::string::npos;
6569 inline auto isBreakableBefore(
char c) ->
bool {
6570 static std::string chars =
"[({<|";
6571 return chars.find(c) != std::string::npos;
6573 inline auto isBreakableAfter(
char c) ->
bool {
6574 static std::string chars =
"])}>.,:;*+-=&/\\";
6575 return chars.find(c) != std::string::npos;
6581 std::vector<std::string> m_strings;
6582 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
6583 size_t m_indent = 0;
6584 size_t m_initialIndent = std::string::npos;
6590 Column
const& m_column;
6591 size_t m_stringIndex = 0;
6596 bool m_suffix =
false;
6598 iterator(Column
const& column,
size_t stringIndex)
6600 m_stringIndex(stringIndex) {}
6602 auto line()
const -> std::string
const& {
return m_column.m_strings[m_stringIndex]; }
6604 auto isBoundary(
size_t at)
const ->
bool {
6606 assert(at <= line().size());
6608 return at == line().size() ||
6609 (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
6610 isBreakableBefore(line()[at]) ||
6611 isBreakableAfter(line()[at - 1]);
6615 assert(m_stringIndex < m_column.m_strings.size());
6618 auto width = m_column.m_width - indent();
6620 while (m_end < line().size() && line()[m_end] !=
'\n')
6623 if (m_end < m_pos + width) {
6624 m_len = m_end - m_pos;
6627 while (len > 0 && !isBoundary(m_pos + len))
6629 while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
6641 auto indent()
const ->
size_t {
6642 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
6643 return initial == std::string::npos ? m_column.m_indent : initial;
6646 auto addIndentAndSuffix(std::string
const &plain)
const -> std::string {
6647 return std::string(indent(),
' ') + (m_suffix ? plain +
"-" : plain);
6651 using difference_type = std::ptrdiff_t;
6652 using value_type = std::string;
6653 using pointer = value_type * ;
6654 using reference = value_type & ;
6655 using iterator_category = std::forward_iterator_tag;
6657 explicit iterator(Column
const& column) : m_column(column) {
6658 assert(m_column.m_width > m_column.m_indent);
6659 assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
6665 auto operator *()
const -> std::string {
6666 assert(m_stringIndex < m_column.m_strings.size());
6667 assert(m_pos <= m_end);
6668 return addIndentAndSuffix(line().substr(m_pos, m_len));
6671 auto operator ++() -> iterator& {
6673 if (m_pos < line().size() && line()[m_pos] ==
'\n')
6676 while (m_pos < line().size() && isWhitespace(line()[m_pos]))
6679 if (m_pos == line().size()) {
6683 if (m_stringIndex < m_column.m_strings.size())
6687 auto operator ++(
int) -> iterator {
6688 iterator prev(*
this);
6693 auto operator ==(iterator
const& other)
const ->
bool {
6695 m_pos == other.m_pos &&
6696 m_stringIndex == other.m_stringIndex &&
6697 &m_column == &other.m_column;
6699 auto operator !=(iterator
const& other)
const ->
bool {
6703 using const_iterator = iterator;
6705 explicit Column(std::string
const& text) { m_strings.push_back(text); }
6707 auto width(
size_t newWidth) -> Column& {
6708 assert(newWidth > 0);
6712 auto indent(
size_t newIndent) -> Column& {
6713 m_indent = newIndent;
6716 auto initialIndent(
size_t newIndent) -> Column& {
6717 m_initialIndent = newIndent;
6721 auto width()
const ->
size_t {
return m_width; }
6722 auto begin()
const -> iterator {
return iterator(*
this); }
6723 auto end()
const -> iterator {
return { *
this, m_strings.size() }; }
6725 inline friend std::ostream&
operator << (std::ostream& os, Column
const& col) {
6727 for (
auto line : col) {
6737 auto operator + (Column
const& other)->Columns;
6739 auto toString()
const -> std::string {
6740 std::ostringstream oss;
6746 class Spacer :
public Column {
6749 explicit Spacer(
size_t spaceWidth) : Column(
"") {
6755 std::vector<Column> m_columns;
6763 std::vector<Column>
const& m_columns;
6764 std::vector<Column::iterator> m_iterators;
6765 size_t m_activeIterators;
6767 iterator(Columns
const& columns, EndTag)
6768 : m_columns(columns.m_columns),
6769 m_activeIterators(0) {
6770 m_iterators.reserve(m_columns.size());
6772 for (
auto const& col : m_columns)
6773 m_iterators.push_back(col.end());
6777 using difference_type = std::ptrdiff_t;
6778 using value_type = std::string;
6779 using pointer = value_type * ;
6780 using reference = value_type & ;
6781 using iterator_category = std::forward_iterator_tag;
6783 explicit iterator(Columns
const& columns)
6784 : m_columns(columns.m_columns),
6785 m_activeIterators(m_columns.size()) {
6786 m_iterators.reserve(m_columns.size());
6788 for (
auto const& col : m_columns)
6789 m_iterators.push_back(col.begin());
6792 auto operator ==(iterator
const& other)
const ->
bool {
6793 return m_iterators == other.m_iterators;
6795 auto operator !=(iterator
const& other)
const ->
bool {
6796 return m_iterators != other.m_iterators;
6798 auto operator *()
const -> std::string {
6799 std::string row, padding;
6801 for (
size_t i = 0; i < m_columns.size(); ++i) {
6802 auto width = m_columns[i].width();
6803 if (m_iterators[i] != m_columns[i].
end()) {
6804 std::string col = *m_iterators[i];
6805 row += padding + col;
6806 if (col.size() < width)
6807 padding = std::string(width - col.size(),
' ');
6811 padding += std::string(width,
' ');
6816 auto operator ++() -> iterator& {
6817 for (
size_t i = 0; i < m_columns.size(); ++i) {
6818 if (m_iterators[i] != m_columns[i].
end())
6823 auto operator ++(
int) -> iterator {
6824 iterator prev(*
this);
6829 using const_iterator = iterator;
6831 auto begin()
const -> iterator {
return iterator(*
this); }
6832 auto end()
const -> iterator {
return { *
this, iterator::EndTag() }; }
6834 auto operator += (Column
const& col) -> Columns& {
6835 m_columns.push_back(col);
6838 auto operator + (Column
const& col) -> Columns {
6839 Columns combined = *
this;
6844 inline friend std::ostream&
operator << (std::ostream& os, Columns
const& cols) {
6847 for (
auto line : cols) {
6857 auto toString()
const -> std::string {
6858 std::ostringstream oss;
6882 #include <algorithm> 6884 #if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) 6885 #define CATCH_PLATFORM_WINDOWS 6888 namespace Catch {
namespace clara {
6892 template<
typename L>
6893 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
6895 template<
typename ClassT,
typename ReturnT,
typename... Args>
6896 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
6897 static const bool isValid =
false;
6900 template<
typename ClassT,
typename ReturnT,
typename ArgT>
6901 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
6902 static const bool isValid =
true;
6903 using ArgType =
typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
6904 using ReturnType = ReturnT;
6912 std::string m_exeName;
6913 std::vector<std::string> m_args;
6916 Args(
int argc,
char const*
const* argv )
6917 : m_exeName(argv[0]),
6918 m_args(argv + 1, argv + argc) {}
6920 Args( std::initializer_list<std::string>
args )
6921 : m_exeName( *args.begin() ),
6922 m_args( args.begin()+1, args.end() )
6925 auto exeName()
const -> std::string {
6932 enum class TokenType {
6940 inline auto isOptPrefix(
char c ) ->
bool {
6942 #ifdef CATCH_PLATFORM_WINDOWS 6950 using Iterator = std::vector<std::string>::const_iterator;
6953 std::vector<Token> m_tokenBuffer;
6956 m_tokenBuffer.resize( 0 );
6959 while( it != itEnd && it->empty() )
6963 auto const &next = *it;
6964 if( isOptPrefix( next[0] ) ) {
6965 auto delimiterPos = next.find_first_of(
" :=" );
6966 if( delimiterPos != std::string::npos ) {
6967 m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
6968 m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
6970 if( next[1] !=
'-' && next.size() > 2 ) {
6971 std::string opt =
"- ";
6972 for(
size_t i = 1; i < next.size(); ++i ) {
6974 m_tokenBuffer.push_back( { TokenType::Option, opt } );
6977 m_tokenBuffer.push_back( { TokenType::Option, next } );
6981 m_tokenBuffer.push_back( { TokenType::Argument, next } );
6987 explicit TokenStream( Args
const &
args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
6989 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
6993 explicit operator bool()
const {
6994 return !m_tokenBuffer.empty() || it != itEnd;
6997 auto count()
const ->
size_t {
return m_tokenBuffer.size() + (itEnd - it); }
7000 assert( !m_tokenBuffer.empty() );
7001 return m_tokenBuffer.front();
7004 auto operator->()
const -> Token
const * {
7005 assert( !m_tokenBuffer.empty() );
7006 return &m_tokenBuffer.front();
7009 auto operator++() -> TokenStream & {
7010 if( m_tokenBuffer.size() >= 2 ) {
7011 m_tokenBuffer.erase( m_tokenBuffer.begin() );
7024 Ok, LogicError, RuntimeError
7028 ResultBase( Type type ) : m_type( type ) {}
7029 virtual ~ResultBase() =
default;
7031 virtual void enforceOk()
const = 0;
7036 template<
typename T>
7037 class ResultValueBase :
public ResultBase {
7039 auto value()
const -> T
const & {
7045 ResultValueBase( Type type ) : ResultBase( type ) {}
7047 ResultValueBase( ResultValueBase
const &other ) : ResultBase( other ) {
7048 if( m_type == ResultBase::Ok )
7049 new( &m_value ) T( other.m_value );
7052 ResultValueBase( Type, T
const &
value ) : ResultBase( Ok ) {
7053 new( &m_value ) T( value );
7056 auto operator=( ResultValueBase
const &other ) -> ResultValueBase & {
7057 if( m_type == ResultBase::Ok )
7059 ResultBase::operator=(other);
7060 if( m_type == ResultBase::Ok )
7061 new( &m_value ) T( other.m_value );
7065 ~ResultValueBase()
override {
7076 class ResultValueBase<void> :
public ResultBase {
7078 using ResultBase::ResultBase;
7081 template<
typename T =
void>
7082 class BasicResult :
public ResultValueBase<T> {
7084 template<
typename U>
7085 explicit BasicResult( BasicResult<U>
const &other )
7086 : ResultValueBase<T>( other.type() ),
7087 m_errorMessage( other.errorMessage() )
7089 assert( type() != ResultBase::Ok );
7092 template<
typename U>
7093 static auto ok( U
const &
value ) -> BasicResult {
return { ResultBase::Ok, value }; }
7094 static auto ok() -> BasicResult {
return { ResultBase::Ok }; }
7095 static auto logicError( std::string
const &message ) -> BasicResult {
return { ResultBase::LogicError, message }; }
7096 static auto runtimeError( std::string
const &message ) -> BasicResult {
return { ResultBase::RuntimeError, message }; }
7098 explicit operator bool()
const {
return m_type == ResultBase::Ok; }
7099 auto type()
const -> ResultBase::Type {
return m_type; }
7100 auto errorMessage()
const -> std::string {
return m_errorMessage; }
7103 void enforceOk()
const override {
7107 assert( m_type != ResultBase::LogicError );
7108 assert( m_type != ResultBase::RuntimeError );
7109 if( m_type != ResultBase::Ok )
7113 std::string m_errorMessage;
7115 BasicResult( ResultBase::Type type, std::string
const &message )
7116 : ResultValueBase<T>(type),
7117 m_errorMessage(message)
7119 assert( m_type != ResultBase::Ok );
7122 using ResultValueBase<T>::ResultValueBase;
7123 using ResultBase::m_type;
7126 enum class ParseResultType {
7127 Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
7133 ParseState( ParseResultType type, TokenStream
const &remainingTokens )
7135 m_remainingTokens( remainingTokens )
7138 auto type()
const -> ParseResultType {
return m_type; }
7139 auto remainingTokens()
const -> TokenStream {
return m_remainingTokens; }
7142 ParseResultType m_type;
7143 TokenStream m_remainingTokens;
7146 using Result = BasicResult<void>;
7147 using ParserResult = BasicResult<ParseResultType>;
7148 using InternalParseResult = BasicResult<ParseState>;
7150 struct HelpColumns {
7155 template<
typename T>
7156 inline auto convertInto( std::string
const &source, T& target ) -> ParserResult {
7157 std::stringstream ss;
7161 return ParserResult::runtimeError(
"Unable to convert '" + source +
"' to destination type" );
7163 return ParserResult::ok( ParseResultType::Matched );
7165 inline auto convertInto( std::string
const &source, std::string& target ) -> ParserResult {
7167 return ParserResult::ok( ParseResultType::Matched );
7169 inline auto convertInto( std::string
const &source,
bool &target ) -> ParserResult {
7170 std::string srcLC = source;
7171 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), [](
char c ) {
return static_cast<char>( std::tolower(c) ); } );
7172 if (srcLC ==
"y" || srcLC ==
"1" || srcLC ==
"true" || srcLC ==
"yes" || srcLC ==
"on")
7174 else if (srcLC ==
"n" || srcLC ==
"0" || srcLC ==
"false" || srcLC ==
"no" || srcLC ==
"off")
7177 return ParserResult::runtimeError(
"Expected a boolean value but did not recognise: '" + source +
"'" );
7178 return ParserResult::ok( ParseResultType::Matched );
7180 #ifdef CLARA_CONFIG_OPTIONAL_TYPE 7181 template<
typename T>
7182 inline auto convertInto( std::string
const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
7184 auto result = convertInto( source, temp );
7186 target = std::move(temp);
7189 #endif // CLARA_CONFIG_OPTIONAL_TYPE 7200 virtual ~BoundRef() =
default;
7201 virtual auto isContainer()
const ->
bool {
return false; }
7202 virtual auto isFlag()
const ->
bool {
return false; }
7204 struct BoundValueRefBase : BoundRef {
7205 virtual auto setValue( std::string
const &arg ) -> ParserResult = 0;
7207 struct BoundFlagRefBase : BoundRef {
7208 virtual auto setFlag(
bool flag ) -> ParserResult = 0;
7209 virtual auto isFlag()
const ->
bool {
return true; }
7212 template<
typename T>
7213 struct BoundValueRef : BoundValueRefBase {
7216 explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
7218 auto setValue( std::string
const &arg ) -> ParserResult
override {
7219 return convertInto( arg, m_ref );
7223 template<
typename T>
7224 struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
7225 std::vector<T> &m_ref;
7227 explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
7229 auto isContainer()
const ->
bool override {
return true; }
7231 auto setValue( std::string
const &arg ) -> ParserResult
override {
7233 auto result = convertInto( arg, temp );
7235 m_ref.push_back( temp );
7240 struct BoundFlagRef : BoundFlagRefBase {
7243 explicit BoundFlagRef(
bool &ref ) : m_ref( ref ) {}
7245 auto setFlag(
bool flag ) -> ParserResult
override {
7247 return ParserResult::ok( ParseResultType::Matched );
7251 template<
typename ReturnType>
7252 struct LambdaInvoker {
7255 template<
typename L,
typename ArgType>
7256 static auto invoke( L
const &lambda, ArgType
const &arg ) -> ParserResult {
7257 return lambda( arg );
7262 struct LambdaInvoker<void> {
7263 template<
typename L,
typename ArgType>
7264 static auto invoke( L
const &lambda, ArgType
const &arg ) -> ParserResult {
7266 return ParserResult::ok( ParseResultType::Matched );
7270 template<
typename ArgType,
typename L>
7271 inline auto invokeLambda( L
const &lambda, std::string
const &arg ) -> ParserResult {
7273 auto result = convertInto( arg, temp );
7276 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
7279 template<
typename L>
7280 struct BoundLambda : BoundValueRefBase {
7283 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
7284 explicit BoundLambda( L
const &lambda ) : m_lambda( lambda ) {}
7286 auto setValue( std::string
const &arg ) -> ParserResult
override {
7287 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
7291 template<
typename L>
7292 struct BoundFlagLambda : BoundFlagRefBase {
7295 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
7296 static_assert( std::is_same<
typename UnaryLambdaTraits<L>::ArgType,
bool>::
value,
"flags must be boolean" );
7298 explicit BoundFlagLambda( L
const &lambda ) : m_lambda( lambda ) {}
7300 auto setFlag(
bool flag ) -> ParserResult
override {
7301 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
7305 enum class Optionality { Optional, Required };
7311 virtual ~ParserBase() =
default;
7312 virtual auto validate()
const -> Result {
return Result::ok(); }
7313 virtual auto parse( std::string
const& exeName, TokenStream
const &tokens)
const -> InternalParseResult = 0;
7314 virtual auto cardinality()
const ->
size_t {
return 1; }
7316 auto parse( Args
const &
args )
const -> InternalParseResult {
7317 return parse( args.exeName(), TokenStream( args ) );
7321 template<
typename DerivedT>
7322 class ComposableParserImpl :
public ParserBase {
7324 template<
typename T>
7325 auto operator|( T
const &other )
const -> Parser;
7327 template<
typename T>
7328 auto operator+( T
const &other )
const -> Parser;
7332 template<
typename DerivedT>
7333 class ParserRefImpl :
public ComposableParserImpl<DerivedT> {
7335 Optionality m_optionality = Optionality::Optional;
7336 std::shared_ptr<BoundRef> m_ref;
7338 std::string m_description;
7340 explicit ParserRefImpl( std::shared_ptr<BoundRef>
const &ref ) : m_ref( ref ) {}
7343 template<
typename T>
7344 ParserRefImpl( T &ref, std::string
const &hint )
7345 : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
7349 template<
typename LambdaT>
7350 ParserRefImpl( LambdaT
const &ref, std::string
const &hint )
7351 : m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
7355 auto operator()( std::string
const &description ) -> DerivedT & {
7356 m_description = description;
7357 return static_cast<DerivedT &
>( *this );
7360 auto optional() -> DerivedT & {
7361 m_optionality = Optionality::Optional;
7362 return static_cast<DerivedT &
>( *this );
7365 auto required() -> DerivedT & {
7366 m_optionality = Optionality::Required;
7367 return static_cast<DerivedT &
>( *this );
7370 auto isOptional()
const ->
bool {
7371 return m_optionality == Optionality::Optional;
7374 auto cardinality()
const ->
size_t override {
7375 if( m_ref->isContainer() )
7381 auto hint()
const -> std::string {
return m_hint; }
7384 class ExeName :
public ComposableParserImpl<ExeName> {
7385 std::shared_ptr<std::string> m_name;
7386 std::shared_ptr<BoundValueRefBase> m_ref;
7388 template<
typename LambdaT>
7389 static auto makeRef(LambdaT
const &lambda) -> std::shared_ptr<BoundValueRefBase> {
7390 return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
7394 ExeName() : m_name( std::make_shared<std::string>(
"<executable>" ) ) {}
7396 explicit ExeName( std::string &ref ) : ExeName() {
7397 m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
7400 template<
typename LambdaT>
7401 explicit ExeName( LambdaT
const& lambda ) : ExeName() {
7402 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );
7406 auto parse( std::string
const&, TokenStream
const &tokens )
const -> InternalParseResult
override {
7407 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
7410 auto name()
const -> std::string {
return *m_name; }
7411 auto set( std::string
const& newName ) -> ParserResult {
7413 auto lastSlash = newName.find_last_of(
"\\/" );
7414 auto filename = ( lastSlash == std::string::npos )
7416 : newName.substr( lastSlash+1 );
7420 return m_ref->setValue(
filename );
7422 return ParserResult::ok( ParseResultType::Matched );
7426 class Arg :
public ParserRefImpl<Arg> {
7428 using ParserRefImpl::ParserRefImpl;
7430 auto parse( std::string
const &, TokenStream
const &tokens )
const -> InternalParseResult
override {
7431 auto validationResult =
validate();
7432 if( !validationResult )
7433 return InternalParseResult( validationResult );
7435 auto remainingTokens = tokens;
7436 auto const &token = *remainingTokens;
7437 if( token.type != TokenType::Argument )
7438 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
7440 assert( !m_ref->isFlag() );
7441 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.get() );
7443 auto result = valueRef->setValue( remainingTokens->token );
7445 return InternalParseResult( result );
7447 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
7451 inline auto normaliseOpt( std::string
const &optName ) -> std::string {
7452 #ifdef CATCH_PLATFORM_WINDOWS 7453 if( optName[0] ==
'/' )
7454 return "-" + optName.substr( 1 );
7460 class Opt :
public ParserRefImpl<Opt> {
7462 std::vector<std::string> m_optNames;
7465 template<
typename LambdaT>
7466 explicit Opt( LambdaT
const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
7468 explicit Opt(
bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}
7470 template<
typename LambdaT>
7471 Opt( LambdaT
const &ref, std::string
const &hint ) : ParserRefImpl( ref, hint ) {}
7473 template<
typename T>
7474 Opt( T &ref, std::string
const &hint ) : ParserRefImpl( ref, hint ) {}
7476 auto operator[]( std::string
const &optName ) -> Opt & {
7477 m_optNames.push_back( optName );
7481 auto getHelpColumns()
const -> std::vector<HelpColumns> {
7482 std::ostringstream oss;
7484 for(
auto const &opt : m_optNames ) {
7491 if( !m_hint.empty() )
7492 oss <<
" <" << m_hint <<
">";
7493 return { { oss.str(), m_description } };
7496 auto isMatch( std::string
const &optToken )
const ->
bool {
7497 auto normalisedToken = normaliseOpt( optToken );
7498 for(
auto const &
name : m_optNames ) {
7499 if( normaliseOpt(
name ) == normalisedToken )
7505 using ParserBase::parse;
7507 auto parse( std::string
const&, TokenStream
const &tokens )
const -> InternalParseResult
override {
7508 auto validationResult =
validate();
7509 if( !validationResult )
7510 return InternalParseResult( validationResult );
7512 auto remainingTokens = tokens;
7513 if( remainingTokens && remainingTokens->type == TokenType::Option ) {
7514 auto const &token = *remainingTokens;
7515 if( isMatch(token.token ) ) {
7516 if( m_ref->isFlag() ) {
7517 auto flagRef =
static_cast<detail::BoundFlagRefBase*
>( m_ref.get() );
7518 auto result = flagRef->setFlag(
true );
7520 return InternalParseResult( result );
7521 if( result.value() == ParseResultType::ShortCircuitAll )
7522 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
7524 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.get() );
7526 if( !remainingTokens )
7527 return InternalParseResult::runtimeError(
"Expected argument following " + token.token );
7528 auto const &argToken = *remainingTokens;
7529 if( argToken.type != TokenType::Argument )
7530 return InternalParseResult::runtimeError(
"Expected argument following " + token.token );
7531 auto result = valueRef->setValue( argToken.token );
7533 return InternalParseResult( result );
7534 if( result.value() == ParseResultType::ShortCircuitAll )
7535 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
7537 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
7540 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
7543 auto validate()
const -> Result
override {
7544 if( m_optNames.empty() )
7545 return Result::logicError(
"No options supplied to Opt" );
7546 for(
auto const &
name : m_optNames ) {
7548 return Result::logicError(
"Option name cannot be empty" );
7549 #ifdef CATCH_PLATFORM_WINDOWS 7550 if(
name[0] !=
'-' &&
name[0] !=
'/' )
7551 return Result::logicError(
"Option name must begin with '-' or '/'" );
7553 if(
name[0] !=
'-' )
7554 return Result::logicError(
"Option name must begin with '-'" );
7562 Help(
bool &showHelpFlag )
7563 : Opt([&](
bool flag ) {
7564 showHelpFlag = flag;
7565 return ParserResult::ok( ParseResultType::ShortCircuitAll );
7568 static_cast<Opt &
>( *this )
7569 (
"display usage information")
7570 [
"-?"][
"-h"][
"--help"]
7575 struct Parser : ParserBase {
7577 mutable ExeName m_exeName;
7578 std::vector<Opt> m_options;
7579 std::vector<Arg> m_args;
7581 auto operator|=( ExeName
const &exeName ) -> Parser & {
7582 m_exeName = exeName;
7586 auto operator|=( Arg
const &arg ) -> Parser & {
7587 m_args.push_back(arg);
7591 auto operator|=( Opt
const &opt ) -> Parser & {
7592 m_options.push_back(opt);
7596 auto operator|=( Parser
const &other ) -> Parser & {
7597 m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
7598 m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
7602 template<
typename T>
7603 auto operator|( T
const &other )
const -> Parser {
7604 return Parser( *
this ) |= other;
7608 template<
typename T>
7609 auto operator+=( T
const &other ) -> Parser & {
return operator|=( other ); }
7610 template<
typename T>
7613 auto getHelpColumns()
const -> std::vector<HelpColumns> {
7614 std::vector<HelpColumns> cols;
7615 for (
auto const &o : m_options) {
7616 auto childCols = o.getHelpColumns();
7617 cols.insert( cols.end(), childCols.begin(), childCols.end() );
7622 void writeToStream( std::ostream &os )
const {
7623 if (!m_exeName.name().empty()) {
7624 os <<
"usage:\n" <<
" " << m_exeName.name() <<
" ";
7625 bool required =
true, first =
true;
7626 for(
auto const &arg : m_args ) {
7631 if( arg.isOptional() && required ) {
7635 os <<
"<" << arg.hint() <<
">";
7636 if( arg.cardinality() == 0 )
7641 if( !m_options.empty() )
7643 os <<
"\n\nwhere options are:" << std::endl;
7646 auto rows = getHelpColumns();
7647 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
7648 size_t optWidth = 0;
7649 for(
auto const &cols : rows )
7650 optWidth = (
std::max)(optWidth, cols.left.size() + 2);
7652 optWidth = (std::min)(optWidth, consoleWidth/2);
7654 for(
auto const &cols : rows ) {
7656 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
7657 TextFlow::Spacer(4) +
7658 TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
7659 os << row << std::endl;
7663 friend auto operator<<( std::ostream &os, Parser
const &
parser ) -> std::ostream& {
7664 parser.writeToStream( os );
7668 auto validate()
const -> Result
override {
7669 for(
auto const &opt : m_options ) {
7670 auto result = opt.validate();
7674 for(
auto const &arg : m_args ) {
7675 auto result = arg.validate();
7679 return Result::ok();
7682 using ParserBase::parse;
7684 auto parse( std::string
const& exeName, TokenStream
const &tokens )
const -> InternalParseResult
override {
7687 ParserBase
const* parser =
nullptr;
7690 const size_t totalParsers = m_options.size() + m_args.size();
7691 assert( totalParsers < 512 );
7693 ParserInfo parseInfos[512];
7697 for (
auto const &opt : m_options) parseInfos[i++].parser = &opt;
7698 for (
auto const &arg : m_args) parseInfos[i++].parser = &arg;
7701 m_exeName.set( exeName );
7703 auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
7704 while( result.value().remainingTokens() ) {
7705 bool tokenParsed =
false;
7707 for(
size_t i = 0; i < totalParsers; ++i ) {
7708 auto& parseInfo = parseInfos[i];
7709 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
7710 result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
7713 if (result.value().type() != ParseResultType::NoMatch) {
7721 if( result.value().type() == ParseResultType::ShortCircuitAll )
7724 return InternalParseResult::runtimeError(
"Unrecognised token: " + result.value().remainingTokens()->token );
7731 template<
typename DerivedT>
7732 template<
typename T>
7734 return Parser() |
static_cast<DerivedT
const &
>( *this ) | other;
7739 using detail::Parser;
7751 using detail::ExeName;
7757 using detail::ParseResultType;
7760 using detail::ParserResult;
7766 #pragma clang diagnostic pop 7770 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 7771 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 7772 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 7778 clara::Parser makeCommandLineParser( ConfigData&
config );
7788 clara::Parser makeCommandLineParser( ConfigData&
config ) {
7790 using namespace clara;
7792 auto const setWarning = [&]( std::string
const& warning ) {
7793 auto warningSet = [&]() {
7794 if( warning ==
"NoAssertions" )
7797 if ( warning ==
"NoTests" )
7804 return ParserResult::runtimeError(
"Unrecognised warning: '" + warning +
"'" );
7805 config.warnings =
static_cast<WarnAbout::What>( config.warnings | warningSet );
7806 return ParserResult::ok( ParseResultType::Matched );
7808 auto const loadTestNamesFromFile = [&]( std::string
const&
filename ) {
7811 return ParserResult::runtimeError(
"Unable to load input file: '" +
filename +
"'" );
7814 while( std::getline(
f, line ) ) {
7816 if( !line.empty() && !
startsWith( line,
'#' ) ) {
7818 line =
'"' + line +
'"';
7819 config.testsOrTags.push_back( line +
',' );
7822 return ParserResult::ok( ParseResultType::Matched );
7824 auto const setTestOrder = [&]( std::string
const& order ) {
7832 return clara::ParserResult::runtimeError(
"Unrecognised ordering: '" + order +
"'" );
7833 return ParserResult::ok( ParseResultType::Matched );
7835 auto const setRngSeed = [&]( std::string
const& seed ) {
7836 if( seed !=
"time" )
7837 return clara::detail::convertInto( seed, config.rngSeed );
7838 config.rngSeed =
static_cast<unsigned int>( std::time(
nullptr) );
7839 return ParserResult::ok( ParseResultType::Matched );
7841 auto const setColourUsage = [&]( std::string
const& useColour ) {
7842 auto mode =
toLower( useColour );
7846 else if( mode ==
"no" )
7848 else if( mode ==
"auto" )
7851 return ParserResult::runtimeError(
"colour mode must be one of: auto, yes or no. '" + useColour +
"' not recognised" );
7852 return ParserResult::ok( ParseResultType::Matched );
7854 auto const setWaitForKeypress = [&]( std::string
const& keypress ) {
7855 auto keypressLc =
toLower( keypress );
7856 if( keypressLc ==
"start" )
7858 else if( keypressLc ==
"exit" )
7860 else if( keypressLc ==
"both" )
7863 return ParserResult::runtimeError(
"keypress argument must be one of: start, exit or both. '" + keypress +
"' not recognised" );
7864 return ParserResult::ok( ParseResultType::Matched );
7866 auto const setVerbosity = [&]( std::string
const& verbosity ) {
7867 auto lcVerbosity =
toLower( verbosity );
7868 if( lcVerbosity ==
"quiet" )
7870 else if( lcVerbosity ==
"normal" )
7872 else if( lcVerbosity ==
"high" )
7875 return ParserResult::runtimeError(
"Unrecognised verbosity, '" + verbosity +
"'" );
7876 return ParserResult::ok( ParseResultType::Matched );
7878 auto const setReporter = [&]( std::string
const& reporter ) {
7881 auto lcReporter =
toLower( reporter );
7882 auto result = factories.find( lcReporter );
7884 if( factories.end() != result )
7885 config.reporterName = lcReporter;
7887 return ParserResult::runtimeError(
"Unrecognized reporter, '" + reporter +
"'. Check available with --list-reporters" );
7888 return ParserResult::ok( ParseResultType::Matched );
7892 = ExeName( config.processName )
7893 | Help( config.showHelp )
7894 | Opt( config.listTests )
7895 ["-l"]["--list-tests"]
7896 (
"list all/matching test cases" )
7897 | Opt( config.listTags )
7898 ["-t"]["--list-tags"]
7899 (
"list all/matching tags" )
7900 | Opt( config.showSuccessfulTests )
7902 (
"include successful tests in output" )
7903 | Opt( config.shouldDebugBreak )
7905 (
"break into debugger on failure" )
7906 | Opt( config.noThrow )
7908 (
"skip exception tests" )
7909 | Opt( config.showInvisibles )
7910 ["-i"]["--invisibles"]
7911 (
"show invisibles (tabs, newlines)" )
7912 | Opt( config.outputFilename,
"filename" )
7914 (
"output filename" )
7915 | Opt( setReporter,
"name" )
7916 ["-r"]["--reporter"]
7917 (
"reporter to use (defaults to console)" )
7918 | Opt( config.name,
"name" )
7921 | Opt( [&](
bool ){ config.abortAfter = 1; } )
7923 (
"abort at first failure" )
7924 | Opt( [&](
int x ){ config.abortAfter = x; },
"no. failures" )
7926 (
"abort after x failures" )
7927 | Opt( setWarning,
"warning name" )
7929 (
"enable warnings" )
7931 [
"-d"][
"--durations"]
7932 (
"show test durations" )
7933 | Opt( loadTestNamesFromFile,
"filename" )
7934 ["-f"]["--input-file"]
7935 (
"load test names to run from a file" )
7936 | Opt( config.filenamesAsTags )
7937 ["-#"]["--filenames-as-tags"]
7938 (
"adds a tag for the filename" )
7939 | Opt( config.sectionsToRun,
"section name" )
7941 (
"specify section to run" )
7943 ["-v"]["--verbosity"]
7944 (
"set output verbosity" )
7945 | Opt( config.listTestNamesOnly )
7946 ["--list-test-names-only"]
7947 (
"list all/matching test cases names only" )
7948 | Opt( config.listReporters )
7949 ["--list-reporters"]
7950 (
"list all reporters" )
7951 | Opt( setTestOrder,
"decl|lex|rand" )
7953 (
"test case order (defaults to decl)" )
7954 | Opt( setRngSeed,
"'time'|number" )
7956 (
"set a specific seed for random numbers" )
7957 | Opt( setColourUsage,
"yes|no" )
7959 (
"should output be colourised" )
7960 | Opt( config.libIdentify )
7962 (
"report name and version according to libidentify standard" )
7963 | Opt( setWaitForKeypress,
"start|exit|both" )
7964 ["--wait-for-keypress"]
7965 (
"waits for a keypress before exiting" )
7966 | Opt( config.benchmarkResolutionMultiple,
"multiplier" )
7967 ["--benchmark-resolution-multiple"]
7968 (
"multiple of clock resolution to run benchmarks" )
7970 | Arg( config.testsOrTags,
"test name|pattern|tags" )
7971 (
"which test or tests to use" );
7986 return file[0] ==
'\0';
7999 os << info.
file <<
'(' << info.
line <<
')';
8001 os << info.
file <<
':' << info.
line;
8007 return std::string();
8019 Config::Config( ConfigData
const&
data )
8021 m_stream( openStream() )
8023 TestSpecParser
parser(ITagAliasRegistry::get());
8024 if (data.testsOrTags.empty()) {
8025 parser.parse(
"~[.]");
8028 m_hasTestFilters =
true;
8029 for(
auto const& testOrTags : data.testsOrTags )
8030 parser.parse( testOrTags );
8032 m_testSpec = parser.testSpec();
8035 std::string
const& Config::getFilename()
const {
8036 return m_data.outputFilename ;
8039 bool Config::listTests()
const {
return m_data.listTests; }
8040 bool Config::listTestNamesOnly()
const {
return m_data.listTestNamesOnly; }
8041 bool Config::listTags()
const {
return m_data.listTags; }
8042 bool Config::listReporters()
const {
return m_data.listReporters; }
8044 std::string Config::getProcessName()
const {
return m_data.processName; }
8045 std::string
const& Config::getReporterName()
const {
return m_data.reporterName; }
8047 std::vector<std::string>
const& Config::getTestsOrTags()
const {
return m_data.testsOrTags; }
8048 std::vector<std::string>
const& Config::getSectionsToRun()
const {
return m_data.sectionsToRun; }
8050 TestSpec
const& Config::testSpec()
const {
return m_testSpec; }
8051 bool Config::hasTestFilters()
const {
return m_hasTestFilters; }
8053 bool Config::showHelp()
const {
return m_data.showHelp; }
8056 bool Config::allowThrows()
const {
return !m_data.noThrow; }
8057 std::ostream& Config::stream()
const {
return m_stream->stream(); }
8058 std::string
Config::name()
const {
return m_data.name.empty() ? m_data.processName : m_data.name; }
8059 bool Config::includeSuccessfulResults()
const {
return m_data.showSuccessfulTests; }
8061 bool Config::warnAboutNoTests()
const {
return !!(m_data.warnings &
WarnAbout::NoTests); }
8065 int Config::benchmarkResolutionMultiple()
const {
return m_data.benchmarkResolutionMultiple; }
8067 bool Config::shouldDebugBreak()
const {
return m_data.shouldDebugBreak; }
8068 int Config::abortAfter()
const {
return m_data.abortAfter; }
8069 bool Config::showInvisibles()
const {
return m_data.showInvisibles; }
8070 Verbosity Config::verbosity()
const {
return m_data.verbosity; }
8072 IStream const* Config::openStream() {
8080 #if defined(__clang__) 8081 # pragma clang diagnostic push 8082 # pragma clang diagnostic ignored "-Wexit-time-destructors" 8105 struct IColourImpl {
8106 virtual ~IColourImpl() =
default;
8107 virtual void use( Colour::Code _colourCode ) = 0;
8110 struct NoColourImpl : IColourImpl {
8111 void use( Colour::Code ) {}
8113 static IColourImpl* instance() {
8114 static NoColourImpl s_instance;
8122 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) 8123 # ifdef CATCH_PLATFORM_WINDOWS 8124 # define CATCH_CONFIG_COLOUR_WINDOWS 8126 # define CATCH_CONFIG_COLOUR_ANSI 8130 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) 8135 class Win32ColourImpl :
public IColourImpl {
8137 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
8139 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
8140 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
8141 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
8142 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
8145 virtual void use( Colour::Code _colourCode )
override {
8146 switch( _colourCode ) {
8147 case Colour::None:
return setTextAttribute( originalForegroundAttributes );
8148 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
8149 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
8150 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
8151 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
8152 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
8153 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
8154 case Colour::Grey:
return setTextAttribute( 0 );
8156 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
8157 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
8158 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
8159 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
8160 case Colour::BrightYellow:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
8170 void setTextAttribute(
WORD _textAttribute ) {
8171 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
8173 HANDLE stdoutHandle;
8174 WORD originalForegroundAttributes;
8175 WORD originalBackgroundAttributes;
8178 IColourImpl* platformColourInstance() {
8179 static Win32ColourImpl s_instance;
8183 ? config->useColour()
8189 : NoColourImpl::instance();
8195 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) 8206 class PosixColourImpl :
public IColourImpl {
8208 virtual void use( Colour::Code _colourCode )
override {
8209 switch( _colourCode ) {
8211 case Colour::White:
return setColour(
"[0m" );
8212 case Colour::Red:
return setColour(
"[0;31m" );
8213 case Colour::Green:
return setColour(
"[0;32m" );
8214 case Colour::Blue:
return setColour(
"[0;34m" );
8215 case Colour::Cyan:
return setColour(
"[0;36m" );
8216 case Colour::Yellow:
return setColour(
"[0;33m" );
8217 case Colour::Grey:
return setColour(
"[1;30m" );
8219 case Colour::LightGrey:
return setColour(
"[0;37m" );
8220 case Colour::BrightRed:
return setColour(
"[1;31m" );
8221 case Colour::BrightGreen:
return setColour(
"[1;32m" );
8222 case Colour::BrightWhite:
return setColour(
"[1;37m" );
8223 case Colour::BrightYellow:
return setColour(
"[1;33m" );
8229 static IColourImpl* instance() {
8230 static PosixColourImpl s_instance;
8235 void setColour(
const char* _escapeCode ) {
8237 <<
'\033' << _escapeCode;
8241 bool useColourOnPlatform() {
8243 #ifdef CATCH_PLATFORM_MAC 8244 !isDebuggerActive() &&
8246 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) 8247 isatty(STDOUT_FILENO)
8253 IColourImpl* platformColourInstance() {
8257 ? config->useColour()
8260 colourMode = useColourOnPlatform()
8264 ? PosixColourImpl::instance()
8265 : NoColourImpl::instance();
8271 #else // not Windows or ANSI 8275 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
8279 #endif // Windows/ ANSI/ None 8283 Colour::Colour( Code _colourCode ) { use( _colourCode ); }
8284 Colour::Colour( Colour&& rhs ) noexcept {
8285 m_moved = rhs.m_moved;
8288 Colour& Colour::operator=( Colour&& rhs ) noexcept {
8289 m_moved = rhs.m_moved;
8294 Colour::~Colour(){
if( !m_moved ) use( None ); }
8296 void Colour::use( Code _colourCode ) {
8297 static IColourImpl* impl = platformColourInstance();
8298 impl->use( _colourCode );
8301 std::ostream&
operator << ( std::ostream& os, Colour
const& ) {
8307 #if defined(__clang__) 8308 # pragma clang diagnostic pop 8320 return m_resultCapture;
8322 virtual IRunner* getRunner()
override {
8326 virtual IConfigPtr const& getConfig()
const override {
8330 virtual ~Context()
override;
8333 virtual void setResultCapture(
IResultCapture* resultCapture )
override {
8334 m_resultCapture = resultCapture;
8336 virtual void setRunner(
IRunner* runner )
override {
8355 currentContext =
new Context();
8360 IMutableContext::currentContext =
nullptr;
8364 Context::~Context() =
default;
8374 void writeToDebugConsole( std::string
const& text );
8378 #ifdef CATCH_PLATFORM_WINDOWS 8381 void writeToDebugConsole( std::string
const& text ) {
8382 ::OutputDebugStringA( text.c_str() );
8389 void writeToDebugConsole( std::string
const& text ) {
8399 #ifdef CATCH_PLATFORM_MAC 8402 # include <stdbool.h> 8403 # include <sys/types.h> 8404 # include <unistd.h> 8405 # include <sys/sysctl.h> 8416 bool isDebuggerActive(){
8419 struct kinfo_proc info;
8425 info.kp_proc.p_flag = 0;
8432 mib[2] = KERN_PROC_PID;
8437 size =
sizeof(info);
8438 if( sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size,
nullptr, 0) != 0 ) {
8439 Catch::cerr() <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
8445 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
8449 #elif defined(CATCH_PLATFORM_LINUX) 8461 bool isDebuggerActive(){
8465 std::ifstream in(
"/proc/self/status");
8466 for( std::string line; std::getline(in, line); ) {
8467 static const int PREFIX_LEN = 11;
8468 if( line.compare(0, PREFIX_LEN,
"TracerPid:\t") == 0 ) {
8472 return line.length() > PREFIX_LEN && line[PREFIX_LEN] !=
'0';
8479 #elif defined(_MSC_VER) 8480 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
8482 bool isDebuggerActive() {
8483 return IsDebuggerPresent() != 0;
8486 #elif defined(__MINGW32__) 8487 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
8489 bool isDebuggerActive() {
8490 return IsDebuggerPresent() != 0;
8495 bool isDebuggerActive() {
return false; }
8506 if( lhs.size() + rhs.size() < 40 &&
8507 lhs.find(
'\n') == std::string::npos &&
8508 rhs.find(
'\n') == std::string::npos )
8509 os << lhs <<
" " << op <<
" " << rhs;
8511 os << lhs <<
"\n" << op <<
"\n" << rhs;
8518 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER) 8521 Catch::cerr() <<
"Catch will terminate because it needed to throw an exception.\n" 8522 <<
"The message was: " << e.what() <<
'\n';
8533 ErrnoGuard::ErrnoGuard():m_oldErrno(
errno){}
8534 ErrnoGuard::~ErrnoGuard() {
errno = m_oldErrno; }
8549 ~ExceptionTranslatorRegistry();
8552 std::string tryTranslators()
const;
8555 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
8561 #import "Foundation/Foundation.h" 8566 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
8569 void ExceptionTranslatorRegistry::registerTranslator(
const IExceptionTranslator* translator ) {
8570 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
8573 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 8579 return tryTranslators();
8581 @catch (NSException *exception) {
8593 if (std::current_exception() ==
nullptr) {
8594 return "Non C++ exception. Possibly a CLR exception.";
8596 return tryTranslators();
8600 std::rethrow_exception(std::current_exception());
8602 catch( std::exception& ex ) {
8605 catch( std::string& msg ) {
8608 catch(
const char* msg ) {
8612 return "Unknown exception";
8616 std::string ExceptionTranslatorRegistry::tryTranslators()
const {
8617 if (m_translators.empty()) {
8618 std::rethrow_exception(std::current_exception());
8620 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
8624 #else // ^^ Exceptions are enabled // Exceptions are disabled vv 8626 CATCH_INTERNAL_ERROR(
"Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
8629 std::string ExceptionTranslatorRegistry::tryTranslators()
const {
8630 CATCH_INTERNAL_ERROR(
"Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
8638 #if defined(__GNUC__) 8639 # pragma GCC diagnostic push 8640 # pragma GCC diagnostic ignored "-Wmissing-field-initializers" 8643 #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) 8647 void reportFatal(
char const *
const message ) {
8652 #endif // signals/SEH handling 8654 #if defined( CATCH_CONFIG_WINDOWS_SEH ) 8657 struct SignalDefs {
DWORD id;
const char*
name; };
8662 static SignalDefs signalDefs[] = {
8663 { EXCEPTION_ILLEGAL_INSTRUCTION,
"SIGILL - Illegal instruction signal" },
8664 { EXCEPTION_STACK_OVERFLOW,
"SIGSEGV - Stack overflow" },
8665 { EXCEPTION_ACCESS_VIOLATION,
"SIGSEGV - Segmentation violation signal" },
8666 { EXCEPTION_INT_DIVIDE_BY_ZERO,
"Divide by zero error" },
8669 LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
8670 for (
auto const& def : signalDefs) {
8671 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
8672 reportFatal(def.name);
8677 return EXCEPTION_CONTINUE_SEARCH;
8680 FatalConditionHandler::FatalConditionHandler() {
8684 guaranteeSize = 32 * 1024;
8685 exceptionHandlerHandle =
nullptr;
8687 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
8689 SetThreadStackGuarantee(&guaranteeSize);
8692 void FatalConditionHandler::reset() {
8694 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
8695 SetThreadStackGuarantee(&guaranteeSize);
8696 exceptionHandlerHandle =
nullptr;
8701 FatalConditionHandler::~FatalConditionHandler() {
8705 bool FatalConditionHandler::isSet =
false;
8706 ULONG FatalConditionHandler::guaranteeSize = 0;
8707 PVOID FatalConditionHandler::exceptionHandlerHandle =
nullptr;
8711 #elif defined( CATCH_CONFIG_POSIX_SIGNALS ) 8722 constexpr
static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
8724 static SignalDefs signalDefs[] = {
8725 { SIGINT,
"SIGINT - Terminal interrupt signal" },
8726 { SIGILL,
"SIGILL - Illegal instruction signal" },
8727 { SIGFPE,
"SIGFPE - Floating point error signal" },
8728 { SIGSEGV,
"SIGSEGV - Segmentation violation signal" },
8729 { SIGTERM,
"SIGTERM - Termination request signal" },
8730 { SIGABRT,
"SIGABRT - Abort (abnormal termination) signal" }
8733 void FatalConditionHandler::handleSignal(
int sig ) {
8734 char const *
name =
"<unknown signal>";
8735 for (
auto const& def : signalDefs) {
8736 if (sig == def.id) {
8746 FatalConditionHandler::FatalConditionHandler() {
8749 sigStack.ss_sp = altStackMem;
8750 sigStack.ss_size = sigStackSize;
8751 sigStack.ss_flags = 0;
8752 sigaltstack(&sigStack, &oldSigStack);
8753 struct sigaction sa = { };
8755 sa.sa_handler = handleSignal;
8756 sa.sa_flags = SA_ONSTACK;
8757 for (std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i) {
8758 sigaction(signalDefs[i].
id, &sa, &oldSigActions[i]);
8762 FatalConditionHandler::~FatalConditionHandler() {
8766 void FatalConditionHandler::reset() {
8769 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i ) {
8770 sigaction(signalDefs[i].
id, &oldSigActions[i],
nullptr);
8773 sigaltstack(&oldSigStack,
nullptr);
8778 bool FatalConditionHandler::isSet =
false;
8779 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
8780 stack_t FatalConditionHandler::oldSigStack = {};
8781 char FatalConditionHandler::altStackMem[sigStackSize] = {};
8788 void FatalConditionHandler::reset() {}
8791 #endif // signals/SEH handling 8793 #if defined(__GNUC__) 8794 # pragma GCC diagnostic pop 8801 #include <algorithm> 8808 std::mt19937& rng();
8826 namespace Generators {
8828 GeneratorUntypedBase::~GeneratorUntypedBase() {}
8869 class ListeningReporter :
public IStreamingReporter {
8870 using Reporters = std::vector<IStreamingReporterPtr>;
8871 Reporters m_listeners;
8872 IStreamingReporterPtr m_reporter =
nullptr;
8873 ReporterPreferences m_preferences;
8876 ListeningReporter();
8878 void addListener( IStreamingReporterPtr&& listener );
8879 void addReporter( IStreamingReporterPtr&& reporter );
8883 ReporterPreferences getPreferences()
const override;
8885 void noMatchingTestCases( std::string
const& spec )
override;
8887 static std::set<Verbosity> getSupportedVerbosities();
8889 void benchmarkStarting( BenchmarkInfo
const& benchmarkInfo )
override;
8890 void benchmarkEnded( BenchmarkStats
const& benchmarkStats )
override;
8892 void testRunStarting( TestRunInfo
const& testRunInfo )
override;
8893 void testGroupStarting( GroupInfo
const& groupInfo )
override;
8894 void testCaseStarting(
TestCaseInfo const& testInfo )
override;
8895 void sectionStarting(
SectionInfo const& sectionInfo )
override;
8896 void assertionStarting(
AssertionInfo const& assertionInfo )
override;
8899 bool assertionEnded( AssertionStats
const& assertionStats )
override;
8900 void sectionEnded( SectionStats
const& sectionStats )
override;
8901 void testCaseEnded( TestCaseStats
const& testCaseStats )
override;
8902 void testGroupEnded( TestGroupStats
const& testGroupStats )
override;
8903 void testRunEnded( TestRunStats
const& testRunStats )
override;
8905 void skipTest(
TestCaseInfo const& testInfo )
override;
8906 bool isMulti()
const override;
8915 ReporterConfig::ReporterConfig(
IConfigPtr const& _fullConfig )
8916 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
8918 ReporterConfig::ReporterConfig(
IConfigPtr const& _fullConfig, std::ostream& _stream )
8919 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
8921 std::ostream& ReporterConfig::stream()
const {
return *m_stream; }
8922 IConfigPtr ReporterConfig::fullConfig()
const {
return m_fullConfig; }
8924 TestRunInfo::TestRunInfo( std::string
const& _name ) :
name( _name ) {}
8926 GroupInfo::GroupInfo( std::string
const& _name,
8927 std::size_t _groupIndex,
8928 std::size_t _groupsCount )
8930 groupIndex( _groupIndex ),
8931 groupsCounts( _groupsCount )
8934 AssertionStats::AssertionStats( AssertionResult
const& _assertionResult,
8935 std::vector<MessageInfo>
const& _infoMessages,
8937 : assertionResult( _assertionResult ),
8938 infoMessages( _infoMessages ),
8941 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
8943 if( assertionResult.hasMessage() ) {
8946 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
8947 builder << assertionResult.getMessage();
8950 infoMessages.push_back( builder.m_info );
8954 AssertionStats::~AssertionStats() =
default;
8956 SectionStats::SectionStats(
SectionInfo const& _sectionInfo,
8957 Counts const& _assertions,
8958 double _durationInSeconds,
8959 bool _missingAssertions )
8960 : sectionInfo( _sectionInfo ),
8961 assertions( _assertions ),
8962 durationInSeconds( _durationInSeconds ),
8963 missingAssertions( _missingAssertions )
8966 SectionStats::~SectionStats() =
default;
8968 TestCaseStats::TestCaseStats(
TestCaseInfo const& _testInfo,
8970 std::string
const& _stdOut,
8971 std::string
const& _stdErr,
8973 : testInfo( _testInfo ),
8977 aborting( _aborting )
8980 TestCaseStats::~TestCaseStats() =
default;
8982 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo,
8985 : groupInfo( _groupInfo ),
8987 aborting( _aborting )
8990 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo )
8991 : groupInfo( _groupInfo ),
8995 TestGroupStats::~TestGroupStats() =
default;
8997 TestRunStats::TestRunStats( TestRunInfo
const& _runInfo,
9000 : runInfo( _runInfo ),
9002 aborting( _aborting )
9005 TestRunStats::~TestRunStats() =
default;
9007 void IStreamingReporter::fatalErrorEncountered(
StringRef ) {}
9008 bool IStreamingReporter::isMulti()
const {
return false; }
9010 IReporterFactory::~IReporterFactory() =
default;
9011 IReporterRegistry::~IReporterRegistry() =
default;
9030 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG 9035 LeakDetector::LeakDetector() {
9036 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
9037 flag |= _CRTDBG_LEAK_CHECK_DF;
9038 flag |= _CRTDBG_ALLOC_MEM_DF;
9039 _CrtSetDbgFlag(flag);
9040 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
9041 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
9043 _CrtSetBreakAlloc(-1);
9049 Catch::LeakDetector::LeakDetector() {}
9053 Catch::LeakDetector::~LeakDetector() {
9065 std::size_t listTests( Config
const&
config );
9067 std::size_t listTestsNamesOnly( Config
const& config );
9070 void add( std::string
const& spelling );
9071 std::string all()
const;
9073 std::set<std::string> spellings;
9074 std::size_t
count = 0;
9077 std::size_t listTags( Config
const& config );
9079 std::size_t listReporters();
9081 Option<std::size_t> list( std::shared_ptr<Config>
const& config );
9089 using namespace clara::TextFlow;
9094 #include <algorithm> 9099 std::size_t listTests( Config
const&
config ) {
9100 TestSpec testSpec = config.testSpec();
9101 if( config.hasTestFilters() )
9108 for(
auto const& testCaseInfo : matchedTestCases ) {
9109 Colour::Code colour = testCaseInfo.isHidden()
9110 ? Colour::SecondaryText
9112 Colour colourGuard( colour );
9114 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) <<
"\n";
9117 std::string description = testCaseInfo.description;
9118 if( description.empty() )
9119 description =
"(NO DESCRIPTION)";
9120 Catch::cout() << Column( description ).indent(4) << std::endl;
9122 if( !testCaseInfo.tags.empty() )
9123 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) <<
"\n";
9126 if( !config.hasTestFilters() )
9129 Catch::cout() <<
pluralise( matchedTestCases.size(),
"matching test case" ) <<
'\n' << std::endl;
9130 return matchedTestCases.size();
9133 std::size_t listTestsNamesOnly( Config
const& config ) {
9134 TestSpec testSpec = config.testSpec();
9135 std::size_t matchedTests = 0;
9137 for(
auto const& testCaseInfo : matchedTestCases ) {
9147 return matchedTests;
9150 void TagInfo::add( std::string
const& spelling ) {
9152 spellings.insert( spelling );
9155 std::string TagInfo::all()
const {
9157 for(
auto const& spelling : spellings )
9158 out +=
"[" + spelling +
"]";
9162 std::size_t listTags( Config
const& config ) {
9163 TestSpec testSpec = config.testSpec();
9164 if( config.hasTestFilters() )
9165 Catch::cout() <<
"Tags for matching test cases:\n";
9170 std::map<std::string, TagInfo> tagCounts;
9173 for(
auto const& testCase : matchedTestCases ) {
9174 for(
auto const& tagName : testCase.getTestCaseInfo().tags ) {
9175 std::string lcaseTagName =
toLower( tagName );
9176 auto countIt = tagCounts.find( lcaseTagName );
9177 if( countIt == tagCounts.end() )
9178 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
9179 countIt->second.add( tagName );
9183 for(
auto const& tagCount : tagCounts ) {
9185 rss <<
" " << std::setw(2) << tagCount.second.count <<
" ";
9186 auto str = rss.
str();
9187 auto wrapper = Column( tagCount.second.all() )
9189 .indent( str.size() )
9190 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
9194 return tagCounts.size();
9197 std::size_t listReporters() {
9200 std::size_t maxNameLen = 0;
9201 for(
auto const& factoryKvp : factories )
9202 maxNameLen = (
std::max)( maxNameLen, factoryKvp.first.size() );
9204 for(
auto const& factoryKvp : factories ) {
9206 << Column( factoryKvp.first +
":" )
9208 .width( 5+maxNameLen )
9209 + Column( factoryKvp.second->getDescription() )
9212 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
9216 return factories.size();
9219 Option<std::size_t> list( std::shared_ptr<Config>
const& config ) {
9220 Option<std::size_t> listedCount;
9222 if( config->listTests() )
9223 listedCount = listedCount.valueOr(0) + listTests( *config );
9224 if( config->listTestNamesOnly() )
9225 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config );
9226 if( config->listTags() )
9227 listedCount = listedCount.valueOr(0) + listTags( *config );
9228 if( config->listReporters() )
9229 listedCount = listedCount.valueOr(0) + listReporters();
9238 namespace Matchers {
9241 std::string MatcherUntypedBase::toString()
const {
9242 if( m_cachedToString.empty() )
9243 m_cachedToString = describe();
9244 return m_cachedToString;
9247 MatcherUntypedBase::~MatcherUntypedBase() =
default;
9252 using namespace Matchers;
9262 bool isnan(
float f);
9263 bool isnan(
double d);
9272 template <
typename T>
9273 std::string to_string(T
const& t) {
9274 #if defined(CATCH_CONFIG_CPP11_TO_STRING) 9275 return std::to_string(t);
9290 namespace Matchers {
9291 namespace Floating {
9292 enum class FloatingPointKind : uint8_t {
9302 template <
typename T>
9306 struct Converter<float> {
9307 static_assert(
sizeof(
float) ==
sizeof(int32_t),
"Important ULP matcher assumption violated");
9308 Converter(
float f) {
9309 std::memcpy(&i, &f,
sizeof(f));
9315 struct Converter<double> {
9316 static_assert(
sizeof(
double) ==
sizeof(int64_t),
"Important ULP matcher assumption violated");
9317 Converter(
double d) {
9318 std::memcpy(&i, &d,
sizeof(d));
9323 template <
typename T>
9324 auto convert(T t) -> Converter<T> {
9325 return Converter<T>(t);
9328 template <
typename FP>
9329 bool almostEqualUlps(FP lhs, FP rhs,
int maxUlpDiff) {
9332 if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
9339 if ((lc.i < 0) != (rc.i < 0)) {
9344 auto ulpDiff = std::abs(lc.i - rc.i);
9345 return ulpDiff <= maxUlpDiff;
9351 namespace Matchers {
9352 namespace Floating {
9353 WithinAbsMatcher::WithinAbsMatcher(
double target,
double margin)
9354 :m_target{ target }, m_margin{ margin } {
9355 CATCH_ENFORCE(margin >= 0,
"Invalid margin: " << margin <<
'.' 9356 <<
" Margin has to be non-negative.");
9361 bool WithinAbsMatcher::match(
double const& matchee)
const {
9362 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
9365 std::string WithinAbsMatcher::describe()
const {
9369 WithinUlpsMatcher::WithinUlpsMatcher(
double target,
int ulps, FloatingPointKind baseType)
9370 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
9371 CATCH_ENFORCE(ulps >= 0,
"Invalid ULP setting: " << ulps <<
'.' 9372 <<
" ULPs have to be non-negative.");
9375 #if defined(__clang__) 9376 #pragma clang diagnostic push 9378 #pragma clang diagnostic ignored "-Wunreachable-code" 9381 bool WithinUlpsMatcher::match(
double const& matchee)
const {
9383 case FloatingPointKind::Float:
9384 return almostEqualUlps<float>(
static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
9385 case FloatingPointKind::Double:
9386 return almostEqualUlps<double>(matchee, m_target, m_ulps);
9392 #if defined(__clang__) 9393 #pragma clang diagnostic pop 9396 std::string WithinUlpsMatcher::describe()
const {
9397 return "is within " + Catch::to_string(m_ulps) +
" ULPs of " +
::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)?
"f" :
"");
9422 return "matches undescribed predicate";
9424 return "matches predicate: \"" + desc +
'"';
9433 namespace Matchers {
9435 namespace StdString {
9438 : m_caseSensitivity( caseSensitivity ),
9439 m_str( adjustString( str ) )
9441 std::string CasedString::adjustString( std::string
const& str )
const {
9446 std::string CasedString::caseSensitivitySuffix()
const {
9448 ?
" (case insensitive)" 9452 StringMatcherBase::StringMatcherBase( std::string
const& operation, CasedString
const& comparator )
9453 : m_comparator( comparator ),
9454 m_operation( operation ) {
9457 std::string StringMatcherBase::describe()
const {
9458 std::string description;
9459 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
9460 m_comparator.caseSensitivitySuffix().size());
9461 description += m_operation;
9462 description +=
": \"";
9463 description += m_comparator.m_str;
9464 description +=
"\"";
9465 description += m_comparator.caseSensitivitySuffix();
9469 EqualsMatcher::EqualsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"equals", comparator ) {}
9471 bool EqualsMatcher::match( std::string
const& source )
const {
9472 return m_comparator.adjustString( source ) == m_comparator.m_str;
9475 ContainsMatcher::ContainsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"contains", comparator ) {}
9477 bool ContainsMatcher::match( std::string
const& source )
const {
9478 return contains( m_comparator.adjustString( source ), m_comparator.m_str );
9481 StartsWithMatcher::StartsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"starts with", comparator ) {}
9483 bool StartsWithMatcher::match( std::string
const& source )
const {
9484 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9487 EndsWithMatcher::EndsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"ends with", comparator ) {}
9489 bool EndsWithMatcher::match( std::string
const& source )
const {
9490 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9493 RegexMatcher::RegexMatcher(std::string regex,
CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}
9495 bool RegexMatcher::match(std::string
const& matchee)
const {
9496 auto flags = std::regex::ECMAScript;
9497 if (m_caseSensitivity == CaseSensitive::Choice::No) {
9498 flags |= std::regex::icase;
9500 auto reg = std::regex(m_regex, flags);
9501 return std::regex_match(matchee, reg);
9504 std::string RegexMatcher::describe()
const {
9505 return "matches " +
::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)?
" case sensitively" :
" case insensitively");
9535 bool uncaught_exceptions();
9547 : macroName( _macroName ),
9548 lineInfo( _lineInfo ),
9550 sequence( ++globalCount )
9569 :m_info(macroName, lineInfo, type) {}
9574 : m_info( builder.
m_info ), m_moved()
9581 : m_info( old.m_info ), m_moved()
9587 if ( !uncaught_exceptions() && !m_moved ){
9593 auto trimmed = [&] (
size_t start,
size_t end) {
9594 while (names[start] ==
',' || isspace(names[start])) {
9597 while (names[end] ==
',' || isspace(names[end])) {
9600 return names.
substr(start, end - start + 1);
9604 std::stack<char> openings;
9605 for (
size_t pos = 0; pos < names.
size(); ++pos) {
9606 char c = names[pos];
9623 if (start != pos && openings.size() == 0) {
9624 m_messages.emplace_back(macroName, lineInfo, resultType);
9625 m_messages.back().message = trimmed(start, pos);
9626 m_messages.back().message +=
" := ";
9631 assert(openings.size() == 0 &&
"Mismatched openings");
9632 m_messages.emplace_back(macroName, lineInfo, resultType);
9633 m_messages.back().message = trimmed(start, names.
size() - 1);
9634 m_messages.back().message +=
" := ";
9637 if ( !uncaught_exceptions() ){
9638 assert( m_captured == m_messages.size() );
9639 for(
size_t i = 0; i < m_captured; ++i )
9640 m_resultCapture.popScopedMessage( m_messages[i] );
9645 assert( index < m_messages.size() );
9646 m_messages[index].message +=
value;
9647 m_resultCapture.pushScopedMessage( m_messages[index] );
9656 #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 9657 #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 9665 class RedirectedStream {
9666 std::ostream& m_originalStream;
9667 std::ostream& m_redirectionStream;
9668 std::streambuf* m_prevBuf;
9671 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
9672 ~RedirectedStream();
9675 class RedirectedStdOut {
9677 RedirectedStream m_cout;
9680 auto str()
const -> std::string;
9686 class RedirectedStdErr {
9688 RedirectedStream m_cerr;
9689 RedirectedStream m_clog;
9692 auto str()
const -> std::string;
9695 class RedirectedStreams {
9697 RedirectedStreams(RedirectedStreams
const&) =
delete;
9698 RedirectedStreams& operator=(RedirectedStreams
const&) =
delete;
9699 RedirectedStreams(RedirectedStreams&&) =
delete;
9700 RedirectedStreams& operator=(RedirectedStreams&&) =
delete;
9702 RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
9703 ~RedirectedStreams();
9705 std::string& m_redirectedCout;
9706 std::string& m_redirectedCerr;
9707 RedirectedStdOut m_redirectedStdOut;
9708 RedirectedStdErr m_redirectedStdErr;
9711 #if defined(CATCH_CONFIG_NEW_CAPTURE) 9719 TempFile(TempFile
const&) =
delete;
9720 TempFile& operator=(TempFile
const&) =
delete;
9721 TempFile(TempFile&&) =
delete;
9722 TempFile& operator=(TempFile&&) =
delete;
9727 std::FILE* getFile();
9728 std::string getContents();
9731 std::FILE* m_file =
nullptr;
9732 #if defined(_MSC_VER) 9733 char m_buffer[L_tmpnam] = { 0 };
9737 class OutputRedirect {
9739 OutputRedirect(OutputRedirect
const&) =
delete;
9740 OutputRedirect& operator=(OutputRedirect
const&) =
delete;
9741 OutputRedirect(OutputRedirect&&) =
delete;
9742 OutputRedirect& operator=(OutputRedirect&&) =
delete;
9744 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
9748 int m_originalStdout = -1;
9749 int m_originalStderr = -1;
9750 TempFile m_stdoutFile;
9751 TempFile m_stderrFile;
9752 std::string& m_stdoutDest;
9753 std::string& m_stderrDest;
9760 #endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H 9766 #include <stdexcept> 9768 #if defined(CATCH_CONFIG_NEW_CAPTURE) 9769 #if defined(_MSC_VER) 9773 #define fileno _fileno 9781 RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
9782 : m_originalStream( originalStream ),
9783 m_redirectionStream( redirectionStream ),
9784 m_prevBuf( m_originalStream.rdbuf() )
9786 m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
9789 RedirectedStream::~RedirectedStream() {
9790 m_originalStream.rdbuf( m_prevBuf );
9793 RedirectedStdOut::RedirectedStdOut() : m_cout(
Catch::cout(), m_rss.get() ) {}
9794 auto RedirectedStdOut::str()
const -> std::string {
return m_rss.str(); }
9796 RedirectedStdErr::RedirectedStdErr()
9800 auto RedirectedStdErr::str()
const -> std::string {
return m_rss.str(); }
9802 RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
9803 : m_redirectedCout(redirectedCout),
9804 m_redirectedCerr(redirectedCerr)
9807 RedirectedStreams::~RedirectedStreams() {
9808 m_redirectedCout += m_redirectedStdOut.str();
9809 m_redirectedCerr += m_redirectedStdErr.str();
9812 #if defined(CATCH_CONFIG_NEW_CAPTURE) 9814 #if defined(_MSC_VER) 9815 TempFile::TempFile() {
9816 if (tmpnam_s(m_buffer)) {
9819 if (fopen_s(&m_file, m_buffer,
"w")) {
9821 if (strerror_s(buffer,
errno)) {
9824 CATCH_RUNTIME_ERROR(
"Coul dnot open the temp file: '" << m_buffer <<
"' because: " << buffer);
9828 TempFile::TempFile() {
9829 m_file = std::tmpfile();
9837 TempFile::~TempFile() {
9839 std::fclose(m_file);
9842 #if defined(_MSC_VER) 9843 std::remove(m_buffer);
9847 FILE* TempFile::getFile() {
9851 std::string TempFile::getContents() {
9852 std::stringstream sstr;
9853 char buffer[100] = {};
9854 std::rewind(m_file);
9855 while (std::fgets(buffer,
sizeof(buffer), m_file)) {
9861 OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
9862 m_originalStdout(dup(1)),
9863 m_originalStderr(dup(2)),
9864 m_stdoutDest(stdout_dest),
9865 m_stderrDest(stderr_dest) {
9866 dup2(fileno(m_stdoutFile.getFile()), 1);
9867 dup2(fileno(m_stderrFile.getFile()), 2);
9870 OutputRedirect::~OutputRedirect() {
9879 dup2(m_originalStdout, 1);
9880 dup2(m_originalStderr, 2);
9882 m_stdoutDest += m_stdoutFile.getContents();
9883 m_stderrDest += m_stderrFile.getContents();
9886 #endif // CATCH_CONFIG_NEW_CAPTURE 9890 #if defined(CATCH_CONFIG_NEW_CAPTURE) 9891 #if defined(_MSC_VER) 9904 #if !defined(CATCH_CONFIG_POLYFILL_ISNAN) 9905 bool isnan(
float f) {
9906 return std::isnan(f);
9908 bool isnan(
double d) {
9909 return std::isnan(d);
9913 bool isnan(
float f) {
9914 return std::_isnan(f);
9916 bool isnan(
double d) {
9917 return std::_isnan(d);
9927 std::mt19937& rng() {
9928 static std::mt19937 s_rng;
9934 std::srand( config.
rngSeed() );
9935 rng().seed( config.
rngSeed() );
9950 #include <algorithm> 9958 std::vector<TestCase> sortTests(
IConfig const&
config, std::vector<TestCase>
const& unsortedTestCases );
9961 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions );
9963 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec,
IConfig const& config );
9968 virtual ~TestRegistry() =
default;
9970 virtual void registerTest(
TestCase const& testCase );
9972 std::vector<TestCase>
const& getAllTests()
const override;
9973 std::vector<TestCase>
const& getAllTestsSorted(
IConfig const& config )
const override;
9976 std::vector<TestCase> m_functions;
9978 mutable std::vector<TestCase> m_sortedFunctions;
9979 std::size_t m_unnamedCount = 0;
9980 std::ios_base::Init m_ostreamInit;
9986 void(*m_testAsFunction)();
9988 TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept;
9990 void invoke()
const override;
9993 std::string extractClassName(
StringRef const& classOrQualifiedMethodName );
10006 class ReporterRegistry :
public IReporterRegistry {
10010 ~ReporterRegistry()
override;
10012 IStreamingReporterPtr create( std::string
const&
name,
IConfigPtr const&
config )
const override;
10017 FactoryMap const& getFactories()
const override;
10018 Listeners
const& getListeners()
const override;
10022 Listeners m_listeners;
10049 class TagAliasRegistry :
public ITagAliasRegistry {
10051 ~TagAliasRegistry()
override;
10052 TagAlias
const* find( std::string
const& alias )
const override;
10053 std::string expandAliases( std::string
const& unexpandedTestSpec )
const override;
10054 void add( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo );
10057 std::map<std::string, TagAlias> m_registry;
10066 #include <exception> 10070 class StartupExceptionRegistry {
10072 void add(std::exception_ptr
const& exception) noexcept;
10073 std::vector<std::exception_ptr>
const& getExceptions()
const noexcept;
10075 std::vector<std::exception_ptr> m_exceptions;
10085 struct ISingleton {
10086 virtual ~ISingleton();
10089 void addSingleton( ISingleton* singleton );
10090 void cleanupSingletons();
10092 template<
typename SingletonImplT,
typename InterfaceT = SingletonImplT,
typename MutableInterfaceT = InterfaceT>
10093 class Singleton : SingletonImplT,
public ISingleton {
10095 static auto getInternal() -> Singleton* {
10096 static Singleton* s_instance =
nullptr;
10097 if( !s_instance ) {
10098 s_instance =
new Singleton;
10099 addSingleton( s_instance );
10105 static auto get() -> InterfaceT
const& {
10106 return *getInternal();
10108 static auto getMutable() -> MutableInterfaceT& {
10109 return *getInternal();
10124 RegistryHub() =
default;
10125 IReporterRegistry
const& getReporterRegistry()
const override {
10126 return m_reporterRegistry;
10129 return m_testCaseRegistry;
10132 return m_exceptionTranslatorRegistry;
10134 ITagAliasRegistry
const& getTagAliasRegistry()
const override {
10135 return m_tagAliasRegistry;
10137 StartupExceptionRegistry
const& getStartupExceptionRegistry()
const override {
10138 return m_exceptionRegistry;
10143 m_reporterRegistry.registerReporter( name, factory );
10146 m_reporterRegistry.registerListener( factory );
10148 void registerTest(
TestCase const& testInfo )
override {
10149 m_testCaseRegistry.registerTest( testInfo );
10152 m_exceptionTranslatorRegistry.registerTranslator( translator );
10154 void registerTagAlias( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo )
override {
10155 m_tagAliasRegistry.add( alias, tag, lineInfo );
10157 void registerStartupException() noexcept
override {
10158 m_exceptionRegistry.add(std::current_exception());
10162 TestRegistry m_testCaseRegistry;
10163 ReporterRegistry m_reporterRegistry;
10164 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
10165 TagAliasRegistry m_tagAliasRegistry;
10166 StartupExceptionRegistry m_exceptionRegistry;
10170 using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
10173 return RegistryHubSingleton::get();
10176 return RegistryHubSingleton::getMutable();
10179 cleanupSingletons();
10192 ReporterRegistry::~ReporterRegistry() =
default;
10194 IStreamingReporterPtr ReporterRegistry::create( std::string
const&
name,
IConfigPtr const&
config )
const {
10195 auto it = m_factories.find( name );
10196 if( it == m_factories.end() )
10198 return it->second->create( ReporterConfig( config ) );
10201 void ReporterRegistry::registerReporter( std::string
const& name,
IReporterFactoryPtr const& factory ) {
10202 m_factories.emplace(name, factory);
10205 m_listeners.push_back( factory );
10208 IReporterRegistry::FactoryMap
const& ReporterRegistry::getFactories()
const {
10209 return m_factories;
10211 IReporterRegistry::Listeners
const& ReporterRegistry::getListeners()
const {
10212 return m_listeners;
10240 #include <algorithm> 10245 namespace Generators {
10249 GeneratorTracker( TestCaseTracking::NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
10250 : TrackerBase( nameAndLocation, ctx, parent )
10252 ~GeneratorTracker();
10254 static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation
const& nameAndLocation ) {
10255 std::shared_ptr<GeneratorTracker> tracker;
10257 ITracker& currentTracker = ctx.currentTracker();
10258 if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
10259 assert( childTracker );
10260 assert( childTracker->isGeneratorTracker() );
10261 tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
10264 tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker );
10265 currentTracker.addChild( tracker );
10268 if( !ctx.completedCycle() && !tracker->isComplete() ) {
10276 bool isGeneratorTracker()
const override {
return true; }
10277 auto hasGenerator()
const ->
bool override {
10278 return !!m_generator;
10280 void close()
override {
10283 if (m_runState == CompletedSuccessfully && m_generator->next()) {
10284 m_children.clear();
10285 m_runState = Executing;
10291 return m_generator;
10294 m_generator = std::move( generator );
10297 GeneratorTracker::~GeneratorTracker() {}
10300 RunContext::RunContext(
IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
10301 : m_runInfo(_config->name()),
10304 m_reporter(std::move(reporter)),
10306 m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
10308 m_context.setRunner(
this);
10309 m_context.setConfig(m_config);
10310 m_context.setResultCapture(
this);
10311 m_reporter->testRunStarting(m_runInfo);
10314 RunContext::~RunContext() {
10315 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
10318 void RunContext::testGroupStarting(std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
10319 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
10322 void RunContext::testGroupEnded(std::string
const& testSpec,
Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {
10323 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
10327 Totals prevTotals = m_totals;
10329 std::string redirectedCout;
10330 std::string redirectedCerr;
10334 m_reporter->testCaseStarting(testInfo);
10336 m_activeTestCase = &testCase;
10338 ITracker& rootTracker = m_trackerContext.startRun();
10339 assert(rootTracker.isSectionTracker());
10340 static_cast<SectionTracker&
>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
10342 m_trackerContext.startCycle();
10343 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
10344 runCurrentTest(redirectedCout, redirectedCerr);
10345 }
while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
10353 m_totals.testCases += deltaTotals.
testCases;
10354 m_reporter->testCaseEnded(TestCaseStats(testInfo,
10360 m_activeTestCase =
nullptr;
10361 m_testCaseTracker =
nullptr;
10363 return deltaTotals;
10370 IStreamingReporter& RunContext::reporter()
const {
10371 return *m_reporter;
10374 void RunContext::assertionEnded(AssertionResult
const & result) {
10376 m_totals.assertions.passed++;
10377 m_lastAssertionPassed =
true;
10378 }
else if (!result.isOk()) {
10379 m_lastAssertionPassed =
false;
10380 if( m_activeTestCase->getTestCaseInfo().okToFail() )
10381 m_totals.assertions.failedButOk++;
10383 m_totals.assertions.failed++;
10386 m_lastAssertionPassed =
true;
10391 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
10394 m_messageScopes.clear();
10397 resetAssertionInfo();
10398 m_lastResult = result;
10400 void RunContext::resetAssertionInfo() {
10401 m_lastAssertionInfo.macroName =
StringRef();
10402 m_lastAssertionInfo.capturedExpression =
"{Unknown expression after the reported line}"_sr;
10405 bool RunContext::sectionStarted(
SectionInfo const & sectionInfo,
Counts & assertions) {
10406 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.
name, sectionInfo.
lineInfo));
10407 if (!sectionTracker.isOpen())
10409 m_activeSections.push_back(§ionTracker);
10411 m_lastAssertionInfo.lineInfo = sectionInfo.
lineInfo;
10413 m_reporter->sectionStarting(sectionInfo);
10415 assertions = m_totals.assertions;
10420 using namespace Generators;
10421 GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation(
"generator", lineInfo ) );
10422 assert( tracker.isOpen() );
10423 m_lastAssertionInfo.lineInfo = lineInfo;
10427 bool RunContext::testForMissingAssertions(
Counts& assertions) {
10428 if (assertions.
total() != 0)
10430 if (!m_config->warnAboutMissingAssertions())
10432 if (m_trackerContext.currentTracker().hasChildren())
10434 m_totals.assertions.failed++;
10441 bool missingAssertions = testForMissingAssertions(assertions);
10443 if (!m_activeSections.empty()) {
10444 m_activeSections.back()->close();
10445 m_activeSections.pop_back();
10449 m_messages.clear();
10450 m_messageScopes.clear();
10453 void RunContext::sectionEndedEarly(
SectionEndInfo const & endInfo) {
10454 if (m_unfinishedSections.empty())
10455 m_activeSections.back()->fail();
10457 m_activeSections.back()->close();
10458 m_activeSections.pop_back();
10460 m_unfinishedSections.push_back(endInfo);
10462 void RunContext::benchmarkStarting( BenchmarkInfo
const& info ) {
10463 m_reporter->benchmarkStarting( info );
10465 void RunContext::benchmarkEnded( BenchmarkStats
const& stats ) {
10466 m_reporter->benchmarkEnded( stats );
10469 void RunContext::pushScopedMessage(
MessageInfo const & message) {
10470 m_messages.push_back(message);
10473 void RunContext::popScopedMessage(
MessageInfo const & message) {
10474 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
10477 void RunContext::emplaceUnscopedMessage(
MessageBuilder const& builder ) {
10478 m_messageScopes.emplace_back( builder );
10481 std::string RunContext::getCurrentTestName()
const {
10482 return m_activeTestCase
10483 ? m_activeTestCase->getTestCaseInfo().name
10487 const AssertionResult * RunContext::getLastResult()
const {
10488 return &(*m_lastResult);
10491 void RunContext::exceptionEarlyReported() {
10492 m_shouldReportUnexpected =
false;
10495 void RunContext::handleFatalErrorCondition(
StringRef message ) {
10497 m_reporter->fatalErrorEncountered(message);
10502 tempResult.message = message;
10503 AssertionResult result(m_lastAssertionInfo, tempResult);
10505 assertionEnded(result);
10507 handleUnfinishedSections();
10510 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
10511 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
10515 SectionStats testCaseSectionStats(testCaseSection, assertions, 0,
false);
10516 m_reporter->sectionEnded(testCaseSectionStats);
10518 auto const& testInfo = m_activeTestCase->getTestCaseInfo();
10523 m_reporter->testCaseEnded(TestCaseStats(testInfo,
10528 m_totals.testCases.failed++;
10529 testGroupEnded(std::string(), m_totals, 1, 1);
10530 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals,
false));
10533 bool RunContext::lastAssertionPassed() {
10534 return m_lastAssertionPassed;
10537 void RunContext::assertionPassed() {
10538 m_lastAssertionPassed =
true;
10539 ++m_totals.assertions.passed;
10540 resetAssertionInfo();
10541 m_messageScopes.clear();
10544 bool RunContext::aborting()
const {
10545 return m_totals.assertions.failed >=
static_cast<std::size_t
>(m_config->abortAfter());
10548 void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
10549 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
10550 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
10551 m_reporter->sectionStarting(testCaseSection);
10552 Counts prevAssertions = m_totals.assertions;
10553 double duration = 0;
10554 m_shouldReportUnexpected =
true;
10557 seedRng(*m_config);
10561 if (m_reporter->getPreferences().shouldRedirectStdOut) {
10562 #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) 10563 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
10566 invokeActiveTestCase();
10568 OutputRedirect r(redirectedCout, redirectedCerr);
10570 invokeActiveTestCase();
10574 invokeActiveTestCase();
10582 if( m_shouldReportUnexpected ) {
10587 Counts assertions = m_totals.assertions - prevAssertions;
10588 bool missingAssertions = testForMissingAssertions(assertions);
10590 m_testCaseTracker->close();
10591 handleUnfinishedSections();
10592 m_messages.clear();
10593 m_messageScopes.clear();
10595 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
10596 m_reporter->sectionEnded(testCaseSectionStats);
10599 void RunContext::invokeActiveTestCase() {
10600 FatalConditionHandler fatalConditionHandler;
10601 m_activeTestCase->invoke();
10602 fatalConditionHandler.reset();
10605 void RunContext::handleUnfinishedSections() {
10608 for (
auto it = m_unfinishedSections.rbegin(),
10609 itEnd = m_unfinishedSections.rend();
10613 m_unfinishedSections.clear();
10616 void RunContext::handleExpr(
10621 m_reporter->assertionStarting( info );
10624 bool result = expr.
getResult() != negated;
10627 if (!m_includeSuccessfulResults) {
10636 populateReaction( reaction );
10639 void RunContext::reportExpr(
10645 m_lastAssertionInfo = info;
10648 AssertionResult assertionResult{ info, data };
10649 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
10651 assertionEnded( assertionResult );
10654 void RunContext::handleMessage(
10660 m_reporter->assertionStarting( info );
10662 m_lastAssertionInfo = info;
10665 data.message = message;
10666 AssertionResult assertionResult{ m_lastAssertionInfo, data };
10667 assertionEnded( assertionResult );
10668 if( !assertionResult.isOk() )
10669 populateReaction( reaction );
10671 void RunContext::handleUnexpectedExceptionNotThrown(
10678 void RunContext::handleUnexpectedInflightException(
10680 std::string
const& message,
10683 m_lastAssertionInfo = info;
10686 data.message = message;
10687 AssertionResult assertionResult{ info, data };
10688 assertionEnded( assertionResult );
10689 populateReaction( reaction );
10697 void RunContext::handleIncomplete(
10700 m_lastAssertionInfo = info;
10703 data.message =
"Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
10704 AssertionResult assertionResult{ info, data };
10705 assertionEnded( assertionResult );
10707 void RunContext::handleNonExpr(
10712 m_lastAssertionInfo = info;
10715 AssertionResult assertionResult{ info, data };
10716 assertionEnded( assertionResult );
10718 if( !assertionResult.isOk() )
10719 populateReaction( reaction );
10736 m_sectionIncluded(
getResultCapture().sectionStarted( m_info, m_assertions ) )
10742 if( m_sectionIncluded ) {
10743 SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
10744 if( uncaught_exceptions() )
10752 Section::operator
bool()
const {
10753 return m_sectionIncluded;
10764 std::string
const& _name )
10766 lineInfo( _lineInfo )
10783 ~Session()
override;
10785 void showHelp()
const;
10786 void libIdentify();
10788 int applyCommandLine(
int argc,
char const *
const * argv );
10789 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) 10790 int applyCommandLine(
int argc,
wchar_t const *
const * argv );
10793 void useConfigData( ConfigData
const& configData );
10795 template<
typename CharT>
10796 int run(
int argc, CharT
const *
const argv[]) {
10797 if (m_startupExceptions)
10799 int returnCode = applyCommandLine(argc, argv);
10800 if (returnCode == 0)
10801 returnCode =
run();
10807 clara::Parser
const& cli()
const;
10808 void cli( clara::Parser
const& newParser );
10809 ConfigData& configData();
10814 clara::Parser m_cli;
10815 ConfigData m_configData;
10816 std::shared_ptr<Config> m_config;
10817 bool m_startupExceptions =
false;
10831 Version( Version
const& ) =
delete;
10832 Version& operator=( Version
const& ) =
delete;
10833 Version(
unsigned int _majorVersion,
10834 unsigned int _minorVersion,
10835 unsigned int _patchNumber,
10836 char const *
const _branchName,
10837 unsigned int _buildNumber );
10839 unsigned int const majorVersion;
10840 unsigned int const minorVersion;
10841 unsigned int const patchNumber;
10844 char const *
const branchName;
10845 unsigned int const buildNumber;
10847 friend std::ostream&
operator << ( std::ostream& os, Version
const& version );
10850 Version
const& libraryVersion();
10860 const int MaxExitCode = 255;
10862 IStreamingReporterPtr createReporter(std::string
const& reporterName,
IConfigPtr const&
config) {
10864 CATCH_ENFORCE(reporter,
"No reporter registered with name: '" << reporterName <<
"'");
10869 IStreamingReporterPtr makeReporter(std::shared_ptr<Config>
const& config) {
10871 return createReporter(config->getReporterName(),
config);
10879 auto ret = std::unique_ptr<IStreamingReporter>(
new ListeningReporter);
10880 auto& multi =
static_cast<ListeningReporter&
>(*ret);
10882 for (
auto const& listener : listeners) {
10883 multi.addListener(listener->create(Catch::ReporterConfig(config)));
10885 multi.addReporter(createReporter(config->getReporterName(),
config));
10889 Catch::Totals runTests(std::shared_ptr<Config>
const& config) {
10890 auto reporter = makeReporter(config);
10892 RunContext context(config, std::move(reporter));
10896 context.testGroupStarting(config->name(), 1, 1);
10898 TestSpec testSpec = config->testSpec();
10901 for (
auto const& testCase : allTestCases) {
10902 if (!context.aborting() &&
matchTest(testCase, testSpec, *config))
10903 totals += context.runTest(testCase);
10905 context.reporter().skipTest(testCase);
10908 if (config->warnAboutNoTests() && totals.
testCases.
total() == 0) {
10912 for (
const auto& input : config->getTestsOrTags()) {
10913 if (!first) { testConfig <<
' '; }
10915 testConfig << input;
10918 context.reporter().noMatchingTestCases(testConfig.
str());
10922 context.testGroupEnded(config->name(), totals, 1, 1);
10928 for (
auto& testCase : tests) {
10929 auto tags = testCase.tags;
10931 std::string
filename = testCase.lineInfo.file;
10932 auto lastSlash = filename.find_last_of(
"\\/");
10933 if (lastSlash != std::string::npos) {
10934 filename.erase(0, lastSlash);
10938 auto lastDot = filename.find_last_of(
'.');
10939 if (lastDot != std::string::npos) {
10940 filename.erase(lastDot);
10943 tags.push_back(std::move(filename));
10944 setTags(testCase, tags);
10950 Session::Session() {
10951 static bool alreadyInstantiated =
false;
10952 if( alreadyInstantiated ) {
10958 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 10960 if ( !exceptions.empty() ) {
10961 m_startupExceptions =
true;
10962 Colour colourGuard( Colour::Red );
10963 Catch::cerr() <<
"Errors occurred during startup!" <<
'\n';
10965 for (
const auto& ex_ptr : exceptions ) {
10967 std::rethrow_exception(ex_ptr);
10968 }
catch ( std::exception
const& ex ) {
10969 Catch::cerr() << Column( ex.what() ).indent(2) <<
'\n';
10975 alreadyInstantiated =
true;
10976 m_cli = makeCommandLineParser( m_configData );
10978 Session::~Session() {
10982 void Session::showHelp()
const {
10984 <<
"\nCatch v" << libraryVersion() <<
"\n" 10985 << m_cli << std::endl
10986 <<
"For more detailed usage please see the project docs\n" << std::endl;
10988 void Session::libIdentify() {
10990 << std::left << std::setw(16) <<
"description: " <<
"A Catch test executable\n" 10991 << std::left << std::setw(16) <<
"category: " <<
"testframework\n" 10992 << std::left << std::setw(16) <<
"framework: " <<
"Catch Test\n" 10993 << std::left << std::setw(16) <<
"version: " << libraryVersion() << std::endl;
10996 int Session::applyCommandLine(
int argc,
char const *
const * argv ) {
10997 if( m_startupExceptions )
11000 auto result = m_cli.parse( clara::Args( argc, argv ) );
11005 << Colour( Colour::Red )
11006 <<
"\nError(s) in input:\n" 11007 << Column( result.errorMessage() ).indent( 2 )
11009 Catch::cerr() <<
"Run with -? for usage\n" << std::endl;
11010 return MaxExitCode;
11013 if( m_configData.showHelp )
11015 if( m_configData.libIdentify )
11021 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) 11022 int Session::applyCommandLine(
int argc,
wchar_t const *
const * argv ) {
11024 char **utf8Argv =
new char *[ argc ];
11026 for (
int i = 0; i < argc; ++i ) {
11027 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1,
NULL, 0,
NULL,
NULL );
11029 utf8Argv[ i ] =
new char[ bufSize ];
11031 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize,
NULL,
NULL );
11034 int returnCode = applyCommandLine( argc, utf8Argv );
11036 for (
int i = 0; i < argc; ++i )
11037 delete [] utf8Argv[ i ];
11039 delete [] utf8Argv;
11045 void Session::useConfigData( ConfigData
const& configData ) {
11046 m_configData = configData;
11050 int Session::run() {
11052 Catch::cout() <<
"...waiting for enter/ return before starting" << std::endl;
11053 static_cast<void>(std::getchar());
11055 int exitCode = runInternal();
11057 Catch::cout() <<
"...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
11058 static_cast<void>(std::getchar());
11063 clara::Parser
const& Session::cli()
const {
11066 void Session::cli( clara::Parser
const& newParser ) {
11069 ConfigData& Session::configData() {
11070 return m_configData;
11074 m_config = std::make_shared<Config>( m_configData );
11078 int Session::runInternal() {
11079 if( m_startupExceptions )
11082 if (m_configData.showHelp || m_configData.libIdentify) {
11089 seedRng( *m_config );
11091 if( m_configData.filenamesAsTags )
11092 applyFilenamesAsTags( *m_config );
11095 if( Option<std::size_t> listed = list( m_config ) )
11096 return static_cast<int>( *listed );
11098 auto totals = runTests( m_config );
11102 return (std::min) (MaxExitCode, (
std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
11104 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) 11105 catch( std::exception& ex ) {
11107 return MaxExitCode;
11121 static auto getSingletons() -> std::vector<ISingleton*>*& {
11122 static std::vector<ISingleton*>* g_singletons =
nullptr;
11123 if( !g_singletons )
11124 g_singletons =
new std::vector<ISingleton*>();
11125 return g_singletons;
11129 ISingleton::~ISingleton() {}
11131 void addSingleton(ISingleton* singleton ) {
11132 getSingletons()->push_back( singleton );
11134 void cleanupSingletons() {
11135 auto& singletons = getSingletons();
11136 for(
auto singleton : *singletons )
11139 singletons =
nullptr;
11147 void StartupExceptionRegistry::add( std::exception_ptr
const& exception ) noexcept {
11149 m_exceptions.push_back(exception);
11156 std::vector<std::exception_ptr>
const& StartupExceptionRegistry::getExceptions()
const noexcept {
11157 return m_exceptions;
11165 #include <iostream> 11175 namespace detail {
namespace {
11176 template<
typename WriterF, std::
size_t bufferSize=256>
11177 class StreamBufImpl :
public std::streambuf {
11178 char data[bufferSize];
11183 setp( data, data +
sizeof(data) );
11186 ~StreamBufImpl() noexcept {
11191 int overflow(
int c )
override {
11195 if( pbase() == epptr() )
11196 m_writer( std::string( 1, static_cast<char>( c ) ) );
11198 sputc( static_cast<char>( c ) );
11203 int sync()
override {
11204 if( pbase() != pptr() ) {
11205 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
11206 setp( pbase(), epptr() );
11214 struct OutputDebugWriter {
11216 void operator()( std::string
const&str ) {
11217 writeToDebugConsole( str );
11223 class FileStream :
public IStream {
11224 mutable std::ofstream m_ofs;
11227 m_ofs.open( filename.
c_str() );
11228 CATCH_ENFORCE( !m_ofs.fail(),
"Unable to open file: '" << filename <<
"'" );
11230 ~FileStream()
override =
default;
11232 std::ostream& stream()
const override {
11239 class CoutStream :
public IStream {
11240 mutable std::ostream m_os;
11245 ~CoutStream()
override =
default;
11248 std::ostream& stream()
const override {
return m_os; }
11253 class DebugOutStream :
public IStream {
11254 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
11255 mutable std::ostream m_os;
11258 : m_streamBuf(
new StreamBufImpl<OutputDebugWriter>() ),
11259 m_os( m_streamBuf.get() )
11262 ~DebugOutStream()
override =
default;
11265 std::ostream& stream()
const override {
return m_os; }
11273 if( filename.
empty() )
11274 return new detail::CoutStream();
11275 else if( filename[0] ==
'%' ) {
11276 if( filename ==
"%debug" )
11277 return new detail::DebugOutStream();
11279 CATCH_ERROR(
"Unrecognised stream: '" << filename <<
"'" );
11282 return new detail::FileStream( filename );
11286 struct StringStreams {
11287 std::vector<std::unique_ptr<std::ostringstream>> m_streams;
11288 std::vector<std::size_t> m_unused;
11289 std::ostringstream m_referenceStream;
11291 auto add() -> std::size_t {
11292 if( m_unused.empty() ) {
11293 m_streams.push_back( std::unique_ptr<std::ostringstream>(
new std::ostringstream ) );
11294 return m_streams.size()-1;
11297 auto index = m_unused.back();
11298 m_unused.pop_back();
11303 void release( std::size_t index ) {
11304 m_streams[index]->copyfmt( m_referenceStream );
11305 m_unused.push_back(index);
11310 : m_index( Singleton<StringStreams>::getMutable().
add() ),
11311 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].
get() )
11315 static_cast<std::ostringstream*
>( m_oss )->str(
"");
11317 Singleton<StringStreams>::getMutable().release( m_index );
11321 return static_cast<std::ostringstream*
>( m_oss )->str();
11326 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions 11335 #include <algorithm> 11343 char toLowerCh(
char c) {
11344 return static_cast<char>( std::tolower( c ) );
11348 bool startsWith( std::string
const&
s, std::string
const& prefix ) {
11349 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
11351 bool startsWith( std::string
const& s,
char prefix ) {
11352 return !s.empty() && s[0] == prefix;
11354 bool endsWith( std::string
const& s, std::string
const& suffix ) {
11355 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
11357 bool endsWith( std::string
const& s,
char suffix ) {
11358 return !s.empty() && s[s.size()-1] == suffix;
11360 bool contains( std::string
const& s, std::string
const& infix ) {
11361 return s.find( infix ) != std::string::npos;
11364 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
11366 std::string
toLower( std::string
const& s ) {
11367 std::string lc = s;
11371 std::string
trim( std::string
const& str ) {
11372 static char const* whitespaceChars =
"\n\r\t ";
11373 std::string::size_type
start = str.find_first_not_of( whitespaceChars );
11374 std::string::size_type end = str.find_last_not_of( whitespaceChars );
11376 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
11379 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis ) {
11380 bool replaced =
false;
11381 std::size_t i = str.find( replaceThis );
11382 while( i != std::string::npos ) {
11384 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
11385 if( i < str.size()-withThis.size() )
11386 i = str.find( replaceThis, i+withThis.size() );
11388 i = std::string::npos;
11394 : m_count( count ),
11400 if( pluraliser.
m_count != 1 )
11409 #if defined(__clang__) 11410 # pragma clang diagnostic push 11411 # pragma clang diagnostic ignored "-Wexit-time-destructors" 11419 const uint32_t byte_2_lead = 0xC0;
11420 const uint32_t byte_3_lead = 0xE0;
11421 const uint32_t byte_4_lead = 0xF0;
11426 :
StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
11429 StringRef::operator std::string()
const {
11430 return std::string( m_start, m_size );
11434 std::swap( m_start, other.
m_start );
11435 std::swap( m_size, other.
m_size );
11436 std::swap( m_data, other.
m_data );
11440 if( isSubstring() )
11441 const_cast<StringRef*
>( this )->takeOwnership();
11449 return m_data !=
nullptr;
11452 return m_start[m_size] !=
'\0';
11457 m_data =
new char[m_size+1];
11458 memcpy( m_data, m_start, m_size );
11459 m_data[m_size] =
'\0';
11464 if( start < m_size )
11465 return StringRef( m_start+start, size );
11471 size() == other.
size() &&
11472 (std::strncmp( m_start, other.
m_start, size() ) == 0);
11479 return m_start[index];
11483 size_type noChars = m_size;
11485 for( size_type i=0; i < m_size; ++i ) {
11486 char c = m_start[i];
11487 if( ( c & byte_2_lead ) == byte_2_lead ) {
11489 if (( c & byte_3_lead ) == byte_3_lead )
11491 if( ( c & byte_4_lead ) == byte_4_lead )
11500 str.reserve( lhs.
size() + rhs.
size() );
11506 return std::string( lhs ) + std::string( rhs );
11509 return std::string( lhs ) + std::string( rhs );
11523 #if defined(__clang__) 11524 # pragma clang diagnostic pop 11530 TagAlias::TagAlias(std::string
const & _tag,
SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
11554 TagAliasRegistry::~TagAliasRegistry() {}
11556 TagAlias
const* TagAliasRegistry::find( std::string
const& alias )
const {
11557 auto it = m_registry.find( alias );
11558 if( it != m_registry.end() )
11559 return &(it->second);
11564 std::string TagAliasRegistry::expandAliases( std::string
const& unexpandedTestSpec )
const {
11565 std::string expandedTestSpec = unexpandedTestSpec;
11566 for(
auto const& registryKvp : m_registry ) {
11567 std::size_t pos = expandedTestSpec.find( registryKvp.first );
11568 if( pos != std::string::npos ) {
11569 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
11570 registryKvp.second.tag +
11571 expandedTestSpec.substr( pos + registryKvp.first.size() );
11574 return expandedTestSpec;
11577 void TagAliasRegistry::add( std::string
const& alias, std::string
const& tag,
SourceLineInfo const& lineInfo ) {
11579 "error: tag alias, '" << alias <<
"' is not of the form [@alias name].\n" << lineInfo );
11581 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
11582 "error: tag alias, '" << alias <<
"' already registered.\n" 11583 <<
"\tFirst seen at: " << find(alias)->lineInfo <<
"\n" 11584 <<
"\tRedefined at: " << lineInfo );
11587 ITagAliasRegistry::~ITagAliasRegistry() {}
11589 ITagAliasRegistry
const& ITagAliasRegistry::get() {
11598 #include <exception> 11599 #include <algorithm> 11609 else if( tag ==
"!throws" )
11611 else if( tag ==
"!shouldfail" )
11613 else if( tag ==
"!mayfail" )
11615 else if( tag ==
"!nonportable" )
11617 else if( tag ==
"!benchmark" )
11622 bool isReservedTag( std::string
const& tag ) {
11623 return parseSpecialTag( tag ) ==
TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
11625 void enforceNotReservedTag( std::string
const& tag,
SourceLineInfo const& _lineInfo ) {
11627 "Tag name: [" << tag <<
"] is not allowed.\n" 11628 <<
"Tag names starting with non alpha-numeric characters are reserved\n" 11634 std::string
const& _className,
11638 bool isHidden =
false;
11641 std::vector<std::string> tags;
11642 std::string desc, tag;
11643 bool inTag =
false;
11644 std::string _descOrTags = nameAndTags.
tags;
11645 for (
char c : _descOrTags) {
11658 enforceNotReservedTag( tag, _lineInfo );
11660 tags.push_back( tag );
11669 tags.push_back(
"." );
11673 return TestCase( _testCase, std::move(info) );
11676 void setTags(
TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
11677 std::sort(
begin(tags),
end(tags));
11678 tags.erase(std::unique(
begin(tags),
end(tags)),
end(tags));
11681 for(
auto const& tag : tags ) {
11682 std::string lcaseTag =
toLower( tag );
11684 testCaseInfo.
lcaseTags.push_back( lcaseTag );
11686 testCaseInfo.
tags = std::move(tags);
11690 std::string
const& _className,
11691 std::string
const& _description,
11692 std::vector<std::string>
const& _tags,
11695 className( _className ),
11696 description( _description ),
11697 lineInfo( _lineInfo ),
11700 setTags( *
this, _tags );
11704 return ( properties & IsHidden ) != 0;
11707 return ( properties & Throws ) != 0;
11710 return ( properties & (ShouldFail | MayFail ) ) != 0;
11713 return ( properties & (ShouldFail ) ) != 0;
11719 std::size_t full_size = 2 * tags.size();
11720 for (
const auto& tag : tags) {
11721 full_size += tag.size();
11723 ret.reserve(full_size);
11724 for (
const auto& tag : tags) {
11725 ret.push_back(
'[');
11727 ret.push_back(
']');
11737 other.
name = _newName;
11746 return test.get() == other.
test.get() &&
11768 std::vector<TestCase> sortTests(
IConfig const&
config, std::vector<TestCase>
const& unsortedTestCases ) {
11770 std::vector<TestCase> sorted = unsortedTestCases;
11774 std::sort( sorted.begin(), sorted.end() );
11778 std::shuffle( sorted.begin(), sorted.end(), rng() );
11787 return testSpec.matches( testCase ) && ( config.
allowThrows() || !testCase.
throws() );
11790 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions ) {
11791 std::set<TestCase> seenFunctions;
11792 for(
auto const&
function : functions ) {
11793 auto prev = seenFunctions.insert(
function );
11795 "error: TEST_CASE( \"" <<
function.name <<
"\" ) already defined.\n" 11796 <<
"\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo <<
"\n" 11797 <<
"\tRedefined at " <<
function.getTestCaseInfo().lineInfo );
11801 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec,
IConfig const& config ) {
11802 std::vector<TestCase> filtered;
11803 filtered.reserve( testCases.size() );
11804 for(
auto const& testCase : testCases )
11805 if(
matchTest( testCase, testSpec, config ) )
11806 filtered.push_back( testCase );
11813 void TestRegistry::registerTest(
TestCase const& testCase ) {
11815 if( name.empty() ) {
11817 rss <<
"Anonymous test case " << ++m_unnamedCount;
11818 return registerTest( testCase.
withName( rss.
str() ) );
11820 m_functions.push_back( testCase );
11823 std::vector<TestCase>
const& TestRegistry::getAllTests()
const {
11824 return m_functions;
11826 std::vector<TestCase>
const& TestRegistry::getAllTestsSorted(
IConfig const& config )
const {
11827 if( m_sortedFunctions.empty() )
11828 enforceNoDuplicateTestCases( m_functions );
11830 if( m_currentSortOrder != config.
runOrder() || m_sortedFunctions.empty() ) {
11831 m_sortedFunctions = sortTests( config, m_functions );
11832 m_currentSortOrder = config.
runOrder();
11834 return m_sortedFunctions;
11838 TestInvokerAsFunction::TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
11840 void TestInvokerAsFunction::invoke()
const {
11841 m_testAsFunction();
11844 std::string extractClassName(
StringRef const& classOrQualifiedMethodName ) {
11845 std::string className = classOrQualifiedMethodName;
11848 std::size_t lastColons = className.rfind(
"::" );
11849 std::size_t penultimateColons = className.rfind(
"::", lastColons-1 );
11850 if( penultimateColons == std::string::npos )
11851 penultimateColons = 1;
11852 className = className.
substr( penultimateColons, lastColons-penultimateColons );
11861 #include <algorithm> 11863 #include <stdexcept> 11867 #if defined(__clang__) 11868 # pragma clang diagnostic push 11869 # pragma clang diagnostic ignored "-Wexit-time-destructors" 11873 namespace TestCaseTracking {
11875 NameAndLocation::NameAndLocation( std::string
const& _name,
SourceLineInfo const& _location )
11877 location( _location )
11880 ITracker::~ITracker() =
default;
11882 TrackerContext& TrackerContext::instance() {
11883 static TrackerContext s_instance;
11887 ITracker& TrackerContext::startRun() {
11888 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation(
"{root}",
CATCH_INTERNAL_LINEINFO ), *
this, nullptr );
11889 m_currentTracker =
nullptr;
11890 m_runState = Executing;
11891 return *m_rootTracker;
11894 void TrackerContext::endRun() {
11895 m_rootTracker.reset();
11896 m_currentTracker =
nullptr;
11897 m_runState = NotStarted;
11900 void TrackerContext::startCycle() {
11901 m_currentTracker = m_rootTracker.get();
11902 m_runState = Executing;
11904 void TrackerContext::completeCycle() {
11905 m_runState = CompletedCycle;
11908 bool TrackerContext::completedCycle()
const {
11909 return m_runState == CompletedCycle;
11911 ITracker& TrackerContext::currentTracker() {
11912 return *m_currentTracker;
11914 void TrackerContext::setCurrentTracker( ITracker* tracker ) {
11915 m_currentTracker = tracker;
11918 TrackerBase::TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
11919 : m_nameAndLocation( nameAndLocation ),
11924 NameAndLocation
const& TrackerBase::nameAndLocation()
const {
11925 return m_nameAndLocation;
11927 bool TrackerBase::isComplete()
const {
11928 return m_runState == CompletedSuccessfully || m_runState == Failed;
11930 bool TrackerBase::isSuccessfullyCompleted()
const {
11931 return m_runState == CompletedSuccessfully;
11933 bool TrackerBase::isOpen()
const {
11934 return m_runState != NotStarted && !isComplete();
11936 bool TrackerBase::hasChildren()
const {
11937 return !m_children.empty();
11940 void TrackerBase::addChild( ITrackerPtr
const& child ) {
11941 m_children.push_back( child );
11944 ITrackerPtr TrackerBase::findChild( NameAndLocation
const& nameAndLocation ) {
11945 auto it = std::find_if( m_children.begin(), m_children.end(),
11946 [&nameAndLocation]( ITrackerPtr
const& tracker ){
11948 tracker->nameAndLocation().location == nameAndLocation.location &&
11949 tracker->nameAndLocation().name == nameAndLocation.name;
11951 return( it != m_children.end() )
11955 ITracker& TrackerBase::parent() {
11956 assert( m_parent );
11960 void TrackerBase::openChild() {
11961 if( m_runState != ExecutingChildren ) {
11962 m_runState = ExecutingChildren;
11964 m_parent->openChild();
11968 bool TrackerBase::isSectionTracker()
const {
return false; }
11969 bool TrackerBase::isGeneratorTracker()
const {
return false; }
11971 void TrackerBase::open() {
11972 m_runState = Executing;
11975 m_parent->openChild();
11981 while( &m_ctx.currentTracker() != this )
11982 m_ctx.currentTracker().close();
11984 switch( m_runState ) {
11985 case NeedsAnotherRun:
11989 m_runState = CompletedSuccessfully;
11991 case ExecutingChildren:
11992 if( m_children.empty() || m_children.back()->isComplete() )
11993 m_runState = CompletedSuccessfully;
11997 case CompletedSuccessfully:
12005 m_ctx.completeCycle();
12007 void TrackerBase::fail() {
12008 m_runState = Failed;
12010 m_parent->markAsNeedingAnotherRun();
12012 m_ctx.completeCycle();
12014 void TrackerBase::markAsNeedingAnotherRun() {
12015 m_runState = NeedsAnotherRun;
12018 void TrackerBase::moveToParent() {
12019 assert( m_parent );
12020 m_ctx.setCurrentTracker( m_parent );
12022 void TrackerBase::moveToThis() {
12023 m_ctx.setCurrentTracker(
this );
12026 SectionTracker::SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
12027 : TrackerBase( nameAndLocation, ctx, parent )
12030 while( !parent->isSectionTracker() )
12031 parent = &parent->parent();
12033 SectionTracker& parentSection =
static_cast<SectionTracker&
>( *parent );
12034 addNextFilters( parentSection.m_filters );
12038 bool SectionTracker::isComplete()
const {
12039 bool complete =
true;
12041 if ((m_filters.empty() || m_filters[0] ==
"") ||
12042 std::find(m_filters.begin(), m_filters.end(),
12043 m_nameAndLocation.name) != m_filters.end())
12044 complete = TrackerBase::isComplete();
12049 bool SectionTracker::isSectionTracker()
const {
return true; }
12051 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation ) {
12052 std::shared_ptr<SectionTracker> section;
12054 ITracker& currentTracker = ctx.currentTracker();
12055 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
12056 assert( childTracker );
12057 assert( childTracker->isSectionTracker() );
12058 section = std::static_pointer_cast<SectionTracker>( childTracker );
12061 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker );
12062 currentTracker.addChild( section );
12064 if( !ctx.completedCycle() )
12065 section->tryOpen();
12069 void SectionTracker::tryOpen() {
12070 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
12074 void SectionTracker::addInitialFilters( std::vector<std::string>
const& filters ) {
12075 if( !filters.empty() ) {
12076 m_filters.push_back(
"");
12077 m_filters.push_back(
"");
12078 m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
12081 void SectionTracker::addNextFilters( std::vector<std::string>
const& filters ) {
12082 if( filters.size() > 1 )
12083 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
12088 using TestCaseTracking::ITracker;
12089 using TestCaseTracking::TrackerContext;
12090 using TestCaseTracking::SectionTracker;
12094 #if defined(__clang__) 12095 # pragma clang diagnostic pop 12103 return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
12114 extractClassName( classOrMethod ),
12128 #include <algorithm> 12135 TestSpec::Pattern::~Pattern() =
default;
12136 TestSpec::NamePattern::~NamePattern() =
default;
12137 TestSpec::TagPattern::~TagPattern() =
default;
12138 TestSpec::ExcludedPattern::~ExcludedPattern() =
default;
12140 TestSpec::NamePattern::NamePattern( std::string
const&
name )
12143 bool TestSpec::NamePattern::matches(
TestCaseInfo const& testCase )
const {
12144 return m_wildcardPattern.matches(
toLower( testCase.
name ) );
12147 TestSpec::TagPattern::TagPattern( std::string
const& tag ) : m_tag(
toLower( tag ) ) {}
12148 bool TestSpec::TagPattern::matches(
TestCaseInfo const& testCase )
const {
12154 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr
const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
12155 bool TestSpec::ExcludedPattern::matches(
TestCaseInfo const& testCase )
const {
return !m_underlyingPattern->matches( testCase ); }
12157 bool TestSpec::Filter::matches(
TestCaseInfo const& testCase )
const {
12159 for(
auto const& pattern : m_patterns ) {
12160 if( !pattern->matches( testCase ) )
12166 bool TestSpec::hasFilters()
const {
12167 return !m_filters.empty();
12169 bool TestSpec::matches(
TestCaseInfo const& testCase )
const {
12171 for(
auto const&
filter : m_filters )
12172 if(
filter.matches( testCase ) )
12182 TestSpecParser::TestSpecParser( ITagAliasRegistry
const& tagAliases ) : m_tagAliases( &tagAliases ) {}
12184 TestSpecParser& TestSpecParser::parse( std::string
const& arg ) {
12186 m_exclusion =
false;
12187 m_start = std::string::npos;
12188 m_arg = m_tagAliases->expandAliases( arg );
12189 m_escapeChars.clear();
12190 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
12191 visitChar( m_arg[m_pos] );
12192 if( m_mode == Name )
12193 addPattern<TestSpec::NamePattern>();
12196 TestSpec TestSpecParser::testSpec() {
12201 void TestSpecParser::visitChar(
char c ) {
12202 if( m_mode == None ) {
12205 case '~': m_exclusion =
true;
return;
12206 case '[':
return startNewMode( Tag, ++m_pos );
12207 case '"':
return startNewMode( QuotedName, ++m_pos );
12208 case '\\':
return escape();
12209 default: startNewMode( Name, m_pos );
break;
12212 if( m_mode == Name ) {
12214 addPattern<TestSpec::NamePattern>();
12217 else if( c ==
'[' ) {
12218 if( subString() ==
"exclude:" )
12219 m_exclusion =
true;
12221 addPattern<TestSpec::NamePattern>();
12222 startNewMode( Tag, ++m_pos );
12224 else if( c ==
'\\' )
12227 else if( m_mode == EscapedName )
12229 else if( m_mode == QuotedName && c ==
'"' )
12230 addPattern<TestSpec::NamePattern>();
12231 else if( m_mode == Tag && c ==
']' )
12232 addPattern<TestSpec::TagPattern>();
12234 void TestSpecParser::startNewMode( Mode mode, std::size_t
start ) {
12238 void TestSpecParser::escape() {
12239 if( m_mode == None )
12241 m_mode = EscapedName;
12242 m_escapeChars.push_back( m_pos );
12244 std::string TestSpecParser::subString()
const {
return m_arg.substr( m_start, m_pos - m_start ); }
12246 void TestSpecParser::addFilter() {
12247 if( !m_currentFilter.m_patterns.empty() ) {
12248 m_testSpec.m_filters.push_back( m_currentFilter );
12249 m_currentFilter = TestSpec::Filter();
12253 TestSpec parseTestSpec( std::string
const& arg ) {
12254 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
12263 static const uint64_t nanosecondsInSecond = 1000000000;
12268 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).
count();
12272 auto estimateClockResolution() -> uint64_t {
12274 static const uint64_t iterations = 1000000;
12278 for( std::size_t i = 0; i < iterations; ++i ) {
12284 }
while( ticks == baseTicks );
12286 auto delta = ticks - baseTicks;
12292 if (ticks > startTime + 3 * nanosecondsInSecond) {
12293 return sum / ( i + 1u );
12299 return sum/iterations;
12303 static auto s_resolution = estimateClockResolution();
12304 return s_resolution;
12314 return getElapsedNanoseconds()/1000;
12317 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
12320 return getElapsedMicroseconds()/1000000.0;
12327 #if defined(__clang__) 12328 # pragma clang diagnostic push 12329 # pragma clang diagnostic ignored "-Wexit-time-destructors" 12330 # pragma clang diagnostic ignored "-Wglobal-constructors" 12334 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) 12335 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER 12345 const std::string unprintableString =
"{?}";
12348 const int hexThreshold = 255;
12350 struct Endianness {
12351 enum Arch { Big, Little };
12353 static Arch which() {
12356 char asChar[sizeof (int)];
12360 return ( u.asChar[
sizeof(
int)-1] == 1 ) ? Big : Little;
12367 int i = 0, end =
static_cast<int>( size ), inc = 1;
12368 if( Endianness::which() == Endianness::Little ) {
12373 unsigned char const *bytes =
static_cast<unsigned char const *
>(object);
12375 rss <<
"0x" << std::setfill(
'0') << std::hex;
12376 for( ; i !=
end; i += inc )
12377 rss << std::setw(2) <<
static_cast<unsigned>(bytes[i]);
12382 template<
typename T>
12383 std::string fpToString( T
value,
int precision ) {
12384 if (Catch::isnan(value)) {
12389 rss << std::setprecision( precision )
12392 std::string
d = rss.
str();
12393 std::size_t i = d.find_last_not_of(
'0' );
12394 if( i != std::string::npos && i != d.size()-1 ) {
12397 d = d.substr( 0, i+1 );
12410 return '"' + str +
'"';
12413 std::string
s(
"\"");
12414 for (
char c : str) {
12431 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW 12441 return{
"{null string}" };
12448 return{
"{null string}" };
12452 #ifdef CATCH_CONFIG_WCHAR 12455 s.reserve(wstr.size());
12456 for (
auto c : wstr) {
12457 s += (c <= 0xff) ? static_cast<char>(c) :
'?';
12462 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW 12472 return{
"{null string}" };
12479 return{
"{null string}" };
12493 if (value > Detail::hexThreshold) {
12494 rss <<
" (0x" << std::hex << value <<
')';
12508 if (value > Detail::hexThreshold) {
12509 rss <<
" (0x" << std::hex << value <<
')';
12515 return b ?
"true" :
"false";
12519 if (value ==
'\r') {
12521 }
else if (value ==
'\f') {
12523 }
else if (value ==
'\n') {
12525 }
else if (value ==
'\t') {
12527 }
else if (
'\0' <= value && value <
' ') {
12530 char chstr[] =
"' '";
12547 return fpToString(value, 5) +
'f';
12550 return fpToString(value, 10);
12553 std::string ratio_string<std::atto>::symbol() {
return "a"; }
12554 std::string ratio_string<std::femto>::symbol() {
return "f"; }
12555 std::string ratio_string<std::pico>::symbol() {
return "p"; }
12556 std::string ratio_string<std::nano>::symbol() {
return "n"; }
12557 std::string ratio_string<std::micro>::symbol() {
return "u"; }
12558 std::string ratio_string<std::milli>::symbol() {
return "m"; }
12562 #if defined(__clang__) 12563 # pragma clang diagnostic pop 12587 return passed + failed + failedButOk;
12590 return failed == 0 && failedButOk == 0;
12593 return failed == 0;
12610 Totals diff = *
this - prevTotals;
12624 #include <exception> 12627 bool uncaught_exceptions() {
12628 #if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) 12629 return std::uncaught_exceptions() > 0;
12631 return std::uncaught_exception();
12643 (
unsigned int _majorVersion,
12644 unsigned int _minorVersion,
12645 unsigned int _patchNumber,
12646 char const *
const _branchName,
12647 unsigned int _buildNumber )
12648 : majorVersion( _majorVersion ),
12649 minorVersion( _minorVersion ),
12650 patchNumber( _patchNumber ),
12651 branchName( _branchName ),
12652 buildNumber( _buildNumber )
12655 std::ostream&
operator << ( std::ostream& os, Version
const& version ) {
12656 os << version.majorVersion <<
'.' 12657 << version.minorVersion <<
'.' 12658 << version.patchNumber;
12660 if (version.branchName[0]) {
12661 os <<
'-' << version.branchName
12662 <<
'.' << version.buildNumber;
12667 Version
const& libraryVersion() {
12668 static Version version( 2, 7, 0,
"", 0 );
12680 WildcardPattern::WildcardPattern( std::string
const& pattern,
12682 : m_caseSensitivity( caseSensitivity ),
12683 m_pattern( adjustCase( pattern ) )
12686 m_pattern = m_pattern.substr( 1 );
12687 m_wildcard = WildcardAtStart;
12689 if(
endsWith( m_pattern,
'*' ) ) {
12690 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
12691 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
12695 bool WildcardPattern::matches( std::string
const& str )
const {
12696 switch( m_wildcard ) {
12698 return m_pattern == adjustCase( str );
12699 case WildcardAtStart:
12700 return endsWith( adjustCase( str ), m_pattern );
12701 case WildcardAtEnd:
12702 return startsWith( adjustCase( str ), m_pattern );
12703 case WildcardAtBothEnds:
12704 return contains( adjustCase( str ), m_pattern );
12710 std::string WildcardPattern::adjustCase( std::string
const& str )
const {
12719 using uchar =
unsigned char;
12725 size_t trailingBytes(
unsigned char c) {
12726 if ((c & 0xE0) == 0xC0) {
12729 if ((c & 0xF0) == 0xE0) {
12732 if ((c & 0xF8) == 0xF0) {
12738 uint32_t headerValue(
unsigned char c) {
12739 if ((c & 0xE0) == 0xC0) {
12742 if ((c & 0xF0) == 0xE0) {
12745 if ((c & 0xF8) == 0xF0) {
12751 void hexEscapeChar(std::ostream& os,
unsigned char c) {
12752 std::ios_base::fmtflags
f(os.flags());
12754 << std::uppercase << std::hex << std::setfill(
'0') << std::setw(2)
12755 <<
static_cast<int>(c);
12761 XmlEncode::XmlEncode( std::string
const& str, ForWhat forWhat )
12763 m_forWhat( forWhat )
12766 void XmlEncode::encodeTo( std::ostream& os )
const {
12770 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
12771 uchar c = m_str[idx];
12773 case '<': os <<
"<";
break;
12774 case '&': os <<
"&";
break;
12778 if (idx > 2 && m_str[idx - 1] ==
']' && m_str[idx - 2] ==
']')
12785 if (m_forWhat == ForAttributes)
12796 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
12797 hexEscapeChar(os, c);
12815 hexEscapeChar(os, c);
12819 auto encBytes = trailingBytes(c);
12821 if (idx + encBytes - 1 >= m_str.size()) {
12822 hexEscapeChar(os, c);
12829 uint32_t
value = headerValue(c);
12830 for (std::size_t n = 1; n < encBytes; ++n) {
12831 uchar nc = m_str[idx + n];
12832 valid &= ((nc & 0xC0) == 0x80);
12833 value = (value << 6) | (nc & 0x3F);
12841 (0x80 <= value && value < 0x800 && encBytes > 2) ||
12842 (0x800 < value && value < 0x10000 && encBytes > 3) ||
12844 (value >= 0x110000)
12846 hexEscapeChar(os, c);
12851 for (std::size_t n = 0; n < encBytes; ++n) {
12852 os << m_str[idx + n];
12854 idx += encBytes - 1;
12860 std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode ) {
12861 xmlEncode.encodeTo( os );
12865 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
12866 : m_writer( writer )
12869 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
12870 : m_writer( other.m_writer ){
12871 other.m_writer =
nullptr;
12873 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
12875 m_writer->endElement();
12877 m_writer = other.m_writer;
12878 other.m_writer =
nullptr;
12882 XmlWriter::ScopedElement::~ScopedElement() {
12884 m_writer->endElement();
12887 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string
const& text,
bool indent ) {
12888 m_writer->writeText( text, indent );
12892 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
12894 writeDeclaration();
12897 XmlWriter::~XmlWriter() {
12898 while( !m_tags.empty() )
12902 XmlWriter& XmlWriter::startElement( std::string
const&
name ) {
12904 newlineIfNecessary();
12905 m_os << m_indent <<
'<' <<
name;
12906 m_tags.push_back( name );
12908 m_tagIsOpen =
true;
12912 XmlWriter::ScopedElement XmlWriter::scopedElement( std::string
const& name ) {
12913 ScopedElement scoped(
this );
12914 startElement( name );
12918 XmlWriter& XmlWriter::endElement() {
12919 newlineIfNecessary();
12920 m_indent = m_indent.substr( 0, m_indent.size()-2 );
12921 if( m_tagIsOpen ) {
12923 m_tagIsOpen =
false;
12926 m_os << m_indent <<
"</" << m_tags.back() <<
">";
12933 XmlWriter& XmlWriter::writeAttribute( std::string
const& name, std::string
const& attribute ) {
12934 if( !name.empty() && !attribute.empty() )
12935 m_os <<
' ' << name <<
"=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) <<
'"';
12939 XmlWriter& XmlWriter::writeAttribute( std::string
const& name,
bool attribute ) {
12940 m_os <<
' ' << name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
'"';
12944 XmlWriter& XmlWriter::writeText( std::string
const& text,
bool indent ) {
12945 if( !text.empty() ){
12946 bool tagWasOpen = m_tagIsOpen;
12948 if( tagWasOpen && indent )
12950 m_os << XmlEncode( text );
12951 m_needsNewline =
true;
12956 XmlWriter& XmlWriter::writeComment( std::string
const& text ) {
12958 m_os << m_indent <<
"<!--" << text <<
"-->";
12959 m_needsNewline =
true;
12963 void XmlWriter::writeStylesheetRef( std::string
const& url ) {
12964 m_os <<
"<?xml-stylesheet type=\"text/xsl\" href=\"" << url <<
"\"?>\n";
12967 XmlWriter& XmlWriter::writeBlankLine() {
12973 void XmlWriter::ensureTagClosed() {
12974 if( m_tagIsOpen ) {
12975 m_os <<
">" << std::endl;
12976 m_tagIsOpen =
false;
12980 void XmlWriter::writeDeclaration() {
12981 m_os <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
12984 void XmlWriter::newlineIfNecessary() {
12985 if( m_needsNewline ) {
12987 m_needsNewline =
false;
13001 void prepareExpandedExpression(AssertionResult& result) {
13002 result.getExpandedExpression();
13007 std::string getFormattedDuration(
double duration ) {
13012 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
13013 char buffer[maxDoubleSize];
13018 sprintf_s(buffer,
"%.3f", duration);
13022 return std::string(buffer);
13025 TestEventListenerBase::TestEventListenerBase(ReporterConfig
const & _config)
13026 :StreamingReporterBase(_config) {}
13028 std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() {
13032 void TestEventListenerBase::assertionStarting(
AssertionInfo const &) {}
13034 bool TestEventListenerBase::assertionEnded(AssertionStats
const &) {
13044 #ifdef CATCH_PLATFORM_MAC 13045 const char* failedString() {
return "FAILED"; }
13046 const char* passedString() {
return "PASSED"; }
13048 const char* failedString() {
return "failed"; }
13049 const char* passedString() {
return "passed"; }
13053 Catch::Colour::Code dimColour() {
return Catch::Colour::FileName; }
13055 std::string bothOrAll( std::size_t
count ) {
13056 return count == 1 ? std::string() :
13057 count == 2 ?
"both " :
"all " ;
13070 void printTotals(std::ostream& out,
const Totals& totals) {
13072 out <<
"No tests ran.";
13074 Colour colour(Colour::ResultError);
13075 const std::string qualify_assertions_failed =
13081 "failed " << qualify_assertions_failed <<
13087 <<
" (no assertions).";
13089 Colour colour(Colour::ResultError);
13094 Colour colour(Colour::ResultSuccess);
13103 class AssertionPrinter {
13105 AssertionPrinter& operator= (AssertionPrinter
const&) =
delete;
13106 AssertionPrinter(AssertionPrinter
const&) =
delete;
13107 AssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
13109 , result(_stats.assertionResult)
13110 , messages(_stats.infoMessages)
13111 , itMessage(_stats.infoMessages.begin())
13112 , printInfoMessages(_printInfoMessages) {}
13117 itMessage = messages.begin();
13119 switch (result.getResultType()) {
13121 printResultType(Colour::ResultSuccess, passedString());
13122 printOriginalExpression();
13123 printReconstructedExpression();
13124 if (!result.hasExpression())
13125 printRemainingMessages(Colour::None);
13127 printRemainingMessages();
13131 printResultType(Colour::ResultSuccess, failedString() + std::string(
" - but was ok"));
13133 printResultType(Colour::Error, failedString());
13134 printOriginalExpression();
13135 printReconstructedExpression();
13136 printRemainingMessages();
13139 printResultType(Colour::Error, failedString());
13140 printIssue(
"unexpected exception with message:");
13142 printExpressionWas();
13143 printRemainingMessages();
13146 printResultType(Colour::Error, failedString());
13147 printIssue(
"fatal error condition with message:");
13149 printExpressionWas();
13150 printRemainingMessages();
13153 printResultType(Colour::Error, failedString());
13154 printIssue(
"expected exception, got none");
13155 printExpressionWas();
13156 printRemainingMessages();
13159 printResultType(Colour::None,
"info");
13161 printRemainingMessages();
13164 printResultType(Colour::None,
"warning");
13166 printRemainingMessages();
13169 printResultType(Colour::Error, failedString());
13170 printIssue(
"explicitly");
13171 printRemainingMessages(Colour::None);
13177 printResultType(Colour::Error,
"** internal error **");
13183 void printSourceInfo()
const {
13184 Colour colourGuard(Colour::FileName);
13185 stream << result.getSourceInfo() <<
':';
13188 void printResultType(Colour::Code colour, std::string
const& passOrFail)
const {
13189 if (!passOrFail.empty()) {
13191 Colour colourGuard(colour);
13192 stream <<
' ' << passOrFail;
13198 void printIssue(std::string
const& issue)
const {
13199 stream <<
' ' << issue;
13202 void printExpressionWas() {
13203 if (result.hasExpression()) {
13206 Colour colour(dimColour());
13207 stream <<
" expression was:";
13209 printOriginalExpression();
13213 void printOriginalExpression()
const {
13214 if (result.hasExpression()) {
13215 stream <<
' ' << result.getExpression();
13219 void printReconstructedExpression()
const {
13220 if (result.hasExpandedExpression()) {
13222 Colour colour(dimColour());
13223 stream <<
" for: ";
13225 stream << result.getExpandedExpression();
13229 void printMessage() {
13230 if (itMessage != messages.end()) {
13231 stream <<
" '" << itMessage->message <<
'\'';
13236 void printRemainingMessages(Colour::Code colour = dimColour()) {
13237 if (itMessage == messages.end())
13241 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
13242 const std::size_t N =
static_cast<std::size_t
>(std::distance(itMessage, itEnd));
13245 Colour colourGuard(colour);
13246 stream <<
" with " <<
pluralise(N,
"message") <<
':';
13249 for (; itMessage != itEnd; ) {
13252 stream <<
" '" << itMessage->message <<
'\'';
13253 if (++itMessage != itEnd) {
13254 Colour colourGuard(dimColour());
13262 std::ostream& stream;
13263 AssertionResult
const& result;
13264 std::vector<MessageInfo> messages;
13265 std::vector<MessageInfo>::const_iterator itMessage;
13266 bool printInfoMessages;
13271 std::string CompactReporter::getDescription() {
13272 return "Reports test results on a single line, suitable for IDEs";
13275 ReporterPreferences CompactReporter::getPreferences()
const {
13276 return m_reporterPrefs;
13279 void CompactReporter::noMatchingTestCases( std::string
const& spec ) {
13280 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
13283 void CompactReporter::assertionStarting(
AssertionInfo const& ) {}
13285 bool CompactReporter::assertionEnded( AssertionStats
const& _assertionStats ) {
13286 AssertionResult
const& result = _assertionStats.assertionResult;
13288 bool printInfoMessages =
true;
13291 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
13294 printInfoMessages =
false;
13297 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
13300 stream << std::endl;
13304 void CompactReporter::sectionEnded(SectionStats
const& _sectionStats) {
13306 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name << std::endl;
13310 void CompactReporter::testRunEnded( TestRunStats
const& _testRunStats ) {
13311 printTotals( stream, _testRunStats.totals );
13312 stream <<
'\n' << std::endl;
13313 StreamingReporterBase::testRunEnded( _testRunStats );
13316 CompactReporter::~CompactReporter() {}
13318 CATCH_REGISTER_REPORTER(
"compact", CompactReporter )
13327 #if defined(_MSC_VER) 13328 #pragma warning(push) 13329 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 13339 class ConsoleAssertionPrinter {
13341 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter
const&) =
delete;
13342 ConsoleAssertionPrinter(ConsoleAssertionPrinter
const&) =
delete;
13343 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
13346 result(_stats.assertionResult),
13347 colour(Colour::None),
13348 message(result.getMessage()),
13349 messages(_stats.infoMessages),
13350 printInfoMessages(_printInfoMessages) {
13351 switch (result.getResultType()) {
13353 colour = Colour::Success;
13354 passOrFail =
"PASSED";
13356 if (_stats.infoMessages.size() == 1)
13357 messageLabel =
"with message";
13358 if (_stats.infoMessages.size() > 1)
13359 messageLabel =
"with messages";
13362 if (result.isOk()) {
13363 colour = Colour::Success;
13364 passOrFail =
"FAILED - but was ok";
13366 colour = Colour::Error;
13367 passOrFail =
"FAILED";
13369 if (_stats.infoMessages.size() == 1)
13370 messageLabel =
"with message";
13371 if (_stats.infoMessages.size() > 1)
13372 messageLabel =
"with messages";
13375 colour = Colour::Error;
13376 passOrFail =
"FAILED";
13377 messageLabel =
"due to unexpected exception with ";
13378 if (_stats.infoMessages.size() == 1)
13379 messageLabel +=
"message";
13380 if (_stats.infoMessages.size() > 1)
13381 messageLabel +=
"messages";
13384 colour = Colour::Error;
13385 passOrFail =
"FAILED";
13386 messageLabel =
"due to a fatal error condition";
13389 colour = Colour::Error;
13390 passOrFail =
"FAILED";
13391 messageLabel =
"because no exception was thrown where one was expected";
13394 messageLabel =
"info";
13397 messageLabel =
"warning";
13400 passOrFail =
"FAILED";
13401 colour = Colour::Error;
13402 if (_stats.infoMessages.size() == 1)
13403 messageLabel =
"explicitly with message";
13404 if (_stats.infoMessages.size() > 1)
13405 messageLabel =
"explicitly with messages";
13411 passOrFail =
"** internal error **";
13412 colour = Colour::Error;
13417 void print()
const {
13419 if (stats.totals.assertions.total() > 0) {
13421 printOriginalExpression();
13422 printReconstructedExpression();
13430 void printResultType()
const {
13431 if (!passOrFail.empty()) {
13432 Colour colourGuard(colour);
13433 stream << passOrFail <<
":\n";
13436 void printOriginalExpression()
const {
13437 if (result.hasExpression()) {
13438 Colour colourGuard(Colour::OriginalExpression);
13440 stream << result.getExpressionInMacro();
13444 void printReconstructedExpression()
const {
13445 if (result.hasExpandedExpression()) {
13446 stream <<
"with expansion:\n";
13447 Colour colourGuard(Colour::ReconstructedExpression);
13448 stream << Column(result.getExpandedExpression()).indent(2) <<
'\n';
13451 void printMessage()
const {
13452 if (!messageLabel.empty())
13453 stream << messageLabel <<
':' <<
'\n';
13454 for (
auto const& msg : messages) {
13457 stream << Column(msg.message).indent(2) <<
'\n';
13460 void printSourceInfo()
const {
13461 Colour colourGuard(Colour::FileName);
13462 stream << result.getSourceInfo() <<
": ";
13465 std::ostream& stream;
13466 AssertionStats
const& stats;
13467 AssertionResult
const& result;
13468 Colour::Code colour;
13469 std::string passOrFail;
13470 std::string messageLabel;
13471 std::string message;
13472 std::vector<MessageInfo> messages;
13473 bool printInfoMessages;
13476 std::size_t makeRatio(std::size_t number, std::size_t total) {
13477 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
13478 return (ratio == 0 && number > 0) ? 1 : ratio;
13481 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {
13482 if (i > j && i > k)
13490 struct ColumnInfo {
13491 enum Justification { Left, Right };
13494 Justification justification;
13496 struct ColumnBreak {};
13497 struct RowBreak {};
13508 static const uint64_t s_nanosecondsInAMicrosecond = 1000;
13509 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
13510 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
13511 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
13513 uint64_t m_inNanoseconds;
13517 explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
13518 : m_inNanoseconds(inNanoseconds),
13520 if (m_units == Unit::Auto) {
13521 if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
13522 m_units = Unit::Nanoseconds;
13523 else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
13524 m_units = Unit::Microseconds;
13525 else if (m_inNanoseconds < s_nanosecondsInASecond)
13526 m_units = Unit::Milliseconds;
13527 else if (m_inNanoseconds < s_nanosecondsInAMinute)
13528 m_units = Unit::Seconds;
13530 m_units = Unit::Minutes;
13535 auto value()
const ->
double {
13537 case Unit::Microseconds:
13538 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMicrosecond);
13539 case Unit::Milliseconds:
13540 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMillisecond);
13541 case Unit::Seconds:
13542 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInASecond);
13543 case Unit::Minutes:
13544 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMinute);
13546 return static_cast<double>(m_inNanoseconds);
13549 auto unitsAsString()
const -> std::string {
13551 case Unit::Nanoseconds:
13553 case Unit::Microseconds:
13555 case Unit::Milliseconds:
13557 case Unit::Seconds:
13559 case Unit::Minutes:
13562 return "** internal error **";
13566 friend auto operator << (std::ostream& os, Duration
const& duration) -> std::ostream& {
13567 return os << duration.value() <<
" " << duration.unitsAsString();
13572 class TablePrinter {
13573 std::ostream& m_os;
13574 std::vector<ColumnInfo> m_columnInfos;
13575 std::ostringstream m_oss;
13576 int m_currentColumn = -1;
13577 bool m_isOpen =
false;
13580 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
13582 m_columnInfos( std::move( columnInfos ) ) {}
13584 auto columnInfos()
const -> std::vector<ColumnInfo>
const& {
13585 return m_columnInfos;
13591 *
this << RowBreak();
13592 for (
auto const& info : m_columnInfos)
13593 *
this << info.name << ColumnBreak();
13594 *
this << RowBreak();
13595 m_os << Catch::getLineOfChars<
'-'>() <<
"\n";
13600 *
this << RowBreak();
13606 template<
typename T>
13612 friend TablePrinter&
operator << (TablePrinter& tp, ColumnBreak) {
13613 auto colStr = tp.m_oss.str();
13618 if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
13619 tp.m_currentColumn = -1;
13622 tp.m_currentColumn++;
13624 auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
13625 auto padding = (strSize + 2 <
static_cast<std::size_t
>(colInfo.width))
13626 ? std::string(colInfo.width - (strSize + 2),
' ')
13628 if (colInfo.justification == ColumnInfo::Left)
13629 tp.m_os << colStr << padding <<
" ";
13631 tp.m_os << padding << colStr <<
" ";
13635 friend TablePrinter&
operator << (TablePrinter& tp, RowBreak) {
13636 if (tp.m_currentColumn > 0) {
13638 tp.m_currentColumn = -1;
13644 ConsoleReporter::ConsoleReporter(ReporterConfig
const&
config)
13645 : StreamingReporterBase(config),
13646 m_tablePrinter(
new TablePrinter(config.stream(),
13648 {
"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
13649 {
"iters", 8, ColumnInfo::Right },
13650 {
"elapsed ns", 14, ColumnInfo::Right },
13651 {
"average", 14, ColumnInfo::Right }
13653 ConsoleReporter::~ConsoleReporter() =
default;
13655 std::string ConsoleReporter::getDescription() {
13656 return "Reports test results as plain lines of text";
13659 void ConsoleReporter::noMatchingTestCases(std::string
const& spec) {
13660 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
13663 void ConsoleReporter::assertionStarting(
AssertionInfo const&) {}
13665 bool ConsoleReporter::assertionEnded(AssertionStats
const& _assertionStats) {
13666 AssertionResult
const& result = _assertionStats.assertionResult;
13668 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
13676 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
13678 stream << std::endl;
13682 void ConsoleReporter::sectionStarting(
SectionInfo const& _sectionInfo) {
13683 m_headerPrinted =
false;
13684 StreamingReporterBase::sectionStarting(_sectionInfo);
13686 void ConsoleReporter::sectionEnded(SectionStats
const& _sectionStats) {
13687 m_tablePrinter->close();
13688 if (_sectionStats.missingAssertions) {
13690 Colour colour(Colour::ResultError);
13691 if (m_sectionStack.size() > 1)
13692 stream <<
"\nNo assertions in section";
13694 stream <<
"\nNo assertions in test case";
13695 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" << std::endl;
13698 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name << std::endl;
13700 if (m_headerPrinted) {
13701 m_headerPrinted =
false;
13703 StreamingReporterBase::sectionEnded(_sectionStats);
13706 void ConsoleReporter::benchmarkStarting(BenchmarkInfo
const& info) {
13707 lazyPrintWithoutClosingBenchmarkTable();
13709 auto nameCol = Column( info.name ).width( static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) );
13711 bool firstLine =
true;
13712 for (
auto line : nameCol) {
13714 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
13718 (*m_tablePrinter) << line << ColumnBreak();
13721 void ConsoleReporter::benchmarkEnded(BenchmarkStats
const& stats) {
13722 Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
13724 << stats.iterations << ColumnBreak()
13725 << stats.elapsedTimeInNanoseconds << ColumnBreak()
13726 << average << ColumnBreak();
13729 void ConsoleReporter::testCaseEnded(TestCaseStats
const& _testCaseStats) {
13730 m_tablePrinter->close();
13731 StreamingReporterBase::testCaseEnded(_testCaseStats);
13732 m_headerPrinted =
false;
13734 void ConsoleReporter::testGroupEnded(TestGroupStats
const& _testGroupStats) {
13735 if (currentGroupInfo.used) {
13736 printSummaryDivider();
13737 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
13738 printTotals(_testGroupStats.totals);
13739 stream <<
'\n' << std::endl;
13741 StreamingReporterBase::testGroupEnded(_testGroupStats);
13743 void ConsoleReporter::testRunEnded(TestRunStats
const& _testRunStats) {
13744 printTotalsDivider(_testRunStats.totals);
13745 printTotals(_testRunStats.totals);
13746 stream << std::endl;
13747 StreamingReporterBase::testRunEnded(_testRunStats);
13750 void ConsoleReporter::lazyPrint() {
13752 m_tablePrinter->close();
13753 lazyPrintWithoutClosingBenchmarkTable();
13756 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
13758 if (!currentTestRunInfo.used)
13759 lazyPrintRunInfo();
13760 if (!currentGroupInfo.used)
13761 lazyPrintGroupInfo();
13763 if (!m_headerPrinted) {
13764 printTestCaseAndSectionHeader();
13765 m_headerPrinted =
true;
13768 void ConsoleReporter::lazyPrintRunInfo() {
13769 stream << '\n' << getLineOfChars<'~'>() <<
'\n';
13770 Colour colour(Colour::SecondaryText);
13771 stream << currentTestRunInfo->name
13772 <<
" is a Catch v" << libraryVersion() <<
" host application.\n" 13773 <<
"Run with -? for options\n\n";
13775 if (m_config->rngSeed() != 0)
13776 stream <<
"Randomness seeded to: " << m_config->rngSeed() <<
"\n\n";
13778 currentTestRunInfo.used =
true;
13780 void ConsoleReporter::lazyPrintGroupInfo() {
13781 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
13782 printClosedHeader(
"Group: " + currentGroupInfo->name);
13783 currentGroupInfo.used =
true;
13786 void ConsoleReporter::printTestCaseAndSectionHeader() {
13787 assert(!m_sectionStack.empty());
13788 printOpenHeader(currentTestCaseInfo->name);
13790 if (m_sectionStack.size() > 1) {
13791 Colour colourGuard(Colour::Headers);
13794 it = m_sectionStack.begin() + 1,
13795 itEnd = m_sectionStack.end();
13796 for (; it != itEnd; ++it)
13797 printHeaderString(it->name, 2);
13802 if (!lineInfo.
empty()) {
13803 stream << getLineOfChars<
'-'>() <<
'\n';
13804 Colour colourGuard(Colour::FileName);
13805 stream << lineInfo <<
'\n';
13807 stream << getLineOfChars<
'.'>() <<
'\n' << std::endl;
13810 void ConsoleReporter::printClosedHeader(std::string
const& _name) {
13811 printOpenHeader(_name);
13812 stream << getLineOfChars<
'.'>() <<
'\n';
13814 void ConsoleReporter::printOpenHeader(std::string
const& _name) {
13815 stream << getLineOfChars<
'-'>() <<
'\n';
13817 Colour colourGuard(Colour::Headers);
13818 printHeaderString(_name);
13824 void ConsoleReporter::printHeaderString(std::string
const& _string, std::size_t indent) {
13825 std::size_t i = _string.find(
": ");
13826 if (i != std::string::npos)
13830 stream << Column(_string).indent(indent + i).initialIndent(indent) <<
'\n';
13833 struct SummaryColumn {
13835 SummaryColumn( std::string _label, Colour::Code _colour )
13836 : label( std::move( _label ) ),
13837 colour( _colour ) {}
13838 SummaryColumn addRow( std::size_t
count ) {
13841 std::string row = rss.
str();
13842 for (
auto& oldRow : rows) {
13843 while (oldRow.size() < row.size())
13844 oldRow =
' ' + oldRow;
13845 while (oldRow.size() > row.size())
13848 rows.push_back(row);
13853 Colour::Code colour;
13854 std::vector<std::string> rows;
13858 void ConsoleReporter::printTotals(
Totals const& totals ) {
13860 stream << Colour(Colour::Warning) <<
"No tests ran\n";
13862 stream << Colour(Colour::ResultSuccess) <<
"All tests passed";
13869 std::vector<SummaryColumn> columns;
13870 columns.push_back(SummaryColumn(
"", Colour::None)
13873 columns.push_back(SummaryColumn(
"passed", Colour::Success)
13876 columns.push_back(SummaryColumn(
"failed", Colour::ResultError)
13879 columns.push_back(SummaryColumn(
"failed as expected", Colour::ResultExpectedFailure)
13883 printSummaryRow(
"test cases", columns, 0);
13884 printSummaryRow(
"assertions", columns, 1);
13887 void ConsoleReporter::printSummaryRow(std::string
const& label, std::vector<SummaryColumn>
const& cols, std::size_t row) {
13888 for (
auto col : cols) {
13889 std::string
value = col.rows[row];
13890 if (col.label.empty()) {
13891 stream << label <<
": ";
13895 stream << Colour(Colour::Warning) <<
"- none -";
13896 }
else if (value !=
"0") {
13897 stream << Colour(Colour::LightGrey) <<
" | ";
13898 stream << Colour(col.colour)
13899 << value <<
' ' << col.label;
13905 void ConsoleReporter::printTotalsDivider(
Totals const& totals) {
13910 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
13911 findMax(failedRatio, failedButOkRatio, passedRatio)++;
13912 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
13913 findMax(failedRatio, failedButOkRatio, passedRatio)--;
13915 stream << Colour(Colour::Error) << std::string(failedRatio,
'=');
13916 stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio,
'=');
13918 stream << Colour(Colour::ResultSuccess) << std::string(passedRatio,
'=');
13920 stream << Colour(Colour::Success) << std::string(passedRatio,
'=');
13922 stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1,
'=');
13926 void ConsoleReporter::printSummaryDivider() {
13927 stream << getLineOfChars<
'-'>() <<
'\n';
13930 CATCH_REGISTER_REPORTER(
"console", ConsoleReporter)
13934 #if defined(_MSC_VER) 13935 #pragma warning(pop) 13943 #include <algorithm> 13948 std::string getCurrentTimestamp() {
13952 std::time(&rawtime);
13953 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
13956 std::tm timeInfo = {};
13957 gmtime_s(&timeInfo, &rawtime);
13960 timeInfo = std::gmtime(&rawtime);
13964 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
13967 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
13969 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
13971 return std::string(timeStamp);
13974 std::string fileNameTag(
const std::vector<std::string> &tags) {
13975 auto it = std::find_if(
begin(tags),
13977 [] (std::string
const& tag) {
return tag.front() ==
'#'; });
13978 if (it != tags.end())
13979 return it->substr(1);
13980 return std::string();
13984 JunitReporter::JunitReporter( ReporterConfig
const& _config )
13985 : CumulativeReporterBase( _config ),
13986 xml( _config.stream() )
13988 m_reporterPrefs.shouldRedirectStdOut =
true;
13989 m_reporterPrefs.shouldReportAllAssertions =
true;
13992 JunitReporter::~JunitReporter() {}
13994 std::string JunitReporter::getDescription() {
13995 return "Reports test results in an XML format that looks like Ant's junitreport target";
13998 void JunitReporter::noMatchingTestCases( std::string
const& ) {}
14000 void JunitReporter::testRunStarting( TestRunInfo
const& runInfo ) {
14001 CumulativeReporterBase::testRunStarting( runInfo );
14002 xml.startElement(
"testsuites" );
14003 if( m_config->rngSeed() != 0 ) {
14004 xml.startElement(
"properties" );
14005 xml.scopedElement(
"property" )
14006 .writeAttribute(
"name",
"random-seed" )
14007 .writeAttribute(
"value", m_config->rngSeed() );
14012 void JunitReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
14013 suiteTimer.start();
14014 stdOutForSuite.clear();
14015 stdErrForSuite.clear();
14016 unexpectedExceptions = 0;
14017 CumulativeReporterBase::testGroupStarting( groupInfo );
14020 void JunitReporter::testCaseStarting(
TestCaseInfo const& testCaseInfo ) {
14021 m_okToFail = testCaseInfo.
okToFail();
14024 bool JunitReporter::assertionEnded( AssertionStats
const& assertionStats ) {
14026 unexpectedExceptions++;
14027 return CumulativeReporterBase::assertionEnded( assertionStats );
14030 void JunitReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
14031 stdOutForSuite += testCaseStats.stdOut;
14032 stdErrForSuite += testCaseStats.stdErr;
14033 CumulativeReporterBase::testCaseEnded( testCaseStats );
14036 void JunitReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
14037 double suiteTime = suiteTimer.getElapsedSeconds();
14038 CumulativeReporterBase::testGroupEnded( testGroupStats );
14039 writeGroup( *m_testGroups.back(), suiteTime );
14042 void JunitReporter::testRunEndedCumulative() {
14046 void JunitReporter::writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
14047 XmlWriter::ScopedElement e = xml.scopedElement(
"testsuite" );
14048 TestGroupStats
const& stats = groupNode.value;
14049 xml.writeAttribute(
"name", stats.groupInfo.name );
14050 xml.writeAttribute(
"errors", unexpectedExceptions );
14051 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
14052 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
14053 xml.writeAttribute(
"hostname",
"tbd" );
14055 xml.writeAttribute(
"time",
"" );
14057 xml.writeAttribute(
"time", suiteTime );
14058 xml.writeAttribute(
"timestamp", getCurrentTimestamp() );
14061 for(
auto const& child : groupNode.children )
14062 writeTestCase( *child );
14064 xml.scopedElement(
"system-out" ).writeText(
trim( stdOutForSuite ),
false );
14065 xml.scopedElement(
"system-err" ).writeText(
trim( stdErrForSuite ),
false );
14068 void JunitReporter::writeTestCase( TestCaseNode
const& testCaseNode ) {
14069 TestCaseStats
const& stats = testCaseNode.value;
14073 assert( testCaseNode.children.size() == 1 );
14074 SectionNode
const& rootSection = *testCaseNode.children.front();
14076 std::string className = stats.testInfo.className;
14078 if( className.empty() ) {
14079 className = fileNameTag(stats.testInfo.tags);
14080 if ( className.empty() )
14081 className =
"global";
14084 if ( !m_config->name().empty() )
14085 className = m_config->name() +
"." + className;
14087 writeSection( className,
"", rootSection );
14090 void JunitReporter::writeSection( std::string
const& className,
14091 std::string
const& rootName,
14092 SectionNode
const& sectionNode ) {
14093 std::string
name =
trim( sectionNode.stats.sectionInfo.name );
14094 if( !rootName.empty() )
14095 name = rootName +
'/' + name;
14097 if( !sectionNode.assertions.empty() ||
14098 !sectionNode.stdOut.empty() ||
14099 !sectionNode.stdErr.empty() ) {
14100 XmlWriter::ScopedElement e = xml.scopedElement(
"testcase" );
14101 if( className.empty() ) {
14102 xml.writeAttribute(
"classname", name );
14103 xml.writeAttribute(
"name",
"root" );
14106 xml.writeAttribute(
"classname", className );
14107 xml.writeAttribute(
"name", name );
14111 writeAssertions( sectionNode );
14113 if( !sectionNode.stdOut.empty() )
14114 xml.scopedElement(
"system-out" ).writeText(
trim( sectionNode.stdOut ),
false );
14115 if( !sectionNode.stdErr.empty() )
14116 xml.scopedElement(
"system-err" ).writeText(
trim( sectionNode.stdErr ),
false );
14118 for(
auto const& childNode : sectionNode.childSections )
14119 if( className.empty() )
14120 writeSection( name,
"", *childNode );
14122 writeSection( className, name, *childNode );
14125 void JunitReporter::writeAssertions( SectionNode
const& sectionNode ) {
14126 for(
auto const& assertion : sectionNode.assertions )
14127 writeAssertion( assertion );
14130 void JunitReporter::writeAssertion( AssertionStats
const& stats ) {
14131 AssertionResult
const& result = stats.assertionResult;
14132 if( !result.isOk() ) {
14133 std::string elementName;
14134 switch( result.getResultType() ) {
14137 elementName =
"error";
14140 elementName =
"failure";
14143 elementName =
"failure";
14146 elementName =
"failure";
14156 elementName =
"internalError";
14160 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
14162 xml.writeAttribute(
"message", result.getExpandedExpression() );
14163 xml.writeAttribute(
"type", result.getTestMacroName() );
14166 if( !result.getMessage().empty() )
14167 rss << result.getMessage() <<
'\n';
14168 for(
auto const& msg : stats.infoMessages )
14170 rss << msg.message <<
'\n';
14172 rss <<
"at " << result.getSourceInfo();
14173 xml.writeText( rss.
str(),
false );
14177 CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
14187 ListeningReporter::ListeningReporter() {
14189 m_preferences.shouldReportAllAssertions =
true;
14192 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
14193 m_listeners.push_back( std::move( listener ) );
14196 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
14197 assert(!m_reporter &&
"Listening reporter can wrap only 1 real reporter");
14198 m_reporter = std::move( reporter );
14199 m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;
14202 ReporterPreferences ListeningReporter::getPreferences()
const {
14203 return m_preferences;
14206 std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
14207 return std::set<Verbosity>{ };
14210 void ListeningReporter::noMatchingTestCases( std::string
const& spec ) {
14211 for (
auto const& listener : m_listeners ) {
14212 listener->noMatchingTestCases( spec );
14214 m_reporter->noMatchingTestCases( spec );
14217 void ListeningReporter::benchmarkStarting( BenchmarkInfo
const& benchmarkInfo ) {
14218 for (
auto const& listener : m_listeners ) {
14219 listener->benchmarkStarting( benchmarkInfo );
14221 m_reporter->benchmarkStarting( benchmarkInfo );
14223 void ListeningReporter::benchmarkEnded( BenchmarkStats
const& benchmarkStats ) {
14224 for (
auto const& listener : m_listeners ) {
14225 listener->benchmarkEnded( benchmarkStats );
14227 m_reporter->benchmarkEnded( benchmarkStats );
14230 void ListeningReporter::testRunStarting( TestRunInfo
const& testRunInfo ) {
14231 for (
auto const& listener : m_listeners ) {
14232 listener->testRunStarting( testRunInfo );
14234 m_reporter->testRunStarting( testRunInfo );
14237 void ListeningReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
14238 for (
auto const& listener : m_listeners ) {
14239 listener->testGroupStarting( groupInfo );
14241 m_reporter->testGroupStarting( groupInfo );
14244 void ListeningReporter::testCaseStarting(
TestCaseInfo const& testInfo ) {
14245 for (
auto const& listener : m_listeners ) {
14246 listener->testCaseStarting( testInfo );
14248 m_reporter->testCaseStarting( testInfo );
14251 void ListeningReporter::sectionStarting(
SectionInfo const& sectionInfo ) {
14252 for (
auto const& listener : m_listeners ) {
14253 listener->sectionStarting( sectionInfo );
14255 m_reporter->sectionStarting( sectionInfo );
14258 void ListeningReporter::assertionStarting(
AssertionInfo const& assertionInfo ) {
14259 for (
auto const& listener : m_listeners ) {
14260 listener->assertionStarting( assertionInfo );
14262 m_reporter->assertionStarting( assertionInfo );
14266 bool ListeningReporter::assertionEnded( AssertionStats
const& assertionStats ) {
14267 for(
auto const& listener : m_listeners ) {
14268 static_cast<void>( listener->assertionEnded( assertionStats ) );
14270 return m_reporter->assertionEnded( assertionStats );
14273 void ListeningReporter::sectionEnded( SectionStats
const& sectionStats ) {
14274 for (
auto const& listener : m_listeners ) {
14275 listener->sectionEnded( sectionStats );
14277 m_reporter->sectionEnded( sectionStats );
14280 void ListeningReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
14281 for (
auto const& listener : m_listeners ) {
14282 listener->testCaseEnded( testCaseStats );
14284 m_reporter->testCaseEnded( testCaseStats );
14287 void ListeningReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
14288 for (
auto const& listener : m_listeners ) {
14289 listener->testGroupEnded( testGroupStats );
14291 m_reporter->testGroupEnded( testGroupStats );
14294 void ListeningReporter::testRunEnded( TestRunStats
const& testRunStats ) {
14295 for (
auto const& listener : m_listeners ) {
14296 listener->testRunEnded( testRunStats );
14298 m_reporter->testRunEnded( testRunStats );
14301 void ListeningReporter::skipTest(
TestCaseInfo const& testInfo ) {
14302 for (
auto const& listener : m_listeners ) {
14303 listener->skipTest( testInfo );
14305 m_reporter->skipTest( testInfo );
14308 bool ListeningReporter::isMulti()
const {
14316 #if defined(_MSC_VER) 14317 #pragma warning(push) 14318 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch 14324 XmlReporter::XmlReporter( ReporterConfig
const& _config )
14325 : StreamingReporterBase( _config ),
14326 m_xml(_config.stream())
14328 m_reporterPrefs.shouldRedirectStdOut =
true;
14329 m_reporterPrefs.shouldReportAllAssertions =
true;
14332 XmlReporter::~XmlReporter() =
default;
14334 std::string XmlReporter::getDescription() {
14335 return "Reports test results as an XML document";
14338 std::string XmlReporter::getStylesheetRef()
const {
14339 return std::string();
14342 void XmlReporter::writeSourceInfo(
SourceLineInfo const& sourceInfo ) {
14344 .writeAttribute(
"filename", sourceInfo.
file )
14345 .writeAttribute(
"line", sourceInfo.
line );
14348 void XmlReporter::noMatchingTestCases( std::string
const&
s ) {
14349 StreamingReporterBase::noMatchingTestCases( s );
14352 void XmlReporter::testRunStarting( TestRunInfo
const& testInfo ) {
14353 StreamingReporterBase::testRunStarting( testInfo );
14354 std::string stylesheetRef = getStylesheetRef();
14355 if( !stylesheetRef.empty() )
14356 m_xml.writeStylesheetRef( stylesheetRef );
14357 m_xml.startElement(
"Catch" );
14358 if( !m_config->name().empty() )
14359 m_xml.writeAttribute(
"name", m_config->name() );
14360 if( m_config->rngSeed() != 0 )
14361 m_xml.scopedElement(
"Randomness" )
14362 .writeAttribute(
"seed", m_config->rngSeed() );
14365 void XmlReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
14366 StreamingReporterBase::testGroupStarting( groupInfo );
14367 m_xml.startElement(
"Group" )
14368 .writeAttribute(
"name", groupInfo.name );
14371 void XmlReporter::testCaseStarting(
TestCaseInfo const& testInfo ) {
14372 StreamingReporterBase::testCaseStarting(testInfo);
14373 m_xml.startElement(
"TestCase" )
14374 .writeAttribute(
"name",
trim( testInfo.
name ) )
14375 .writeAttribute(
"description", testInfo.
description )
14378 writeSourceInfo( testInfo.
lineInfo );
14381 m_testCaseTimer.start();
14382 m_xml.ensureTagClosed();
14385 void XmlReporter::sectionStarting(
SectionInfo const& sectionInfo ) {
14386 StreamingReporterBase::sectionStarting( sectionInfo );
14387 if( m_sectionDepth++ > 0 ) {
14388 m_xml.startElement(
"Section" )
14389 .writeAttribute(
"name",
trim( sectionInfo.
name ) );
14390 writeSourceInfo( sectionInfo.
lineInfo );
14391 m_xml.ensureTagClosed();
14395 void XmlReporter::assertionStarting(
AssertionInfo const& ) { }
14397 bool XmlReporter::assertionEnded( AssertionStats
const& assertionStats ) {
14399 AssertionResult
const& result = assertionStats.assertionResult;
14401 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
14405 for(
auto const& msg : assertionStats.infoMessages ) {
14407 m_xml.scopedElement(
"Info" )
14408 .writeText( msg.message );
14410 m_xml.scopedElement(
"Warning" )
14411 .writeText( msg.message );
14421 if( result.hasExpression() ) {
14422 m_xml.startElement(
"Expression" )
14423 .writeAttribute(
"success", result.succeeded() )
14424 .writeAttribute(
"type", result.getTestMacroName() );
14426 writeSourceInfo( result.getSourceInfo() );
14428 m_xml.scopedElement(
"Original" )
14429 .writeText( result.getExpression() );
14430 m_xml.scopedElement(
"Expanded" )
14431 .writeText( result.getExpandedExpression() );
14435 switch( result.getResultType() ) {
14437 m_xml.startElement(
"Exception" );
14438 writeSourceInfo( result.getSourceInfo() );
14439 m_xml.writeText( result.getMessage() );
14440 m_xml.endElement();
14443 m_xml.startElement(
"FatalErrorCondition" );
14444 writeSourceInfo( result.getSourceInfo() );
14445 m_xml.writeText( result.getMessage() );
14446 m_xml.endElement();
14449 m_xml.scopedElement(
"Info" )
14450 .writeText( result.getMessage() );
14456 m_xml.startElement(
"Failure" );
14457 writeSourceInfo( result.getSourceInfo() );
14458 m_xml.writeText( result.getMessage() );
14459 m_xml.endElement();
14465 if( result.hasExpression() )
14466 m_xml.endElement();
14471 void XmlReporter::sectionEnded( SectionStats
const& sectionStats ) {
14472 StreamingReporterBase::sectionEnded( sectionStats );
14473 if( --m_sectionDepth > 0 ) {
14474 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResults" );
14475 e.writeAttribute(
"successes", sectionStats.assertions.passed );
14476 e.writeAttribute(
"failures", sectionStats.assertions.failed );
14477 e.writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
14480 e.writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
14482 m_xml.endElement();
14486 void XmlReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
14487 StreamingReporterBase::testCaseEnded( testCaseStats );
14488 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResult" );
14489 e.writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
14492 e.writeAttribute(
"durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
14494 if( !testCaseStats.stdOut.empty() )
14495 m_xml.scopedElement(
"StdOut" ).writeText(
trim( testCaseStats.stdOut ),
false );
14496 if( !testCaseStats.stdErr.empty() )
14497 m_xml.scopedElement(
"StdErr" ).writeText(
trim( testCaseStats.stdErr ),
false );
14499 m_xml.endElement();
14502 void XmlReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
14503 StreamingReporterBase::testGroupEnded( testGroupStats );
14505 m_xml.scopedElement(
"OverallResults" )
14506 .writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
14507 .writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
14508 .writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
14509 m_xml.endElement();
14512 void XmlReporter::testRunEnded( TestRunStats
const& testRunStats ) {
14513 StreamingReporterBase::testRunEnded( testRunStats );
14514 m_xml.scopedElement(
"OverallResults" )
14515 .writeAttribute(
"successes", testRunStats.totals.assertions.passed )
14516 .writeAttribute(
"failures", testRunStats.totals.assertions.failed )
14517 .writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
14518 m_xml.endElement();
14521 CATCH_REGISTER_REPORTER(
"xml", XmlReporter )
14525 #if defined(_MSC_VER) 14526 #pragma warning(pop) 14531 LeakDetector leakDetector;
14535 #pragma clang diagnostic pop 14541 #ifdef CATCH_CONFIG_MAIN 14546 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) 14548 extern "C" int wmain (
int argc,
wchar_t * argv[],
wchar_t * []) {
14551 int main (
int argc,
char * argv[]) {
14554 return Catch::Session().run( argc, argv );
14560 int main (
int argc,
char *
const argv[]) {
14561 #if !CATCH_ARC_ENABLED 14562 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
14565 Catch::registerTestMethods();
14566 int result = Catch::Session().run( argc, (
char**)argv );
14568 #if !CATCH_ARC_ENABLED 14580 #if !defined(CATCH_CONFIG_IMPL_ONLY) 14582 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED 14583 # undef CLARA_CONFIG_MAIN 14586 #if !defined(CATCH_CONFIG_DISABLE) 14589 #ifdef CATCH_CONFIG_PREFIX_ALL 14591 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14592 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 14594 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14595 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 14596 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 14597 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14598 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 14599 #endif// CATCH_CONFIG_DISABLE_MATCHERS 14600 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14602 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14603 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 14604 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14605 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14606 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 14608 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14609 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 14610 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 14611 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14612 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 14613 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14614 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14616 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14617 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 14619 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 14620 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14622 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 14623 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 14624 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ ) 14626 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 14627 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14628 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 14629 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 14630 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 14631 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 14632 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14633 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14634 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14636 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 14638 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 14639 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14640 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14641 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 14642 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14644 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 14645 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 14646 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 14647 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 14650 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 14651 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ ) 14652 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ ) 14654 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ ) 14655 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ ) 14659 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 14660 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 14661 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 14662 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 14663 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 14664 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 14665 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 14666 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 14671 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14672 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 14674 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14675 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 14676 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 14677 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14678 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) 14679 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14680 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14682 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14683 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) 14684 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14685 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14686 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) 14688 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14689 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 14690 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 14691 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14692 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 14693 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14694 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14696 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14697 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 14699 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 14700 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14702 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 14703 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) 14704 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 14705 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) 14707 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 14708 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14709 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 14710 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 14711 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 14712 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ ) 14713 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 14714 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14715 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 14716 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() 14718 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 14719 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14720 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14721 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) 14722 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14724 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) ) 14725 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 14726 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) ) 14727 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) ) 14730 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE) 14731 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ ) 14732 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" ) 14734 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ ) 14735 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ ) 14740 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 14743 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 14744 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 14746 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc ) 14747 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc ) 14748 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc ) 14749 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc ) 14750 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc ) 14751 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc ) 14755 #else // CATCH_CONFIG_DISABLE 14759 #ifdef CATCH_CONFIG_PREFIX_ALL 14761 #define CATCH_REQUIRE( ... ) (void)(0) 14762 #define CATCH_REQUIRE_FALSE( ... ) (void)(0) 14764 #define CATCH_REQUIRE_THROWS( ... ) (void)(0) 14765 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 14766 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 14767 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14768 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 14769 #endif// CATCH_CONFIG_DISABLE_MATCHERS 14770 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) 14772 #define CATCH_CHECK( ... ) (void)(0) 14773 #define CATCH_CHECK_FALSE( ... ) (void)(0) 14774 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) 14775 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 14776 #define CATCH_CHECK_NOFAIL( ... ) (void)(0) 14778 #define CATCH_CHECK_THROWS( ... ) (void)(0) 14779 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 14780 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) 14781 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14782 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 14783 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14784 #define CATCH_CHECK_NOTHROW( ... ) (void)(0) 14786 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14787 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0) 14789 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) 14790 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14792 #define CATCH_INFO( msg ) (void)(0) 14793 #define CATCH_WARN( msg ) (void)(0) 14794 #define CATCH_CAPTURE( msg ) (void)(0) 14796 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14797 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14798 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) 14799 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) 14800 #define CATCH_SECTION( ... ) 14801 #define CATCH_DYNAMIC_SECTION( ... ) 14802 #define CATCH_FAIL( ... ) (void)(0) 14803 #define CATCH_FAIL_CHECK( ... ) (void)(0) 14804 #define CATCH_SUCCEED( ... ) (void)(0) 14806 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14808 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 14809 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) 14810 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) 14811 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14812 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14814 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) ) 14815 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) ) 14816 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14817 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14821 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14822 #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 ) 14823 #define CATCH_GIVEN( desc ) 14824 #define CATCH_AND_GIVEN( desc ) 14825 #define CATCH_WHEN( desc ) 14826 #define CATCH_AND_WHEN( desc ) 14827 #define CATCH_THEN( desc ) 14828 #define CATCH_AND_THEN( desc ) 14830 #define CATCH_STATIC_REQUIRE( ... ) (void)(0) 14831 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0) 14836 #define REQUIRE( ... ) (void)(0) 14837 #define REQUIRE_FALSE( ... ) (void)(0) 14839 #define REQUIRE_THROWS( ... ) (void)(0) 14840 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) 14841 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) 14842 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14843 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 14844 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14845 #define REQUIRE_NOTHROW( ... ) (void)(0) 14847 #define CHECK( ... ) (void)(0) 14848 #define CHECK_FALSE( ... ) (void)(0) 14849 #define CHECKED_IF( ... ) if (__VA_ARGS__) 14850 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) 14851 #define CHECK_NOFAIL( ... ) (void)(0) 14853 #define CHECK_THROWS( ... ) (void)(0) 14854 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) 14855 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0) 14856 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14857 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) 14858 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14859 #define CHECK_NOTHROW( ... ) (void)(0) 14861 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS) 14862 #define CHECK_THAT( arg, matcher ) (void)(0) 14864 #define REQUIRE_THAT( arg, matcher ) (void)(0) 14865 #endif // CATCH_CONFIG_DISABLE_MATCHERS 14867 #define INFO( msg ) (void)(0) 14868 #define WARN( msg ) (void)(0) 14869 #define CAPTURE( msg ) (void)(0) 14871 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14872 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14873 #define METHOD_AS_TEST_CASE( method, ... ) 14874 #define REGISTER_TEST_CASE( Function, ... ) (void)(0) 14875 #define SECTION( ... ) 14876 #define DYNAMIC_SECTION( ... ) 14877 #define FAIL( ... ) (void)(0) 14878 #define FAIL_CHECK( ... ) (void)(0) 14879 #define SUCCEED( ... ) (void)(0) 14880 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) 14882 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR 14883 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) 14884 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) 14885 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14886 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14888 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) ) 14889 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) ) 14890 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ ) 14891 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) 14894 #define STATIC_REQUIRE( ... ) (void)(0) 14895 #define STATIC_REQUIRE_FALSE( ... ) (void)(0) 14899 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 14902 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) 14903 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) 14905 #define GIVEN( desc ) 14906 #define AND_GIVEN( desc ) 14907 #define WHEN( desc ) 14908 #define AND_WHEN( desc ) 14909 #define THEN( desc ) 14910 #define AND_THEN( desc ) 14916 #endif // ! CATCH_CONFIG_IMPL_ONLY 14922 # ifdef __ICC // icpc defines the __clang__ macro 14923 # pragma warning(pop) 14925 # pragma clang diagnostic pop 14927 #elif defined __GNUC__ 14928 # pragma GCC diagnostic pop 14933 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED EqualsMatcher(std::vector< T > const &comparator)
virtual T const & get() const =0
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 operator==(StringRef const &other) const noexcept -> bool
TFSIMD_FORCE_INLINE Vector3 operator*(const Matrix3x3 &m, const Vector3 &v)
auto getResult() const -> bool
Totals & operator+=(Totals const &other)
ChunkGenerator(size_t size, GeneratorWrapper< T > generator)
std::vector< MatcherBase< ArgT > const * > m_matchers
std::string rawMemoryToString(const T &object)
std::unique_ptr< GeneratorUntypedBase > GeneratorBasePtr
FixedValuesGenerator(std::initializer_list< T > values)
const char * what() const noexcept override final
CaseSensitive::Choice m_caseSensitivity
bool isFalseTest(int flags)
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
TestCase(ITestInvoker *testCase, TestCaseInfo &&info)
bool operator>(const TiXmlString &a, const TiXmlString &b)
bool match(std::vector< T > const &v) const override
std::string m_description
GeneratorWrapper< T > map(Func &&function, GeneratorWrapper< T > &&generator)
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)
TFSIMD_FORCE_INLINE Quaternion operator-(const Quaternion &q)
void toLowerInPlace(std::string &s)
virtual StartupExceptionRegistry const & getStartupExceptionRegistry() const =0
std::vector< std::unique_ptr< IExceptionTranslator const > > ExceptionTranslators
std::shared_ptr< ITestInvoker > test
void handleMessage(ResultWas::OfType resultType, StringRef const &message)
void handleExceptionNotThrownAsExpected()
void populate(U &&valueOrGenerator, Gs... moreGenerators)
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)
void run(class_loader::ClassLoader *loader)
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
virtual void registerTagAlias(std::string const &alias, std::string const &tag, SourceLineInfo const &lineInfo)=0
GeneratorWrapper< std::tuple< Ts... > > table(std::initializer_list< std::tuple< typename std::decay< Ts >::type... >> tuples)
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
bool operator<(const TiXmlString &a, const TiXmlString &b)
PredicateMatcher(std::function< bool(T const &)> const &elem, std::string const &descr)
auto makeUnaryExpr() const -> UnaryExpr< LhsT >
std::vector< double > values
std::vector< T > const & m_target
GeneratorWrapper< T > m_generator
virtual void registerReporter(std::string const &name, IReporterFactoryPtr const &factory)=0
ros::Time * timeStamp(M &m)
virtual IConfigPtr const & getConfig() const =0
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
GeneratorWrapper(std::unique_ptr< IGenerator< T >> generator)
GeneratorWrapper< U > m_generator
typename append< Final<>, typename rewrap< Containers, Types... >::type... >::type type
std::string toString() const
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(*)() exceptionTranslateFunction
Approx & epsilon(T const &newEpsilon)
Capturer(StringRef macroName, SourceLineInfo const &lineInfo, ResultWas::OfType resultType, StringRef names)
static std::string convert(T const(&arr)[SZ])
std::vector< std::string > lcaseTags
GeneratorWrapper< T > value(T &&value)
StdString::RegexMatcher Matches(std::string const ®ex, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
auto operator!=(StringRef const &other) const noexcept -> bool
GeneratorWrapper< std::vector< T > > chunk(size_t size, GeneratorWrapper< T > &&generator)
virtual auto hasGenerator() const -> bool=0
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name)
virtual RunTests::InWhatOrder runOrder() const =0
#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
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
virtual void handleFatalErrorCondition(StringRef message)=0
GeneratorWrapper< T > m_generator
std::enable_if< std::is_floating_point< T >::value, GeneratorWrapper< T > >::type random(T a, T b)
std::uniform_int_distribution< Integer > m_dist
virtual auto getGenerator() const -> Generators::GeneratorBasePtr const &=0
StringRef(std::string const &stdString) noexcept
typename append< L1< E1..., E2... >, Rest... >::type type
std::vector< std::string > tags
std::string operator+() const
#define CATCH_INTERNAL_ERROR(msg)
static std::string convert(signed char const *str)
IMutableRegistryHub & getMutableRegistryHub()
Counts & operator+=(Counts const &other)
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
void swap(Bag &a, Bag &b)
#define max(a, b)
Takes the maximal value of a and b.
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)
auto makeGenerators(as< T >, U &&val, Gs... moreGenerators) -> Generators< T >
std::vector< T > const & m_comparator
bool add(const actionlib::TwoIntsGoal &req, actionlib::TwoIntsResult &res)
auto isSubstring() const noexcept -> bool
static std::string convert(U *p)
virtual void registerStartupException() noexcept=0
auto operator[](size_type index) const noexcept -> char
std::vector< GeneratorWrapper< T > > m_generators
virtual void pushScopedMessage(MessageInfo const &message)=0
virtual ~ITestCaseRegistry()
auto getElapsedSeconds() const -> double
GeneratorWrapper< T > filter(Predicate &&pred, GeneratorWrapper< T > &&generator)
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)
bool expectedToFail() const
auto str() const -> std::string
std::unique_ptr< T > make_unique(Args &&... args)
bool isJustInfo(int flags)
GeneratorWrapper< T > m_generator
auto empty() const noexcept -> bool
GeneratorException(const char *msg)
AutoReg(ITestInvoker *invoker, SourceLineInfo const &lineInfo, StringRef const &classOrMethod, NameAndTags const &nameAndTags) noexcept
static std::string convert(R const &range)
GeneratorWrapper< T > range(T const &start, T const &end)
std::string tagsAsString() const
std::vector< TestCase > filterTests(std::vector< TestCase > const &testCases, TestSpec const &testSpec, IConfig const &config)
AssertionReaction m_reaction
TestCase withName(std::string const &_newName) const
std::uniform_real_distribution< Float > m_dist
AssertionInfo m_assertionInfo
void handleUnexpectedInflightException()
Floating::WithinAbsMatcher WithinAbs(double target, double margin)
auto currentData() const noexcept -> char const *
Approx & scale(T const &newScale)
void populate(GeneratorWrapper< T > &&generator)
static FRESULT sync(FATFS *fs)
static std::string convert(R C::*p)
StringRef m_matcherString
BinaryExpr(bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs)
auto makeTestInvoker(void(*testAsFunction)()) noexcept -> ITestInvoker *
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)
virtual ~IExceptionTranslatorRegistry()
virtual bool allowThrows() const =0
bool isOk(ResultWas::OfType resultType)
virtual void registerTranslator(const IExceptionTranslator *translator)=0
XMLRPCPP_DECL void setVerbosity(int level)
ReusableStringStream m_stream
bool operator<(MessageInfo const &other) const
virtual ~ITransientExpression()
GeneratorWrapper< T > m_generator
TestCaseInfo const & getTestCaseInfo() const
bool operator<(SourceLineInfo const &other) const noexcept
void handleThrowingCallSkipped()
void handleExceptionThrownAsExpected()
Totals operator-(Totals const &other) const
std::unique_ptr< IGenerator< T > > m_generator
Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff)
ROSCPP_DECL bool get(const std::string &key, std::string &s)
virtual std::string translateActiveException() const =0
auto needsMoreIterations() -> bool
std::map< ClassName, impl::AbstractMetaObjectBase *> FactoryMap
void captureValues(size_t index, T const &value)
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::vector< T > m_returned
SingleValueGenerator(T &&value)
std::string describe() const override
std::string toLower(std::string const &s)
void captureValues(size_t index, T const &value, Ts const &... values)
std::string translateActiveException()
virtual void benchmarkStarting(BenchmarkInfo const &info)=0
Vector::EqualsMatcher< T > Equals(std::vector< T > const &comparator)
virtual ~IMutableContext()
virtual void streamReconstructedExpression(std::ostream &os) const =0
std::string describe() const override
ContainsElementMatcher(T const &comparator)
Counts operator-(Counts const &other) const
bool operator==(const TiXmlString &a, const TiXmlString &b)
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 handleExpr(ExprLhs< T > const &expr)
bool match(ArgT const &arg) const override
bool operator<(TestCase const &other) const
std::size_t total() const
auto numberOfCharacters() const noexcept -> size_type
IContext & getCurrentContext()
StringRef(StringRef &&other) noexcept
bool match(ArgT const &arg) const override
auto operator+=(std::string &lhs, StringRef const &sr) -> std::string &
auto generate(SourceLineInfo const &lineInfo, L const &generatorExpression) -> decltype(std::declval< decltype(generatorExpression())>().get())
GeneratorWrapper< T > repeat(size_t repeats, GeneratorWrapper< T > &&generator)
RegistrarForTagAliases(char const *alias, char const *tag, SourceLineInfo const &lineInfo)
RangeGenerator(T const &start, T const &end, T const &step)
BenchmarkLooper(StringRef name)
virtual ~IMutableRegistryHub()
USBInterfaceDescriptor data
MessageBuilder(StringRef const ¯oName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
IResultCapture & m_resultCapture
void throw_exception(std::exception const &e)
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
auto getElapsedMicroseconds() const -> uint64_t
MapGenerator(F2 &&function, GeneratorWrapper< U > &&generator)
bool operator==(TestCase const &other) const
const std::string unprintableString
void * malloc(size_t size)
NMI_API sint8 close(SOCKET sock)
static std::enable_if<::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
bool operator>=(const TiXmlString &a, const TiXmlString &b)
virtual void handleIncomplete(AssertionInfo const &info)=0
std::string rangeToString(std::vector< bool, Allocator > const &v)
auto isBinaryExpression() const -> bool
unsigned char bool
Boolean.
auto isOwned() const noexcept -> bool
MessageInfo(StringRef const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
std::string m_cachedToString
Generators(Gs... moreGenerators)
Section(SectionInfo const &info)
bool operator!=(const TiXmlString &a, const TiXmlString &b)
virtual IReporterRegistry const & getReporterRegistry() const =0
std::vector< MatcherBase< ArgT > const * > m_matchers
virtual IResultCapture * getResultCapture()=0
auto acquireGeneratorTracker(SourceLineInfo const &lineInfo) -> IGeneratorTracker &
MatchAllOf< T > operator&&(MatcherBase const &other) const
FilterGenerator(P &&pred, GeneratorWrapper< T > &&generator)
virtual unsigned int rngSeed() const =0
Totals delta(Totals const &prevTotals) const
auto makeMatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef const &matcherString) -> MatchExpr< ArgT, MatcherT >
RandomIntegerGenerator(Integer a, Integer b)
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)
std::string describe() const override
RepeatGenerator(size_t repeats, GeneratorWrapper< T > &&generator)
MatchNotOf< T > operator!() const
std::string describe() const override
void convert(const A &a, B &b)
std::function< bool(T const &)> m_predicate
virtual void sectionEnded(SectionEndInfo const &endInfo)=0
void handleExceptionMatchExpr(AssertionHandler &handler, std::string const &str, StringRef const &matcherString)
MatcherBase< ArgT > const & m_underlyingMatcher
bool match(std::vector< T > const &v) const override
std::vector< T > const & m_comparator
static IMutableContext * currentContext
virtual IExceptionTranslatorRegistry const & getExceptionTranslatorRegistry() const =0
auto size() const noexcept -> size_type
IMutableContext & getCurrentMutableContext()
void swap(StringRef &other) noexcept
void streamReconstructedExpression(std::ostream &os) const override
bool contains(InputIterator first, InputIterator last, T const &item)
IRegistryHub const & getRegistryHub()
Vector::UnorderedEqualsMatcher< T > UnorderedEquals(std::vector< T > const &target)
virtual ~IExceptionTranslator()
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
static FRESULT validate(FATFS *fs, WORD id)
void handleUnexpectedExceptionNotThrown()
bool operator<=(const TiXmlString &a, const TiXmlString &b)
MatchAnyOf< T > operator||(MatcherBase const &other) const
auto compareEqual(LhsT const &lhs, RhsT const &rhs) -> bool
void captureValue(size_t index, std::string const &value)
std::shared_ptr< IConfig const > IConfigPtr
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)
typename append< TypeList< Container< Elems... > >, typename rewrap< Container, Elements... >::type >::type type
auto substr(size_type start, size_type size) const noexcept -> StringRef
RandomFloatingGenerator(Float a, Float b)
virtual void setConfig(IConfigPtr const &config)=0
static void createContext()
std::string rangeToString(Range const &range)
void invoke() const override
bool equalityComparisonImpl(double other) const
auto makeStream(StringRef const &filename) -> IStream const *
static std::string convert(unsigned char const *str)
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
GeneratorWrapper< T > take(size_t target, GeneratorWrapper< T > &&generator)
TakeGenerator(size_t target, GeneratorWrapper< T > &&generator)
bool startsWith(std::string const &s, std::string const &prefix)
RangeGenerator(T const &start, T const &end)
bool operator==(MessageInfo const &other) const
Vector::ContainsElementMatcher< T > VectorContains(T const &comparator)
auto getElapsedMilliseconds() const -> unsigned int