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 2
21# pragma clang system_header
23# pragma GCC system_header
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"
42# pragma GCC diagnostic ignored "-Wparentheses"
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
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
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
299# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
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))
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__ )
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
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;
559 : m_start( rawChars ),
564 : m_start( stdString.c_str() ),
565 m_size( stdString.size() )
575 m_start = other.m_start;
576 m_size = other.m_size;
580 operator std::string()
const;
591 auto empty() const noexcept ->
bool {
609 auto isOwned() const noexcept ->
bool;
610 auto isSubstring() const noexcept ->
bool;
614 auto operator + (
StringRef const& lhs,
char const* rhs ) ->
std::
string;
615 auto operator + (
char const* lhs,
StringRef const& rhs ) ->
std::
string;
617 auto operator += (
std::
string& lhs,
StringRef const& sr ) ->
std::
string&;
620 inline auto operator "" _sr(
char const* rawChars,
std::
size_t size ) noexcept ->
StringRef {
626inline 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...>
648template <
typename...>
651template <
typename T0,
typename T1,
typename... Rest>
652struct 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(...)
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>
750template<
typename... >
753template<
typename... >
756template<
template<
typename...>
class L1
758 ,
template<
typename...>
class L2
762 using type = L1<E1..., E2...>;
765template<
template<
typename...>
class L1
767 ,
template<
typename...>
class L2
771struct append< L1<E1...>, L2<E2...>, Rest...> {
775template<
template<
typename...>
class
780template<
template<
typename...>
class Container
781 ,
template<
typename...>
class List
788template<
template<
typename...>
class Container
789 ,
template<
typename...>
class List
791 ,
typename...Elements>
796template<
template<
typename...>
class...Containers >
798 template<
typename...Types >
800 template<
template <
typename...>
class Final >
817 void (C::*m_testAsMethod)();
823 (obj.*m_testAsMethod)();
827auto makeTestInvoker(
void(*testAsFunction)() ) noexcept -> ITestInvoker*;
830auto
makeTestInvoker(
void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
831 return new(std::nothrow) TestInvokerAsMethod<C>( 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__ ) )
1127#include <type_traits>
1137 std::ostream&
cout();
1138 std::ostream&
cerr();
1139 std::ostream&
clog();
1151 std::size_t m_index;
1152 std::ostream* m_oss;
1164 auto get() -> std::ostream& {
return *m_oss; }
1170#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1171#include <string_view>
1177#import <Foundation/Foundation.h>
1180#define CATCH_ARC_ENABLED __has_feature(objc_arc)
1182#define CATCH_ARC_ENABLED 0
1188#if !CATCH_ARC_ENABLED
1193 if( [obj respondsToSelector: sel] )
1194 return [obj performSelector: sel];
1197#define CATCH_UNSAFE_UNRETAINED
1198#define CATCH_ARC_STRONG
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)
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<
1255 !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
1259 template<
typename T>
1260 typename std::enable_if<
1261 !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
1266 template<
typename T>
1267 typename std::enable_if<
1268 std::is_enum<T>::value
1273#if defined(_MANAGED)
1275 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>
1292 typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
1297 rss.operator<<(
value);
1301 template <
typename Fake = T>
1303 typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
1305#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
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>
1324 return ::Catch::Detail::stringify(
static_cast<typename std::underlying_type<E>::type
>(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);
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);
1387 return ::Catch::Detail::stringify(std::string{ str });
1392 static std::string
convert(
signed char const* str) {
1393 return ::Catch::Detail::stringify(std::string{
reinterpret_cast<char const *
>(str) });
1398 static std::string
convert(
unsigned char const* str) {
1399 return ::Catch::Detail::stringify(std::string{
reinterpret_cast<char const *
>(str) });
1460 template <
typename T>
1462 template <
typename U>
1465 return ::Catch::Detail::rawMemoryToString(
p);
1472 template <
typename R,
typename C>
1476 return ::Catch::Detail::rawMemoryToString(
p);
1483#if defined(_MANAGED)
1484 template <
typename T>
1485 struct StringMaker<
T^> {
1486 static std::string convert(
T^ ref ) {
1487 return ::Catch::Detail::clrReferenceToString(ref);
1493 template<
typename InputIterator>
1494 std::string
rangeToString(InputIterator first, InputIterator last) {
1495 ReusableStringStream rss;
1497 if (first != last) {
1499 for (++first; first != last; ++first)
1509 struct StringMaker<NSString*> {
1510 static std::string convert(NSString * nsstring) {
1513 return std::string(
"@") + [nsstring UTF8String];
1517 struct StringMaker<NSObject*> {
1518 static std::string convert(NSObject* nsObject) {
1519 return ::Catch::Detail::stringify([nsObject description]);
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>
1550 struct StringMaker<
std::pair<T1, T2> > {
1551 static std::string
convert(
const std::pair<T1, T2>& pair) {
1552 ReusableStringStream rss;
1564#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
1567 template<
typename T>
1568 struct StringMaker<
std::optional<T> > {
1569 static std::string
convert(
const std::optional<T>& optional) {
1570 ReusableStringStream rss;
1571 if (optional.has_value()) {
1583#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
1590 bool = (N < std::tuple_size<Tuple>::value)
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>
1611 struct StringMaker<
std::tuple<Types...>> {
1612 static std::string
convert(
const std::tuple<Types...>& tuple) {
1613 ReusableStringStream rss;
1615 Detail::TupleElementPrinter<std::tuple<Types...>>
::print(tuple, rss.get());
1623#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
1627 struct StringMaker<
std::monostate> {
1628 static std::string
convert(
const std::monostate&) {
1633 template<
typename... Elements>
1634 struct StringMaker<
std::variant<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) {
1641 return ::Catch::Detail::stringify(
value);
1661 template <
typename T>
1663 static const bool value =
1668#if defined(_MANAGED)
1669 template <
typename T>
1671 static const bool value =
false;
1675 template<
typename Range>
1677 return ::Catch::Detail::rangeToString(
begin( range ),
end( range ) );
1681 template<
typename Allocator>
1682 std::string
rangeToString( std::vector<bool, Allocator>
const& v ) {
1683 ReusableStringStream rss;
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)
1721template <
class Ratio>
1722struct ratio_string {
1723 static std::string symbol();
1726template <
class Ratio>
1727std::string ratio_string<Ratio>::symbol() {
1729 rss <<
'[' << Ratio::num <<
'/'
1730 << Ratio::den <<
']';
1734struct ratio_string<
std::atto> {
1735 static std::string symbol();
1738struct ratio_string<
std::femto> {
1739 static std::string symbol();
1742struct ratio_string<
std::pico> {
1743 static std::string symbol();
1746struct ratio_string<
std::nano> {
1747 static std::string symbol();
1750struct ratio_string<
std::micro> {
1751 static std::string symbol();
1754struct 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) {
1763 ReusableStringStream rss;
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) {
1771 ReusableStringStream rss;
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) {
1779 ReusableStringStream rss;
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) {
1787 ReusableStringStream rss;
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");
1816 char timeStamp[timeStampSize];
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);
1838#pragma warning(push)
1839#pragma warning(disable:4389)
1840#pragma warning(disable:4018)
1841#pragma warning(disable:4312)
1842#pragma warning(disable:4180)
1843#pragma warning(disable:4800)
1869 template<
typename LhsT,
typename RhsT>
1875 void streamReconstructedExpression( std::ostream &
os )
const override {
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>
1949 void streamReconstructedExpression( std::ostream &
os )
const override {
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>
2072 class AssertionResult;
2073 struct AssertionInfo;
2075 struct SectionEndInfo;
2077 struct MessageBuilder;
2079 struct BenchmarkInfo;
2080 struct BenchmarkStats;
2081 struct AssertionReaction;
2082 struct SourceLineInfo;
2084 struct ITransientExpression;
2085 struct IGeneratorTracker;
2092 Counts& assertions ) = 0;
2122 std::string
const& message,
2163 explicit operator bool()
const;
2176 bool m_completed =
false;
2186 if ( !m_completed ) {
2191 template<
typename T>
2238 static unsigned int globalCount;
2243 template<
typename T>
2257 template<
typename T>
2278 std::vector<MessageInfo> m_messages;
2280 size_t m_captured = 0;
2287 template<
typename T>
2292 template<
typename T,
typename... Ts>
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 )
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__) ) )
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 ) \
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 ) {}
2496 std::string description;
2503 double durationInSeconds;
2515 auto getCurrentNanosecondsSinceEpoch() ->
uint64_t;
2516 auto getEstimatedClockResolution() ->
uint64_t;
2524 auto getElapsedMilliseconds() const ->
unsigned int;
2525 auto getElapsedSeconds() const ->
double;
2541 explicit operator bool()
const;
2548 bool m_sectionIncluded;
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() )
2591 explicit operator bool() {
2592 if( m_count < m_iterationsToRun )
2594 return needsMoreIterations();
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;
2629 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
2656 std::
string translateActiveException();
2661#if defined(CATCH_CONFIG_DISABLE)
2662 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
2663 static std::string translatorName( signature )
2678 virtual std::string
translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd )
const = 0;
2688 template<
typename T>
2692 ExceptionTranslator( std::string(*translateFunction)(
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>
2716 (
new ExceptionTranslator<T>( translateFunction ) );
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);
2756 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2759 approx.m_epsilon = m_epsilon;
2760 approx.m_margin = m_margin;
2761 approx.m_scale = m_scale;
2765 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2769 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2771 auto lhs_v =
static_cast<double>(lhs);
2772 return rhs.equalityComparisonImpl(lhs_v);
2775 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2780 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2785 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2790 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2792 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
2795 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2797 return lhs.m_value <
static_cast<double>(rhs) || lhs == rhs;
2800 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2802 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
2805 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2807 return lhs.m_value >
static_cast<double>(rhs) || lhs == rhs;
2810 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2812 double epsilonAsDouble =
static_cast<double>(newEpsilon);
2813 setEpsilon(epsilonAsDouble);
2817 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2819 double marginAsDouble =
static_cast<double>(newMargin);
2820 setMargin(marginAsDouble);
2824 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2826 m_scale =
static_cast<double>(newScale);
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 );
2865 void toLowerInPlace( std::string&
s );
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 );
2875 std::size_t m_count;
2876 std::string m_label;
2881#ifndef CATCH_CONFIG_DISABLE_MATCHERS
2893 template<
typename ArgT>
struct MatchAllOf;
2894 template<
typename ArgT>
struct MatchAnyOf;
2895 template<
typename ArgT>
struct MatchNotOf;
2907 mutable std::string m_cachedToString;
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 );
2962 std::vector<MatcherBase<ArgT>
const*> m_matchers;
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 );
2995 std::vector<MatcherBase<ArgT>
const*> m_matchers;
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>
3015 return MatchAllOf<T>() && *
this && other;
3017 template<
typename T>
3019 return MatchAnyOf<T>() || *
this || other;
3021 template<
typename T>
3022 MatchNotOf<T> MatcherBase<T>::operator ! ()
const {
3023 return MatchNotOf<T>( *
this );
3030using namespace Matchers;
3031using Matchers::Impl::MatcherBase;
3038#include <type_traits>
3044 namespace Floating {
3050 bool match(
double const& matchee)
const override;
3059 bool match(
double const& matchee)
const override;
3081#include <functional>
3089 std::string finalizeDescription(
const std::string& desc);
3092template <
typename T>
3094 std::function<bool(
T const&)> m_predicate;
3095 std::string m_description;
3099 :m_predicate(
std::move(elem)),
3100 m_description(Detail::finalizeDescription(descr))
3104 return m_predicate(item);
3108 return m_description;
3118 template<
typename T>
3134 namespace StdString {
3151 std::string m_operation;
3173 bool match( std::string
const& matchee )
const override;
3177 std::string m_regex;
3204 template<
typename T>
3209 bool match(std::vector<T>
const &v)
const override {
3210 for (
auto const& el : v) {
3211 if (el == m_comparator) {
3222 T const& m_comparator;
3225 template<
typename T>
3230 bool match(std::vector<T>
const &v)
const override {
3232 if (m_comparator.size() > v.size())
3234 for (
auto const& comparator : m_comparator) {
3235 auto present =
false;
3236 for (
const auto& el : v) {
3237 if (el == comparator) {
3252 std::vector<T>
const& m_comparator;
3255 template<
typename T>
3260 bool match(std::vector<T>
const &v)
const override {
3265 if (m_comparator.size() != v.size())
3267 for (std::size_t i = 0; i < v.size(); ++i)
3268 if (m_comparator[i] != v[i])
3275 std::vector<T>
const& m_comparator;
3278 template<
typename T>
3283 bool match(std::vector<T>
const &v)
const override {
3284 if (m_comparator.size() != v.size())
3286 for (std::size_t i = 0; i < v.size(); ++i)
3287 if (m_comparator[i] != approx(v[i]))
3294 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3299 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3301 approx.
margin(newMargin);
3304 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3306 approx.
scale(newScale);
3310 std::vector<T>
const& m_comparator;
3314 template<
typename T>
3317 bool match(std::vector<T>
const& vec)
const override {
3320 if (m_target.size() != vec.size()) {
3323 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
3330 std::vector<T>
const& m_target;
3338 template<
typename T>
3343 template<
typename T>
3344 Vector::ContainsElementMatcher<T> VectorContains(
T const& comparator ) {
3345 return Vector::ContainsElementMatcher<T>( comparator );
3348 template<
typename T>
3349 Vector::EqualsMatcher<T>
Equals( std::vector<T>
const& comparator ) {
3350 return Vector::EqualsMatcher<T>( comparator );
3353 template<
typename T>
3354 Vector::ApproxMatcher<T>
Approx( std::vector<T>
const& comparator ) {
3355 return Vector::ApproxMatcher<T>( comparator );
3358 template<
typename T>
3359 Vector::UnorderedEqualsMatcher<T>
UnorderedEquals(std::vector<T>
const& target) {
3360 return Vector::UnorderedEqualsMatcher<T>(target);
3369 template<
typename ArgT,
typename MatcherT>
3378 m_matcher( matcher ),
3379 m_matcherString( matcherString )
3383 auto matcherAsString = m_matcher.toString();
3385 if( matcherAsString == Detail::unprintableString )
3386 os << m_matcherString;
3388 os << matcherAsString;
3392 using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
3394 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher
const& matcher,
StringRef const& matcherString );
3396 template<
typename ArgT,
typename MatcherT>
3397 auto makeMatchExpr( ArgT
const& arg, MatcherT
const& matcher,
StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> {
3398 return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
3404#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
3406 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3407 INTERNAL_CATCH_TRY { \
3408 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \
3409 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
3410 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3414#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
3416 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3417 if( catchAssertionHandler.allowThrows() ) \
3419 static_cast<void>(__VA_ARGS__ ); \
3420 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
3422 catch( exceptionType const& ex ) { \
3423 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \
3426 catchAssertionHandler.handleUnexpectedInflightException(); \
3429 catchAssertionHandler.handleThrowingCallSkipped(); \
3430 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3444 namespace Generators {
3462 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
3463 virtual
void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
3474#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
3475 template <
typename Ex>
3486#define CATCH_PREPARE_EXCEPTION( type, msg ) \
3487 type( ( Catch::ReusableStringStream() << msg ).str() )
3488#define CATCH_INTERNAL_ERROR( msg ) \
3489 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg))
3490#define CATCH_ERROR( msg ) \
3491 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg ))
3492#define CATCH_RUNTIME_ERROR( msg ) \
3493 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg ))
3494#define CATCH_ENFORCE( condition, msg ) \
3495 do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
3508 const char*
const m_msg =
"";
3515 const char*
what() const noexcept override final;
3518namespace Generators {
3522 template<
typename T,
typename... Args>
3523 std::unique_ptr<T> make_unique( Args&&... args ) {
3524 return std::unique_ptr<T>(
new T(std::forward<Args>(args)...));
3528 template<
typename T>
3540 template<
typename T>
3555 template<
typename T>
3557 std::vector<T> m_values;
3563 return m_values[m_idx];
3567 return m_idx < m_values.size();
3571 template <
typename T>
3573 std::unique_ptr<IGenerator<T>> m_generator;
3576 m_generator(
std::move(generator))
3579 return m_generator->get();
3582 return m_generator->next();
3586 template <
typename T>
3588 return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(
value)));
3590 template <
typename T>
3591 GeneratorWrapper<T> values(std::initializer_list<T> values) {
3592 return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));
3595 template<
typename T>
3597 std::vector<GeneratorWrapper<T>> m_generators;
3598 size_t m_current = 0;
3601 m_generators.emplace_back(std::move(generator));
3603 void populate(
T&& val) {
3604 m_generators.emplace_back(
value(std::move(val)));
3606 template<
typename U>
3607 void populate(
U&& val) {
3608 populate(
T(std::move(val)));
3610 template<
typename U,
typename... Gs>
3611 void populate(
U&& valueOrGenerator, Gs... moreGenerators) {
3612 populate(std::forward<U>(valueOrGenerator));
3613 populate(std::forward<Gs>(moreGenerators)...);
3617 template <
typename... Gs>
3619 m_generators.reserve(
sizeof...(Gs));
3620 populate(std::forward<Gs>(moreGenerators)...);
3624 return m_generators[m_current].get();
3628 if (m_current >= m_generators.size()) {
3631 const bool current_status = m_generators[m_current].next();
3632 if (!current_status) {
3635 return m_current < m_generators.size();
3639 template<
typename... Ts>
3640 GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<
typename std::decay<Ts>::type...>> tuples ) {
3641 return values<std::tuple<Ts...>>( tuples );
3645 template <
typename T>
3648 template<
typename T,
typename... Gs>
3650 return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
3652 template<
typename T>
3653 auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
3654 return Generators<T>(std::move(generator));
3656 template<
typename T,
typename... Gs>
3657 auto makeGenerators(
T&& val, Gs... moreGenerators ) -> Generators<T> {
3658 return makeGenerators(
value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
3660 template<
typename T,
typename U,
typename... Gs>
3661 auto makeGenerators( as<T>,
U&& val, Gs... moreGenerators ) -> Generators<T> {
3662 return makeGenerators(
value(
T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
3667 template<
typename L>
3671 auto generate( SourceLineInfo
const& lineInfo, L
const& generatorExpression ) ->
decltype(std::declval<decltype(generatorExpression())>().get()) {
3672 using UnderlyingType =
typename decltype(generatorExpression())::type;
3675 if (!tracker.hasGenerator()) {
3676 tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
3679 auto const& generator =
static_cast<IGenerator<UnderlyingType> const&
>( *tracker.getGenerator() );
3680 return generator.get();
3686#define GENERATE( ... ) \
3687 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
3688#define GENERATE_COPY( ... ) \
3689 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
3690#define GENERATE_REF( ... ) \
3691 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
3697namespace Generators {
3699 template <
typename T>
3702 size_t m_returned = 0;
3706 m_generator(
std::move(generator)),
3709 assert(target != 0 &&
"Empty generators are not allowed");
3712 return m_generator.
get();
3716 if (m_returned >= m_target) {
3720 const auto success = m_generator.
next();
3724 m_returned = m_target;
3730 template <
typename T>
3731 GeneratorWrapper<T> take(
size_t target, GeneratorWrapper<T>&& generator) {
3732 return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
3735 template <
typename T,
typename Predicate>
3740 template <
typename P = Predicate>
3742 m_generator(
std::move(generator)),
3743 m_predicate(
std::forward<
P>(pred))
3745 if (!m_predicate(m_generator.
get())) {
3748 auto has_initial_value = next();
3749 if (!has_initial_value) {
3750 Catch::throw_exception(GeneratorException(
"No valid value found in filtered generator"));
3756 return m_generator.get();
3760 bool success = m_generator.next();
3764 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) ==
true);
3769 template <
typename T,
typename Predicate>
3770 GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
3771 return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
3774 template <
typename T>
3777 mutable std::vector<T> m_returned;
3778 size_t m_target_repeats;
3779 size_t m_current_repeat = 0;
3780 size_t m_repeat_index = 0;
3783 m_generator(
std::move(generator)),
3784 m_target_repeats(repeats)
3786 assert(m_target_repeats > 0 &&
"Repeat generator must repeat at least once");
3790 if (m_current_repeat == 0) {
3791 m_returned.push_back(m_generator.
get());
3792 return m_returned.back();
3794 return m_returned[m_repeat_index];
3804 if (m_current_repeat == 0) {
3805 const auto success = m_generator.
next();
3809 return m_current_repeat < m_target_repeats;
3814 if (m_repeat_index == m_returned.size()) {
3818 return m_current_repeat < m_target_repeats;
3822 template <
typename T>
3823 GeneratorWrapper<T> repeat(
size_t repeats, GeneratorWrapper<T>&& generator) {
3824 return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
3827 template <
typename T,
typename U,
typename Func>
3835 template <
typename F2 = Func>
3837 m_generator(
std::move(generator)),
3838 m_function(
std::forward<F2>(function)),
3839 m_cache(m_function(m_generator.get()))
3846 const auto success = m_generator.
next();
3848 m_cache = m_function(m_generator.
get());
3854#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
3858 template <
typename Func,
typename U>
3859 using MapFunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>;
3861 template <
typename Func,
typename U>
3862 using MapFunctionReturnType =
typename std::remove_reference<
typename std::remove_cv<
typename std::result_of<Func(
U)>::type>::type>
::type;
3865 template <
typename Func,
typename U,
typename T = MapFunctionReturnType<Func, U>>
3866 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
3867 return GeneratorWrapper<T>(
3868 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
3872 template <
typename T,
typename U,
typename Func>
3873 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
3874 return GeneratorWrapper<T>(
3875 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
3879 template <
typename T>
3881 std::vector<T> m_chunk;
3882 size_t m_chunk_size;
3884 bool m_used_up =
false;
3887 m_chunk_size(size), m_generator(
std::move(generator))
3889 m_chunk.reserve(m_chunk_size);
3890 m_chunk.push_back(m_generator.
get());
3891 for (
size_t i = 1; i < m_chunk_size; ++i) {
3892 if (!m_generator.
next()) {
3895 m_chunk.push_back(m_generator.
get());
3898 std::vector<T>
const&
get()
const override {
3903 for (
size_t idx = 0; idx < m_chunk_size; ++idx) {
3904 if (!m_generator.
next()) {
3907 m_chunk.push_back(m_generator.
get());
3913 template <
typename T>
3914 GeneratorWrapper<std::vector<T>> chunk(
size_t size, GeneratorWrapper<T>&& generator) {
3915 return GeneratorWrapper<std::vector<T>>(
3916 pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
3932 struct IResultCapture;
3935 struct IMutableContext;
3937 using IConfigPtr = std::shared_ptr<IConfig const>;
3959 static void createContext();
3964 if( !IMutableContext::currentContext )
3965 IMutableContext::createContext();
3966 return *IMutableContext::currentContext;
3969 inline IContext& getCurrentContext()
3971 return getCurrentMutableContext();
3995 NoAssertions = 0x01,
4006 InLexicographicalOrder,
4018 BeforeStartAndExit = BeforeStart | BeforeExit
4029 virtual std::string
name()
const = 0;
4048 using IConfigPtr = std::shared_ptr<IConfig const>;
4055namespace Generators {
4057template <
typename Float>
4060 std::minstd_rand m_rand;
4061 std::uniform_real_distribution<Float> m_dist;
4062 Float m_current_number;
4068 static_cast<void>(next());
4071 Float
const&
get()
const override {
4072 return m_current_number;
4075 m_current_number = m_dist(m_rand);
4080template <
typename Integer>
4082 std::minstd_rand m_rand;
4083 std::uniform_int_distribution<Integer> m_dist;
4084 Integer m_current_number;
4090 static_cast<void>(next());
4093 Integer
const&
get()
const override {
4094 return m_current_number;
4097 m_current_number = m_dist(m_rand);
4104template <
typename T>
4105typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value,
4106GeneratorWrapper<T>>::type
4108 return GeneratorWrapper<T>(
4109 pf::make_unique<RandomIntegerGenerator<T>>(
a, b)
4113template <
typename T>
4114typename std::enable_if<std::is_floating_point<T>::value,
4115GeneratorWrapper<T>>::type
4117 return GeneratorWrapper<T>(
4118 pf::make_unique<RandomFloatingGenerator<T>>(
a, b)
4122template <
typename T>
4134 m_positive(m_step >
T(0))
4136 assert(m_current != m_end &&
"Range start and end cannot be equal");
4137 assert(m_step !=
T(0) &&
"Step size cannot be zero");
4138 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) &&
"Step moves away from end");
4150 m_current += m_step;
4151 return (m_positive) ? (m_current < m_end) : (m_current > m_end);
4155template <
typename T>
4156GeneratorWrapper<T> range(
T const& start,
T const& end,
T const& step) {
4157 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value,
"Type must be an integer");
4158 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
4161template <
typename T>
4162GeneratorWrapper<T> range(
T const& start,
T const& end) {
4163 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value,
"Type must be an integer");
4164 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end));
4181#pragma clang diagnostic push
4182#pragma clang diagnostic ignored "-Wpadded"
4187 struct ITestInvoker;
4193 ShouldFail = 1 << 2,
4196 NonPortable = 1 << 5,
4201 std::string
const& _className,
4202 std::string
const& _description,
4203 std::vector<std::string>
const& _tags,
4209 bool throws()
const;
4216 std::string className;
4217 std::string description;
4218 std::vector<std::string> tags;
4219 std::vector<std::string> lcaseTags;
4239 std::shared_ptr<ITestInvoker> test;
4243 std::string
const& className,
4249#pragma clang diagnostic pop
4268#import <objc/runtime.h>
4290 class OcMethod :
public ITestInvoker {
4293 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
4295 virtual void invoke()
const {
4296 id obj = [[m_cls alloc] init];
4305 virtual ~OcMethod() {}
4314 std::string
const& annotationName,
4315 std::string
const& testCaseName ) {
4316 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
4317 SEL sel = NSSelectorFromString( selStr );
4321 return [(NSString*)value UTF8String];
4327 std::size_t noTestMethods = 0;
4328 int noClasses = objc_getClassList(
nullptr, 0 );
4331 objc_getClassList( classes, noClasses );
4333 for(
int c = 0; c < noClasses; c++ ) {
4334 Class cls = classes[c];
4337 Method* methods = class_copyMethodList( cls, &
count );
4338 for( u_int m = 0; m <
count ; m++ ) {
4339 SEL selector = method_getName(methods[m]);
4340 std::string methodName = sel_getName(selector);
4341 if(
startsWith( methodName,
"Catch_TestCase_" ) ) {
4342 std::string testCaseName = methodName.substr( 15 );
4343 std::string
name = Detail::getAnnotation( cls,
"Name", testCaseName );
4344 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
4345 const char* className = class_getName( cls );
4354 return noTestMethods;
4357#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
4359 namespace Matchers {
4361 namespace NSStringMatchers {
4363 struct StringHolder : MatcherBase<NSString*>{
4364 StringHolder( NSString* substr ) : m_substr( [substr
copy] ){}
4365 StringHolder( StringHolder
const& other ) : m_substr( [
other.m_substr
copy] ){}
4370 bool match( NSString*
const& str )
const override {
4377 struct Equals : StringHolder {
4378 Equals( NSString* substr ) : StringHolder( substr ){}
4380 bool match( NSString*
const& str )
const override {
4381 return (str != nil || m_substr == nil ) &&
4382 [str isEqualToString:m_substr];
4385 std::string describe()
const override {
4386 return "equals string: " +
Catch::Detail::stringify( m_substr );
4390 struct Contains : StringHolder {
4391 Contains( NSString* substr ) : StringHolder( substr ){}
4393 bool match( NSString*
const& str )
const override {
4394 return (str != nil || m_substr == nil ) &&
4395 [str rangeOfString:m_substr].location != NSNotFound;
4398 std::string describe()
const override {
4399 return "contains string: " +
Catch::Detail::stringify( m_substr );
4403 struct StartsWith : StringHolder {
4404 StartsWith( NSString* substr ) : StringHolder( substr ){}
4406 bool match( NSString*
const& str )
const override {
4407 return (str != nil || m_substr == nil ) &&
4408 [str rangeOfString:m_substr].location == 0;
4411 std::string describe()
const override {
4412 return "starts with: " +
Catch::Detail::stringify( m_substr );
4415 struct EndsWith : StringHolder {
4416 EndsWith( NSString* substr ) : StringHolder( substr ){}
4418 bool match( NSString*
const& str )
const override {
4419 return (str != nil || m_substr == nil ) &&
4420 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
4423 std::string describe()
const override {
4424 return "ends with: " +
Catch::Detail::stringify( m_substr );
4431 inline Impl::NSStringMatchers::Equals
4432 Equals( NSString* substr ){
return Impl::NSStringMatchers::Equals( substr ); }
4434 inline Impl::NSStringMatchers::Contains
4435 Contains( NSString* substr ){
return Impl::NSStringMatchers::Contains( substr ); }
4437 inline Impl::NSStringMatchers::StartsWith
4438 StartsWith( NSString* substr ){
return Impl::NSStringMatchers::StartsWith( substr ); }
4440 inline Impl::NSStringMatchers::EndsWith
4441 EndsWith( NSString* substr ){
return Impl::NSStringMatchers::EndsWith( substr ); }
4445 using namespace Matchers;
4452#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix
4453#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \
4454+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \
4458+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \
4462-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )
4464#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )
4469#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES
4481#pragma clang diagnostic push
4482#pragma clang diagnostic ignored "-Wpadded"
4488#pragma clang diagnostic push
4489#pragma clang diagnostic ignored "-Wpadded"
4496 class WildcardPattern {
4497 enum WildcardPosition {
4499 WildcardAtStart = 1,
4501 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
4506 WildcardPattern( std::string
const& pattern, CaseSensitive::Choice caseSensitivity );
4507 virtual ~WildcardPattern() =
default;
4508 virtual bool matches( std::string
const& str )
const;
4511 std::string adjustCase( std::string
const& str )
const;
4512 CaseSensitive::Choice m_caseSensitivity;
4513 WildcardPosition m_wildcard = NoWildcard;
4514 std::string m_pattern;
4528 virtual bool matches( TestCaseInfo
const& testCase )
const = 0;
4530 using PatternPtr = std::shared_ptr<Pattern>;
4532 class NamePattern :
public Pattern {
4534 NamePattern( std::string
const&
name );
4535 virtual ~NamePattern();
4536 bool matches( TestCaseInfo
const& testCase )
const override;
4538 WildcardPattern m_wildcardPattern;
4541 class TagPattern :
public Pattern {
4543 TagPattern( std::string
const& tag );
4544 virtual ~TagPattern();
4545 bool matches( TestCaseInfo
const& testCase )
const override;
4550 class ExcludedPattern :
public Pattern {
4552 ExcludedPattern( PatternPtr
const& underlyingPattern );
4553 virtual ~ExcludedPattern();
4554 bool matches( TestCaseInfo
const& testCase )
const override;
4556 PatternPtr m_underlyingPattern;
4560 std::vector<PatternPtr> m_patterns;
4562 bool matches( TestCaseInfo
const& testCase )
const;
4566 bool hasFilters()
const;
4567 bool matches( TestCaseInfo
const& testCase )
const;
4570 std::vector<Filter> m_filters;
4572 friend class TestSpecParser;
4577#pragma clang diagnostic pop
4589 struct ITagAliasRegistry {
4590 virtual ~ITagAliasRegistry();
4592 virtual TagAlias
const*
find( std::string
const& alias )
const = 0;
4593 virtual std::string expandAliases( std::string
const& unexpandedTestSpec )
const = 0;
4595 static ITagAliasRegistry
const& get();
4603 class TestSpecParser {
4604 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
4606 bool m_exclusion =
false;
4607 std::size_t m_start = std::string::npos, m_pos = 0;
4609 std::vector<std::size_t> m_escapeChars;
4610 TestSpec::Filter m_currentFilter;
4611 TestSpec m_testSpec;
4612 ITagAliasRegistry
const* m_tagAliases =
nullptr;
4615 TestSpecParser( ITagAliasRegistry
const& tagAliases );
4617 TestSpecParser& parse( std::string
const& arg );
4618 TestSpec testSpec();
4621 void visitChar(
char c );
4622 void startNewMode( Mode mode, std::size_t start );
4624 std::string subString()
const;
4626 template<
typename T>
4628 std::string token = subString();
4629 for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
4630 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
4631 m_escapeChars.clear();
4634 token = token.substr( 8 );
4636 if( !token.empty() ) {
4637 TestSpec::PatternPtr pattern = std::make_shared<T>( token );
4639 pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
4640 m_currentFilter.m_patterns.push_back( pattern );
4642 m_exclusion =
false;
4653#pragma clang diagnostic pop
4663#ifndef CATCH_CONFIG_CONSOLE_WIDTH
4664#define CATCH_CONFIG_CONSOLE_WIDTH 80
4675 bool listTestNamesOnly =
false;
4677 bool showSuccessfulTests =
false;
4678 bool shouldDebugBreak =
false;
4679 bool noThrow =
false;
4680 bool showHelp =
false;
4681 bool showInvisibles =
false;
4682 bool filenamesAsTags =
false;
4683 bool libIdentify =
false;
4685 int abortAfter = -1;
4687 int benchmarkResolutionMultiple = 100;
4689 Verbosity verbosity = Verbosity::Normal;
4690 WarnAbout::What warnings = WarnAbout::Nothing;
4691 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
4692 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
4693 UseColour::YesOrNo useColour = UseColour::Auto;
4694 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
4696 std::string outputFilename;
4698 std::string processName;
4699#ifndef CATCH_CONFIG_DEFAULT_REPORTER
4700#define CATCH_CONFIG_DEFAULT_REPORTER "console"
4703#undef CATCH_CONFIG_DEFAULT_REPORTER
4705 std::vector<std::string> testsOrTags;
4706 std::vector<std::string> sectionsToRun;
4709 class Config :
public IConfig {
4713 Config( ConfigData
const& data );
4714 virtual ~Config() =
default;
4716 std::string
const& getFilename()
const;
4719 bool listTestNamesOnly()
const;
4723 std::string getProcessName()
const;
4724 std::string
const& getReporterName()
const;
4726 std::vector<std::string>
const& getTestsOrTags()
const override;
4727 std::vector<std::string>
const& getSectionsToRun()
const override;
4729 TestSpec
const& testSpec()
const override;
4730 bool hasTestFilters()
const override;
4732 bool showHelp()
const;
4735 bool allowThrows()
const override;
4736 std::ostream& stream()
const override;
4737 std::string
name()
const override;
4738 bool includeSuccessfulResults()
const override;
4739 bool warnAboutMissingAssertions()
const override;
4740 bool warnAboutNoTests()
const override;
4741 ShowDurations::OrNot showDurations()
const override;
4742 RunTests::InWhatOrder runOrder()
const override;
4743 unsigned int rngSeed()
const override;
4744 int benchmarkResolutionMultiple()
const override;
4745 UseColour::YesOrNo useColour()
const override;
4746 bool shouldDebugBreak()
const override;
4747 int abortAfter()
const override;
4748 bool showInvisibles()
const override;
4753 IStream
const* openStream();
4756 std::unique_ptr<IStream const> m_stream;
4757 TestSpec m_testSpec;
4758 bool m_hasTestFilters =
false;
4770 struct AssertionResultData
4772 AssertionResultData() =
delete;
4774 AssertionResultData( ResultWas::OfType _resultType, LazyExpression
const& _lazyExpression );
4776 std::string message;
4777 mutable std::string reconstructedExpression;
4778 LazyExpression lazyExpression;
4779 ResultWas::OfType resultType;
4781 std::string reconstructExpression()
const;
4784 class AssertionResult {
4786 AssertionResult() =
delete;
4787 AssertionResult( AssertionInfo
const& info, AssertionResultData
const& data );
4790 bool succeeded()
const;
4791 ResultWas::OfType getResultType()
const;
4792 bool hasExpression()
const;
4793 bool hasMessage()
const;
4794 std::string getExpression()
const;
4795 std::string getExpressionInMacro()
const;
4796 bool hasExpandedExpression()
const;
4797 std::string getExpandedExpression()
const;
4798 std::string getMessage()
const;
4799 SourceLineInfo getSourceInfo()
const;
4803 AssertionInfo m_info;
4804 AssertionResultData m_resultData;
4815 template<
typename T>
4818 Option() : nullableValue( nullptr ) {}
4820 : nullableValue( new( storage )
T( _value ) )
4822 Option( Option
const& _other )
4823 : nullableValue( _other ? new( storage )
T( *_other ) : nullptr )
4830 Option& operator= ( Option
const& _other ) {
4831 if( &_other !=
this ) {
4834 nullableValue =
new( storage )
T( *_other );
4838 Option& operator = (
T const& _value ) {
4840 nullableValue =
new( storage )
T( _value );
4846 nullableValue->~T();
4847 nullableValue =
nullptr;
4851 T const&
operator*()
const {
return *nullableValue; }
4852 T* operator->() {
return nullableValue; }
4853 const T* operator->()
const {
return nullableValue; }
4859 bool some()
const {
return nullableValue !=
nullptr; }
4860 bool none()
const {
return nullableValue ==
nullptr; }
4862 bool operator !()
const {
return nullableValue ==
nullptr; }
4863 explicit operator bool()
const {
4869 alignas(
alignof(
T))
char storage[
sizeof(
T)];
4883 struct ReporterConfig {
4884 explicit ReporterConfig( IConfigPtr
const& _fullConfig );
4886 ReporterConfig( IConfigPtr
const& _fullConfig, std::ostream& _stream );
4888 std::ostream& stream()
const;
4892 std::ostream* m_stream;
4896 struct ReporterPreferences {
4897 bool shouldRedirectStdOut =
false;
4898 bool shouldReportAllAssertions =
false;
4901 template<
typename T>
4903 LazyStat& operator=(
T const& _value ) {
4904 Option<T>::operator=( _value );
4915 struct TestRunInfo {
4916 TestRunInfo( std::string
const& _name );
4920 GroupInfo( std::string
const& _name,
4921 std::size_t _groupIndex,
4922 std::size_t _groupsCount );
4925 std::size_t groupIndex;
4926 std::size_t groupsCounts;
4929 struct AssertionStats {
4930 AssertionStats( AssertionResult
const& _assertionResult,
4931 std::vector<MessageInfo>
const& _infoMessages,
4932 Totals
const& _totals );
4934 AssertionStats( AssertionStats
const& ) =
default;
4935 AssertionStats( AssertionStats && ) =
default;
4936 AssertionStats& operator = ( AssertionStats
const& ) =
delete;
4937 AssertionStats& operator = ( AssertionStats && ) =
delete;
4938 virtual ~AssertionStats();
4940 AssertionResult assertionResult;
4941 std::vector<MessageInfo> infoMessages;
4945 struct SectionStats {
4946 SectionStats( SectionInfo
const& _sectionInfo,
4947 Counts
const& _assertions,
4948 double _durationInSeconds,
4949 bool _missingAssertions );
4950 SectionStats( SectionStats
const& ) =
default;
4951 SectionStats( SectionStats && ) =
default;
4952 SectionStats& operator = ( SectionStats
const& ) =
default;
4953 SectionStats& operator = ( SectionStats && ) =
default;
4954 virtual ~SectionStats();
4956 SectionInfo sectionInfo;
4958 double durationInSeconds;
4959 bool missingAssertions;
4962 struct TestCaseStats {
4963 TestCaseStats( TestCaseInfo
const& _testInfo,
4964 Totals
const& _totals,
4965 std::string
const& _stdOut,
4966 std::string
const& _stdErr,
4969 TestCaseStats( TestCaseStats
const& ) =
default;
4970 TestCaseStats( TestCaseStats && ) =
default;
4971 TestCaseStats& operator = ( TestCaseStats
const& ) =
default;
4972 TestCaseStats& operator = ( TestCaseStats && ) =
default;
4973 virtual ~TestCaseStats();
4975 TestCaseInfo testInfo;
4982 struct TestGroupStats {
4983 TestGroupStats( GroupInfo
const& _groupInfo,
4984 Totals
const& _totals,
4986 TestGroupStats( GroupInfo
const& _groupInfo );
4988 TestGroupStats( TestGroupStats
const& ) =
default;
4989 TestGroupStats( TestGroupStats && ) =
default;
4990 TestGroupStats& operator = ( TestGroupStats
const& ) =
default;
4991 TestGroupStats& operator = ( TestGroupStats && ) =
default;
4992 virtual ~TestGroupStats();
4994 GroupInfo groupInfo;
4999 struct TestRunStats {
5000 TestRunStats( TestRunInfo
const& _runInfo,
5001 Totals
const& _totals,
5004 TestRunStats( TestRunStats
const& ) =
default;
5005 TestRunStats( TestRunStats && ) =
default;
5006 TestRunStats& operator = ( TestRunStats
const& ) =
default;
5007 TestRunStats& operator = ( TestRunStats && ) =
default;
5008 virtual ~TestRunStats();
5010 TestRunInfo runInfo;
5015 struct BenchmarkInfo {
5018 struct BenchmarkStats {
5020 std::size_t iterations;
5024 struct IStreamingReporter {
5025 virtual ~IStreamingReporter() =
default;
5031 virtual ReporterPreferences getPreferences()
const = 0;
5033 virtual void noMatchingTestCases( std::string
const& spec ) = 0;
5035 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
5036 virtual void testGroupStarting( GroupInfo
const& groupInfo ) = 0;
5038 virtual void testCaseStarting( TestCaseInfo
const& testInfo ) = 0;
5039 virtual void sectionStarting( SectionInfo
const& sectionInfo ) = 0;
5042 virtual void benchmarkStarting( BenchmarkInfo
const& ) {}
5044 virtual void assertionStarting( AssertionInfo
const& assertionInfo ) = 0;
5047 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
5050 virtual void benchmarkEnded( BenchmarkStats
const& ) {}
5052 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
5053 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
5054 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
5055 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
5057 virtual void skipTest( TestCaseInfo
const& testInfo ) = 0;
5062 virtual bool isMulti()
const;
5066 struct IReporterFactory {
5067 virtual ~IReporterFactory();
5069 virtual std::string getDescription()
const = 0;
5073 struct IReporterRegistry {
5074 using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
5075 using Listeners = std::vector<IReporterFactoryPtr>;
5077 virtual ~IReporterRegistry();
5079 virtual FactoryMap
const& getFactories()
const = 0;
5080 virtual Listeners
const& getListeners()
const = 0;
5102 template<
typename DerivedT>
5103 struct StreamingReporterBase : IStreamingReporter {
5105 StreamingReporterBase( ReporterConfig
const& _config )
5106 : m_config( _config.fullConfig() ),
5107 stream( _config.stream() )
5109 m_reporterPrefs.shouldRedirectStdOut =
false;
5110 if( !DerivedT::getSupportedVerbosities().
count( m_config->verbosity() ) )
5111 CATCH_ERROR(
"Verbosity level not supported by this reporter" );
5114 ReporterPreferences getPreferences()
const override {
5115 return m_reporterPrefs;
5118 static std::set<Verbosity> getSupportedVerbosities() {
5119 return { Verbosity::Normal };
5122 ~StreamingReporterBase()
override =
default;
5124 void noMatchingTestCases(std::string
const&)
override {}
5126 void testRunStarting(TestRunInfo
const& _testRunInfo)
override {
5127 currentTestRunInfo = _testRunInfo;
5130 void testGroupStarting(GroupInfo
const& _groupInfo)
override {
5131 currentGroupInfo = _groupInfo;
5134 void testCaseStarting(TestCaseInfo
const& _testInfo)
override {
5135 currentTestCaseInfo = _testInfo;
5137 void sectionStarting(SectionInfo
const& _sectionInfo)
override {
5138 m_sectionStack.push_back(_sectionInfo);
5141 void sectionEnded(SectionStats
const& )
override {
5142 m_sectionStack.pop_back();
5144 void testCaseEnded(TestCaseStats
const& )
override {
5145 currentTestCaseInfo.reset();
5147 void testGroupEnded(TestGroupStats
const& )
override {
5148 currentGroupInfo.reset();
5150 void testRunEnded(TestRunStats
const& )
override {
5151 currentTestCaseInfo.reset();
5152 currentGroupInfo.reset();
5153 currentTestRunInfo.reset();
5156 void skipTest(TestCaseInfo
const&)
override {
5162 std::ostream& stream;
5164 LazyStat<TestRunInfo> currentTestRunInfo;
5165 LazyStat<GroupInfo> currentGroupInfo;
5166 LazyStat<TestCaseInfo> currentTestCaseInfo;
5168 std::vector<SectionInfo> m_sectionStack;
5169 ReporterPreferences m_reporterPrefs;
5172 template<
typename DerivedT>
5173 struct CumulativeReporterBase : IStreamingReporter {
5174 template<
typename T,
typename ChildNodeT>
5176 explicit Node(
T const& _value ) :
value( _value ) {}
5179 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
5181 ChildNodes children;
5183 struct SectionNode {
5184 explicit SectionNode(SectionStats
const& _stats) : stats(_stats) {}
5185 virtual ~SectionNode() =
default;
5187 bool operator == (SectionNode
const& other)
const {
5188 return stats.sectionInfo.lineInfo ==
other.stats.sectionInfo.lineInfo;
5190 bool operator == (std::shared_ptr<SectionNode>
const& other)
const {
5195 using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
5196 using Assertions = std::vector<AssertionStats>;
5197 ChildSections childSections;
5198 Assertions assertions;
5203 struct BySectionInfo {
5204 BySectionInfo( SectionInfo
const& other ) : m_other(
other ) {}
5205 BySectionInfo( BySectionInfo
const& other ) : m_other(
other.m_other ) {}
5206 bool operator() (std::shared_ptr<SectionNode>
const& node)
const {
5207 return ((node->stats.sectionInfo.name == m_other.name) &&
5208 (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
5210 void operator=(BySectionInfo
const&) =
delete;
5213 SectionInfo
const& m_other;
5220 CumulativeReporterBase( ReporterConfig
const& _config )
5221 : m_config( _config.fullConfig() ),
5222 stream( _config.stream() )
5224 m_reporterPrefs.shouldRedirectStdOut =
false;
5225 if( !DerivedT::getSupportedVerbosities().
count( m_config->verbosity() ) )
5226 CATCH_ERROR(
"Verbosity level not supported by this reporter" );
5228 ~CumulativeReporterBase()
override =
default;
5230 ReporterPreferences getPreferences()
const override {
5231 return m_reporterPrefs;
5234 static std::set<Verbosity> getSupportedVerbosities() {
5235 return { Verbosity::Normal };
5238 void testRunStarting( TestRunInfo
const& )
override {}
5239 void testGroupStarting( GroupInfo
const& )
override {}
5241 void testCaseStarting( TestCaseInfo
const& )
override {}
5243 void sectionStarting( SectionInfo
const& sectionInfo )
override {
5244 SectionStats incompleteStats( sectionInfo, Counts(), 0,
false );
5245 std::shared_ptr<SectionNode> node;
5246 if( m_sectionStack.empty() ) {
5247 if( !m_rootSection )
5248 m_rootSection = std::make_shared<SectionNode>( incompleteStats );
5249 node = m_rootSection;
5252 SectionNode& parentNode = *m_sectionStack.back();
5254 std::find_if( parentNode.childSections.begin(),
5255 parentNode.childSections.end(),
5256 BySectionInfo( sectionInfo ) );
5257 if( it == parentNode.childSections.end() ) {
5258 node = std::make_shared<SectionNode>( incompleteStats );
5259 parentNode.childSections.push_back( node );
5264 m_sectionStack.push_back( node );
5265 m_deepestSection = std::move(node);
5268 void assertionStarting(AssertionInfo
const&)
override {}
5270 bool assertionEnded(AssertionStats
const& assertionStats)
override {
5271 assert(!m_sectionStack.empty());
5278 SectionNode& sectionNode = *m_sectionStack.back();
5279 sectionNode.assertions.push_back(assertionStats);
5282 void sectionEnded(SectionStats
const& sectionStats)
override {
5283 assert(!m_sectionStack.empty());
5284 SectionNode& node = *m_sectionStack.back();
5285 node.stats = sectionStats;
5286 m_sectionStack.pop_back();
5288 void testCaseEnded(TestCaseStats
const& testCaseStats)
override {
5289 auto node = std::make_shared<TestCaseNode>(testCaseStats);
5290 assert(m_sectionStack.size() == 0);
5291 node->children.push_back(m_rootSection);
5292 m_testCases.push_back(node);
5293 m_rootSection.reset();
5295 assert(m_deepestSection);
5296 m_deepestSection->stdOut = testCaseStats.stdOut;
5297 m_deepestSection->stdErr = testCaseStats.stdErr;
5299 void testGroupEnded(TestGroupStats
const& testGroupStats)
override {
5300 auto node = std::make_shared<TestGroupNode>(testGroupStats);
5301 node->children.swap(m_testCases);
5302 m_testGroups.push_back(node);
5304 void testRunEnded(TestRunStats
const& testRunStats)
override {
5305 auto node = std::make_shared<TestRunNode>(testRunStats);
5306 node->children.swap(m_testGroups);
5307 m_testRuns.push_back(node);
5308 testRunEndedCumulative();
5310 virtual void testRunEndedCumulative() = 0;
5312 void skipTest(TestCaseInfo
const&)
override {}
5315 std::ostream& stream;
5316 std::vector<AssertionStats> m_assertions;
5317 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
5318 std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
5319 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
5321 std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
5323 std::shared_ptr<SectionNode> m_rootSection;
5324 std::shared_ptr<SectionNode> m_deepestSection;
5325 std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
5326 ReporterPreferences m_reporterPrefs;
5331 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
5334 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
5339 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
5340 TestEventListenerBase( ReporterConfig
const& _config );
5342 static std::set<Verbosity> getSupportedVerbosities();
5344 void assertionStarting(AssertionInfo
const&)
override;
5345 bool assertionEnded(AssertionStats
const&)
override;
5369 BrightRed = Bright |
Red,
5370 BrightGreen = Bright |
Green,
5371 LightGrey = Bright | Grey,
5372 BrightWhite = Bright | White,
5373 BrightYellow = Bright | Yellow,
5376 FileName = LightGrey,
5377 Warning = BrightYellow,
5378 ResultError = BrightRed,
5379 ResultSuccess = BrightGreen,
5380 ResultExpectedFailure = Warning,
5385 OriginalExpression = Cyan,
5386 ReconstructedExpression = BrightYellow,
5388 SecondaryText = LightGrey,
5393 Colour(
Code _colourCode );
5394 Colour( Colour&& other )
noexcept;
5395 Colour& operator=( Colour&& other )
noexcept;
5399 static void use(
Code _colourCode );
5402 bool m_moved =
false;
5405 std::ostream&
operator << ( std::ostream&
os, Colour
const& );
5415 template<
typename T>
5416 class ReporterRegistrar {
5418 class ReporterFactory :
public IReporterFactory {
5421 return std::unique_ptr<T>(
new T(
config ) );
5424 std::string getDescription()
const override {
5425 return T::getDescription();
5431 explicit ReporterRegistrar( std::string
const&
name ) {
5436 template<
typename T>
5437 class ListenerRegistrar {
5439 class ListenerFactory :
public IReporterFactory {
5442 return std::unique_ptr<T>(
new T(
config ) );
5444 std::string getDescription()
const override {
5445 return std::string();
5451 ListenerRegistrar() {
5457#if !defined(CATCH_CONFIG_DISABLE)
5459#define CATCH_REGISTER_REPORTER( name, reporterType ) \
5460 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
5461 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
5462 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
5464#define CATCH_REGISTER_LISTENER( listenerType ) \
5465 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
5466 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
5467 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
5470#define CATCH_REGISTER_REPORTER(name, reporterType)
5471#define CATCH_REGISTER_LISTENER(listenerType)
5481 struct CompactReporter : StreamingReporterBase<CompactReporter> {
5483 using StreamingReporterBase::StreamingReporterBase;
5485 ~CompactReporter()
override;
5487 static std::string getDescription();
5489 ReporterPreferences getPreferences()
const override;
5491 void noMatchingTestCases(std::string
const& spec)
override;
5493 void assertionStarting(AssertionInfo
const&)
override;
5495 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
5497 void sectionEnded(SectionStats
const& _sectionStats)
override;
5499 void testRunEnded(TestRunStats
const& _testRunStats)
override;
5508#if defined(_MSC_VER)
5509#pragma warning(push)
5510#pragma warning(disable:4061)
5517 struct SummaryColumn;
5520 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
5521 std::unique_ptr<TablePrinter> m_tablePrinter;
5523 ConsoleReporter(ReporterConfig
const&
config);
5524 ~ConsoleReporter()
override;
5525 static std::string getDescription();
5527 void noMatchingTestCases(std::string
const& spec)
override;
5529 void assertionStarting(AssertionInfo
const&)
override;
5531 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
5533 void sectionStarting(SectionInfo
const& _sectionInfo)
override;
5534 void sectionEnded(SectionStats
const& _sectionStats)
override;
5536 void benchmarkStarting(BenchmarkInfo
const& info)
override;
5537 void benchmarkEnded(BenchmarkStats
const& stats)
override;
5539 void testCaseEnded(TestCaseStats
const& _testCaseStats)
override;
5540 void testGroupEnded(TestGroupStats
const& _testGroupStats)
override;
5541 void testRunEnded(TestRunStats
const& _testRunStats)
override;
5542 void testRunStarting(TestRunInfo
const& _testRunInfo)
override;
5547 void lazyPrintWithoutClosingBenchmarkTable();
5548 void lazyPrintRunInfo();
5549 void lazyPrintGroupInfo();
5550 void printTestCaseAndSectionHeader();
5552 void printClosedHeader(std::string
const& _name);
5553 void printOpenHeader(std::string
const& _name);
5557 void printHeaderString(std::string
const& _string, std::size_t indent = 0);
5559 void printTotals(Totals
const& totals);
5560 void printSummaryRow(std::string
const&
label, std::vector<SummaryColumn>
const& cols, std::size_t row);
5562 void printTotalsDivider(Totals
const& totals);
5563 void printSummaryDivider();
5564 void printTestFilters();
5567 bool m_headerPrinted =
false;
5572#if defined(_MSC_VER)
5587 enum ForWhat { ForTextNodes, ForAttributes };
5589 XmlEncode( std::string
const& str, ForWhat forWhat = ForTextNodes );
5591 void encodeTo( std::ostream&
os )
const;
5593 friend std::ostream&
operator << ( std::ostream&
os, XmlEncode
const& xmlEncode );
5603 class ScopedElement {
5605 ScopedElement( XmlWriter* writer );
5607 ScopedElement( ScopedElement&& other )
noexcept;
5608 ScopedElement& operator=( ScopedElement&& other )
noexcept;
5612 ScopedElement& writeText( std::string
const& text,
bool indent =
true );
5614 template<
typename T>
5615 ScopedElement& writeAttribute( std::string
const&
name,
T const& attribute ) {
5616 m_writer->writeAttribute(
name, attribute );
5621 mutable XmlWriter* m_writer =
nullptr;
5627 XmlWriter( XmlWriter
const& ) =
delete;
5628 XmlWriter& operator=( XmlWriter
const& ) =
delete;
5630 XmlWriter& startElement( std::string
const&
name );
5632 ScopedElement scopedElement( std::string
const&
name );
5634 XmlWriter& endElement();
5636 XmlWriter& writeAttribute( std::string
const&
name, std::string
const& attribute );
5638 XmlWriter& writeAttribute( std::string
const&
name,
bool attribute );
5640 template<
typename T>
5641 XmlWriter& writeAttribute( std::string
const&
name,
T const& attribute ) {
5642 ReusableStringStream rss;
5644 return writeAttribute(
name, rss.str() );
5647 XmlWriter& writeText( std::string
const& text,
bool indent =
true );
5649 XmlWriter& writeComment( std::string
const& text );
5651 void writeStylesheetRef( std::string
const&
url );
5653 XmlWriter& writeBlankLine();
5655 void ensureTagClosed();
5659 void writeDeclaration();
5661 void newlineIfNecessary();
5663 bool m_tagIsOpen =
false;
5664 bool m_needsNewline =
false;
5665 std::vector<std::string> m_tags;
5666 std::string m_indent;
5675 class JunitReporter :
public CumulativeReporterBase<JunitReporter> {
5677 JunitReporter(ReporterConfig
const& _config);
5679 ~JunitReporter()
override;
5681 static std::string getDescription();
5683 void noMatchingTestCases(std::string
const& )
override;
5685 void testRunStarting(TestRunInfo
const& runInfo)
override;
5687 void testGroupStarting(GroupInfo
const& groupInfo)
override;
5689 void testCaseStarting(TestCaseInfo
const& testCaseInfo)
override;
5690 bool assertionEnded(AssertionStats
const& assertionStats)
override;
5692 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
5694 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
5696 void testRunEndedCumulative()
override;
5698 void writeGroup(TestGroupNode
const& groupNode,
double suiteTime);
5700 void writeTestCase(TestCaseNode
const& testCaseNode);
5702 void writeSection(std::string
const& className,
5703 std::string
const& rootName,
5704 SectionNode
const& sectionNode);
5706 void writeAssertions(SectionNode
const& sectionNode);
5707 void writeAssertion(AssertionStats
const& stats);
5711 std::string stdOutForSuite;
5712 std::string stdErrForSuite;
5713 unsigned int unexpectedExceptions = 0;
5714 bool m_okToFail =
false;
5723 class XmlReporter :
public StreamingReporterBase<XmlReporter> {
5725 XmlReporter(ReporterConfig
const& _config);
5727 ~XmlReporter()
override;
5729 static std::string getDescription();
5731 virtual std::string getStylesheetRef()
const;
5733 void writeSourceInfo(SourceLineInfo
const& sourceInfo);
5737 void noMatchingTestCases(std::string
const&
s)
override;
5739 void testRunStarting(TestRunInfo
const& testInfo)
override;
5741 void testGroupStarting(GroupInfo
const& groupInfo)
override;
5743 void testCaseStarting(TestCaseInfo
const& testInfo)
override;
5745 void sectionStarting(SectionInfo
const& sectionInfo)
override;
5747 void assertionStarting(AssertionInfo
const&)
override;
5749 bool assertionEnded(AssertionStats
const& assertionStats)
override;
5751 void sectionEnded(SectionStats
const& sectionStats)
override;
5753 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
5755 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
5757 void testRunEnded(TestRunStats
const& testRunStats)
override;
5760 Timer m_testCaseTimer;
5762 int m_sectionDepth = 0;
5778#pragma clang diagnostic push
5779#pragma clang diagnostic ignored "-Wweak-vtables"
5790namespace TestCaseTracking {
5792 struct NameAndLocation {
5794 SourceLineInfo location;
5796 NameAndLocation( std::string
const& _name, SourceLineInfo
const& _location );
5804 virtual ~ITracker();
5807 virtual NameAndLocation
const& nameAndLocation()
const = 0;
5810 virtual bool isComplete()
const = 0;
5811 virtual bool isSuccessfullyCompleted()
const = 0;
5812 virtual bool isOpen()
const = 0;
5813 virtual bool hasChildren()
const = 0;
5815 virtual ITracker& parent() = 0;
5818 virtual void close() = 0;
5819 virtual void fail() = 0;
5820 virtual void markAsNeedingAnotherRun() = 0;
5822 virtual void addChild( ITrackerPtr
const& child ) = 0;
5823 virtual ITrackerPtr findChild( NameAndLocation
const& nameAndLocation ) = 0;
5824 virtual void openChild() = 0;
5827 virtual bool isSectionTracker()
const = 0;
5828 virtual bool isGeneratorTracker()
const = 0;
5831 class TrackerContext {
5840 ITracker* m_currentTracker =
nullptr;
5841 RunState m_runState = NotStarted;
5845 ITracker& startRun();
5849 void completeCycle();
5851 bool completedCycle()
const;
5852 ITracker& currentTracker();
5853 void setCurrentTracker( ITracker* tracker );
5856 class TrackerBase :
public ITracker {
5863 CompletedSuccessfully,
5867 using Children = std::vector<ITrackerPtr>;
5868 NameAndLocation m_nameAndLocation;
5869 TrackerContext& m_ctx;
5871 Children m_children;
5872 CycleState m_runState = NotStarted;
5875 TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
5877 NameAndLocation
const& nameAndLocation()
const override;
5878 bool isComplete()
const override;
5879 bool isSuccessfullyCompleted()
const override;
5880 bool isOpen()
const override;
5881 bool hasChildren()
const override;
5883 void addChild( ITrackerPtr
const& child )
override;
5885 ITrackerPtr findChild( NameAndLocation
const& nameAndLocation )
override;
5886 ITracker& parent()
override;
5888 void openChild()
override;
5890 bool isSectionTracker()
const override;
5891 bool isGeneratorTracker()
const override;
5895 void close()
override;
5896 void fail()
override;
5897 void markAsNeedingAnotherRun()
override;
5900 void moveToParent();
5904 class SectionTracker :
public TrackerBase {
5905 std::vector<std::string> m_filters;
5907 SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
5909 bool isSectionTracker()
const override;
5911 bool isComplete()
const override;
5913 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation );
5917 void addInitialFilters( std::vector<std::string>
const& filters );
5918 void addNextFilters( std::vector<std::string>
const& filters );
5923using TestCaseTracking::ITracker;
5924using TestCaseTracking::TrackerContext;
5925using TestCaseTracking::SectionTracker;
5935 struct LeakDetector {
5952bool marginComparison(
double lhs,
double rhs,
double margin) {
5953 return (lhs + margin >= rhs) && (rhs + margin >= lhs);
5961 Approx::Approx (
double value )
5962 : m_epsilon(
std::numeric_limits<float>::epsilon()*100 ),
5968 Approx Approx::custom() {
5972 Approx Approx::operator-()
const {
5974 temp.m_value = -temp.m_value;
5978 std::string Approx::toString()
const {
5979 ReusableStringStream rss;
5984 bool Approx::equalityComparisonImpl(
const double other)
const {
5987 return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
5990 void Approx::setMargin(
double newMargin) {
5992 "Invalid Approx::margin: " << newMargin <<
'.'
5993 <<
" Approx::Margin has to be non-negative.");
5994 m_margin = newMargin;
5997 void Approx::setEpsilon(
double newEpsilon) {
5999 "Invalid Approx::epsilon: " << newEpsilon <<
'.'
6000 <<
" Approx::epsilon has to be in [0, 1]");
6001 m_epsilon = newEpsilon;
6007 Detail::Approx
operator "" _a(
long double val) {
6008 return Detail::Approx(val);
6010 Detail::Approx
operator "" _a(
unsigned long long val) {
6011 return Detail::Approx(val);
6016 return value.toString();
6029#ifdef CATCH_PLATFORM_MAC
6031 #define CATCH_TRAP() __asm__("int $3\n" : : )
6033#elif defined(CATCH_PLATFORM_LINUX)
6037 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
6038 #define CATCH_TRAP() asm volatile ("int $3")
6042 #define CATCH_TRAP() raise(SIGTRAP)
6044#elif defined(_MSC_VER)
6045 #define CATCH_TRAP() __debugbreak()
6046#elif defined(__MINGW32__)
6047 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
6048 #define CATCH_TRAP() DebugBreak()
6052 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
6054 #define CATCH_BREAK_INTO_DEBUGGER() []{}()
6065#if defined(CATCH_PLATFORM_WINDOWS)
6067#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
6068# define CATCH_DEFINED_NOMINMAX
6071#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
6072# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
6073# define WIN32_LEAN_AND_MEAN
6082#ifdef CATCH_DEFINED_NOMINMAX
6085#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
6086# undef WIN32_LEAN_AND_MEAN
6092#if defined( CATCH_CONFIG_WINDOWS_SEH )
6096 struct FatalConditionHandler {
6098 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
6100 static void reset();
6105 static ULONG guaranteeSize;
6106 static PVOID exceptionHandlerHandle;
6111#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
6117 struct FatalConditionHandler {
6128 static void reset();
6136 struct FatalConditionHandler {
6148 struct IMutableContext;
6152 class RunContext :
public IResultCapture,
public IRunner {
6162 void testGroupStarting( std::string
const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
6163 void testGroupEnded( std::string
const& testSpec, Totals
const& totals, std::size_t groupIndex, std::size_t groupsCount );
6165 Totals
runTest(TestCase
const& testCase);
6168 IStreamingReporter&
reporter()
const;
6174 ( AssertionInfo
const& info,
6175 ITransientExpression
const& expr,
6176 AssertionReaction& reaction )
override;
6178 ( AssertionInfo
const& info,
6181 AssertionReaction& reaction )
override;
6183 ( AssertionInfo
const& info,
6184 AssertionReaction& reaction )
override;
6186 ( AssertionInfo
const& info,
6187 std::string
const& message,
6188 AssertionReaction& reaction )
override;
6190 ( AssertionInfo
const& info )
override;
6192 ( AssertionInfo
const &info,
6194 AssertionReaction &reaction )
override;
6196 bool sectionStarted( SectionInfo
const& sectionInfo, Counts& assertions )
override;
6198 void sectionEnded( SectionEndInfo
const& endInfo )
override;
6229 void runCurrentTest(
std::
string& redirectedCout,
std::
string& redirectedCerr );
6230 void invokeActiveTestCase();
6232 void resetAssertionInfo();
6233 bool testForMissingAssertions( Counts& assertions );
6235 void assertionEnded( AssertionResult const& result );
6237 ( AssertionInfo const &info,
6238 ResultWas::OfType resultType,
6239 ITransientExpression const *expr,
6242 void populateReaction( AssertionReaction& reaction );
6246 void handleUnfinishedSections();
6248 TestRunInfo m_runInfo;
6249 IMutableContext& m_context;
6250 TestCase const* m_activeTestCase =
nullptr;
6251 ITracker* m_testCaseTracker =
nullptr;
6252 Option<AssertionResult> m_lastResult;
6257 std::vector<MessageInfo> m_messages;
6258 std::vector<ScopedMessage> m_messageScopes;
6259 AssertionInfo m_lastAssertionInfo;
6260 std::vector<SectionEndInfo> m_unfinishedSections;
6261 std::vector<ITracker*> m_activeSections;
6262 TrackerContext m_trackerContext;
6263 bool m_lastAssertionPassed = false;
6264 bool m_shouldReportUnexpected = true;
6265 bool m_includeSuccessfulResults;
6274 auto operator <<( std::ostream&
os, ITransientExpression
const& expr ) -> std::ostream& {
6275 expr.streamReconstructedExpression(
os );
6281 : m_isNegated( isNegated )
6286 LazyExpression::operator bool()
const {
6287 return m_transientExpression !=
nullptr;
6290 auto operator << ( std::ostream&
os, LazyExpression
const& lazyExpr ) -> std::ostream& {
6291 if( lazyExpr.m_isNegated )
6295 if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
6296 os <<
"(" << *lazyExpr.m_transientExpression <<
")";
6298 os << *lazyExpr.m_transientExpression;
6301 os <<
"{** error - unchecked empty expression requested **}";
6308 SourceLineInfo
const& lineInfo,
6311 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
6316 m_resultCapture.
handleExpr( m_assertionInfo, expr, m_reaction );
6319 m_resultCapture.
handleMessage( m_assertionInfo, resultType, message, m_reaction );
6337#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
6340 CATCH_ERROR(
"Test failure requires aborting test!" );
6379 lazyExpression(_lazyExpression),
6380 resultType(_resultType) {}
6386 ReusableStringStream rss;
6396 m_resultData( data )
6423 return "!(" +
m_info.capturedExpression + ")";
6434 expr +=
m_info.macroName;
6436 expr +=
m_info.capturedExpression;
6470 auto BenchmarkLooper::getResolution() ->
uint64_t {
6478 auto elapsed = m_timer.getElapsedNanoseconds();
6481 if( elapsed < m_resolution ) {
6482 m_iterationsToRun *= 10;
6496 using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
6503 MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
6504 handler.handleExpr( expr );
6516#ifdef CLARA_CONFIG_CONSOLE_WIDTH
6517#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6518#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6520#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
6523#pragma clang diagnostic push
6524#pragma clang diagnostic ignored "-Wweak-vtables"
6525#pragma clang diagnostic ignored "-Wexit-time-destructors"
6526#pragma clang diagnostic ignored "-Wshadow"
6540#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
6541#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
6544#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6545#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
6548#ifndef CLARA_CONFIG_OPTIONAL_TYPE
6550#if __has_include(<optional>) && __cplusplus >= 201703L
6552#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
6574#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6575#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
6583 static std::string chars =
" \t\n\r";
6584 return chars.find(c) != std::string::npos;
6587 static std::string chars =
"[({<|";
6588 return chars.find(c) != std::string::npos;
6591 static std::string chars =
"])}>.,:;*+-=&/\\";
6592 return chars.find(c) != std::string::npos;
6598 std::vector<std::string> m_strings;
6600 size_t m_indent = 0;
6601 size_t m_initialIndent = std::string::npos;
6607 Column
const& m_column;
6608 size_t m_stringIndex = 0;
6613 bool m_suffix =
false;
6615 iterator(Column
const& column,
size_t stringIndex)
6617 m_stringIndex(stringIndex) {}
6619 auto line() const ->
std::
string const& {
return m_column.m_strings[m_stringIndex]; }
6621 auto isBoundary(
size_t at)
const ->
bool {
6623 assert(at <= line().size());
6625 return at == line().size() ||
6632 assert(m_stringIndex < m_column.m_strings.size());
6635 auto width = m_column.m_width - indent();
6637 if (line()[m_pos] ==
'\n') {
6640 while (m_end < line().size() && line()[m_end] !=
'\n')
6643 if (m_end < m_pos +
width) {
6644 m_len = m_end - m_pos;
6647 while (
len > 0 && !isBoundary(m_pos +
len))
6661 auto indent() const ->
size_t {
6662 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
6663 return initial == std::string::npos ? m_column.m_indent : initial;
6666 auto addIndentAndSuffix(std::string
const &plain)
const -> std::string {
6667 return std::string(indent(),
' ') + (m_suffix ?
plain + "-" : plain);
6677 explicit iterator(Column
const& column) : m_column(column) {
6678 assert(m_column.m_width > m_column.m_indent);
6679 assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
6686 assert(m_stringIndex < m_column.m_strings.size());
6687 assert(m_pos <= m_end);
6688 return addIndentAndSuffix(line().substr(m_pos, m_len));
6693 if (m_pos < line().size() && line()[m_pos] ==
'\n')
6696 while (m_pos < line().size() &&
isWhitespace(line()[m_pos]))
6699 if (m_pos == line().size()) {
6703 if (m_stringIndex < m_column.m_strings.size())
6708 iterator prev(*
this);
6713 auto operator ==(iterator
const& other)
const ->
bool {
6715 m_pos ==
other.m_pos &&
6716 m_stringIndex ==
other.m_stringIndex &&
6717 &m_column == &
other.m_column;
6719 auto operator !=(iterator
const& other)
const ->
bool {
6725 explicit Column(std::string
const& text) { m_strings.push_back(text); }
6728 assert(newWidth > 0);
6733 m_indent = newIndent;
6737 m_initialIndent = newIndent;
6741 auto width() const ->
size_t {
return m_width; }
6742 auto begin() const -> iterator {
return iterator(*
this); }
6743 auto end() const -> iterator {
return { *
this, m_strings.size() }; }
6747 for (
auto line : col) {
6760 std::ostringstream oss;
6766class Spacer :
public Column {
6775 std::vector<Column> m_columns;
6783 std::vector<Column>
const& m_columns;
6784 std::vector<Column::iterator> m_iterators;
6785 size_t m_activeIterators;
6787 iterator(Columns
const& columns, EndTag)
6788 : m_columns(columns.m_columns),
6789 m_activeIterators(0) {
6790 m_iterators.reserve(m_columns.size());
6792 for (
auto const& col : m_columns)
6793 m_iterators.push_back(col.end());
6803 explicit iterator(Columns
const& columns)
6804 : m_columns(columns.m_columns),
6805 m_activeIterators(m_columns.size()) {
6806 m_iterators.reserve(m_columns.size());
6808 for (
auto const& col : m_columns)
6809 m_iterators.push_back(col.begin());
6812 auto operator ==(iterator
const& other)
const ->
bool {
6813 return m_iterators ==
other.m_iterators;
6815 auto operator !=(iterator
const& other)
const ->
bool {
6816 return m_iterators !=
other.m_iterators;
6819 std::string row, padding;
6821 for (
size_t i = 0; i < m_columns.size(); ++i) {
6822 auto width = m_columns[i].width();
6823 if (m_iterators[i] != m_columns[i].
end()) {
6824 std::string col = *m_iterators[i];
6825 row += padding + col;
6826 if (col.size() <
width)
6827 padding = std::string(
width - col.size(),
' ');
6831 padding +=
std::string(
width, ' ');
6836 auto operator ++() -> iterator& {
6837 for (
size_t i = 0; i < m_columns.size(); ++i) {
6838 if (m_iterators[i] != m_columns[i].
end())
6843 auto operator ++(
int) -> iterator {
6844 iterator prev(*
this);
6849 using const_iterator = iterator;
6851 auto begin() const -> iterator {
return iterator(*
this); }
6852 auto end() const -> iterator {
return { *
this, iterator::EndTag() }; }
6854 auto operator += (Column
const& col) -> Columns& {
6855 m_columns.push_back(col);
6858 auto operator + (Column
const& col) -> Columns {
6859 Columns combined = *
this;
6864 inline friend std::ostream&
operator << (std::ostream&
os, Columns
const& cols) {
6867 for (
auto line : cols) {
6877 auto toString() const ->
std::
string {
6878 std::ostringstream oss;
6904#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
6905#define CATCH_PLATFORM_WINDOWS
6912 template<
typename L>
6913 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
6915 template<
typename ClassT,
typename ReturnT,
typename... Args>
6916 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
6917 static const bool isValid =
false;
6920 template<
typename ClassT,
typename ReturnT,
typename ArgT>
6921 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
6922 static const bool isValid =
true;
6923 using ArgType =
typename std::remove_const<typename std::remove_reference<ArgT>::type>
::type;
6924 using ReturnType = ReturnT;
6932 std::string m_exeName;
6933 std::vector<std::string> m_args;
6936 Args(
int argc,
char const*
const*
argv )
6937 : m_exeName(
argv[0]),
6940 Args( std::initializer_list<std::string> args )
6941 : m_exeName( *args.begin() ),
6942 m_args( args.begin()+1, args.end() )
6962#ifdef CATCH_PLATFORM_WINDOWS
6970 using Iterator = std::vector<std::string>::const_iterator;
6973 std::vector<Token> m_tokenBuffer;
6976 m_tokenBuffer.resize( 0 );
6979 while( it != itEnd && it->empty() )
6983 auto const &
next = *it;
6985 auto delimiterPos =
next.find_first_of(
" :=" );
6986 if( delimiterPos != std::string::npos ) {
6990 if( next[1] !=
'-' &&
next.size() > 2 ) {
6991 std::string opt =
"- ";
6992 for(
size_t i = 1; i <
next.size(); ++i ) {
7007 explicit TokenStream( Args
const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
7009 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
7013 explicit operator bool()
const {
7014 return !m_tokenBuffer.empty() || it != itEnd;
7017 auto count() const ->
size_t {
return m_tokenBuffer.size() + (itEnd - it); }
7020 assert( !m_tokenBuffer.empty() );
7021 return m_tokenBuffer.front();
7024 auto operator->() const -> Token const * {
7025 assert( !m_tokenBuffer.empty() );
7026 return &m_tokenBuffer.front();
7029 auto operator++() -> TokenStream & {
7030 if( m_tokenBuffer.size() >= 2 ) {
7031 m_tokenBuffer.erase( m_tokenBuffer.begin() );
7044 Ok, LogicError, RuntimeError
7048 ResultBase(
Type type ) : m_type( type ) {}
7049 virtual ~ResultBase() =
default;
7051 virtual void enforceOk()
const = 0;
7056 template<
typename T>
7057 class ResultValueBase :
public ResultBase {
7059 auto value() const ->
T const & {
7065 ResultValueBase(
Type type ) : ResultBase( type ) {}
7067 ResultValueBase( ResultValueBase
const &other ) : ResultBase(
other ) {
7068 if( m_type == ResultBase::Ok )
7069 new( &m_value )
T(
other.m_value );
7072 ResultValueBase(
Type,
T const &
value ) : ResultBase( Ok ) {
7073 new( &m_value )
T(
value );
7076 auto operator=( ResultValueBase
const &other ) -> ResultValueBase & {
7077 if( m_type == ResultBase::Ok )
7079 ResultBase::operator=(other);
7080 if( m_type == ResultBase::Ok )
7081 new( &m_value )
T(
other.m_value );
7085 ~ResultValueBase()
override {
7096 class ResultValueBase<void> :
public ResultBase {
7098 using ResultBase::ResultBase;
7101 template<
typename T =
void>
7102 class BasicResult :
public ResultValueBase<
T> {
7104 template<
typename U>
7105 explicit BasicResult( BasicResult<U>
const &other )
7106 : ResultValueBase<
T>(
other.type() ),
7107 m_errorMessage(
other.errorMessage() )
7109 assert(
type() != ResultBase::Ok );
7112 template<
typename U>
7113 static auto ok(
U const &
value ) -> BasicResult {
return { ResultBase::Ok,
value }; }
7114 static auto ok() -> BasicResult {
return { ResultBase::Ok }; }
7115 static auto logicError( std::string
const &message ) -> BasicResult {
return { ResultBase::LogicError, message }; }
7116 static auto runtimeError( std::string
const &message ) -> BasicResult {
return { ResultBase::RuntimeError, message }; }
7118 explicit operator bool()
const {
return m_type == ResultBase::Ok; }
7119 auto type() const -> ResultBase::
Type {
return m_type; }
7120 auto errorMessage() const ->
std::
string {
return m_errorMessage; }
7123 void enforceOk()
const override {
7127 assert( m_type != ResultBase::LogicError );
7128 assert( m_type != ResultBase::RuntimeError );
7129 if( m_type != ResultBase::Ok )
7133 std::string m_errorMessage;
7135 BasicResult( ResultBase::Type type, std::string
const &message )
7136 : ResultValueBase<
T>(type),
7137 m_errorMessage(message)
7139 assert( m_type != ResultBase::Ok );
7142 using ResultValueBase<
T>::ResultValueBase;
7143 using ResultBase::m_type;
7153 ParseState( ParseResultType type, TokenStream
const &remainingTokens )
7155 m_remainingTokens( remainingTokens )
7158 auto type() const -> ParseResultType {
return m_type; }
7159 auto remainingTokens() const -> TokenStream {
return m_remainingTokens; }
7163 TokenStream m_remainingTokens;
7166 using Result = BasicResult<void>;
7170 struct HelpColumns {
7175 template<
typename T>
7177 std::stringstream
ss;
7190 std::string srcLC =
source;
7191 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), [](
char c ) { return static_cast<char>( std::tolower(c) ); } );
7192 if (srcLC ==
"y" || srcLC ==
"1" || srcLC ==
"true" || srcLC ==
"yes" || srcLC ==
"on")
7194 else if (srcLC ==
"n" || srcLC ==
"0" || srcLC ==
"false" || srcLC ==
"no" || srcLC ==
"off")
7200#ifdef CLARA_CONFIG_OPTIONAL_TYPE
7201 template<
typename T>
7206 target = std::move(temp);
7211 struct NonCopyable {
7212 NonCopyable() =
default;
7213 NonCopyable( NonCopyable
const & ) =
delete;
7214 NonCopyable( NonCopyable && ) =
delete;
7215 NonCopyable &operator=( NonCopyable
const & ) =
delete;
7216 NonCopyable &operator=( NonCopyable && ) =
delete;
7219 struct BoundRef : NonCopyable {
7220 virtual ~BoundRef() =
default;
7221 virtual auto isContainer() const ->
bool {
return false; }
7222 virtual auto isFlag() const ->
bool {
return false; }
7224 struct BoundValueRefBase : BoundRef {
7225 virtual auto setValue( std::string
const &arg ) ->
ParserResult = 0;
7227 struct BoundFlagRefBase : BoundRef {
7229 virtual auto isFlag() const ->
bool {
return true; }
7232 template<
typename T>
7233 struct BoundValueRef : BoundValueRefBase {
7236 explicit BoundValueRef(
T &ref ) : m_ref( ref ) {}
7238 auto setValue( std::string
const &arg ) ->
ParserResult override {
7243 template<
typename T>
7244 struct BoundValueRef<
std::vector<
T>> : BoundValueRefBase {
7245 std::vector<T> &m_ref;
7247 explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
7249 auto isContainer() const ->
bool override {
return true; }
7251 auto setValue( std::string
const &arg ) ->
ParserResult override {
7255 m_ref.push_back( temp );
7260 struct BoundFlagRef : BoundFlagRefBase {
7263 explicit BoundFlagRef(
bool &ref ) : m_ref( ref ) {}
7267 return ParserResult::ok( ParseResultType::Matched );
7271 template<
typename ReturnType>
7272 struct LambdaInvoker {
7273 static_assert( std::is_same<ReturnType, ParserResult>::value,
"Lambda must return void or clara::ParserResult" );
7275 template<
typename L,
typename ArgType>
7277 return lambda( arg );
7282 struct LambdaInvoker<void> {
7283 template<
typename L,
typename ArgType>
7286 return ParserResult::ok( ParseResultType::Matched );
7290 template<
typename ArgType,
typename L>
7296 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
7299 template<
typename L>
7300 struct BoundLambda : BoundValueRefBase {
7303 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
7304 explicit BoundLambda( L
const &lambda ) : m_lambda( lambda ) {}
7306 auto setValue( std::string
const &arg ) ->
ParserResult override {
7307 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
7311 template<
typename L>
7312 struct BoundFlagLambda : BoundFlagRefBase {
7315 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
7316 static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType,
bool>
::value,
"flags must be boolean" );
7318 explicit BoundFlagLambda( L
const &lambda ) : m_lambda( lambda ) {}
7321 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
7331 virtual ~ParserBase() =
default;
7332 virtual auto validate() const -> Result {
return Result::ok(); }
7333 virtual auto parse( std::string
const& exeName, TokenStream
const &tokens)
const ->
InternalParseResult = 0;
7334 virtual auto cardinality() const ->
size_t {
return 1; }
7337 return parse( args.exeName(), TokenStream( args ) );
7341 template<
typename DerivedT>
7342 class ComposableParserImpl :
public ParserBase {
7344 template<
typename T>
7347 template<
typename T>
7352 template<
typename DerivedT>
7353 class ParserRefImpl :
public ComposableParserImpl<DerivedT> {
7355 Optionality m_optionality = Optionality::Optional;
7356 std::shared_ptr<BoundRef> m_ref;
7358 std::string m_description;
7360 explicit ParserRefImpl( std::shared_ptr<BoundRef>
const &ref ) : m_ref( ref ) {}
7363 template<
typename T>
7364 ParserRefImpl(
T &ref, std::string
const &hint )
7365 : m_ref(
std::make_shared<BoundValueRef<
T>>( ref ) ),
7369 template<
typename LambdaT>
7370 ParserRefImpl( LambdaT
const &ref, std::string
const &hint )
7371 : m_ref(
std::make_shared<BoundLambda<LambdaT>>( ref ) ),
7375 auto operator()( std::string
const &description ) -> DerivedT & {
7376 m_description = description;
7377 return static_cast<DerivedT &
>( *this );
7381 m_optionality = Optionality::Optional;
7382 return static_cast<DerivedT &
>( *this );
7385 auto required() -> DerivedT & {
7386 m_optionality = Optionality::Required;
7387 return static_cast<DerivedT &
>( *this );
7390 auto isOptional() const ->
bool {
7391 return m_optionality == Optionality::Optional;
7394 auto cardinality() const ->
size_t override {
7395 if( m_ref->isContainer() )
7401 auto hint() const ->
std::
string {
return m_hint; }
7404 class ExeName :
public ComposableParserImpl<ExeName> {
7405 std::shared_ptr<std::string> m_name;
7406 std::shared_ptr<BoundValueRefBase> m_ref;
7408 template<
typename LambdaT>
7409 static auto makeRef(LambdaT
const &lambda) -> std::shared_ptr<BoundValueRefBase> {
7410 return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
7414 ExeName() : m_name(
std::make_shared<
std::string>(
"<executable>" ) ) {}
7417 m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
7420 template<
typename LambdaT>
7422 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );
7430 auto name() const ->
std::
string {
return *m_name; }
7433 auto lastSlash = newName.find_last_of(
"\\/" );
7434 auto filename = ( lastSlash == std::string::npos )
7436 : newName.substr( lastSlash+1 );
7440 return m_ref->setValue( filename );
7446 class Arg :
public ParserRefImpl<Arg> {
7451 auto validationResult =
validate();
7452 if( !validationResult )
7455 auto remainingTokens = tokens;
7456 auto const &token = *remainingTokens;
7460 assert( !
m_ref->isFlag() );
7461 auto valueRef =
static_cast<detail::BoundValueRefBase*
>(
m_ref.get() );
7463 auto result = valueRef->setValue( remainingTokens->token );
7471 inline auto normaliseOpt( std::string
const &optName ) -> std::string {
7472#ifdef CATCH_PLATFORM_WINDOWS
7473 if( optName[0] ==
'/' )
7474 return "-" + optName.substr( 1 );
7480 class Opt :
public ParserRefImpl<Opt> {
7485 template<
typename LambdaT>
7486 explicit Opt( LambdaT
const &ref ) :
ParserRefImpl(
std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
7490 template<
typename LambdaT>
7493 template<
typename T>
7502 std::ostringstream oss;
7512 oss <<
" <" <<
m_hint <<
">";
7516 auto isMatch( std::string
const &optToken )
const ->
bool {
7528 auto validationResult =
validate();
7529 if( !validationResult )
7532 auto remainingTokens = tokens;
7534 auto const &token = *remainingTokens;
7536 if(
m_ref->isFlag() ) {
7537 auto flagRef =
static_cast<detail::BoundFlagRefBase*
>(
m_ref.get() );
7538 auto result = flagRef->setFlag(
true );
7544 auto valueRef =
static_cast<detail::BoundValueRefBase*
>(
m_ref.get() );
7546 if( !remainingTokens )
7548 auto const &argToken = *remainingTokens;
7551 auto result = valueRef->setValue( argToken.token );
7563 auto validate() const -> Result
override {
7569#ifdef CATCH_PLATFORM_WINDOWS
7570 if(
name[0] !=
'-' &&
name[0] !=
'/' )
7573 if(
name[0] !=
'-' )
7582 Help(
bool &showHelpFlag )
7583 :
Opt([&]( bool flag ) {
7584 showHelpFlag = flag;
7588 static_cast<Opt &
>( *this )
7589 (
"display usage information")
7590 [
"-?"][
"-h"][
"--help"]
7595 struct Parser : ParserBase {
7622 template<
typename T>
7628 template<
typename T>
7630 template<
typename T>
7634 std::vector<HelpColumns> cols;
7636 auto childCols = o.getHelpColumns();
7637 cols.insert( cols.end(), childCols.begin(), childCols.end() );
7645 bool required =
true, first =
true;
7646 for(
auto const &arg :
m_args ) {
7651 if( arg.isOptional() && required ) {
7655 os <<
"<" << arg.hint() <<
">";
7656 if( arg.cardinality() == 0 )
7663 os <<
"\n\nwhere options are:" << std::endl;
7668 size_t optWidth = 0;
7669 for(
auto const &cols : rows )
7670 optWidth = (std::max)(optWidth, cols.left.size() + 2);
7672 optWidth = (std::min)(optWidth, consoleWidth/2);
7674 for(
auto const &cols : rows ) {
7676 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
7677 TextFlow::Spacer(4) +
7678 TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
7679 os << row << std::endl;
7684 parser.writeToStream(
os );
7688 auto validate() const -> Result
override {
7690 auto result = opt.validate();
7694 for(
auto const &arg :
m_args ) {
7695 auto result = arg.validate();
7707 ParserBase
const* parser =
nullptr;
7711 assert( totalParsers < 512 );
7713 ParserInfo parseInfos[512];
7717 for (
auto const &opt :
m_options) parseInfos[i++].parser = &opt;
7718 for (
auto const &arg :
m_args) parseInfos[i++].parser = &arg;
7724 while( result.value().remainingTokens() ) {
7725 bool tokenParsed =
false;
7727 for(
size_t i = 0; i < totalParsers; ++i ) {
7728 auto& parseInfo = parseInfos[i];
7729 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
7730 result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
7733 if (result.value().type() != ParseResultType::NoMatch) {
7751 template<
typename DerivedT>
7752 template<
typename T>
7753 auto ComposableParserImpl<DerivedT>::operator|(
T const &other )
const ->
Parser {
7754 return Parser() |
static_cast<DerivedT
const &
>( *this ) |
other;
7759using detail::Parser;
7771using detail::ExeName;
7777using detail::ParseResultType;
7780using detail::ParserResult;
7786#pragma clang diagnostic pop
7790#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
7791#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
7792#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
7810 using namespace clara;
7812 auto const setWarning = [&]( std::string
const& warning ) {
7813 auto warningSet = [&]() {
7814 if( warning ==
"NoAssertions" )
7817 if ( warning ==
"NoTests" )
7828 auto const loadTestNamesFromFile = [&]( std::string
const& filename ) {
7829 std::ifstream
f( filename.c_str() );
7834 while( std::getline(
f, line ) ) {
7836 if( !line.empty() && !
startsWith( line,
'#' ) ) {
7838 line =
'"' + line + '"';
7839 config.testsOrTags.push_back( line +
',' );
7844 auto const setTestOrder = [&]( std::string
const& order ) {
7855 auto const setRngSeed = [&]( std::string
const& seed ) {
7856 if( seed !=
"time" )
7858 config.rngSeed =
static_cast<unsigned int>( std::time(
nullptr) );
7861 auto const setColourUsage = [&]( std::string
const& useColour ) {
7862 auto mode =
toLower( useColour );
7866 else if( mode ==
"no" )
7868 else if( mode ==
"auto" )
7874 auto const setWaitForKeypress = [&]( std::string
const& keypress ) {
7875 auto keypressLc =
toLower( keypress );
7876 if( keypressLc ==
"start" )
7878 else if( keypressLc ==
"exit" )
7880 else if( keypressLc ==
"both" )
7883 return ParserResult::runtimeError(
"keypress argument must be one of: start, exit or both. '" + keypress +
"' not recognised" );
7886 auto const setVerbosity = [&]( std::string
const& verbosity ) {
7887 auto lcVerbosity =
toLower( verbosity );
7888 if( lcVerbosity ==
"quiet" )
7890 else if( lcVerbosity ==
"normal" )
7892 else if( lcVerbosity ==
"high" )
7898 auto const setReporter = [&]( std::string
const& reporter ) {
7901 auto lcReporter =
toLower( reporter );
7902 auto result = factories.find( lcReporter );
7904 if( factories.end() != result )
7905 config.reporterName = lcReporter;
7915 ["-l"]["--list-tests"]
7916 (
"list all/matching test cases" )
7918 ["-t"]["--list-tags"]
7919 (
"list all/matching tags" )
7922 (
"include successful tests in output" )
7925 (
"break into debugger on failure" )
7928 (
"skip exception tests" )
7930 ["-i"]["--invisibles"]
7931 (
"show invisibles (tabs, newlines)" )
7932 |
Opt(
config.outputFilename,
"filename" )
7934 (
"output filename" )
7935 |
Opt( setReporter,
"name" )
7936 ["-r"]["--reporter"]
7937 (
"reporter to use (defaults to console)" )
7941 |
Opt( [&](
bool ){
config.abortAfter = 1; } )
7943 (
"abort at first failure" )
7944 |
Opt( [&](
int x ){
config.abortAfter = x; },
"no. failures" )
7946 (
"abort after x failures" )
7947 |
Opt( setWarning,
"warning name" )
7949 (
"enable warnings" )
7951 [
"-d"][
"--durations"]
7952 (
"show test durations" )
7953 |
Opt( loadTestNamesFromFile,
"filename" )
7954 ["-f"]["--input-file"]
7955 (
"load test names to run from a file" )
7957 ["-#"]["--filenames-as-tags"]
7958 (
"adds a tag for the filename" )
7959 |
Opt(
config.sectionsToRun,
"section name" )
7961 (
"specify section to run" )
7962 |
Opt( setVerbosity,
"quiet|normal|high" )
7963 ["-v"]["--verbosity"]
7964 (
"set output verbosity" )
7966 ["--list-test-names-only"]
7967 (
"list all/matching test cases names only" )
7969 ["--list-reporters"]
7970 (
"list all reporters" )
7971 |
Opt( setTestOrder,
"decl|lex|rand" )
7973 (
"test case order (defaults to decl)" )
7974 |
Opt( setRngSeed,
"'time'|number" )
7976 (
"set a specific seed for random numbers" )
7977 |
Opt( setColourUsage,
"yes|no" )
7979 (
"should output be colourised" )
7982 (
"report name and version according to libidentify standard" )
7983 |
Opt( setWaitForKeypress,
"start|exit|both" )
7984 ["--wait-for-keypress"]
7985 (
"waits for a keypress before exiting" )
7986 |
Opt(
config.benchmarkResolutionMultiple,
"multiplier" )
7987 ["--benchmark-resolution-multiple"]
7988 (
"multiple of clock resolution to run benchmarks" )
7990 |
Arg(
config.testsOrTags,
"test name|pattern|tags" )
7991 (
"which test or tests to use" );
8006 return file[0] ==
'\0';
8009 return line ==
other.line && (file ==
other.file || std::strcmp(file,
other.file) == 0);
8014 return line <
other.line || ( line ==
other.line && file !=
other.file && (std::strcmp(file,
other.file) < 0));
8017 std::ostream&
operator << ( std::ostream&
os, SourceLineInfo
const& info ) {
8019 os << info.file <<
'(' << info.line <<
')';
8021 os << info.file <<
':' << info.line;
8027 return std::string();
8041 m_stream( openStream() )
8044 if (!data.testsOrTags.empty()) {
8045 m_hasTestFilters =
true;
8046 for(
auto const& testOrTags : data.testsOrTags )
8047 parser.parse( testOrTags );
8049 m_testSpec = parser.testSpec();
8074 std::ostream&
Config::stream()
const {
return m_stream->stream(); }
8089 IStream
const* Config::openStream() {
8097#if defined(__clang__)
8098# pragma clang diagnostic push
8099# pragma clang diagnostic ignored "-Wexit-time-destructors"
8122 struct IColourImpl {
8123 virtual ~IColourImpl() =
default;
8127 struct NoColourImpl : IColourImpl {
8130 static IColourImpl* instance() {
8131 static NoColourImpl s_instance;
8139#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
8140# ifdef CATCH_PLATFORM_WINDOWS
8141# define CATCH_CONFIG_COLOUR_WINDOWS
8143# define CATCH_CONFIG_COLOUR_ANSI
8147#if defined ( CATCH_CONFIG_COLOUR_WINDOWS )
8152 class Win32ColourImpl :
public IColourImpl {
8154 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
8156 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
8157 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
8158 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
8159 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
8162 void use( Colour::Code _colourCode )
override {
8163 switch( _colourCode ) {
8164 case Colour::None:
return setTextAttribute( originalForegroundAttributes );
8165 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
8166 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
8167 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
8168 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
8169 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
8170 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
8171 case Colour::Grey:
return setTextAttribute( 0 );
8173 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
8174 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
8175 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
8176 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
8177 case Colour::BrightYellow:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
8187 void setTextAttribute( WORD _textAttribute ) {
8188 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
8190 HANDLE stdoutHandle;
8191 WORD originalForegroundAttributes;
8192 WORD originalBackgroundAttributes;
8195 IColourImpl* platformColourInstance() {
8196 static Win32ColourImpl s_instance;
8206 : NoColourImpl::instance();
8212#elif defined( CATCH_CONFIG_COLOUR_ANSI )
8223 class PosixColourImpl :
public IColourImpl {
8226 switch( _colourCode ) {
8246 static IColourImpl* instance() {
8247 static PosixColourImpl s_instance;
8252 void setColour(
const char* _escapeCode ) {
8254 <<
'\033' << _escapeCode;
8258 bool useColourOnPlatform() {
8260#ifdef CATCH_PLATFORM_MAC
8263#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
8264 isatty(STDOUT_FILENO)
8270 IColourImpl* platformColourInstance() {
8277 colourMode = useColourOnPlatform()
8281 ? PosixColourImpl::instance()
8282 : NoColourImpl::instance();
8292 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
8302 m_moved = rhs.m_moved;
8306 m_moved = rhs.m_moved;
8314 static IColourImpl* impl = platformColourInstance();
8315 impl->use( _colourCode );
8318 std::ostream&
operator << ( std::ostream&
os, Colour
const& ) {
8324#if defined(__clang__)
8325# pragma clang diagnostic pop
8333 class Context :
public IMutableContext, NonCopyable {
8337 return m_resultCapture;
8351 m_resultCapture = resultCapture;
8353 void setRunner( IRunner* runner )
override {
8364 IRunner* m_runner =
nullptr;
8365 IResultCapture* m_resultCapture =
nullptr;
8368 IMutableContext *IMutableContext::currentContext =
nullptr;
8370 void IMutableContext::createContext()
8372 currentContext =
new Context();
8376 delete IMutableContext::currentContext;
8377 IMutableContext::currentContext =
nullptr;
8395#ifdef CATCH_PLATFORM_WINDOWS
8399 ::OutputDebugStringA(
text.c_str() );
8416#ifdef CATCH_PLATFORM_MAC
8419# include <stdbool.h>
8420# include <sys/types.h>
8425#ifdef __apple_build_version__
8428# include <sys/sysctl.h>
8432 #ifdef __apple_build_version__
8440 struct kinfo_proc info;
8446 info.kp_proc.p_flag = 0;
8453 mib[2] = KERN_PROC_PID;
8458 size =
sizeof(info);
8459 if( sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size,
nullptr, 0) != 0 ) {
8460 Catch::cerr() <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
8466 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
8476#elif defined(CATCH_PLATFORM_LINUX)
8492 std::ifstream in(
"/proc/self/status");
8493 for( std::string line; std::getline(in, line); ) {
8494 static const int PREFIX_LEN = 11;
8495 if( line.compare(0, PREFIX_LEN,
"TracerPid:\t") == 0 ) {
8499 return line.length() > PREFIX_LEN && line[PREFIX_LEN] !=
'0';
8506#elif defined(_MSC_VER)
8507 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
8510 return IsDebuggerPresent() != 0;
8513#elif defined(__MINGW32__)
8514 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
8517 return IsDebuggerPresent() != 0;
8533 if( lhs.size() + rhs.size() < 40 &&
8534 lhs.find(
'\n') == std::string::npos &&
8535 rhs.find(
'\n') == std::string::npos )
8536 os << lhs <<
" " <<
op <<
" " << rhs;
8538 os << lhs <<
"\n" <<
op <<
"\n" << rhs;
8545#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
8548 Catch::cerr() <<
"Catch will terminate because it needed to throw an exception.\n"
8549 <<
"The message was: " << e.what() <<
'\n';
8574 class ExceptionTranslatorRegistry :
public IExceptionTranslatorRegistry {
8582 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
8588#import "Foundation/Foundation.h"
8597 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
8600#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
8608 @catch (NSException *exception) {
8620 if (std::current_exception() ==
nullptr) {
8621 return "Non C++ exception. Possibly a CLR exception.";
8626 catch( TestFailureException& ) {
8627 std::rethrow_exception(std::current_exception());
8629 catch( std::exception& ex ) {
8632 catch( std::string& msg ) {
8635 catch(
const char* msg ) {
8639 return "Unknown exception";
8644 if (m_translators.empty()) {
8645 std::rethrow_exception(std::current_exception());
8647 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
8653 CATCH_INTERNAL_ERROR(
"Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
8657 CATCH_INTERNAL_ERROR(
"Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
8665#if defined(__GNUC__)
8666# pragma GCC diagnostic push
8667# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
8670#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
8674 void reportFatal(
char const *
const message ) {
8681#if defined( CATCH_CONFIG_WINDOWS_SEH )
8684 struct SignalDefs { DWORD
id;
const char*
name; };
8689 static SignalDefs signalDefs[] = {
8690 {
static_cast<DWORD
>(EXCEPTION_ILLEGAL_INSTRUCTION),
"SIGILL - Illegal instruction signal" },
8691 {
static_cast<DWORD
>(EXCEPTION_STACK_OVERFLOW),
"SIGSEGV - Stack overflow" },
8692 {
static_cast<DWORD
>(EXCEPTION_ACCESS_VIOLATION),
"SIGSEGV - Segmentation violation signal" },
8693 {
static_cast<DWORD
>(EXCEPTION_INT_DIVIDE_BY_ZERO),
"Divide by zero error" },
8696 LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
8697 for (
auto const& def : signalDefs) {
8698 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
8699 reportFatal(def.name);
8704 return EXCEPTION_CONTINUE_SEARCH;
8711 guaranteeSize = 32 * 1024;
8712 exceptionHandlerHandle =
nullptr;
8714 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
8716 SetThreadStackGuarantee(&guaranteeSize);
8721 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
8722 SetThreadStackGuarantee(&guaranteeSize);
8723 exceptionHandlerHandle =
nullptr;
8733ULONG FatalConditionHandler::guaranteeSize = 0;
8734PVOID FatalConditionHandler::exceptionHandlerHandle =
nullptr;
8738#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
8749 constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
8751 static SignalDefs signalDefs[] = {
8752 { SIGINT,
"SIGINT - Terminal interrupt signal" },
8753 { SIGILL,
"SIGILL - Illegal instruction signal" },
8754 { SIGFPE,
"SIGFPE - Floating point error signal" },
8755 { SIGSEGV,
"SIGSEGV - Segmentation violation signal" },
8756 { SIGTERM,
"SIGTERM - Termination request signal" },
8757 { SIGABRT,
"SIGABRT - Abort (abnormal termination) signal" }
8761 char const *
name =
"<unknown signal>";
8762 for (
auto const& def : signalDefs) {
8763 if (sig == def.id) {
8777 sigStack.ss_size = sigStackSize;
8778 sigStack.ss_flags = 0;
8780 struct sigaction sa = { };
8783 sa.sa_flags = SA_ONSTACK;
8784 for (std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i) {
8785 sigaction(signalDefs[i].
id, &sa, &oldSigActions[i]);
8796 for( std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i ) {
8797 sigaction(signalDefs[i].
id, &oldSigActions[i],
nullptr);
8806 struct sigaction FatalConditionHandler::oldSigActions[
sizeof(signalDefs)/
sizeof(SignalDefs)] = {};
8820#if defined(__GNUC__)
8821# pragma GCC diagnostic pop
8835 std::mt19937&
rng();
8853namespace Generators {
8896 class ListeningReporter :
public IStreamingReporter {
8897 using Reporters = std::vector<IStreamingReporterPtr>;
8898 Reporters m_listeners;
8900 ReporterPreferences m_preferences;
8917 void benchmarkEnded( BenchmarkStats
const& benchmarkStats )
override;
8926 bool assertionEnded( AssertionStats
const& assertionStats )
override;
8927 void sectionEnded( SectionStats
const& sectionStats )
override;
8928 void testCaseEnded( TestCaseStats
const& testCaseStats )
override;
8929 void testGroupEnded( TestGroupStats
const& testGroupStats )
override;
8930 void testRunEnded( TestRunStats
const& testRunStats )
override;
8932 void skipTest( TestCaseInfo
const& testInfo )
override;
8933 bool isMulti()
const override;
8943 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
8946 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
8954 std::size_t _groupIndex,
8955 std::size_t _groupsCount )
8957 groupIndex( _groupIndex ),
8958 groupsCounts( _groupsCount )
8962 std::vector<MessageInfo>
const& _infoMessages,
8963 Totals
const& _totals )
8964 : assertionResult( _assertionResult ),
8965 infoMessages( _infoMessages ),
8968 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
8970 if( assertionResult.hasMessage() ) {
8973 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
8974 builder << assertionResult.getMessage();
8975 builder.m_info.message = builder.m_stream.str();
8977 infoMessages.push_back( builder.m_info );
8984 Counts
const& _assertions,
8985 double _durationInSeconds,
8986 bool _missingAssertions )
8987 : sectionInfo( _sectionInfo ),
8988 assertions( _assertions ),
8989 durationInSeconds( _durationInSeconds ),
8990 missingAssertions( _missingAssertions )
8996 Totals
const& _totals,
8997 std::string
const& _stdOut,
8998 std::string
const& _stdErr,
9000 : testInfo( _testInfo ),
9004 aborting( _aborting )
9010 Totals
const& _totals,
9012 : groupInfo( _groupInfo ),
9014 aborting( _aborting )
9018 : groupInfo( _groupInfo ),
9025 Totals
const& _totals,
9027 : runInfo( _runInfo ),
9029 aborting( _aborting )
9057#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
9063 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
9064 flag |= _CRTDBG_LEAK_CHECK_DF;
9065 flag |= _CRTDBG_ALLOC_MEM_DF;
9066 _CrtSetDbgFlag(flag);
9067 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
9068 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
9070 _CrtSetBreakAlloc(-1);
9097 void add( std::string
const& spelling );
9098 std::string
all()
const;
9101 std::size_t
count = 0;
9108 Option<std::size_t>
list( std::shared_ptr<Config>
const&
config );
9127 TestSpec testSpec =
config.testSpec();
9128 if(
config.hasTestFilters() )
9135 for(
auto const& testCaseInfo : matchedTestCases ) {
9139 Colour colourGuard( colour );
9144 std::string description = testCaseInfo.description;
9145 if( description.empty() )
9146 description =
"(NO DESCRIPTION)";
9149 if( !testCaseInfo.tags.empty() )
9153 if( !
config.hasTestFilters() )
9154 Catch::cout() << pluralise( matchedTestCases.size(),
"test case" ) <<
'\n' << std::endl;
9156 Catch::cout() << pluralise( matchedTestCases.size(),
"matching test case" ) <<
'\n' << std::endl;
9157 return matchedTestCases.size();
9161 TestSpec testSpec =
config.testSpec();
9162 std::size_t matchedTests = 0;
9164 for(
auto const& testCaseInfo : matchedTestCases ) {
9174 return matchedTests;
9185 out += "[" + spelling + "]";
9190 TestSpec testSpec =
config.testSpec();
9191 if(
config.hasTestFilters() )
9192 Catch::cout() <<
"Tags for matching test cases:\n";
9197 std::map<std::string, TagInfo> tagCounts;
9200 for(
auto const& testCase : matchedTestCases ) {
9201 for(
auto const& tagName : testCase.getTestCaseInfo().tags ) {
9202 std::string lcaseTagName =
toLower( tagName );
9203 auto countIt = tagCounts.find( lcaseTagName );
9204 if( countIt == tagCounts.end() )
9205 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
9206 countIt->second.add( tagName );
9210 for(
auto const& tagCount : tagCounts ) {
9211 ReusableStringStream rss;
9212 rss <<
" " << std::setw(2) << tagCount.second.count <<
" ";
9213 auto str = rss.str();
9214 auto wrapper =
Column( tagCount.second.all() )
9216 .indent(
str.size() )
9220 Catch::cout() << pluralise( tagCounts.size(),
"tag" ) <<
'\n' << std::endl;
9221 return tagCounts.size();
9227 std::size_t maxNameLen = 0;
9228 for(
auto const& factoryKvp : factories )
9229 maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );
9231 for(
auto const& factoryKvp : factories ) {
9233 <<
Column( factoryKvp.first +
":" )
9235 .width( 5+maxNameLen )
9236 +
Column( factoryKvp.second->getDescription() )
9243 return factories.size();
9246 Option<std::size_t>
list( std::shared_ptr<Config>
const&
config ) {
9247 Option<std::size_t> listedCount;
9249 if(
config->listTests() )
9251 if(
config->listTestNamesOnly() )
9255 if(
config->listReporters() )
9279using namespace Matchers;
9280using Matchers::Impl::MatcherBase;
9290 bool isnan(
double d);
9299 template <
typename T>
9301#if defined(CATCH_CONFIG_CPP11_TO_STRING)
9302 return std::to_string(t);
9304 ReusableStringStream rss;
9329template <
typename T>
9333struct Converter<float> {
9334 static_assert(
sizeof(float) ==
sizeof(
int32_t),
"Important ULP matcher assumption violated");
9335 Converter(
float f) {
9336 std::memcpy(&i, &
f,
sizeof(
f));
9342struct Converter<double> {
9343 static_assert(
sizeof(double) ==
sizeof(
int64_t),
"Important ULP matcher assumption violated");
9344 Converter(
double d) {
9345 std::memcpy(&i, &d,
sizeof(d));
9350template <
typename T>
9351auto convert(
T t) -> Converter<T> {
9352 return Converter<T>(t);
9355template <
typename FP>
9356bool almostEqualUlps(FP lhs, FP rhs,
int maxUlpDiff) {
9363 auto lc = convert(lhs);
9364 auto rc = convert(rhs);
9366 if ((lc.i < 0) != (
rc.i < 0)) {
9371 auto ulpDiff = std::abs(lc.i -
rc.i);
9372 return ulpDiff <= maxUlpDiff;
9381 :m_target{ target }, m_margin{ margin } {
9382 CATCH_ENFORCE(margin >= 0,
"Invalid margin: " << margin <<
'.'
9383 <<
" Margin has to be non-negative.");
9388 bool WithinAbsMatcher::match(
double const& matchee)
const {
9389 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
9392 std::string WithinAbsMatcher::describe()
const {
9393 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
9396 WithinUlpsMatcher::WithinUlpsMatcher(
double target,
int ulps, FloatingPointKind baseType)
9397 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
9398 CATCH_ENFORCE(ulps >= 0,
"Invalid ULP setting: " << ulps <<
'.'
9399 <<
" ULPs have to be non-negative.");
9402#if defined(__clang__)
9403#pragma clang diagnostic push
9405#pragma clang diagnostic ignored "-Wunreachable-code"
9408 bool WithinUlpsMatcher::match(
double const& matchee)
const {
9410 case FloatingPointKind::Float:
9411 return almostEqualUlps<float>(
static_cast<float>(matchee),
static_cast<float>(m_target), m_ulps);
9412 case FloatingPointKind::Double:
9413 return almostEqualUlps<double>(matchee, m_target, m_ulps);
9419#if defined(__clang__)
9420#pragma clang diagnostic pop
9423 std::string WithinUlpsMatcher::describe()
const {
9424 return "is within " +
Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type ==
FloatingPointKind::
Float)? "f" : "");
9429Floating::WithinUlpsMatcher
WithinULP(
double target,
int maxUlpDiff) {
9430 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
9433Floating::WithinUlpsMatcher
WithinULP(
float target,
int maxUlpDiff) {
9434 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
9437Floating::WithinAbsMatcher
WithinAbs(
double target,
double margin) {
9438 return Floating::WithinAbsMatcher(target, margin);
9449 return "matches undescribed predicate";
9451 return "matches predicate: \"" + desc + '"';
9462 namespace StdString {
9465 : m_caseSensitivity( caseSensitivity ),
9466 m_str( adjustString(
str ) )
9468 std::string CasedString::adjustString( std::string
const& str )
const {
9473 std::string CasedString::caseSensitivitySuffix()
const {
9475 ?
" (case insensitive)"
9479 StringMatcherBase::StringMatcherBase( std::string
const& operation, CasedString
const& comparator )
9480 : m_comparator( comparator ),
9481 m_operation( operation ) {
9484 std::string StringMatcherBase::describe()
const {
9485 std::string description;
9486 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
9487 m_comparator.caseSensitivitySuffix().size());
9488 description += m_operation;
9489 description += ": \"";
9490 description += m_comparator.m_str;
9491 description += "\"";
9492 description += m_comparator.caseSensitivitySuffix();
9496 EqualsMatcher::EqualsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"equals", comparator ) {}
9498 bool EqualsMatcher::match( std::string
const&
source )
const {
9499 return m_comparator.adjustString(
source ) == m_comparator.m_str;
9502 ContainsMatcher::ContainsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"contains", comparator ) {}
9504 bool ContainsMatcher::match( std::string
const&
source )
const {
9505 return contains( m_comparator.adjustString(
source ), m_comparator.m_str );
9508 StartsWithMatcher::StartsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"starts with", comparator ) {}
9510 bool StartsWithMatcher::match( std::string
const&
source )
const {
9511 return startsWith( m_comparator.adjustString(
source ), m_comparator.m_str );
9514 EndsWithMatcher::EndsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"ends with", comparator ) {}
9516 bool EndsWithMatcher::match( std::string
const&
source )
const {
9517 return endsWith( m_comparator.adjustString(
source ), m_comparator.m_str );
9520 RegexMatcher::RegexMatcher(std::string regex,
CaseSensitive::Choice caseSensitivity): m_regex(
std::move(regex)), m_caseSensitivity(caseSensitivity) {}
9522 bool RegexMatcher::match(std::string
const& matchee)
const {
9523 auto flags = std::regex::ECMAScript;
9524 if (m_caseSensitivity == CaseSensitive::Choice::No) {
9525 flags |= std::regex::icase;
9527 auto reg = std::regex(m_regex,
flags);
9528 return std::regex_match(matchee, reg);
9531 std::string RegexMatcher::describe()
const {
9532 return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");
9537 StdString::EqualsMatcher
Equals( std::string
const& str, CaseSensitive::Choice caseSensitivity ) {
9538 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
9540 StdString::ContainsMatcher Contains( std::string
const& str, CaseSensitive::Choice caseSensitivity ) {
9541 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
9543 StdString::EndsWithMatcher EndsWith( std::string
const& str, CaseSensitive::Choice caseSensitivity ) {
9544 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9546 StdString::StartsWithMatcher StartsWith( std::string
const& str, CaseSensitive::Choice caseSensitivity ) {
9547 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9550 StdString::RegexMatcher Matches(std::string
const& regex, CaseSensitive::Choice caseSensitivity) {
9551 return StdString::RegexMatcher(regex, caseSensitivity);
9572 SourceLineInfo
const& _lineInfo,
9574 : macroName( _macroName ),
9575 lineInfo( _lineInfo ),
9577 sequence( ++globalCount )
9589 unsigned int MessageInfo::globalCount = 0;
9594 SourceLineInfo
const& lineInfo,
9596 :m_info(macroName, lineInfo, type) {}
9601 : m_info( builder.m_info ), m_moved()
9603 m_info.message = builder.m_stream.str();
9608 : m_info( old.m_info ), m_moved()
9620 auto trimmed = [&] (
size_t start,
size_t end) {
9621 while (names[start] ==
',' || isspace(names[start])) {
9624 while (names[end] ==
',' || isspace(names[end])) {
9627 return names.substr(start, end - start + 1);
9631 std::stack<char> openings;
9632 for (
size_t pos = 0; pos < names.size(); ++pos) {
9633 char c = names[pos];
9650 if (start != pos && openings.size() == 0) {
9651 m_messages.emplace_back(macroName, lineInfo, resultType);
9652 m_messages.back().message = trimmed(start, pos);
9653 m_messages.back().message += " := ";
9658 assert(openings.size() == 0 &&
"Mismatched openings");
9659 m_messages.emplace_back(macroName, lineInfo, resultType);
9660 m_messages.back().message = trimmed(start, names.size() - 1);
9661 m_messages.back().message += " := ";
9663 Capturer::~Capturer() {
9665 assert( m_captured == m_messages.size() );
9666 for(
size_t i = 0; i < m_captured; ++i )
9667 m_resultCapture.popScopedMessage( m_messages[i] );
9671 void Capturer::captureValue(
size_t index, std::string
const&
value ) {
9672 assert( index < m_messages.size() );
9673 m_messages[index].message +=
value;
9683#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
9684#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
9692 class RedirectedStream {
9693 std::ostream& m_originalStream;
9694 std::ostream& m_redirectionStream;
9695 std::streambuf* m_prevBuf;
9698 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
9702 class RedirectedStdOut {
9703 ReusableStringStream m_rss;
9704 RedirectedStream m_cout;
9707 auto str() const ->
std::
string;
9713 class RedirectedStdErr {
9714 ReusableStringStream m_rss;
9715 RedirectedStream m_cerr;
9716 RedirectedStream m_clog;
9719 auto str() const ->
std::
string;
9722 class RedirectedStreams {
9724 RedirectedStreams(RedirectedStreams
const&) =
delete;
9725 RedirectedStreams& operator=(RedirectedStreams
const&) =
delete;
9726 RedirectedStreams(RedirectedStreams&&) =
delete;
9727 RedirectedStreams& operator=(RedirectedStreams&&) =
delete;
9729 RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
9730 ~RedirectedStreams();
9732 std::string& m_redirectedCout;
9733 std::string& m_redirectedCerr;
9735 RedirectedStdErr m_redirectedStdErr;
9738#if defined(CATCH_CONFIG_NEW_CAPTURE)
9754 std::FILE* getFile();
9755 std::string getContents();
9758 std::FILE* m_file =
nullptr;
9759 #if defined(_MSC_VER)
9760 char m_buffer[L_tmpnam] = { 0 };
9764 class OutputRedirect {
9766 OutputRedirect(OutputRedirect
const&) =
delete;
9767 OutputRedirect& operator=(OutputRedirect
const&) =
delete;
9768 OutputRedirect(OutputRedirect&&) =
delete;
9769 OutputRedirect& operator=(OutputRedirect&&) =
delete;
9771 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
9775 int m_originalStdout = -1;
9776 int m_originalStderr = -1;
9779 std::string& m_stdoutDest;
9780 std::string& m_stderrDest;
9795#if defined(CATCH_CONFIG_NEW_CAPTURE)
9796 #if defined(_MSC_VER)
9800 #define fileno _fileno
9809 : m_originalStream( originalStream ),
9810 m_redirectionStream( redirectionStream ),
9811 m_prevBuf( m_originalStream.rdbuf() )
9813 m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
9817 m_originalStream.rdbuf( m_prevBuf );
9830 : m_redirectedCout(redirectedCout),
9831 m_redirectedCerr(redirectedCerr)
9835 m_redirectedCout += m_redirectedStdOut.
str();
9836 m_redirectedCerr += m_redirectedStdErr.
str();
9839#if defined(CATCH_CONFIG_NEW_CAPTURE)
9841#if defined(_MSC_VER)
9842 TempFile::TempFile() {
9843 if (tmpnam_s(m_buffer)) {
9846 if (fopen_s(&m_file, m_buffer,
"w")) {
9848 if (strerror_s(buffer, errno)) {
9851 CATCH_RUNTIME_ERROR(
"Could not open the temp file: '" << m_buffer <<
"' because: " << buffer);
9855 TempFile::TempFile() {
9856 m_file = std::tmpfile();
9864 TempFile::~TempFile() {
9866 std::fclose(m_file);
9869#if defined(_MSC_VER)
9870 std::remove(m_buffer);
9874 FILE* TempFile::getFile() {
9878 std::string TempFile::getContents() {
9879 std::stringstream sstr;
9880 char buffer[100] = {};
9881 std::rewind(m_file);
9882 while (std::fgets(buffer,
sizeof(buffer), m_file)) {
9888 OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
9889 m_originalStdout(dup(1)),
9890 m_originalStderr(dup(2)),
9891 m_stdoutDest(stdout_dest),
9892 m_stderrDest(stderr_dest) {
9893 dup2(fileno(m_stdoutFile.getFile()), 1);
9894 dup2(fileno(m_stderrFile.getFile()), 2);
9897 OutputRedirect::~OutputRedirect() {
9906 dup2(m_originalStdout, 1);
9907 dup2(m_originalStderr, 2);
9909 m_stdoutDest += m_stdoutFile.getContents();
9910 m_stderrDest += m_stderrFile.getContents();
9917#if defined(CATCH_CONFIG_NEW_CAPTURE)
9918 #if defined(_MSC_VER)
9931#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
9933 return std::isnan(
f);
9935 bool isnan(
double d) {
9936 return std::isnan(d);
9941 return std::_isnan(
f);
9943 bool isnan(
double d) {
9944 return std::_isnan(d);
9954 std::mt19937&
rng() {
9955 static std::mt19937 s_rng;
9960 if(
config.rngSeed() != 0 ) {
9961 std::srand(
config.rngSeed() );
9985 std::vector<TestCase>
sortTests( IConfig
const&
config, std::vector<TestCase>
const& unsortedTestCases );
9986 bool matchTest( TestCase
const& testCase, TestSpec
const& testSpec, IConfig
const&
config );
9990 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const&
config );
9993 class TestRegistry :
public ITestCaseRegistry {
9999 std::vector<TestCase>
const&
getAllTests()
const override;
10003 std::vector<TestCase> m_functions;
10005 mutable std::vector<TestCase> m_sortedFunctions;
10006 std::size_t m_unnamedCount = 0;
10007 std::ios_base::Init m_ostreamInit;
10012 class TestInvokerAsFunction :
public ITestInvoker {
10013 void(*m_testAsFunction)();
10017 void invoke() const override;
10033 class ReporterRegistry :
public IReporterRegistry {
10063 TagAlias(std::string
const& _tag, SourceLineInfo _lineInfo);
10066 SourceLineInfo lineInfo;
10076 class TagAliasRegistry :
public ITagAliasRegistry {
10078 ~TagAliasRegistry()
override;
10079 TagAlias
const*
find( std::string
const& alias )
const override;
10080 std::string expandAliases( std::string
const& unexpandedTestSpec )
const override;
10081 void add( std::string
const& alias, std::string
const& tag, SourceLineInfo
const& lineInfo );
10084 std::map<std::string, TagAlias> m_registry;
10093#include <exception>
10097 class StartupExceptionRegistry {
10099 void add(std::exception_ptr
const& exception)
noexcept;
10100 std::vector<std::exception_ptr>
const& getExceptions() const noexcept;
10102 std::vector<
std::exception_ptr> m_exceptions;
10112 struct ISingleton {
10113 virtual ~ISingleton();
10119 template<
typename SingletonImplT,
typename InterfaceT = SingletonImplT,
typename MutableInterfaceT = InterfaceT>
10120 class Singleton : SingletonImplT,
public ISingleton {
10122 static auto getInternal() -> Singleton* {
10123 static Singleton* s_instance =
nullptr;
10124 if( !s_instance ) {
10125 s_instance =
new Singleton;
10132 static auto get() -> InterfaceT
const& {
10133 return *getInternal();
10135 static auto getMutable() -> MutableInterfaceT& {
10136 return *getInternal();
10147 class RegistryHub :
public IRegistryHub,
public IMutableRegistryHub,
10148 private NonCopyable {
10151 RegistryHub() =
default;
10152 IReporterRegistry
const& getReporterRegistry()
const override {
10153 return m_reporterRegistry;
10155 ITestCaseRegistry
const& getTestCaseRegistry()
const override {
10156 return m_testCaseRegistry;
10158 IExceptionTranslatorRegistry
const& getExceptionTranslatorRegistry()
const override {
10159 return m_exceptionTranslatorRegistry;
10161 ITagAliasRegistry
const& getTagAliasRegistry()
const override {
10162 return m_tagAliasRegistry;
10164 StartupExceptionRegistry
const& getStartupExceptionRegistry()
const override {
10165 return m_exceptionRegistry;
10169 void registerReporter( std::string
const&
name, IReporterFactoryPtr
const& factory )
override {
10170 m_reporterRegistry.registerReporter(
name, factory );
10172 void registerListener( IReporterFactoryPtr
const& factory )
override {
10173 m_reporterRegistry.registerListener( factory );
10175 void registerTest( TestCase
const& testInfo )
override {
10176 m_testCaseRegistry.registerTest( testInfo );
10178 void registerTranslator(
const IExceptionTranslator* translator )
override {
10179 m_exceptionTranslatorRegistry.registerTranslator( translator );
10181 void registerTagAlias( std::string
const& alias, std::string
const& tag, SourceLineInfo
const& lineInfo )
override {
10182 m_tagAliasRegistry.add( alias, tag, lineInfo );
10184 void registerStartupException() noexcept
override {
10185 m_exceptionRegistry.add(std::current_exception());
10189 TestRegistry m_testCaseRegistry;
10190 ReporterRegistry m_reporterRegistry;
10191 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
10192 TagAliasRegistry m_tagAliasRegistry;
10193 StartupExceptionRegistry m_exceptionRegistry;
10200 return RegistryHubSingleton::get();
10203 return RegistryHubSingleton::getMutable();
10219 ReporterRegistry::~ReporterRegistry() =
default;
10222 auto it = m_factories.find(
name );
10223 if( it == m_factories.end() )
10225 return it->second->create( ReporterConfig(
config ) );
10228 void ReporterRegistry::registerReporter( std::string
const&
name, IReporterFactoryPtr
const& factory ) {
10229 m_factories.emplace(
name, factory);
10231 void ReporterRegistry::registerListener( IReporterFactoryPtr
const& factory ) {
10232 m_listeners.push_back( factory );
10235 IReporterRegistry::FactoryMap
const& ReporterRegistry::getFactories()
const {
10236 return m_factories;
10238 IReporterRegistry::Listeners
const& ReporterRegistry::getListeners()
const {
10239 return m_listeners;
10248 bool isOk( ResultWas::OfType resultType ) {
10249 return ( resultType & ResultWas::FailureBit ) == 0;
10252 return flags == ResultWas::Info;
10255 ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
10256 return static_cast<ResultDisposition::Flags
>(
static_cast<int>( lhs ) |
static_cast<int>( rhs ) );
10267#include <algorithm>
10272 namespace Generators {
10273 struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
10276 GeneratorTracker( TestCaseTracking::NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
10277 : TrackerBase( nameAndLocation, ctx, parent )
10279 ~GeneratorTracker();
10281 static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation
const& nameAndLocation ) {
10282 std::shared_ptr<GeneratorTracker> tracker;
10284 ITracker& currentTracker = ctx.currentTracker();
10285 if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
10286 assert( childTracker );
10287 assert( childTracker->isGeneratorTracker() );
10288 tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
10291 tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker );
10292 currentTracker.addChild( tracker );
10295 if( !ctx.completedCycle() && !tracker->isComplete() ) {
10303 bool isGeneratorTracker()
const override {
return true; }
10304 auto hasGenerator() const ->
bool override {
10305 return !!m_generator;
10307 void close()
override {
10308 TrackerBase::close();
10310 if (m_runState == CompletedSuccessfully && m_generator->next()) {
10311 m_children.clear();
10312 m_runState = Executing;
10317 auto getGenerator() const -> GeneratorBasePtr const&
override {
10318 return m_generator;
10320 void setGenerator( GeneratorBasePtr&& generator )
override {
10321 m_generator = std::move( generator );
10324 GeneratorTracker::~GeneratorTracker() {}
10327 RunContext::RunContext(IConfigPtr
const& _config, IStreamingReporterPtr&& reporter)
10328 : m_runInfo(_config->
name()),
10331 m_reporter(
std::move(reporter)),
10333 m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
10335 m_context.setRunner(
this);
10336 m_context.setConfig(m_config);
10337 m_context.setResultCapture(
this);
10338 m_reporter->testRunStarting(m_runInfo);
10342 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals,
aborting()));
10346 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
10349 void RunContext::testGroupEnded(std::string
const& testSpec, Totals
const& totals, std::size_t groupIndex, std::size_t groupsCount) {
10350 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals,
aborting()));
10354 Totals prevTotals = m_totals;
10356 std::string redirectedCout;
10357 std::string redirectedCerr;
10359 auto const& testInfo = testCase.getTestCaseInfo();
10361 m_reporter->testCaseStarting(testInfo);
10363 m_activeTestCase = &testCase;
10365 ITracker& rootTracker = m_trackerContext.startRun();
10366 assert(rootTracker.isSectionTracker());
10367 static_cast<SectionTracker&
>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
10369 m_trackerContext.startCycle();
10370 m_testCaseTracker = &
SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
10371 runCurrentTest(redirectedCout, redirectedCerr);
10374 Totals deltaTotals = m_totals.delta(prevTotals);
10375 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
10376 deltaTotals.assertions.failed++;
10377 deltaTotals.testCases.passed--;
10378 deltaTotals.testCases.failed++;
10380 m_totals.testCases += deltaTotals.testCases;
10381 m_reporter->testCaseEnded(TestCaseStats(testInfo,
10387 m_activeTestCase =
nullptr;
10388 m_testCaseTracker =
nullptr;
10390 return deltaTotals;
10398 return *m_reporter;
10401 void RunContext::assertionEnded(AssertionResult
const & result) {
10403 m_totals.assertions.passed++;
10404 m_lastAssertionPassed =
true;
10405 }
else if (!result.isOk()) {
10406 m_lastAssertionPassed =
false;
10408 m_totals.assertions.failedButOk++;
10410 m_totals.assertions.failed++;
10413 m_lastAssertionPassed =
true;
10418 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
10421 m_messageScopes.clear();
10424 resetAssertionInfo();
10425 m_lastResult = result;
10427 void RunContext::resetAssertionInfo() {
10428 m_lastAssertionInfo.macroName =
StringRef();
10429 m_lastAssertionInfo.capturedExpression =
"{Unknown expression after the reported line}"_sr;
10433 ITracker& sectionTracker =
SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
10434 if (!sectionTracker.isOpen())
10436 m_activeSections.push_back(§ionTracker);
10438 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
10440 m_reporter->sectionStarting(sectionInfo);
10442 assertions = m_totals.assertions;
10447 using namespace Generators;
10448 GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation(
"generator", lineInfo ) );
10449 assert( tracker.isOpen() );
10450 m_lastAssertionInfo.lineInfo = lineInfo;
10454 bool RunContext::testForMissingAssertions(Counts& assertions) {
10455 if (assertions.total() != 0)
10457 if (!m_config->warnAboutMissingAssertions())
10459 if (m_trackerContext.currentTracker().hasChildren())
10461 m_totals.assertions.failed++;
10462 assertions.failed++;
10467 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
10468 bool missingAssertions = testForMissingAssertions(assertions);
10470 if (!m_activeSections.empty()) {
10471 m_activeSections.back()->close();
10472 m_activeSections.pop_back();
10475 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
10476 m_messages.clear();
10477 m_messageScopes.clear();
10481 if (m_unfinishedSections.empty())
10482 m_activeSections.back()->fail();
10484 m_activeSections.back()->close();
10485 m_activeSections.pop_back();
10487 m_unfinishedSections.push_back(endInfo);
10490 m_reporter->benchmarkStarting( info );
10493 m_reporter->benchmarkEnded( stats );
10497 m_messages.push_back(message);
10501 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
10505 m_messageScopes.emplace_back( builder );
10509 return m_activeTestCase
10515 return &(*m_lastResult);
10519 m_shouldReportUnexpected =
false;
10524 m_reporter->fatalErrorEncountered(message);
10529 tempResult.message = message;
10530 AssertionResult result(m_lastAssertionInfo, tempResult);
10532 assertionEnded(result);
10534 handleUnfinishedSections();
10538 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
10541 assertions.failed = 1;
10542 SectionStats testCaseSectionStats(testCaseSection, assertions, 0,
false);
10543 m_reporter->sectionEnded(testCaseSectionStats);
10547 Totals deltaTotals;
10548 deltaTotals.testCases.failed = 1;
10549 deltaTotals.assertions.failed = 1;
10550 m_reporter->testCaseEnded(TestCaseStats(testInfo,
10555 m_totals.testCases.failed++;
10557 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals,
false));
10561 return m_lastAssertionPassed;
10565 m_lastAssertionPassed =
true;
10566 ++m_totals.assertions.passed;
10567 resetAssertionInfo();
10568 m_messageScopes.clear();
10572 return m_totals.assertions.failed >=
static_cast<std::size_t
>(m_config->abortAfter());
10575 void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
10577 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
10578 m_reporter->sectionStarting(testCaseSection);
10579 Counts prevAssertions = m_totals.assertions;
10580 double duration = 0;
10581 m_shouldReportUnexpected =
true;
10588 if (m_reporter->getPreferences().shouldRedirectStdOut) {
10589#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
10590 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
10593 invokeActiveTestCase();
10595 OutputRedirect
r(redirectedCout, redirectedCerr);
10597 invokeActiveTestCase();
10601 invokeActiveTestCase();
10603 duration = timer.getElapsedSeconds();
10609 if( m_shouldReportUnexpected ) {
10610 AssertionReaction dummyReaction;
10614 Counts assertions = m_totals.assertions - prevAssertions;
10615 bool missingAssertions = testForMissingAssertions(assertions);
10617 m_testCaseTracker->
close();
10618 handleUnfinishedSections();
10619 m_messages.clear();
10620 m_messageScopes.clear();
10622 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
10623 m_reporter->sectionEnded(testCaseSectionStats);
10626 void RunContext::invokeActiveTestCase() {
10627 FatalConditionHandler fatalConditionHandler;
10628 m_activeTestCase->
invoke();
10629 fatalConditionHandler.reset();
10632 void RunContext::handleUnfinishedSections() {
10635 for (
auto it = m_unfinishedSections.rbegin(),
10636 itEnd = m_unfinishedSections.rend();
10640 m_unfinishedSections.clear();
10644 AssertionInfo
const& info,
10645 ITransientExpression
const& expr,
10646 AssertionReaction& reaction
10648 m_reporter->assertionStarting( info );
10650 bool negated =
isFalseTest( info.resultDisposition );
10651 bool result = expr.getResult() != negated;
10654 if (!m_includeSuccessfulResults) {
10663 populateReaction( reaction );
10666 void RunContext::reportExpr(
10667 AssertionInfo
const &info,
10669 ITransientExpression
const *expr,
10672 m_lastAssertionInfo = info;
10673 AssertionResultData data( resultType, LazyExpression( negated ) );
10675 AssertionResult assertionResult{ info, data };
10676 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
10678 assertionEnded( assertionResult );
10682 AssertionInfo
const& info,
10685 AssertionReaction& reaction
10687 m_reporter->assertionStarting( info );
10689 m_lastAssertionInfo = info;
10691 AssertionResultData data( resultType, LazyExpression(
false ) );
10692 data.message = message;
10693 AssertionResult assertionResult{ m_lastAssertionInfo, data };
10694 assertionEnded( assertionResult );
10695 if( !assertionResult.isOk() )
10696 populateReaction( reaction );
10699 AssertionInfo
const& info,
10700 AssertionReaction& reaction
10706 AssertionInfo
const& info,
10707 std::string
const& message,
10708 AssertionReaction& reaction
10710 m_lastAssertionInfo = info;
10713 data.message = message;
10714 AssertionResult assertionResult{ info, data };
10715 assertionEnded( assertionResult );
10716 populateReaction( reaction );
10719 void RunContext::populateReaction( AssertionReaction& reaction ) {
10720 reaction.shouldDebugBreak = m_config->shouldDebugBreak();
10725 AssertionInfo
const& info
10727 m_lastAssertionInfo = info;
10730 data.message =
"Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
10731 AssertionResult assertionResult{ info, data };
10732 assertionEnded( assertionResult );
10735 AssertionInfo
const &info,
10737 AssertionReaction &reaction
10739 m_lastAssertionInfo = info;
10741 AssertionResultData data( resultType, LazyExpression(
false ) );
10742 AssertionResult assertionResult{ info, data };
10743 assertionEnded( assertionResult );
10745 if( !assertionResult.isOk() )
10746 populateReaction( reaction );
10763 m_sectionIncluded(
getResultCapture().sectionStarted( m_info, m_assertions ) )
10769 if( m_sectionIncluded ) {
10779 Section::operator bool()
const {
10780 return m_sectionIncluded;
10790 ( SourceLineInfo
const& _lineInfo,
10791 std::string
const& _name )
10793 lineInfo( _lineInfo )
10806 class Session : NonCopyable {
10816 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
10822 template<
typename CharT>
10823 int run(
int argc, CharT
const *
const argv[]) {
10824 if (m_startupExceptions)
10827 if (returnCode == 0)
10828 returnCode =
run();
10842 ConfigData m_configData;
10843 std::shared_ptr<Config> m_config;
10844 bool m_startupExceptions =
false;
10860 Version(
unsigned int _majorVersion,
10861 unsigned int _minorVersion,
10862 unsigned int _patchNumber,
10863 char const *
const _branchName,
10864 unsigned int _buildNumber );
10887 const int MaxExitCode = 255;
10891 CATCH_ENFORCE(reporter,
"No reporter registered with name: '" << reporterName <<
"'");
10898 return createReporter(
config->getReporterName(),
config);
10906 auto ret = std::unique_ptr<IStreamingReporter>(
new ListeningReporter);
10907 auto&
multi =
static_cast<ListeningReporter&
>(*ret);
10909 for (
auto const& listener : listeners) {
10917 auto reporter = makeReporter(
config);
10925 TestSpec testSpec =
config->testSpec();
10928 for (
auto const& testCase : allTestCases) {
10929 bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) ||
10932 if (!
context.aborting() && matching)
10933 totals +=
context.runTest(testCase);
10935 context.reporter().skipTest(testCase);
10938 if (
config->warnAboutNoTests() && totals.testCases.total() == 0) {
10939 ReusableStringStream testConfig;
10942 for (
const auto& input :
config->getTestsOrTags()) {
10943 if (!first) { testConfig <<
' '; }
10945 testConfig << input;
10948 context.reporter().noMatchingTestCases(testConfig.str());
10958 for (
auto& testCase : tests) {
10959 auto tags = testCase.tags;
10961 std::string filename = testCase.lineInfo.file;
10962 auto lastSlash = filename.find_last_of(
"\\/");
10963 if (lastSlash != std::string::npos) {
10964 filename.erase(0, lastSlash);
10968 auto lastDot = filename.find_last_of(
'.');
10969 if (lastDot != std::string::npos) {
10970 filename.erase(lastDot);
10973 tags.push_back(std::move(filename));
10981 static bool alreadyInstantiated =
false;
10982 if( alreadyInstantiated ) {
10988#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
10990 if ( !exceptions.empty() ) {
10991 m_startupExceptions =
true;
10993 Catch::cerr() <<
"Errors occurred during startup!" <<
'\n';
10995 for (
const auto& ex_ptr : exceptions ) {
10997 std::rethrow_exception(ex_ptr);
10998 }
catch ( std::exception
const& ex ) {
11005 alreadyInstantiated =
true;
11015 << m_cli << std::endl
11016 <<
"For more detailed usage please see the project docs\n" << std::endl;
11020 << std::left << std::setw(16) <<
"description: " <<
"A Catch test executable\n"
11021 << std::left << std::setw(16) <<
"category: " <<
"testframework\n"
11022 << std::left << std::setw(16) <<
"framework: " <<
"Catch Test\n"
11023 << std::left << std::setw(16) <<
"version: " <<
libraryVersion() << std::endl;
11027 if( m_startupExceptions )
11036 <<
"\nError(s) in input:\n"
11039 Catch::cerr() <<
"Run with -? for usage\n" << std::endl;
11040 return MaxExitCode;
11051#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
11054 char **utf8Argv =
new char *[ argc ];
11056 for (
int i = 0; i < argc; ++i ) {
11057 int bufSize = WideCharToMultiByte( CP_UTF8, 0,
argv[i], -1, NULL, 0, NULL, NULL );
11059 utf8Argv[ i ] =
new char[ bufSize ];
11061 WideCharToMultiByte( CP_UTF8, 0,
argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
11064 int returnCode = applyCommandLine( argc, utf8Argv );
11066 for (
int i = 0; i < argc; ++i )
11067 delete [] utf8Argv[ i ];
11069 delete [] utf8Argv;
11075 void Session::useConfigData( ConfigData
const& configData ) {
11076 m_configData = configData;
11080 int Session::run() {
11081 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
11082 Catch::cout() <<
"...waiting for enter/ return before starting" << std::endl;
11083 static_cast<void>(std::getchar());
11085 int exitCode = runInternal();
11086 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
11087 Catch::cout() <<
"...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
11088 static_cast<void>(std::getchar());
11099 ConfigData& Session::configData() {
11100 return m_configData;
11102 Config& Session::config() {
11104 m_config = std::make_shared<Config>( m_configData );
11108 int Session::runInternal() {
11109 if( m_startupExceptions )
11112 if (m_configData.showHelp || m_configData.libIdentify) {
11121 if( m_configData.filenamesAsTags )
11122 applyFilenamesAsTags( *m_config );
11125 if( Option<std::size_t> listed = list( m_config ) )
11126 return static_cast<int>( *listed );
11128 auto totals = runTests( m_config );
11132 return (std::min) (MaxExitCode, (std::max) (totals.error,
static_cast<int>(totals.assertions.failed)));
11134#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
11135 catch( std::exception& ex ) {
11137 return MaxExitCode;
11151 static auto getSingletons() -> std::vector<ISingleton*>*& {
11152 static std::vector<ISingleton*>* g_singletons =
nullptr;
11153 if( !g_singletons )
11154 g_singletons =
new std::vector<ISingleton*>();
11155 return g_singletons;
11162 getSingletons()->push_back( singleton );
11165 auto& singletons = getSingletons();
11166 for(
auto singleton : *singletons )
11169 singletons =
nullptr;
11179 m_exceptions.push_back(exception);
11187 return m_exceptions;
11205 namespace detail {
namespace {
11206 template<
typename WriterF, std::
size_t bufferSize=256>
11207 class StreamBufImpl :
public std::streambuf {
11208 char data[bufferSize];
11213 setp( data, data +
sizeof(data) );
11216 ~StreamBufImpl() noexcept {
11217 StreamBufImpl::sync();
11225 if( pbase() == epptr() )
11226 m_writer( std::string( 1,
static_cast<char>( c ) ) );
11228 sputc(
static_cast<char>( c ) );
11233 int sync()
override {
11234 if( pbase() != pptr() ) {
11235 m_writer( std::string( pbase(),
static_cast<std::string::size_type
>( pptr() - pbase() ) ) );
11236 setp( pbase(), epptr() );
11244 struct OutputDebugWriter {
11246 void operator()( std::string
const&str ) {
11253 class FileStream :
public IStream {
11254 mutable std::ofstream m_ofs;
11257 m_ofs.open( filename.c_str() );
11258 CATCH_ENFORCE( !m_ofs.fail(),
"Unable to open file: '" << filename <<
"'" );
11260 ~FileStream()
override =
default;
11262 std::ostream& stream()
const override {
11269 class CoutStream :
public IStream {
11270 mutable std::ostream m_os;
11274 CoutStream() : m_os(
Catch::cout().rdbuf() ) {}
11275 ~CoutStream()
override =
default;
11278 std::ostream& stream()
const override {
return m_os; }
11283 class DebugOutStream :
public IStream {
11284 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
11285 mutable std::ostream m_os;
11288 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
11289 m_os( m_streamBuf.get() )
11292 ~DebugOutStream()
override =
default;
11295 std::ostream& stream()
const override {
return m_os; }
11303 if( filename.empty() )
11304 return new detail::CoutStream();
11305 else if( filename[0] ==
'%' ) {
11306 if( filename ==
"%debug" )
11307 return new detail::DebugOutStream();
11309 CATCH_ERROR(
"Unrecognised stream: '" << filename <<
"'" );
11312 return new detail::FileStream( filename );
11316 struct StringStreams {
11317 std::vector<std::unique_ptr<std::ostringstream>>
m_streams;
11318 std::vector<std::size_t>
m_unused;
11321 auto add() -> std::size_t {
11323 m_streams.push_back( std::unique_ptr<std::ostringstream>(
new std::ostringstream ) );
11333 void release( std::size_t index ) {
11340 : m_index( Singleton<StringStreams>::getMutable().
add() ),
11341 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
11345 static_cast<std::ostringstream*
>( m_oss )->
str(
"");
11351 return static_cast<std::ostringstream*
>( m_oss )->
str();
11356#ifndef CATCH_CONFIG_NOSTDOUT
11357 std::ostream&
cout() {
return std::cout; }
11358 std::ostream&
cerr() {
return std::cerr; }
11359 std::ostream&
clog() {
return std::clog; }
11365#include <algorithm>
11373 char toLowerCh(
char c) {
11374 return static_cast<char>( std::tolower( c ) );
11378 bool startsWith( std::string
const&
s, std::string
const& prefix ) {
11379 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(),
s.begin());
11381 bool startsWith( std::string
const&
s,
char prefix ) {
11382 return !
s.empty() &&
s[0] == prefix;
11384 bool endsWith( std::string
const&
s, std::string
const& suffix ) {
11385 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(),
s.rbegin());
11387 bool endsWith( std::string
const&
s,
char suffix ) {
11388 return !
s.empty() &&
s[s.size()-1] == suffix;
11390 bool contains( std::string
const&
s, std::string
const& infix ) {
11391 return s.find( infix ) != std::string::npos;
11394 std::transform(
s.begin(),
s.end(),
s.begin(), toLowerCh );
11396 std::string
toLower( std::string
const&
s ) {
11397 std::string lc =
s;
11401 std::string
trim( std::string
const& str ) {
11402 static char const* whitespaceChars =
"\n\r\t ";
11403 std::string::size_type
start =
str.find_first_not_of( whitespaceChars );
11404 std::string::size_type end =
str.find_last_not_of( whitespaceChars );
11406 return start != std::string::npos ?
str.substr( start, 1+end-start ) : std::string();
11409 bool replaceInPlace( std::string& str, std::string
const& replaceThis, std::string
const& withThis ) {
11410 bool replaced =
false;
11411 std::size_t i =
str.find( replaceThis );
11412 while( i != std::string::npos ) {
11414 str =
str.substr( 0, i ) + withThis +
str.substr( i+replaceThis.size() );
11415 if( i <
str.size()-withThis.size() )
11416 i =
str.find( replaceThis, i+withThis.size() );
11418 i = std::string::npos;
11424 : m_count(
count ),
11428 std::ostream&
operator << ( std::ostream&
os, pluralise
const& pluraliser ) {
11429 os << pluraliser.m_count <<
' ' << pluraliser.m_label;
11430 if( pluraliser.m_count != 1 )
11439#if defined(__clang__)
11440# pragma clang diagnostic push
11441# pragma clang diagnostic ignored "-Wexit-time-destructors"
11449 const uint32_t byte_2_lead = 0xC0;
11450 const uint32_t byte_3_lead = 0xE0;
11451 const uint32_t byte_4_lead = 0xF0;
11459 StringRef::operator std::string()
const {
11460 return std::string( m_start, m_size );
11470 if( isSubstring() )
11471 const_cast<StringRef*
>( this )->takeOwnership();
11478 auto StringRef::isOwned() const noexcept ->
bool {
11479 return m_data !=
nullptr;
11481 auto StringRef::isSubstring() const noexcept ->
bool {
11482 return m_start[m_size] !=
'\0';
11485 void StringRef::takeOwnership() {
11487 m_data =
new char[m_size+1];
11488 memcpy( m_data, m_start, m_size );
11489 m_data[m_size] =
'\0';
11494 if( start < m_size )
11495 return StringRef( m_start+start, size );
11501 size() ==
other.size() &&
11502 (std::strncmp( m_start,
other.m_start, size() ) == 0);
11509 return m_start[index];
11515 for(
size_type i=0; i < m_size; ++i ) {
11516 char c = m_start[i];
11517 if( ( c & byte_2_lead ) == byte_2_lead ) {
11519 if (( c & byte_3_lead ) == byte_3_lead )
11521 if( ( c & byte_4_lead ) == byte_4_lead )
11530 str.reserve( lhs.size() + rhs.size() );
11536 return std::string( lhs ) +
std::string( rhs );
11539 return std::string( lhs ) +
std::string( rhs );
11543 return os.write(
str.currentData(),
str.size());
11547 lhs.append(rhs.currentData(), rhs.size());
11553#if defined(__clang__)
11554# pragma clang diagnostic pop
11560 TagAlias::TagAlias(std::string
const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
11587 auto it = m_registry.find( alias );
11588 if( it != m_registry.end() )
11589 return &(it->second);
11595 std::string expandedTestSpec = unexpandedTestSpec;
11596 for(
auto const& registryKvp : m_registry ) {
11597 std::size_t pos = expandedTestSpec.find( registryKvp.first );
11598 if( pos != std::string::npos ) {
11599 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
11600 registryKvp.second.tag +
11601 expandedTestSpec.substr( pos + registryKvp.first.size() );
11604 return expandedTestSpec;
11607 void TagAliasRegistry::add( std::string
const& alias, std::string
const& tag, SourceLineInfo
const& lineInfo ) {
11609 "error: tag alias, '" << alias <<
"' is not of the form [@alias name].\n" << lineInfo );
11611 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
11612 "error: tag alias, '" << alias <<
"' already registered.\n"
11613 <<
"\tFirst seen at: " <<
find(alias)->lineInfo <<
"\n"
11614 <<
"\tRedefined at: " << lineInfo );
11628#include <exception>
11629#include <algorithm>
11639 else if( tag ==
"!throws" )
11641 else if( tag ==
"!shouldfail" )
11643 else if( tag ==
"!mayfail" )
11645 else if( tag ==
"!nonportable" )
11647 else if( tag ==
"!benchmark" )
11652 bool isReservedTag( std::string
const& tag ) {
11653 return parseSpecialTag( tag ) ==
TestCaseInfo::None && tag.size() > 0 && !std::isalnum(
static_cast<unsigned char>(tag[0]) );
11655 void enforceNotReservedTag( std::string
const& tag, SourceLineInfo
const& _lineInfo ) {
11657 "Tag name: [" << tag <<
"] is not allowed.\n"
11658 <<
"Tag names starting with non alphanumeric characters are reserved\n"
11664 std::string
const& _className,
11665 NameAndTags
const& nameAndTags,
11666 SourceLineInfo
const& _lineInfo )
11668 bool isHidden =
false;
11671 std::vector<std::string> tags;
11672 std::string desc, tag;
11673 bool inTag =
false;
11674 std::string _descOrTags = nameAndTags.
tags;
11675 for (
char c : _descOrTags) {
11688 enforceNotReservedTag( tag, _lineInfo );
11693 if (
startsWith(tag,
'.') && tag.size() > 1) {
11696 tags.push_back( tag );
11705 tags.push_back(
"." );
11708 TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
11709 return TestCase( _testCase, std::move(info) );
11712 void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
11713 std::sort(
begin(tags),
end(tags));
11714 tags.erase(std::unique(
begin(tags),
end(tags)),
end(tags));
11715 testCaseInfo.lcaseTags.clear();
11717 for(
auto const& tag : tags ) {
11718 std::string lcaseTag =
toLower( tag );
11720 testCaseInfo.lcaseTags.push_back( lcaseTag );
11722 testCaseInfo.tags = std::move(tags);
11726 std::string
const& _className,
11727 std::string
const& _description,
11728 std::vector<std::string>
const& _tags,
11729 SourceLineInfo
const& _lineInfo )
11731 className( _className ),
11732 description( _description ),
11733 lineInfo( _lineInfo ),
11755 std::size_t full_size = 2 *
tags.size();
11756 for (
const auto& tag :
tags) {
11757 full_size += tag.size();
11759 ret.reserve(full_size);
11760 for (
const auto& tag :
tags) {
11761 ret.push_back(
'[');
11763 ret.push_back(
']');
11769 TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo(
std::move(info) ),
test( testCase ) {}
11773 other.name = _newName;
11782 return test.get() ==
other.test.get() &&
11804 std::vector<TestCase>
sortTests( IConfig
const&
config, std::vector<TestCase>
const& unsortedTestCases ) {
11806 std::vector<TestCase> sorted = unsortedTestCases;
11808 switch(
config.runOrder() ) {
11810 std::sort( sorted.begin(), sorted.end() );
11814 std::shuffle( sorted.begin(), sorted.end(),
rng() );
11822 bool matchTest( TestCase
const& testCase, TestSpec
const& testSpec, IConfig
const&
config ) {
11823 return testSpec.matches( testCase ) && (
config.allowThrows() || !testCase.throws() );
11827 std::set<TestCase> seenFunctions;
11828 for(
auto const& function : functions ) {
11829 auto prev = seenFunctions.insert( function );
11831 "error: TEST_CASE( \"" << function.name <<
"\" ) already defined.\n"
11832 <<
"\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo <<
"\n"
11833 <<
"\tRedefined at " << function.getTestCaseInfo().lineInfo );
11837 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const&
config ) {
11838 std::vector<TestCase> filtered;
11839 filtered.reserve( testCases.size() );
11840 for (
auto const& testCase : testCases) {
11841 if ((!testSpec.hasFilters() && !testCase.isHidden()) ||
11843 filtered.push_back(testCase);
11853 std::string
name = testCase.getTestCaseInfo().name;
11854 if(
name.empty() ) {
11855 ReusableStringStream rss;
11856 rss <<
"Anonymous test case " << ++m_unnamedCount;
11857 return registerTest( testCase.withName( rss.str() ) );
11859 m_functions.push_back( testCase );
11863 return m_functions;
11866 if( m_sortedFunctions.empty() )
11869 if( m_currentSortOrder !=
config.runOrder() || m_sortedFunctions.empty() ) {
11871 m_currentSortOrder =
config.runOrder();
11873 return m_sortedFunctions;
11880 m_testAsFunction();
11884 std::string className = classOrQualifiedMethodName;
11887 std::size_t lastColons = className.rfind(
"::" );
11888 std::size_t penultimateColons = className.rfind(
"::", lastColons-1 );
11889 if( penultimateColons == std::string::npos )
11890 penultimateColons = 1;
11891 className = className.substr( penultimateColons, lastColons-penultimateColons );
11900#include <algorithm>
11902#include <stdexcept>
11906#if defined(__clang__)
11907# pragma clang diagnostic push
11908# pragma clang diagnostic ignored "-Wexit-time-destructors"
11912namespace TestCaseTracking {
11916 location( _location )
11922 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation(
"{root}",
CATCH_INTERNAL_LINEINFO ), *
this,
nullptr );
11923 m_currentTracker =
nullptr;
11924 m_runState = Executing;
11925 return *m_rootTracker;
11929 m_rootTracker.reset();
11930 m_currentTracker =
nullptr;
11931 m_runState = NotStarted;
11935 m_currentTracker = m_rootTracker.get();
11936 m_runState = Executing;
11939 m_runState = CompletedCycle;
11943 return m_runState == CompletedCycle;
11946 return *m_currentTracker;
11949 m_currentTracker = tracker;
11953 : m_nameAndLocation( nameAndLocation ),
11958 NameAndLocation
const& TrackerBase::nameAndLocation()
const {
11959 return m_nameAndLocation;
11961 bool TrackerBase::isComplete()
const {
11962 return m_runState == CompletedSuccessfully || m_runState == Failed;
11964 bool TrackerBase::isSuccessfullyCompleted()
const {
11965 return m_runState == CompletedSuccessfully;
11967 bool TrackerBase::isOpen()
const {
11968 return m_runState != NotStarted && !isComplete();
11970 bool TrackerBase::hasChildren()
const {
11971 return !m_children.empty();
11974 void TrackerBase::addChild( ITrackerPtr
const& child ) {
11975 m_children.push_back( child );
11978 ITrackerPtr TrackerBase::findChild( NameAndLocation
const& nameAndLocation ) {
11979 auto it = std::find_if( m_children.begin(), m_children.end(),
11980 [&nameAndLocation]( ITrackerPtr
const& tracker ){
11982 tracker->nameAndLocation().location == nameAndLocation.location &&
11983 tracker->nameAndLocation().name == nameAndLocation.name;
11985 return( it != m_children.end() )
11989 ITracker& TrackerBase::parent() {
11990 assert( m_parent );
11994 void TrackerBase::openChild() {
11995 if( m_runState != ExecutingChildren ) {
11996 m_runState = ExecutingChildren;
11998 m_parent->openChild();
12002 bool TrackerBase::isSectionTracker()
const {
return false; }
12003 bool TrackerBase::isGeneratorTracker()
const {
return false; }
12005 void TrackerBase::open() {
12006 m_runState = Executing;
12009 m_parent->openChild();
12012 void TrackerBase::close() {
12015 while( &m_ctx.currentTracker() !=
this )
12016 m_ctx.currentTracker().close();
12018 switch( m_runState ) {
12019 case NeedsAnotherRun:
12023 m_runState = CompletedSuccessfully;
12025 case ExecutingChildren:
12026 if( m_children.empty() || m_children.back()->isComplete() )
12027 m_runState = CompletedSuccessfully;
12031 case CompletedSuccessfully:
12039 m_ctx.completeCycle();
12041 void TrackerBase::fail() {
12042 m_runState = Failed;
12044 m_parent->markAsNeedingAnotherRun();
12046 m_ctx.completeCycle();
12048 void TrackerBase::markAsNeedingAnotherRun() {
12049 m_runState = NeedsAnotherRun;
12052 void TrackerBase::moveToParent() {
12053 assert( m_parent );
12054 m_ctx.setCurrentTracker( m_parent );
12056 void TrackerBase::moveToThis() {
12057 m_ctx.setCurrentTracker(
this );
12061 : TrackerBase( nameAndLocation, ctx, parent )
12064 while( !parent->isSectionTracker() )
12065 parent = &parent->parent();
12067 SectionTracker& parentSection =
static_cast<SectionTracker&
>( *parent );
12068 addNextFilters( parentSection.m_filters );
12073 bool complete =
true;
12075 if ((m_filters.empty() || m_filters[0] ==
"") ||
12076 std::find(m_filters.begin(), m_filters.end(),
12086 std::shared_ptr<SectionTracker> section;
12088 ITracker& currentTracker = ctx.currentTracker();
12090 assert( childTracker );
12091 assert( childTracker->isSectionTracker() );
12092 section = std::static_pointer_cast<SectionTracker>( childTracker );
12095 section = std::make_shared<SectionTracker>(
nameAndLocation, ctx, ¤tTracker );
12096 currentTracker.addChild( section );
12098 if( !ctx.completedCycle() )
12099 section->tryOpen();
12109 if( !filters.empty() ) {
12110 m_filters.push_back(
"");
12111 m_filters.push_back(
"");
12112 m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
12116 if( filters.size() > 1 )
12117 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
12122using TestCaseTracking::ITracker;
12123using TestCaseTracking::TrackerContext;
12124using TestCaseTracking::SectionTracker;
12128#if defined(__clang__)
12129# pragma clang diagnostic pop
12136 auto makeTestInvoker(
void(*testAsFunction)() ) noexcept -> ITestInvoker* {
12137 return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
12142 AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo
const& lineInfo,
StringRef const& classOrMethod, NameAndTags
const& nameAndTags )
noexcept {
12162#include <algorithm>
12169 TestSpec::Pattern::~Pattern() =
default;
12170 TestSpec::NamePattern::~NamePattern() =
default;
12171 TestSpec::TagPattern::~TagPattern() =
default;
12172 TestSpec::ExcludedPattern::~ExcludedPattern() =
default;
12174 TestSpec::NamePattern::NamePattern( std::string
const&
name )
12175 : m_wildcardPattern(
toLower(
name ), CaseSensitive::No )
12177 bool TestSpec::NamePattern::matches( TestCaseInfo
const& testCase )
const {
12181 TestSpec::TagPattern::TagPattern( std::string
const& tag ) : m_tag(
toLower( tag ) ) {}
12182 bool TestSpec::TagPattern::matches( TestCaseInfo
const& testCase )
const {
12183 return std::find(
begin(testCase.lcaseTags),
12184 end(testCase.lcaseTags),
12185 m_tag) !=
end(testCase.lcaseTags);
12188 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr
const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
12189 bool TestSpec::ExcludedPattern::matches( TestCaseInfo
const& testCase )
const {
return !m_underlyingPattern->matches( testCase ); }
12191 bool TestSpec::Filter::matches( TestCaseInfo
const& testCase )
const {
12193 for(
auto const& pattern : m_patterns ) {
12194 if( !pattern->matches( testCase ) )
12201 return !m_filters.empty();
12205 for(
auto const& filter : m_filters )
12206 if( filter.matches( testCase ) )
12220 m_exclusion =
false;
12221 m_start = std::string::npos;
12222 m_arg = m_tagAliases->expandAliases( arg );
12223 m_escapeChars.clear();
12224 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
12225 visitChar( m_arg[m_pos] );
12226 if( m_mode == Name )
12227 addPattern<TestSpec::NamePattern>();
12235 void TestSpecParser::visitChar(
char c ) {
12236 if( m_mode == None ) {
12239 case '~': m_exclusion =
true;
return;
12240 case '[':
return startNewMode( Tag, ++m_pos );
12241 case '"':
return startNewMode( QuotedName, ++m_pos );
12242 case '\\':
return escape();
12243 default: startNewMode( Name, m_pos );
break;
12246 if( m_mode == Name ) {
12248 addPattern<TestSpec::NamePattern>();
12251 else if( c ==
'[' ) {
12252 if( subString() ==
"exclude:" )
12253 m_exclusion =
true;
12255 addPattern<TestSpec::NamePattern>();
12256 startNewMode( Tag, ++m_pos );
12258 else if( c ==
'\\' )
12261 else if( m_mode == EscapedName )
12263 else if( m_mode == QuotedName && c ==
'"' )
12264 addPattern<TestSpec::NamePattern>();
12265 else if( m_mode == Tag && c ==
']' )
12266 addPattern<TestSpec::TagPattern>();
12268 void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
12272 void TestSpecParser::escape() {
12273 if( m_mode == None )
12275 m_mode = EscapedName;
12276 m_escapeChars.push_back( m_pos );
12278 std::string TestSpecParser::subString()
const {
return m_arg.substr( m_start, m_pos - m_start ); }
12280 void TestSpecParser::addFilter() {
12281 if( !m_currentFilter.m_patterns.empty() ) {
12282 m_testSpec.m_filters.push_back( m_currentFilter );
12283 m_currentFilter = TestSpec::Filter();
12297static const uint64_t nanosecondsInSecond = 1000000000;
12302 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
12306 auto estimateClockResolution() ->
uint64_t {
12308 static const uint64_t iterations = 1000000;
12312 for( std::size_t i = 0; i < iterations; ++i ) {
12318 }
while( ticks == baseTicks );
12320 auto delta = ticks - baseTicks;
12326 if (ticks > startTime + 3 * nanosecondsInSecond) {
12327 return sum / ( i + 1u );
12333 return sum/iterations;
12337 static auto s_resolution = estimateClockResolution();
12338 return s_resolution;
12341 void Timer::start() {
12344 auto Timer::getElapsedNanoseconds() const ->
uint64_t {
12347 auto Timer::getElapsedMicroseconds() const ->
uint64_t {
12348 return getElapsedNanoseconds()/1000;
12350 auto Timer::getElapsedMilliseconds() const ->
unsigned int {
12351 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
12353 auto Timer::getElapsedSeconds() const ->
double {
12354 return getElapsedMicroseconds()/1000000.0;
12361#if defined(__clang__)
12362# pragma clang diagnostic push
12363# pragma clang diagnostic ignored "-Wexit-time-destructors"
12364# pragma clang diagnostic ignored "-Wglobal-constructors"
12368#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
12369#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
12382 const int hexThreshold = 255;
12384 struct Endianness {
12385 enum Arch { Big, Little };
12387 static Arch which() {
12390 char asChar[sizeof (int)];
12394 return ( u.asChar[
sizeof(
int)-1] == 1 ) ? Big : Little;
12401 int i = 0, end =
static_cast<int>( size ),
inc = 1;
12402 if( Endianness::which() == Endianness::Little ) {
12407 unsigned char const *
bytes =
static_cast<unsigned char const *
>(
object);
12408 ReusableStringStream rss;
12409 rss <<
"0x" << std::setfill(
'0') << std::hex;
12410 for( ; i !=
end; i +=
inc )
12411 rss <<
std::setw(2) << static_cast<unsigned>(
bytes[i]);
12416template<
typename T>
12422 ReusableStringStream rss;
12423 rss << std::setprecision( precision )
12426 std::string
d = rss.str();
12427 std::size_t i =
d.find_last_not_of(
'0' );
12428 if( i != std::string::npos && i !=
d.size()-1 ) {
12431 d =
d.substr( 0, i+1 );
12444 return '"' +
str + '"';
12447 std::string
s(
"\"");
12448 for (
char c : str) {
12465#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
12467 return ::Catch::Detail::stringify(std::string{
str });
12473 return ::Catch::Detail::stringify(std::string{
str });
12475 return{
"{null string}" };
12480 return ::Catch::Detail::stringify(std::string{
str });
12482 return{
"{null string}" };
12486#ifdef CATCH_CONFIG_WCHAR
12489 s.reserve(wstr.size());
12490 for (
auto c : wstr) {
12491 s += (c <= 0xff) ? static_cast<char>(c) : '?';
12493 return ::Catch::Detail::stringify(
s);
12496# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
12504 return ::Catch::Detail::stringify(std::wstring{
str });
12506 return{
"{null string}" };
12511 return ::Catch::Detail::stringify(std::wstring{
str });
12513 return{
"{null string}" };
12519 return ::Catch::Detail::stringify(
static_cast<long long>(
value));
12522 return ::Catch::Detail::stringify(
static_cast<long long>(
value));
12525 ReusableStringStream rss;
12527 if (
value > Detail::hexThreshold) {
12528 rss <<
" (0x" << std::hex <<
value <<
')';
12534 return ::Catch::Detail::stringify(
static_cast<unsigned long long>(
value));
12537 return ::Catch::Detail::stringify(
static_cast<unsigned long long>(
value));
12540 ReusableStringStream rss;
12542 if (
value > Detail::hexThreshold) {
12543 rss <<
" (0x" << std::hex <<
value <<
')';
12549 return b ?
"true" :
"false";
12553 if (
value ==
'\r') {
12555 }
else if (
value ==
'\f') {
12557 }
else if (
value ==
'\n') {
12559 }
else if (
value ==
'\t') {
12562 return ::Catch::Detail::stringify(
static_cast<unsigned int>(
value));
12564 char chstr[] =
"' '";
12570 return ::Catch::Detail::stringify(
static_cast<signed char>(c));
12573 return ::Catch::Detail::stringify(
static_cast<char>(c));
12587std::string ratio_string<std::atto>::symbol() {
return "a"; }
12588std::string ratio_string<std::femto>::symbol() {
return "f"; }
12589std::string ratio_string<std::pico>::symbol() {
return "p"; }
12590std::string ratio_string<std::nano>::symbol() {
return "n"; }
12591std::string ratio_string<std::micro>::symbol() {
return "u"; }
12592std::string ratio_string<std::milli>::symbol() {
return "m"; }
12596#if defined(__clang__)
12597# pragma clang diagnostic pop
12644 Totals
diff = *
this - prevTotals;
12645 if(
diff.assertions.failed > 0 )
12647 else if(
diff.assertions.failedButOk > 0 )
12658#include <exception>
12662#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
12663 return std::uncaught_exceptions() > 0;
12665 return std::uncaught_exception();
12677 (
unsigned int _majorVersion,
12678 unsigned int _minorVersion,
12679 unsigned int _patchNumber,
12680 char const *
const _branchName,
12681 unsigned int _buildNumber )
12682 : majorVersion( _majorVersion ),
12683 minorVersion( _minorVersion ),
12684 patchNumber( _patchNumber ),
12685 branchName( _branchName ),
12686 buildNumber( _buildNumber )
12689 std::ostream&
operator << ( std::ostream&
os, Version
const& version ) {
12691 <<
version.minorVersion <<
'.'
12696 <<
'.' <<
version.buildNumber;
12702 static Version
version( 2, 7, 2,
"", 0 );
12716 : m_caseSensitivity( caseSensitivity ),
12717 m_pattern( adjustCase( pattern ) )
12720 m_pattern = m_pattern.substr( 1 );
12721 m_wildcard = WildcardAtStart;
12723 if(
endsWith( m_pattern,
'*' ) ) {
12724 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
12725 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
12730 switch( m_wildcard ) {
12732 return m_pattern == adjustCase( str );
12733 case WildcardAtStart:
12734 return endsWith( adjustCase( str ), m_pattern );
12735 case WildcardAtEnd:
12736 return startsWith( adjustCase( str ), m_pattern );
12737 case WildcardAtBothEnds:
12738 return contains( adjustCase( str ), m_pattern );
12744 std::string WildcardPattern::adjustCase( std::string
const& str )
const {
12753using uchar =
unsigned char;
12759 size_t trailingBytes(
unsigned char c) {
12760 if ((c & 0xE0) == 0xC0) {
12763 if ((c & 0xF0) == 0xE0) {
12766 if ((c & 0xF8) == 0xF0) {
12772 uint32_t headerValue(
unsigned char c) {
12773 if ((c & 0xE0) == 0xC0) {
12776 if ((c & 0xF0) == 0xE0) {
12779 if ((c & 0xF8) == 0xF0) {
12785 void hexEscapeChar(std::ostream&
os,
unsigned char c) {
12786 std::ios_base::fmtflags
f(
os.flags());
12788 << std::uppercase << std::hex << std::setfill(
'0') << std::setw(2)
12789 <<
static_cast<int>(c);
12797 m_forWhat( forWhat )
12804 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
12805 uchar c = m_str[idx];
12807 case '<':
os <<
"<";
break;
12808 case '&':
os <<
"&";
break;
12812 if (idx > 2 && m_str[idx - 1] ==
']' && m_str[idx - 2] ==
']')
12830 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
12831 hexEscapeChar(
os, c);
12849 hexEscapeChar(
os, c);
12853 auto encBytes = trailingBytes(c);
12855 if (idx + encBytes - 1 >= m_str.size()) {
12856 hexEscapeChar(
os, c);
12864 for (std::size_t n = 1; n < encBytes; ++n) {
12865 uchar nc = m_str[idx + n];
12866 valid &= ((nc & 0xC0) == 0x80);
12878 (
value >= 0x110000)
12880 hexEscapeChar(
os, c);
12885 for (std::size_t n = 0; n < encBytes; ++n) {
12886 os << m_str[idx + n];
12888 idx += encBytes - 1;
12894 std::ostream&
operator << ( std::ostream&
os, XmlEncode
const& xmlEncode ) {
12895 xmlEncode.encodeTo(
os );
12899 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
12900 : m_writer( writer )
12904 : m_writer(
other.m_writer ){
12905 other.m_writer =
nullptr;
12909 m_writer->endElement();
12911 m_writer =
other.m_writer;
12912 other.m_writer =
nullptr;
12918 m_writer->endElement();
12922 m_writer->writeText( text, indent );
12928 writeDeclaration();
12932 while( !m_tags.empty() )
12938 newlineIfNecessary();
12939 m_os << m_indent <<
'<' <<
name;
12940 m_tags.push_back(
name );
12942 m_tagIsOpen =
true;
12947 ScopedElement scoped(
this );
12953 newlineIfNecessary();
12954 m_indent = m_indent.substr( 0, m_indent.size()-2 );
12955 if( m_tagIsOpen ) {
12957 m_tagIsOpen =
false;
12960 m_os << m_indent <<
"</" << m_tags.back() <<
">";
12968 if( !
name.empty() && !attribute.empty() )
12974 m_os <<
' ' <<
name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
'"';
12979 if( !
text.empty() ){
12980 bool tagWasOpen = m_tagIsOpen;
12982 if( tagWasOpen && indent )
12984 m_os << XmlEncode( text );
12985 m_needsNewline =
true;
12992 m_os << m_indent <<
"<!--" <<
text <<
"-->";
12993 m_needsNewline =
true;
12998 m_os <<
"<?xml-stylesheet type=\"text/xsl\" href=\"" <<
url <<
"\"?>\n";
13008 if( m_tagIsOpen ) {
13009 m_os <<
">" << std::endl;
13010 m_tagIsOpen =
false;
13014 void XmlWriter::writeDeclaration() {
13015 m_os <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
13018 void XmlWriter::newlineIfNecessary() {
13019 if( m_needsNewline ) {
13021 m_needsNewline =
false;
13046 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
13047 char buffer[maxDoubleSize];
13052 sprintf_s(buffer,
"%.3f", duration);
13054 std::sprintf(buffer,
"%.3f", duration);
13056 return std::string(buffer);
13059 std::string
serializeFilters( std::vector<std::string>
const& container ) {
13060 ReusableStringStream oss;
13062 for (
auto&& filter : container)
13075 :StreamingReporterBase(_config) {}
13093#ifdef CATCH_PLATFORM_MAC
13094 const char* failedString() {
return "FAILED"; }
13095 const char* passedString() {
return "PASSED"; }
13097 const char* failedString() {
return "failed"; }
13098 const char* passedString() {
return "passed"; }
13104 std::string bothOrAll( std::size_t
count ) {
13105 return count == 1 ? std::string() :
13106 count == 2 ?
"both " :
"all " ;
13119void printTotals(std::ostream& out,
const Totals& totals) {
13120 if (totals.testCases.total() == 0) {
13121 out <<
"No tests ran.";
13122 }
else if (totals.testCases.failed == totals.testCases.total()) {
13124 const std::string qualify_assertions_failed =
13125 totals.assertions.failed == totals.assertions.total() ?
13126 bothOrAll(totals.assertions.failed) :
std::string();
13128 "Failed " << bothOrAll(totals.testCases.failed)
13129 << pluralise(totals.testCases.failed,
"test case") <<
", "
13130 "failed " << qualify_assertions_failed <<
13131 pluralise(totals.assertions.failed,
"assertion") <<
'.';
13132 }
else if (totals.assertions.total() == 0) {
13134 "Passed " << bothOrAll(totals.testCases.total())
13135 << pluralise(totals.testCases.total(),
"test case")
13136 <<
" (no assertions).";
13137 }
else if (totals.assertions.failed) {
13140 "Failed " << pluralise(totals.testCases.failed,
"test case") <<
", "
13141 "failed " << pluralise(totals.assertions.failed,
"assertion") <<
'.';
13145 "Passed " << bothOrAll(totals.testCases.passed)
13146 << pluralise(totals.testCases.passed,
"test case") <<
13147 " with " << pluralise(totals.assertions.passed,
"assertion") <<
'.';
13152class AssertionPrinter {
13154 AssertionPrinter& operator= (AssertionPrinter
const&) =
delete;
13155 AssertionPrinter(AssertionPrinter
const&) =
delete;
13156 AssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
13158 , result(_stats.assertionResult)
13159 , messages(_stats.infoMessages)
13160 , itMessage(_stats.infoMessages.begin())
13161 , printInfoMessages(_printInfoMessages) {}
13166 itMessage = messages.begin();
13168 switch (result.getResultType()) {
13171 printOriginalExpression();
13172 printReconstructedExpression();
13173 if (!result.hasExpression())
13176 printRemainingMessages();
13183 printOriginalExpression();
13184 printReconstructedExpression();
13185 printRemainingMessages();
13189 printIssue(
"unexpected exception with message:");
13191 printExpressionWas();
13192 printRemainingMessages();
13196 printIssue(
"fatal error condition with message:");
13198 printExpressionWas();
13199 printRemainingMessages();
13203 printIssue(
"expected exception, got none");
13204 printExpressionWas();
13205 printRemainingMessages();
13210 printRemainingMessages();
13215 printRemainingMessages();
13219 printIssue(
"explicitly");
13232 void printSourceInfo()
const {
13234 stream << result.getSourceInfo() <<
':';
13237 void printResultType(
Colour::Code colour, std::string
const& passOrFail)
const {
13238 if (!passOrFail.empty()) {
13240 Colour colourGuard(colour);
13241 stream <<
' ' << passOrFail;
13247 void printIssue(std::string
const& issue)
const {
13248 stream <<
' ' << issue;
13251 void printExpressionWas() {
13252 if (result.hasExpression()) {
13255 Colour colour(dimColour());
13256 stream <<
" expression was:";
13258 printOriginalExpression();
13262 void printOriginalExpression()
const {
13263 if (result.hasExpression()) {
13264 stream <<
' ' << result.getExpression();
13268 void printReconstructedExpression()
const {
13269 if (result.hasExpandedExpression()) {
13271 Colour colour(dimColour());
13272 stream <<
" for: ";
13274 stream << result.getExpandedExpression();
13278 void printMessage() {
13279 if (itMessage != messages.end()) {
13280 stream <<
" '" << itMessage->message <<
'\'';
13285 void printRemainingMessages(
Colour::Code colour = dimColour()) {
13286 if (itMessage == messages.end())
13290 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
13291 const std::size_t
N =
static_cast<std::size_t
>(std::distance(itMessage, itEnd));
13294 Colour colourGuard(colour);
13295 stream <<
" with " << pluralise(
N,
"message") <<
':';
13298 for (; itMessage != itEnd; ) {
13301 stream <<
" '" << itMessage->message <<
'\'';
13302 if (++itMessage != itEnd) {
13303 Colour colourGuard(dimColour());
13311 std::ostream& stream;
13312 AssertionResult
const& result;
13313 std::vector<MessageInfo> messages;
13314 std::vector<MessageInfo>::const_iterator itMessage;
13315 bool printInfoMessages;
13321 return "Reports test results on a single line, suitable for IDEs";
13329 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
13335 AssertionResult
const& result = _assertionStats.assertionResult;
13337 bool printInfoMessages =
true;
13340 if( !
m_config->includeSuccessfulResults() && result.isOk() ) {
13343 printInfoMessages =
false;
13346 AssertionPrinter printer(
stream, _assertionStats, printInfoMessages );
13360 printTotals(
stream, _testRunStats.totals );
13361 stream <<
'\n' << std::endl;
13376#if defined(_MSC_VER)
13377#pragma warning(push)
13378#pragma warning(disable:4061)
13388class ConsoleAssertionPrinter {
13390 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter
const&) =
delete;
13391 ConsoleAssertionPrinter(ConsoleAssertionPrinter
const&) =
delete;
13392 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
13395 result(_stats.assertionResult),
13396 colour(Colour::None),
13397 message(result.getMessage()),
13398 messages(_stats.infoMessages),
13399 printInfoMessages(_printInfoMessages) {
13400 switch (result.getResultType()) {
13401 case ResultWas::Ok:
13402 colour = Colour::Success;
13403 passOrFail =
"PASSED";
13405 if (_stats.infoMessages.size() == 1)
13406 messageLabel =
"with message";
13407 if (_stats.infoMessages.size() > 1)
13408 messageLabel =
"with messages";
13410 case ResultWas::ExpressionFailed:
13411 if (result.isOk()) {
13412 colour = Colour::Success;
13413 passOrFail =
"FAILED - but was ok";
13415 colour = Colour::Error;
13416 passOrFail =
"FAILED";
13418 if (_stats.infoMessages.size() == 1)
13419 messageLabel =
"with message";
13420 if (_stats.infoMessages.size() > 1)
13421 messageLabel =
"with messages";
13425 passOrFail =
"FAILED";
13426 messageLabel =
"due to unexpected exception with ";
13427 if (_stats.infoMessages.size() == 1)
13428 messageLabel +=
"message";
13429 if (_stats.infoMessages.size() > 1)
13430 messageLabel +=
"messages";
13434 passOrFail =
"FAILED";
13435 messageLabel =
"due to a fatal error condition";
13439 passOrFail =
"FAILED";
13440 messageLabel =
"because no exception was thrown where one was expected";
13443 messageLabel =
"info";
13446 messageLabel =
"warning";
13449 passOrFail =
"FAILED";
13451 if (_stats.infoMessages.size() == 1)
13452 messageLabel =
"explicitly with message";
13453 if (_stats.infoMessages.size() > 1)
13454 messageLabel =
"explicitly with messages";
13460 passOrFail =
"** internal error **";
13466 void print()
const {
13470 printOriginalExpression();
13471 printReconstructedExpression();
13479 void printResultType()
const {
13480 if (!passOrFail.empty()) {
13481 Colour colourGuard(colour);
13482 stream << passOrFail <<
":\n";
13485 void printOriginalExpression()
const {
13493 void printReconstructedExpression()
const {
13495 stream <<
"with expansion:\n";
13500 void printMessage()
const {
13501 if (!messageLabel.empty())
13502 stream << messageLabel <<
':' <<
'\n';
13503 for (
auto const& msg : messages) {
13509 void printSourceInfo()
const {
13514 std::ostream& stream;
13515 AssertionStats
const& stats;
13516 AssertionResult
const& result;
13518 std::string passOrFail;
13519 std::string messageLabel;
13520 std::string message;
13521 std::vector<MessageInfo> messages;
13522 bool printInfoMessages;
13525std::size_t makeRatio(std::size_t number, std::size_t total) {
13527 return (ratio == 0 && number > 0) ? 1 :
ratio;
13530std::size_t& findMax(std::size_t& i, std::size_t&
j, std::size_t& k) {
13531 if (i >
j && i > k)
13540 enum Justification { Left, Right };
13545struct ColumnBreak {};
13557 static const uint64_t s_nanosecondsInAMicrosecond = 1000;
13558 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
13559 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
13560 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
13566 explicit Duration(
uint64_t inNanoseconds, Unit units = Unit::Auto)
13567 : m_inNanoseconds(inNanoseconds),
13569 if (m_units == Unit::Auto) {
13570 if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
13571 m_units = Unit::Nanoseconds;
13572 else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
13573 m_units = Unit::Microseconds;
13574 else if (m_inNanoseconds < s_nanosecondsInASecond)
13575 m_units = Unit::Milliseconds;
13576 else if (m_inNanoseconds < s_nanosecondsInAMinute)
13577 m_units = Unit::Seconds;
13579 m_units = Unit::Minutes;
13584 auto value() const ->
double {
13586 case Unit::Microseconds:
13587 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMicrosecond);
13588 case Unit::Milliseconds:
13589 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMillisecond);
13590 case Unit::Seconds:
13591 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInASecond);
13592 case Unit::Minutes:
13593 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMinute);
13595 return static_cast<double>(m_inNanoseconds);
13598 auto unitsAsString() const ->
std::
string {
13600 case Unit::Nanoseconds:
13602 case Unit::Microseconds:
13604 case Unit::Milliseconds:
13606 case Unit::Seconds:
13608 case Unit::Minutes:
13611 return "** internal error **";
13615 friend auto operator << (std::ostream&
os, Duration
const& duration) -> std::ostream& {
13616 return os << duration.value() <<
" " << duration.unitsAsString();
13621class TablePrinter {
13622 std::ostream& m_os;
13623 std::vector<ColumnInfo> m_columnInfos;
13624 std::ostringstream m_oss;
13625 int m_currentColumn = -1;
13626 bool m_isOpen =
false;
13629 TablePrinter( std::ostream&
os, std::vector<ColumnInfo> columnInfos )
13631 m_columnInfos(
std::move( columnInfos ) ) {}
13633 auto columnInfos() const ->
std::vector<ColumnInfo> const& {
13634 return m_columnInfos;
13640 *
this << RowBreak();
13641 for (
auto const& info : m_columnInfos)
13642 *
this << info.name << ColumnBreak();
13643 *
this << RowBreak();
13649 *
this << RowBreak();
13655 template<
typename T>
13661 friend TablePrinter&
operator << (TablePrinter& tp, ColumnBreak) {
13662 auto colStr = tp.m_oss.str();
13667 if (tp.m_currentColumn ==
static_cast<int>(tp.m_columnInfos.size() - 1)) {
13668 tp.m_currentColumn = -1;
13671 tp.m_currentColumn++;
13673 auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
13674 auto padding = (strSize + 2 < static_cast<
std::size_t>(colInfo.
width))
13675 ? std::string(colInfo.
width - (strSize + 2), ' ')
13677 if (colInfo.justification == ColumnInfo::Left)
13678 tp.m_os << colStr << padding <<
" ";
13680 tp.m_os << padding << colStr <<
" ";
13684 friend TablePrinter&
operator << (TablePrinter& tp, RowBreak) {
13685 if (tp.m_currentColumn > 0) {
13687 tp.m_currentColumn = -1;
13693ConsoleReporter::ConsoleReporter(ReporterConfig
const&
config)
13694 : StreamingReporterBase(
config),
13695 m_tablePrinter(new TablePrinter(
config.stream(),
13698 {
"iters", 8, ColumnInfo::Right },
13699 {
"elapsed ns", 14, ColumnInfo::Right },
13700 {
"average", 14, ColumnInfo::Right }
13705 return "Reports test results as plain lines of text";
13709 stream <<
"No test cases matched '" << spec <<
'\'' << std::endl;
13715 AssertionResult
const& result = _assertionStats.assertionResult;
13717 bool includeResults =
m_config->includeSuccessfulResults() || !result.isOk();
13725 ConsoleAssertionPrinter printer(
stream, _assertionStats, includeResults);
13732 m_headerPrinted =
false;
13737 if (_sectionStats.missingAssertions) {
13741 stream <<
"\nNo assertions in section";
13743 stream <<
"\nNo assertions in test case";
13744 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" << std::endl;
13749 if (m_headerPrinted) {
13750 m_headerPrinted =
false;
13756 lazyPrintWithoutClosingBenchmarkTable();
13760 bool firstLine =
true;
13761 for (
auto line : nameCol) {
13763 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
13767 (*m_tablePrinter) << line << ColumnBreak();
13771 Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
13773 << stats.iterations << ColumnBreak()
13774 << stats.elapsedTimeInNanoseconds << ColumnBreak()
13775 << average << ColumnBreak();
13781 m_headerPrinted =
false;
13785 printSummaryDivider();
13786 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
13787 printTotals(_testGroupStats.totals);
13788 stream <<
'\n' << std::endl;
13793 printTotalsDivider(_testRunStats.totals);
13794 printTotals(_testRunStats.totals);
13800 printTestFilters();
13803void ConsoleReporter::lazyPrint() {
13806 lazyPrintWithoutClosingBenchmarkTable();
13809void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
13812 lazyPrintRunInfo();
13814 lazyPrintGroupInfo();
13816 if (!m_headerPrinted) {
13817 printTestCaseAndSectionHeader();
13818 m_headerPrinted =
true;
13821void ConsoleReporter::lazyPrintRunInfo() {
13825 <<
" is a Catch v" <<
libraryVersion() <<
" host application.\n"
13826 <<
"Run with -? for options\n\n";
13829 stream <<
"Randomness seeded to: " <<
m_config->rngSeed() <<
"\n\n";
13833void ConsoleReporter::lazyPrintGroupInfo() {
13839void ConsoleReporter::printTestCaseAndSectionHeader() {
13849 for (; it != itEnd; ++it)
13850 printHeaderString(it->
name, 2);
13855 if (!lineInfo.empty()) {
13856 stream << getLineOfChars<
'-'>() <<
'\n';
13857 Colour colourGuard(Colour::FileName);
13858 stream << lineInfo <<
'\n';
13863void ConsoleReporter::printClosedHeader(std::string
const& _name) {
13864 printOpenHeader(_name);
13867void ConsoleReporter::printOpenHeader(std::string
const& _name) {
13871 printHeaderString(_name);
13877void ConsoleReporter::printHeaderString(std::string
const& _string, std::size_t indent) {
13878 std::size_t i = _string.find(
": ");
13879 if (i != std::string::npos)
13886struct SummaryColumn {
13892 ReusableStringStream rss;
13894 std::string row = rss.str();
13895 for (
auto& oldRow :
rows) {
13896 while (oldRow.size() < row.size())
13897 oldRow =
' ' + oldRow;
13898 while (oldRow.size() > row.size())
13901 rows.push_back(row);
13907 std::vector<std::string>
rows;
13911void ConsoleReporter::printTotals( Totals
const& totals ) {
13912 if (totals.testCases.total() == 0) {
13914 }
else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {
13917 << pluralise(totals.assertions.passed,
"assertion") <<
" in "
13918 << pluralise(totals.testCases.passed,
"test case") <<
')'
13922 std::vector<SummaryColumn> columns;
13924 .addRow(totals.testCases.total())
13925 .addRow(totals.assertions.total()));
13927 .addRow(totals.testCases.passed)
13928 .addRow(totals.assertions.passed));
13930 .addRow(totals.testCases.failed)
13931 .addRow(totals.assertions.failed));
13933 .addRow(totals.testCases.failedButOk)
13934 .addRow(totals.assertions.failedButOk));
13936 printSummaryRow(
"test cases", columns, 0);
13937 printSummaryRow(
"assertions", columns, 1);
13940void ConsoleReporter::printSummaryRow(std::string
const&
label, std::vector<SummaryColumn>
const& cols, std::size_t row) {
13941 for (
auto col : cols) {
13942 std::string
value = col.rows[row];
13943 if (col.label.empty()) {
13949 }
else if (
value !=
"0") {
13951 stream << Colour(col.colour)
13952 <<
value <<
' ' << col.label;
13958void ConsoleReporter::printTotalsDivider(Totals
const& totals) {
13959 if (totals.testCases.total() > 0) {
13960 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
13961 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
13962 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
13964 findMax(failedRatio, failedButOkRatio, passedRatio)++;
13966 findMax(failedRatio, failedButOkRatio, passedRatio)--;
13970 if (totals.testCases.allPassed())
13979void ConsoleReporter::printSummaryDivider() {
13983void ConsoleReporter::printTestFilters() {
13984 if (
m_config->testSpec().hasFilters())
13992#if defined(_MSC_VER)
13993#pragma warning(pop)
14001#include <algorithm>
14006 std::string getCurrentTimestamp() {
14010 std::time(&rawtime);
14011 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
14014 std::tm timeInfo = {};
14015 gmtime_s(&timeInfo, &rawtime);
14018 timeInfo = std::gmtime(&rawtime);
14021 char timeStamp[timeStampSize];
14022 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
14025 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
14027 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
14029 return std::string(timeStamp);
14032 std::string fileNameTag(
const std::vector<std::string> &tags) {
14033 auto it = std::find_if(
begin(tags),
14035 [] (std::string
const& tag) {
return tag.front() ==
'#'; });
14036 if (it != tags.end())
14037 return it->substr(1);
14038 return std::string();
14043 : CumulativeReporterBase( _config ),
14044 xml( _config.stream() )
14046 m_reporterPrefs.shouldRedirectStdOut =
true;
14047 m_reporterPrefs.shouldReportAllAssertions =
true;
14053 return "Reports test results in an XML format that looks like Ant's junitreport target";
14100 TestGroupStats
const& stats = groupNode.value;
14128 for(
auto const& child : groupNode.children )
14136 TestCaseStats
const& stats = testCaseNode.value;
14140 assert( testCaseNode.children.size() == 1 );
14141 SectionNode
const& rootSection = *testCaseNode.children.front();
14143 std::string className = stats.testInfo.className;
14145 if( className.empty() ) {
14146 className = fileNameTag(stats.testInfo.tags);
14147 if ( className.empty() )
14148 className =
"global";
14152 className =
m_config->name() + "." + className;
14158 std::string
const& rootName,
14159 SectionNode
const& sectionNode ) {
14160 std::string
name =
trim( sectionNode.stats.sectionInfo.name );
14161 if( !rootName.empty() )
14164 if( !sectionNode.assertions.empty() ||
14165 !sectionNode.stdOut.empty() ||
14166 !sectionNode.stdErr.empty() ) {
14168 if( className.empty() ) {
14180 if( !sectionNode.stdOut.empty() )
14182 if( !sectionNode.stdErr.empty() )
14185 for(
auto const& childNode : sectionNode.childSections )
14186 if( className.empty() )
14193 for(
auto const& assertion : sectionNode.assertions )
14198 AssertionResult
const& result = stats.assertionResult;
14199 if( !result.isOk() ) {
14200 std::string elementName;
14201 switch( result.getResultType() ) {
14204 elementName =
"error";
14207 elementName =
"failure";
14210 elementName =
"failure";
14213 elementName =
"failure";
14223 elementName =
"internalError";
14232 ReusableStringStream rss;
14233 if( !result.getMessage().empty() )
14234 rss << result.getMessage() <<
'\n';
14235 for(
auto const& msg : stats.infoMessages )
14237 rss << msg.message <<
'\n';
14239 rss <<
"at " << result.getSourceInfo();
14260 m_listeners.push_back( std::move( listener ) );
14264 assert(!m_reporter &&
"Listening reporter can wrap only 1 real reporter");
14265 m_reporter = std::move( reporter );
14270 return m_preferences;
14274 return std::set<Verbosity>{ };
14278 for (
auto const& listener : m_listeners ) {
14279 listener->noMatchingTestCases( spec );
14281 m_reporter->noMatchingTestCases( spec );
14285 for (
auto const& listener : m_listeners ) {
14286 listener->benchmarkStarting( benchmarkInfo );
14288 m_reporter->benchmarkStarting( benchmarkInfo );
14291 for (
auto const& listener : m_listeners ) {
14292 listener->benchmarkEnded( benchmarkStats );
14294 m_reporter->benchmarkEnded( benchmarkStats );
14298 for (
auto const& listener : m_listeners ) {
14299 listener->testRunStarting( testRunInfo );
14301 m_reporter->testRunStarting( testRunInfo );
14305 for (
auto const& listener : m_listeners ) {
14306 listener->testGroupStarting( groupInfo );
14308 m_reporter->testGroupStarting( groupInfo );
14312 for (
auto const& listener : m_listeners ) {
14313 listener->testCaseStarting( testInfo );
14315 m_reporter->testCaseStarting( testInfo );
14319 for (
auto const& listener : m_listeners ) {
14320 listener->sectionStarting( sectionInfo );
14322 m_reporter->sectionStarting( sectionInfo );
14326 for (
auto const& listener : m_listeners ) {
14327 listener->assertionStarting( assertionInfo );
14329 m_reporter->assertionStarting( assertionInfo );
14334 for(
auto const& listener : m_listeners ) {
14335 static_cast<void>( listener->assertionEnded( assertionStats ) );
14337 return m_reporter->assertionEnded( assertionStats );
14341 for (
auto const& listener : m_listeners ) {
14342 listener->sectionEnded( sectionStats );
14344 m_reporter->sectionEnded( sectionStats );
14348 for (
auto const& listener : m_listeners ) {
14349 listener->testCaseEnded( testCaseStats );
14351 m_reporter->testCaseEnded( testCaseStats );
14355 for (
auto const& listener : m_listeners ) {
14356 listener->testGroupEnded( testGroupStats );
14358 m_reporter->testGroupEnded( testGroupStats );
14362 for (
auto const& listener : m_listeners ) {
14363 listener->testRunEnded( testRunStats );
14365 m_reporter->testRunEnded( testRunStats );
14369 for (
auto const& listener : m_listeners ) {
14370 listener->skipTest( testInfo );
14372 m_reporter->skipTest( testInfo );
14383#if defined(_MSC_VER)
14384#pragma warning(push)
14385#pragma warning(disable:4061)
14392 : StreamingReporterBase( _config ),
14393 m_xml(_config.stream())
14395 m_reporterPrefs.shouldRedirectStdOut =
true;
14396 m_reporterPrefs.shouldReportAllAssertions =
true;
14402 return "Reports test results as an XML document";
14406 return std::string();
14422 if( !stylesheetRef.empty() )
14427 if (
m_config->testSpec().hasFilters())
14450 m_testCaseTimer.
start();
14456 if( m_sectionDepth++ > 0 ) {
14468 AssertionResult
const& result = assertionStats.assertionResult;
14470 bool includeResults =
m_config->includeSuccessfulResults() || !result.isOk();
14474 for(
auto const& msg : assertionStats.infoMessages ) {
14490 if( result.hasExpression() ) {
14500 .
writeText( result.getExpandedExpression() );
14504 switch( result.getResultType() ) {
14508 m_xml.
writeText( result.getMessage() );
14514 m_xml.
writeText( result.getMessage() );
14527 m_xml.
writeText( result.getMessage() );
14534 if( result.hasExpression() )
14542 if( --m_sectionDepth > 0 ) {
14543 XmlWriter::ScopedElement e = m_xml.
scopedElement(
"OverallResults" );
14544 e.
writeAttribute(
"successes", sectionStats.assertions.passed );
14546 e.
writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
14549 e.
writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
14557 XmlWriter::ScopedElement e = m_xml.
scopedElement(
"OverallResult" );
14558 e.
writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
14563 if( !testCaseStats.stdOut.empty() )
14565 if( !testCaseStats.stdErr.empty() )
14575 .
writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
14576 .
writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
14577 .
writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
14584 .
writeAttribute(
"successes", testRunStats.totals.assertions.passed )
14585 .
writeAttribute(
"failures", testRunStats.totals.assertions.failed )
14586 .
writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
14594#if defined(_MSC_VER)
14595#pragma warning(pop)
14604#pragma clang diagnostic pop
14610#ifdef CATCH_CONFIG_MAIN
14615#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
14617extern "C" int wmain (
int argc,
wchar_t *
argv[],
wchar_t * []) {
14620int main (
int argc,
char *
argv[]) {
14629int main (
int argc,
char *
const argv[]) {
14630#if !CATCH_ARC_ENABLED
14631 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
14637#if !CATCH_ARC_ENABLED
14649#if !defined(CATCH_CONFIG_IMPL_ONLY)
14651#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
14652# undef CLARA_CONFIG_MAIN
14655#if !defined(CATCH_CONFIG_DISABLE)
14658#ifdef CATCH_CONFIG_PREFIX_ALL
14660#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14661#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
14663#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14664#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
14665#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
14666#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14667#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
14669#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14671#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14672#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
14673#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14674#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14675#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
14677#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14678#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
14679#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
14680#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14681#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
14683#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14685#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14686#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
14688#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
14691#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
14692#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
14693#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )
14695#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
14696#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
14697#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
14698#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
14699#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
14700#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
14701#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
14702#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14703#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14705#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
14707#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
14708#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
14709#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14710#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
14711#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
14713#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
14714#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
14715#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
14716#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
14719#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
14720#define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ )
14721#define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
14723#define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ )
14724#define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
14728#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
14729#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
14730#define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
14731#define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
14732#define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
14733#define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
14734#define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
14735#define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
14740#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14741#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
14743#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14744#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
14745#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
14746#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14747#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
14749#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14751#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14752#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
14753#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14754#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14755#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
14757#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14758#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
14759#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
14760#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14761#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
14763#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14765#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14766#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
14768#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
14771#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
14772#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
14773#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
14774#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
14776#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
14777#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
14778#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
14779#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
14780#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
14781#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
14782#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
14783#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14784#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14785#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
14787#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
14788#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
14789#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14790#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
14791#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
14793#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
14794#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
14795#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
14796#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
14799#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
14800#define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
14801#define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
14803#define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ )
14804#define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
14809#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
14812#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
14813#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
14815#define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
14816#define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
14817#define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
14818#define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
14819#define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
14820#define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
14828#ifdef CATCH_CONFIG_PREFIX_ALL
14830#define CATCH_REQUIRE( ... ) (void)(0)
14831#define CATCH_REQUIRE_FALSE( ... ) (void)(0)
14833#define CATCH_REQUIRE_THROWS( ... ) (void)(0)
14834#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
14835#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
14836#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14837#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
14839#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
14841#define CATCH_CHECK( ... ) (void)(0)
14842#define CATCH_CHECK_FALSE( ... ) (void)(0)
14843#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__)
14844#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
14845#define CATCH_CHECK_NOFAIL( ... ) (void)(0)
14847#define CATCH_CHECK_THROWS( ... ) (void)(0)
14848#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
14849#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0)
14850#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14851#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
14853#define CATCH_CHECK_NOTHROW( ... ) (void)(0)
14855#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14856#define CATCH_CHECK_THAT( arg, matcher ) (void)(0)
14858#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
14861#define CATCH_INFO( msg ) (void)(0)
14862#define CATCH_WARN( msg ) (void)(0)
14863#define CATCH_CAPTURE( msg ) (void)(0)
14865#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14866#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14867#define CATCH_METHOD_AS_TEST_CASE( method, ... )
14868#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
14869#define CATCH_SECTION( ... )
14870#define CATCH_DYNAMIC_SECTION( ... )
14871#define CATCH_FAIL( ... ) (void)(0)
14872#define CATCH_FAIL_CHECK( ... ) (void)(0)
14873#define CATCH_SUCCEED( ... ) (void)(0)
14875#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14877#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
14878#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____ ) )
14879#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 )
14880#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
14881#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14883#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____ ) ) )
14884#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 ) )
14885#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
14886#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14890#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14891#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 )
14892#define CATCH_GIVEN( desc )
14893#define CATCH_AND_GIVEN( desc )
14894#define CATCH_WHEN( desc )
14895#define CATCH_AND_WHEN( desc )
14896#define CATCH_THEN( desc )
14897#define CATCH_AND_THEN( desc )
14899#define CATCH_STATIC_REQUIRE( ... ) (void)(0)
14900#define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
14905#define REQUIRE( ... ) (void)(0)
14906#define REQUIRE_FALSE( ... ) (void)(0)
14908#define REQUIRE_THROWS( ... ) (void)(0)
14909#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
14910#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
14911#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14912#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
14914#define REQUIRE_NOTHROW( ... ) (void)(0)
14916#define CHECK( ... ) (void)(0)
14917#define CHECK_FALSE( ... ) (void)(0)
14918#define CHECKED_IF( ... ) if (__VA_ARGS__)
14919#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
14920#define CHECK_NOFAIL( ... ) (void)(0)
14922#define CHECK_THROWS( ... ) (void)(0)
14923#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
14924#define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
14925#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14926#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
14928#define CHECK_NOTHROW( ... ) (void)(0)
14930#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14931#define CHECK_THAT( arg, matcher ) (void)(0)
14933#define REQUIRE_THAT( arg, matcher ) (void)(0)
14936#define INFO( msg ) (void)(0)
14937#define WARN( msg ) (void)(0)
14938#define CAPTURE( msg ) (void)(0)
14940#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14941#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14942#define METHOD_AS_TEST_CASE( method, ... )
14943#define REGISTER_TEST_CASE( Function, ... ) (void)(0)
14944#define SECTION( ... )
14945#define DYNAMIC_SECTION( ... )
14946#define FAIL( ... ) (void)(0)
14947#define FAIL_CHECK( ... ) (void)(0)
14948#define SUCCEED( ... ) (void)(0)
14949#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14951#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
14952#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____ ) )
14953#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 )
14954#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
14955#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14957#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____ ) ) )
14958#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 ) )
14959#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
14960#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14963#define STATIC_REQUIRE( ... ) (void)(0)
14964#define STATIC_REQUIRE_FALSE( ... ) (void)(0)
14968#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
14971#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )
14972#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
14974#define GIVEN( desc )
14975#define AND_GIVEN( desc )
14976#define WHEN( desc )
14977#define AND_WHEN( desc )
14978#define THEN( desc )
14979#define AND_THEN( desc )
14992# pragma warning(pop)
14994# pragma clang diagnostic pop
14996#elif defined __GNUC__
14997# pragma GCC diagnostic pop
void print(std::ostream &os, int const level, std::string const &title, Catch::SourceLineInfo const &info)
Unary< NodeType::optional > Optional
#define CATCH_CONFIG_FALLBACK_STRINGIFIER
const CBigNum operator*(const CBigNum &a, const CBigNum &b)
bool operator<(const CBigNum &a, const CBigNum &b)
const CBigNum operator+(const CBigNum &a, const CBigNum &b)
bool operator<=(const CBigNum &a, const CBigNum &b)
bool operator>=(const CBigNum &a, const CBigNum &b)
const CBigNum operator-(const CBigNum &a, const CBigNum &b)
#define CATCH_INTERNAL_LINEINFO
#define CATCH_CATCH_ANON(type)
#define CATCH_CONFIG_CONSOLE_WIDTH
#define CATCH_CONFIG_DEFAULT_REPORTER
#define CATCH_BREAK_INTO_DEBUGGER()
#define CATCH_INTERNAL_ERROR(msg)
#define CATCH_RUNTIME_ERROR(msg)
#define CATCH_ENFORCE(condition, msg)
void arcSafeRelease(NSObject *obj)
id performOptionalSelector(id obj, SEL sel)
#define CATCH_UNSAFE_UNRETAINED
Justification justification
#define CATCH_REGISTER_REPORTER(name, reporterType)
auto allowThrows() const -> bool
void handleExpr(ExprLhs< T > const &expr)
AssertionHandler(StringRef const ¯oName, SourceLineInfo const &lineInfo, StringRef capturedExpression, ResultDisposition::Flags resultDisposition)
void handleExceptionNotThrownAsExpected()
void handleThrowingCallSkipped()
void handleUnexpectedExceptionNotThrown()
void handleUnexpectedInflightException()
void handleExceptionThrownAsExpected()
void handleMessage(ResultWas::OfType resultType, StringRef const &message)
void handleExpr(ITransientExpression const &expr)
StringRef getTestMacroName() const
std::string getExpression() const
bool hasExpandedExpression() const
SourceLineInfo getSourceInfo() const
std::string getExpandedExpression() const
std::string getExpressionInMacro() const
bool hasExpression() const
ResultWas::OfType getResultType() const
AssertionResultData m_resultData
std::string getMessage() const
auto needsMoreIterations() -> bool
BenchmarkLooper(StringRef name)
auto operator==(T) const -> BinaryExpr< LhsT, RhsT const & > const
auto operator||(T) const -> BinaryExpr< LhsT, RhsT const & > const
auto operator<=(T) const -> BinaryExpr< LhsT, RhsT const & > const
BinaryExpr(bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs)
auto operator>=(T) const -> BinaryExpr< LhsT, RhsT const & > const
auto operator<(T) const -> BinaryExpr< LhsT, RhsT const & > const
auto operator>(T) const -> BinaryExpr< LhsT, RhsT const & > const
auto operator!=(T) const -> BinaryExpr< LhsT, RhsT const & > const
auto operator&&(T) const -> BinaryExpr< LhsT, RhsT const & > const
void captureValue(size_t index, std::string const &value)
void captureValues(size_t index, T const &value)
void captureValues(size_t index, T const &value, Ts const &... values)
Capturer(StringRef macroName, SourceLineInfo const &lineInfo, ResultWas::OfType resultType, StringRef names)
std::vector< std::string > const & getTestsOrTags() const override
bool hasTestFilters() const override
std::string name() const override
std::vector< std::string > const & getSectionsToRun() const override
unsigned int rngSeed() const override
bool listReporters() const
bool warnAboutMissingAssertions() const override
int benchmarkResolutionMultiple() const override
bool showInvisibles() const override
UseColour::YesOrNo useColour() const override
std::string const & getFilename() const
ShowDurations::OrNot showDurations() const override
bool includeSuccessfulResults() const override
bool listTestNamesOnly() const
TestSpec const & testSpec() const override
Verbosity verbosity() const override
RunTests::InWhatOrder runOrder() const override
int abortAfter() const override
bool warnAboutNoTests() const override
std::string getProcessName() const
std::ostream & stream() const override
std::string const & getReporterName() const
bool allowThrows() const override
bool shouldDebugBreak() const override
void setResultCapture(IResultCapture *resultCapture) override
IResultCapture * getResultCapture() override
IRunner * getRunner() override
void setConfig(IConfigPtr const &config) override
void setRunner(IRunner *runner) override
friend IMutableContext & getCurrentMutableContext()
IConfigPtr const & getConfig() const override
Approx & epsilon(T const &newEpsilon)
Approx & margin(T const &newMargin)
Approx & scale(T const &newScale)
std::string toString() const
Approx operator()(T const &value)
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
std::string translateActiveException() const override
virtual void registerTranslator(const IExceptionTranslator *translator)
~ExceptionTranslatorRegistry()
std::string tryTranslators() const
auto operator!=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
auto operator>=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
auto operator>(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
auto operator<=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
auto makeUnaryExpr() const -> UnaryExpr< LhsT >
auto operator&&(RhsT const &) -> BinaryExpr< LhsT, RhsT const & > const
auto operator||(RhsT const &) -> BinaryExpr< LhsT, RhsT const & > const
auto operator==(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
auto operator<(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
GeneratorException(const char *msg)
const char * what() const noexcept override final
ChunkGenerator(size_t size, GeneratorWrapper< T > generator)
std::vector< T > const & get() const override
T const & get() const override
FilterGenerator(P &&pred, GeneratorWrapper< T > &&generator)
FixedValuesGenerator(std::initializer_list< T > values)
T const & get() const override
GeneratorUntypedBase()=default
virtual ~GeneratorUntypedBase()
virtual ~GeneratorUntypedBase()
GeneratorWrapper(std::unique_ptr< IGenerator< T > > generator)
Generators(Gs... moreGenerators)
T const & get() const override
MapGenerator(F2 &&function, GeneratorWrapper< U > &&generator)
T const & get() const override
Float const & get() const override
RandomFloatingGenerator(Float a, Float b)
RandomIntegerGenerator(Integer a, Integer b)
Integer const & get() const override
T const & get() const override
RangeGenerator(T const &start, T const &end, T const &step)
RangeGenerator(T const &start, T const &end)
T const & get() const override
RepeatGenerator(size_t repeats, GeneratorWrapper< T > &&generator)
SingleValueGenerator(T const &value)
SingleValueGenerator(T &&value)
T const & get() const override
T const & get() const override
TakeGenerator(size_t target, GeneratorWrapper< T > &&generator)
void writeGroup(TestGroupNode const &groupNode, double suiteTime)
void testCaseStarting(TestCaseInfo const &testCaseInfo) override
std::string stdErrForSuite
std::string stdOutForSuite
JunitReporter(ReporterConfig const &_config)
void testGroupStarting(GroupInfo const &groupInfo) override
void testRunStarting(TestRunInfo const &runInfo) override
void testRunEndedCumulative() override
void writeAssertion(AssertionStats const &stats)
~JunitReporter() override
void writeSection(std::string const &className, std::string const &rootName, SectionNode const §ionNode)
void testGroupEnded(TestGroupStats const &testGroupStats) override
void writeAssertions(SectionNode const §ionNode)
void testCaseEnded(TestCaseStats const &testCaseStats) override
void noMatchingTestCases(std::string const &) override
void writeTestCase(TestCaseNode const &testCaseNode)
static std::string getDescription()
unsigned int unexpectedExceptions
bool assertionEnded(AssertionStats const &assertionStats) override
LazyExpression & operator=(LazyExpression const &)=delete
LazyExpression(bool isNegated)
friend auto operator<<(std::ostream &os, LazyExpression const &lazyExpr) -> std::ostream &
LazyExpression(LazyExpression const &other)
void addReporter(IStreamingReporterPtr &&reporter)
bool assertionEnded(AssertionStats const &assertionStats) override
void testGroupStarting(GroupInfo const &groupInfo) override
void testCaseStarting(TestCaseInfo const &testInfo) override
void testRunStarting(TestRunInfo const &testRunInfo) override
void benchmarkStarting(BenchmarkInfo const &benchmarkInfo) override
void skipTest(TestCaseInfo const &testInfo) override
void sectionEnded(SectionStats const §ionStats) override
bool isMulti() const override
void testCaseEnded(TestCaseStats const &testCaseStats) override
void testGroupEnded(TestGroupStats const &testGroupStats) override
void noMatchingTestCases(std::string const &spec) override
ReporterPreferences getPreferences() const override
void assertionStarting(AssertionInfo const &assertionInfo) override
static std::set< Verbosity > getSupportedVerbosities()
void testRunEnded(TestRunStats const &testRunStats) override
void addListener(IStreamingReporterPtr &&listener)
void sectionStarting(SectionInfo const §ionInfo) override
void benchmarkEnded(BenchmarkStats const &benchmarkStats) override
void streamReconstructedExpression(std::ostream &os) const override
MatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef const &matcherString)
bool match(T const &item) const override
PredicateMatcher(std::function< bool(T const &)> const &elem, std::string const &descr)
std::string describe() const override
std::string toString() const
virtual ~MatcherUntypedBase()
virtual std::string describe() const =0
std::string m_cachedToString
MatcherUntypedBase(MatcherUntypedBase const &)=default
virtual ~MatcherUntypedBase()
MatcherUntypedBase()=default
auto str() const -> std::string
auto str() const -> std::string
RedirectedStream(std::ostream &originalStream, std::ostream &redirectionStream)
RedirectedStreams(RedirectedStreams const &)=delete
Listeners const & getListeners() const override
~ReporterRegistry() override
void registerListener(IReporterFactoryPtr const &factory)
void registerReporter(std::string const &name, IReporterFactoryPtr const &factory)
IStreamingReporterPtr create(std::string const &name, IConfigPtr const &config) const override
FactoryMap const & getFactories() const override
auto str() const -> std::string
auto get() -> std::ostream &
void handleIncomplete(AssertionInfo const &info) override
IConfigPtr config() const
void benchmarkStarting(BenchmarkInfo const &info) override
auto acquireGeneratorTracker(SourceLineInfo const &lineInfo) -> IGeneratorTracker &override
RunContext(RunContext const &)=delete
void popScopedMessage(MessageInfo const &message) override
void benchmarkEnded(BenchmarkStats const &stats) override
void sectionEnded(SectionEndInfo const &endInfo) override
Totals runTest(TestCase const &testCase)
void emplaceUnscopedMessage(MessageBuilder const &builder) override
std::string getCurrentTestName() const override
RunContext & operator=(RunContext const &)=delete
void handleExpr(AssertionInfo const &info, ITransientExpression const &expr, AssertionReaction &reaction) override
void sectionEndedEarly(SectionEndInfo const &endInfo) override
void testGroupEnded(std::string const &testSpec, Totals const &totals, std::size_t groupIndex, std::size_t groupsCount)
IStreamingReporter & reporter() const
void exceptionEarlyReported() override
void assertionPassed() override
bool lastAssertionPassed() override
void pushScopedMessage(MessageInfo const &message) override
void handleNonExpr(AssertionInfo const &info, ResultWas::OfType resultType, AssertionReaction &reaction) override
const AssertionResult * getLastResult() const override
void handleFatalErrorCondition(StringRef message) override
void handleMessage(AssertionInfo const &info, ResultWas::OfType resultType, StringRef const &message, AssertionReaction &reaction) override
bool sectionStarted(SectionInfo const §ionInfo, Counts &assertions) override
bool aborting() const final
void handleUnexpectedExceptionNotThrown(AssertionInfo const &info, AssertionReaction &reaction) override
void testGroupStarting(std::string const &testSpec, std::size_t groupIndex, std::size_t groupsCount)
void handleUnexpectedInflightException(AssertionInfo const &info, std::string const &message, AssertionReaction &reaction) override
ScopedMessage(MessageBuilder const &builder)
ScopedMessage(ScopedMessage &duplicate)=delete
ScopedMessage(ScopedMessage &&old)
Section(SectionInfo const &info)
clara::Parser const & cli() const
void useConfigData(ConfigData const &configData)
int run(int argc, CharT const *const argv[])
ConfigData & configData()
int applyCommandLine(int argc, char const *const *argv)
static auto getMutable() -> MutableInterfaceT &
std::vector< std::exception_ptr > const & getExceptions() const noexcept
void add(std::exception_ptr const &exception) noexcept
auto operator=(StringRef const &other) noexcept -> StringRef &
auto c_str() const -> char const *
auto substr(size_type start, size_type size) const noexcept -> StringRef
StringRef(StringRef const &other) noexcept
StringRef(char const *rawChars, size_type size) noexcept
StringRef(StringRef &&other) noexcept
auto operator[](size_type index) const noexcept -> char
auto numberOfCharacters() const noexcept -> size_type
StringRef(std::string const &stdString) noexcept
void swap(StringRef &other) noexcept
auto operator!=(StringRef const &other) const noexcept -> bool
auto operator==(StringRef const &other) const noexcept -> bool
auto empty() const noexcept -> bool
auto size() const noexcept -> size_type
StringRef(char const *rawChars) noexcept
auto currentData() const noexcept -> char const *
void add(std::string const &alias, std::string const &tag, SourceLineInfo const &lineInfo)
TagAlias const * find(std::string const &alias) const override
std::string expandAliases(std::string const &unexpandedTestSpec) const override
~TagAliasRegistry() override
bool operator<(TestCase const &other) const
TestCase withName(std::string const &_newName) const
bool operator==(TestCase const &other) const
TestCaseInfo const & getTestCaseInfo() const
TestCase(ITestInvoker *testCase, TestCaseInfo &&info)
void addNextFilters(std::vector< std::string > const &filters)
void addInitialFilters(std::vector< std::string > const &filters)
static SectionTracker & acquire(TrackerContext &ctx, NameAndLocation const &nameAndLocation)
bool isSectionTracker() const override
bool isComplete() const override
SectionTracker(NameAndLocation const &nameAndLocation, TrackerContext &ctx, ITracker *parent)
NameAndLocation m_nameAndLocation
bool isComplete() const override
NameAndLocation const & nameAndLocation() const override
TrackerBase(NameAndLocation const &nameAndLocation, TrackerContext &ctx, ITracker *parent)
void setCurrentTracker(ITracker *tracker)
ITracker & currentTracker()
bool completedCycle() const
TestInvokerAsFunction(void(*testAsFunction)()) noexcept
void invoke() const override
TestInvokerAsMethod(void(C::*testAsMethod)()) noexcept
void invoke() const override
virtual ~TestRegistry()=default
std::vector< TestCase > const & getAllTests() const override
virtual void registerTest(TestCase const &testCase)
std::vector< TestCase > const & getAllTestsSorted(IConfig const &config) const override
bool matches(TestCaseInfo const &testCase) const
TestSpecParser(ITagAliasRegistry const &tagAliases)
TestSpecParser & parse(std::string const &arg)
auto getElapsedSeconds() const -> double
auto getElapsedNanoseconds() const -> uint64_t
WildcardPattern(std::string const &pattern, CaseSensitive::Choice caseSensitivity)
virtual bool matches(std::string const &str) const
void encodeTo(std::ostream &os) const
XmlEncode(std::string const &str, ForWhat forWhat=ForTextNodes)
void sectionStarting(SectionInfo const §ionInfo) override
bool assertionEnded(AssertionStats const &assertionStats) override
void testCaseStarting(TestCaseInfo const &testInfo) override
void writeSourceInfo(SourceLineInfo const &sourceInfo)
void testRunEnded(TestRunStats const &testRunStats) override
void assertionStarting(AssertionInfo const &) override
void noMatchingTestCases(std::string const &s) override
void sectionEnded(SectionStats const §ionStats) override
void testGroupStarting(GroupInfo const &groupInfo) override
XmlReporter(ReporterConfig const &_config)
void testRunStarting(TestRunInfo const &testInfo) override
void testCaseEnded(TestCaseStats const &testCaseStats) override
static std::string getDescription()
void testGroupEnded(TestGroupStats const &testGroupStats) override
virtual std::string getStylesheetRef() const
ScopedElement & writeText(std::string const &text, bool indent=true)
ScopedElement & writeAttribute(std::string const &name, T const &attribute)
ScopedElement & operator=(ScopedElement &&other) noexcept
ScopedElement(XmlWriter *writer)
XmlWriter(std::ostream &os=Catch::cout())
ScopedElement scopedElement(std::string const &name)
XmlWriter & writeText(std::string const &text, bool indent=true)
XmlWriter & startElement(std::string const &name)
void writeStylesheetRef(std::string const &url)
XmlWriter & writeComment(std::string const &text)
XmlWriter & writeBlankLine()
XmlWriter & writeAttribute(std::string const &name, std::string const &attribute)
std::forward_iterator_tag iterator_category
auto operator!=(iterator const &other) const -> bool
std::ptrdiff_t difference_type
auto operator++() -> iterator &
auto operator*() const -> std::string
auto operator==(iterator const &other) const -> bool
auto width() const -> size_t
auto operator+(Column const &other) -> Columns
Column(std::string const &text)
auto indent(size_t newIndent) -> Column &
auto begin() const -> iterator
auto toString() const -> std::string
auto end() const -> iterator
friend std::ostream & operator<<(std::ostream &os, Column const &col)
auto initialIndent(size_t newIndent) -> Column &
auto operator==(iterator const &other) const -> bool
std::ptrdiff_t difference_type
auto operator*() const -> std::string
auto operator!=(iterator const &other) const -> bool
std::forward_iterator_tag iterator_category
auto end() const -> iterator
Spacer(size_t spaceWidth)
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override
Args(int argc, char const *const *argv)
auto exeName() const -> std::string
static auto runtimeError(std::string const &message) -> BasicResult
static auto ok() -> BasicResult
static auto logicError(std::string const &message) -> BasicResult
auto name() const -> std::string
auto set(std::string const &newName) -> ParserResult
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override
std::vector< std::string > m_optNames
auto getHelpColumns() const -> std::vector< HelpColumns >
auto parse(std::string const &, TokenStream const &tokens) const -> InternalParseResult override
auto isMatch(std::string const &optToken) const -> bool
auto operator[](std::string const &optName) -> Opt &
auto validate() const -> Result override
virtual auto validate() const -> Result
virtual auto parse(std::string const &exeName, TokenStream const &tokens) const -> InternalParseResult=0
std::string m_description
ParserRefImpl(std::shared_ptr< BoundRef > const &ref)
std::shared_ptr< BoundRef > m_ref
auto hint() const -> std::string
auto width(size_t newWidth) -> Column &
auto indent(size_t newIndent) -> Column &
auto initialIndent(size_t newIndent) -> Column &
constexpr const microseconds & time_since_epoch() const
DataStream & operator<<(DataStream &ds, const float64_t &v)
bool validate(server *, websocketpp::connection_hdl)
GenericStringRef< CharType > StringRef(const CharType *str)
Mark a character pointer as constant string.
bool operator!=(const environment &other)
bool operator==(const environment &other)
#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH
#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
void close(T *e, websocketpp::connection_hdl hdl)
void diff(const std::string &a, const std::string &b)
std::string convertUnknownEnumToString(E e)
const std::string unprintableString
std::string rangeToString(InputIterator first, InputIterator last)
std::string getAnnotation(Class cls, std::string const &annotationName, std::string const &testCaseName)
std::enable_if<!std::is_enum< T >::value &&!std::is_base_of< std::exception, T >::value, std::string >::type convertUnstreamable(T const &)
std::string rawMemoryToString(const void *object, std::size_t size)
std::string stringify(const T &e)
auto acquireGeneratorTracker(SourceLineInfo const &lineInfo) -> IGeneratorTracker &
std::unique_ptr< GeneratorUntypedBase > GeneratorBasePtr
auto makeGenerators(GeneratorWrapper< T > &&generator, Gs... moreGenerators) -> Generators< T >
auto generate(SourceLineInfo const &lineInfo, L const &generatorExpression) -> decltype(std::declval< decltype(generatorExpression())>().get())
GeneratorWrapper< T > values(std::initializer_list< T > values)
std::string finalizeDescription(const std::string &desc)
Floating::WithinAbsMatcher WithinAbs(double target, double margin)
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
StdString::EqualsMatcher Equals(std::string const &str, CaseSensitive::Choice caseSensitivity)
Vector::ApproxMatcher< T > Approx(std::vector< T > const &comparator)
Vector::UnorderedEqualsMatcher< T > UnorderedEquals(std::vector< T > const &target)
Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff)
std::shared_ptr< ITracker > ITrackerPtr
auto isBreakableBefore(char c) -> bool
auto isWhitespace(char c) -> bool
auto isBreakableAfter(char c) -> bool
auto convertInto(std::string const &source, T &target) -> ParserResult
BasicResult< ParseState > InternalParseResult
BasicResult< ParseResultType > ParserResult
auto normaliseOpt(std::string const &optName) -> std::string
auto invokeLambda(L const &lambda, std::string const &arg) -> ParserResult
auto isOptPrefix(char c) -> bool
T const & operator+(T const &value, StreamEndStop)
void toLowerInPlace(std::string &s)
std::string trim(std::string const &str)
TestCase makeTestCase(ITestInvoker *_testCase, std::string const &_className, NameAndTags const &nameAndTags, SourceLineInfo const &_lineInfo)
std::vector< TestCase > filterTests(std::vector< TestCase > const &testCases, TestSpec const &testSpec, IConfig const &config)
char const * getLineOfChars()
void seedRng(IConfig const &config)
void setTags(TestCaseInfo &testCaseInfo, std::vector< std::string > tags)
std::unique_ptr< IStreamingReporter > IStreamingReporterPtr
std::size_t listTags(Config const &config)
IContext & getCurrentContext()
LeakDetector leakDetector
TestSpec parseTestSpec(std::string const &arg)
void prepareExpandedExpression(AssertionResult &result)
Version const & libraryVersion()
std::size_t listReporters()
void throw_exception(std::exception const &e)
std::vector< std::unique_ptr< IExceptionTranslator const > > ExceptionTranslators
bool uncaught_exceptions()
std::string serializeFilters(std::vector< std::string > const &container)
void formatReconstructedExpression(std::ostream &os, std::string const &lhs, StringRef op, std::string const &rhs)
bool isOk(ResultWas::OfType resultType)
bool isJustInfo(int flags)
IMutableRegistryHub & getMutableRegistryHub()
IRegistryHub const & getRegistryHub()
void handleExpression(ITransientExpression const &expr)
std::shared_ptr< IReporterFactory > IReporterFactoryPtr
bool startsWith(std::string const &s, std::string const &prefix)
IMutableContext & getCurrentMutableContext()
void enforceNoDuplicateTestCases(std::vector< TestCase > const &functions)
auto operator+=(std::string &lhs, StringRef const &rhs) -> std::string &
void addSingleton(ISingleton *singleton)
std::size_t listTestsNamesOnly(Config const &config)
bool shouldContinueOnFailure(int flags)
std::string to_string(T const &t)
Option< std::size_t > list(std::shared_ptr< Config > const &config)
auto compareNotEqual(LhsT const &lhs, RhsT &&rhs) -> bool
bool isFalseTest(int flags)
std::shared_ptr< IConfig const > IConfigPtr
std::vector< TestCase > const & getAllTestCasesSorted(IConfig const &config)
auto getCurrentNanosecondsSinceEpoch() -> uint64_t
std::string extractClassName(StringRef const &classOrQualifiedMethodName)
bool contains(std::string const &s, std::string const &infix)
Singleton< RegistryHub, IRegistryHub, IMutableRegistryHub > RegistryHubSingleton
void writeToDebugConsole(std::string const &text)
std::vector< TestCase > sortTests(IConfig const &config, std::vector< TestCase > const &unsortedTestCases)
bool matchTest(TestCase const &testCase, TestSpec const &testSpec, IConfig const &config)
ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
auto makeTestInvoker(void(*testAsFunction)()) noexcept -> ITestInvoker *
bool shouldSuppressFailure(int flags)
auto operator<<(std::ostream &os, LazyExpression const &lazyExpr) -> std::ostream &
std::string toLower(std::string const &s)
std::size_t listTests(Config const &config)
Matchers::Impl::MatcherBase< std::string > StringMatcher
auto getEstimatedClockResolution() -> uint64_t
std::string fpToString(T value, int precision)
std::size_t registerTestMethods()
std::string(*)() exceptionTranslateFunction
bool endsWith(std::string const &s, std::string const &suffix)
std::string translateActiveException()
clara::Parser makeCommandLineParser(ConfigData &config)
void handleExceptionMatchExpr(AssertionHandler &handler, std::string const &str, StringRef const &matcherString)
std::string rangeToString(Range const &range)
std::string getFormattedDuration(double duration)
auto makeStream(StringRef const &filename) -> IStream const *
IResultCapture & getResultCapture()
auto compareEqual(LhsT const &lhs, RhsT const &rhs) -> bool
bool replaceInPlace(std::string &str, std::string const &replaceThis, std::string const &withThis)
RUNTIME_API Runtime::ObjectInstance * find(const std::string &name, const IR::ObjectType &type)
static const Segment ss(Segment::ss)
bloom_filter operator|(const bloom_filter &a, const bloom_filter &b)
void copy(const path &from, const path &to)
void swap(picojson::value &x, picojson::value &y)
impl::ratio< uint64_t > ratio
sysio::time_point time_point
FloatingPoint< float > Float
uint32_t next(octet_iterator &it, octet_iterator end)
@ test
Unit testing utility error code.
const GenericPointer< typename T::ValueType > T2 defaultValue
const CharType(& source)[N]
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
#define T(meth, val, expected)
sysio::client::http::http_context context
void multi(const bn::CurveParam &cp)
std::ostream & operator<<(std::ostream &, Catch_global_namespace_dummy)
unsigned __int64 uint64_t
ResultDisposition::Flags resultDisposition
StringRef capturedExpression
std::string reconstructExpression() const
ResultWas::OfType resultType
AssertionResultData()=delete
std::string reconstructedExpression
LazyExpression lazyExpression
AssertionStats(AssertionResult const &_assertionResult, std::vector< MessageInfo > const &_infoMessages, Totals const &_totals)
virtual ~AssertionStats()
AutoReg(ITestInvoker *invoker, SourceLineInfo const &lineInfo, StringRef const &classOrMethod, NameAndTags const &nameAndTags) noexcept
@ ReconstructedExpression
static void use(Code _colourCode)
Colour & operator=(Colour &&other) noexcept
void noMatchingTestCases(std::string const &spec) override
static std::string getDescription()
void assertionStarting(AssertionInfo const &) override
void sectionEnded(SectionStats const &_sectionStats) override
ReporterPreferences getPreferences() const override
~CompactReporter() override
void testRunEnded(TestRunStats const &_testRunStats) override
bool assertionEnded(AssertionStats const &_assertionStats) override
ShowDurations::OrNot showDurations
RunTests::InWhatOrder runOrder
std::string outputFilename
std::vector< std::string > sectionsToRun
std::vector< std::string > testsOrTags
UseColour::YesOrNo useColour
int benchmarkResolutionMultiple
void testCaseEnded(TestCaseStats const &_testCaseStats) override
static std::string getDescription()
void sectionStarting(SectionInfo const &_sectionInfo) override
void testRunEnded(TestRunStats const &_testRunStats) override
void benchmarkStarting(BenchmarkInfo const &info) override
void noMatchingTestCases(std::string const &spec) override
std::unique_ptr< TablePrinter > m_tablePrinter
void sectionEnded(SectionStats const &_sectionStats) override
void testRunStarting(TestRunInfo const &_testRunInfo) override
bool assertionEnded(AssertionStats const &_assertionStats) override
void assertionStarting(AssertionInfo const &) override
void testGroupEnded(TestGroupStats const &_testGroupStats) override
void benchmarkEnded(BenchmarkStats const &stats) override
~ConsoleReporter() override
Counts & operator+=(Counts const &other)
std::size_t total() const
Counts operator-(Counts const &other) const
void testGroupStarting(GroupInfo const &) override
void testCaseEnded(TestCaseStats const &testCaseStats) override
void testGroupEnded(TestGroupStats const &testGroupStats) override
std::vector< std::shared_ptr< TestGroupNode > > m_testGroups
void testRunStarting(TestRunInfo const &) override
bool assertionEnded(AssertionStats const &assertionStats) override
auto operator<=(T const &lhs) -> ExprLhs< T const & >
static stack_t oldSigStack
static void handleSignal(int sig)
static char altStackMem[]
static struct sigaction oldSigActions[]
virtual T const & get() const =0
virtual ~IGenerator()=default
GroupInfo(std::string const &_name, std::size_t _groupIndex, std::size_t _groupsCount)
virtual RunTests::InWhatOrder runOrder() const =0
virtual bool includeSuccessfulResults() const =0
virtual bool warnAboutNoTests() const =0
virtual int abortAfter() const =0
virtual std::vector< std::string > const & getTestsOrTags() const =0
virtual bool hasTestFilters() const =0
virtual std::ostream & stream() const =0
virtual Verbosity verbosity() const =0
virtual bool shouldDebugBreak() const =0
virtual TestSpec const & testSpec() const =0
virtual bool warnAboutMissingAssertions() const =0
virtual int benchmarkResolutionMultiple() const =0
virtual UseColour::YesOrNo useColour() const =0
virtual std::string name() const =0
virtual bool showInvisibles() const =0
virtual bool allowThrows() const =0
virtual ShowDurations::OrNot showDurations() const =0
virtual unsigned int rngSeed() const =0
virtual std::vector< std::string > const & getSectionsToRun() const =0
virtual IResultCapture * getResultCapture()=0
virtual IRunner * getRunner()=0
virtual IConfigPtr const & getConfig() const =0
virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const =0
virtual ~IExceptionTranslator()
virtual ~IExceptionTranslator()
virtual ~IExceptionTranslatorRegistry()
virtual ~IExceptionTranslatorRegistry()
virtual std::string translateActiveException() const =0
virtual ~IGeneratorTracker()
virtual ~IGeneratorTracker()
virtual auto hasGenerator() const -> bool=0
virtual void setResultCapture(IResultCapture *resultCapture)=0
virtual ~IMutableContext()
virtual ~IMutableContext()
virtual void setConfig(IConfigPtr const &config)=0
virtual void setRunner(IRunner *runner)=0
virtual void registerTest(TestCase const &testInfo)=0
virtual void registerReporter(std::string const &name, IReporterFactoryPtr const &factory)=0
virtual void registerStartupException() noexcept=0
virtual ~IMutableRegistryHub()
virtual ~IMutableRegistryHub()
virtual void registerListener(IReporterFactoryPtr const &factory)=0
virtual void registerTagAlias(std::string const &alias, std::string const &tag, SourceLineInfo const &lineInfo)=0
virtual void registerTranslator(const IExceptionTranslator *translator)=0
virtual ITestCaseRegistry const & getTestCaseRegistry() const =0
virtual ITagAliasRegistry const & getTagAliasRegistry() const =0
virtual StartupExceptionRegistry const & getStartupExceptionRegistry() const =0
virtual IExceptionTranslatorRegistry const & getExceptionTranslatorRegistry() const =0
virtual IReporterRegistry const & getReporterRegistry() const =0
virtual ~IReporterFactory()
std::map< std::string, IReporterFactoryPtr > FactoryMap
virtual Listeners const & getListeners() const =0
virtual IStreamingReporterPtr create(std::string const &name, IConfigPtr const &config) const =0
std::vector< IReporterFactoryPtr > Listeners
virtual ~IReporterRegistry()
virtual FactoryMap const & getFactories() const =0
virtual void handleMessage(AssertionInfo const &info, ResultWas::OfType resultType, StringRef const &message, AssertionReaction &reaction)=0
virtual void benchmarkStarting(BenchmarkInfo const &info)=0
virtual const AssertionResult * getLastResult() const =0
virtual ~IResultCapture()
virtual void popScopedMessage(MessageInfo const &message)=0
virtual void handleFatalErrorCondition(StringRef message)=0
virtual void emplaceUnscopedMessage(MessageBuilder const &builder)=0
virtual void sectionEnded(SectionEndInfo const &endInfo)=0
virtual void handleExpr(AssertionInfo const &info, ITransientExpression const &expr, AssertionReaction &reaction)=0
virtual bool sectionStarted(SectionInfo const §ionInfo, Counts &assertions)=0
virtual void handleUnexpectedExceptionNotThrown(AssertionInfo const &info, AssertionReaction &reaction)=0
virtual void benchmarkEnded(BenchmarkStats const &stats)=0
virtual ~IResultCapture()
virtual void handleIncomplete(AssertionInfo const &info)=0
virtual void pushScopedMessage(MessageInfo const &message)=0
virtual bool lastAssertionPassed()=0
virtual void assertionPassed()=0
virtual auto acquireGeneratorTracker(SourceLineInfo const &lineInfo) -> IGeneratorTracker &=0
virtual void handleNonExpr(AssertionInfo const &info, ResultWas::OfType resultType, AssertionReaction &reaction)=0
virtual void exceptionEarlyReported()=0
virtual std::string getCurrentTestName() const =0
virtual void handleUnexpectedInflightException(AssertionInfo const &info, std::string const &message, AssertionReaction &reaction)=0
virtual void sectionEndedEarly(SectionEndInfo const &endInfo)=0
virtual bool aborting() const =0
virtual std::ostream & stream() const =0
virtual bool isMulti() const
virtual void fatalErrorEncountered(StringRef name)
virtual ~ITagAliasRegistry()
static ITagAliasRegistry const & get()
virtual std::vector< TestCase > const & getAllTestsSorted(IConfig const &config) const =0
virtual ~ITestCaseRegistry()
virtual std::vector< TestCase > const & getAllTests() const =0
virtual ~ITestCaseRegistry()
virtual void invoke() const =0
virtual ~ITransientExpression()
auto getResult() const -> bool
auto isBinaryExpression() const -> bool
bool m_isBinaryExpression
virtual void streamReconstructedExpression(std::ostream &os) const =0
ITransientExpression(bool isBinaryExpression, bool result)
virtual ~ITransientExpression()
std::string describe() const override
WithinAbsMatcher(double target, double margin)
bool match(double const &matchee) const override
WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
bool match(double const &matchee) const override
std::string describe() const override
std::string describe() const override
bool match(ArgT const &arg) const override
std::string describe() const override
bool match(ArgT const &arg) const override
bool match(ArgT const &arg) const override
MatchNotOf(MatcherBase< ArgT > const &underlyingMatcher)
std::string describe() const override
virtual bool match(ObjectT const &arg) const =0
std::string adjustString(std::string const &str) const
std::string caseSensitivitySuffix() const
CasedString(std::string const &str, CaseSensitive::Choice caseSensitivity)
bool match(std::string const &source) const override
ContainsMatcher(CasedString const &comparator)
EndsWithMatcher(CasedString const &comparator)
bool match(std::string const &source) const override
bool match(std::string const &source) const override
EqualsMatcher(CasedString const &comparator)
std::string describe() const override
bool match(std::string const &matchee) const override
RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity)
StartsWithMatcher(CasedString const &comparator)
bool match(std::string const &source) const override
StringMatcherBase(std::string const &operation, CasedString const &comparator)
std::string describe() const override
std::string describe() const override
ApproxMatcher & epsilon(T const &newEpsilon)
ApproxMatcher & margin(T const &newMargin)
ApproxMatcher(std::vector< T > const &comparator)
ApproxMatcher & scale(T const &newScale)
bool match(std::vector< T > const &v) const override
ContainsElementMatcher(T const &comparator)
bool match(std::vector< T > const &v) const override
std::string describe() const override
std::string describe() const override
ContainsMatcher(std::vector< T > const &comparator)
bool match(std::vector< T > const &v) const override
bool match(std::vector< T > const &v) const override
std::string describe() const override
EqualsMatcher(std::vector< T > const &comparator)
bool match(std::vector< T > const &vec) const override
UnorderedEqualsMatcher(std::vector< T > const &target)
std::string describe() const override
MessageBuilder(StringRef const ¯oName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
MessageBuilder & operator<<(T const &value)
bool operator<(MessageInfo const &other) const
bool operator==(MessageInfo const &other) const
MessageInfo(StringRef const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
MessageStream & operator<<(T const &value)
ReusableStringStream m_stream
RegistrarForTagAliases(char const *alias, char const *tag, SourceLineInfo const &lineInfo)
std::ostream & stream() const
IConfigPtr fullConfig() const
ReporterConfig(IConfigPtr const &_fullConfig)
bool shouldReportAllAssertions
bool shouldRedirectStdOut
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name, std::string const &)
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name)
SectionStats(SectionInfo const &_sectionInfo, Counts const &_assertions, double _durationInSeconds, bool _missingAssertions)
bool empty() const noexcept
SourceLineInfo(char const *_file, std::size_t _line) noexcept
SourceLineInfo(SourceLineInfo &&) noexcept=default
SourceLineInfo(SourceLineInfo const &other)=default
SourceLineInfo & operator=(SourceLineInfo const &)=default
bool operator==(SourceLineInfo const &other) const noexcept
bool operator<(SourceLineInfo const &other) const noexcept
std::string operator+() const
LazyStat< GroupInfo > currentGroupInfo
void sectionStarting(SectionInfo const &_sectionInfo) override
void noMatchingTestCases(std::string const &) override
void testRunStarting(TestRunInfo const &_testRunInfo) override
std::vector< SectionInfo > m_sectionStack
void testGroupStarting(GroupInfo const &_groupInfo) override
void testRunEnded(TestRunStats const &) override
LazyStat< TestCaseInfo > currentTestCaseInfo
ReporterPreferences m_reporterPrefs
void sectionEnded(SectionStats const &) override
LazyStat< TestRunInfo > currentTestRunInfo
void testCaseStarting(TestCaseInfo const &_testInfo) override
void testCaseEnded(TestCaseStats const &) override
void testGroupEnded(TestGroupStats const &) override
static std::string convert(Catch::Detail::Approx const &value)
static std::string convert(R const &range)
static std::string convert(R C::*p)
static std::string convert(U *p)
static std::string convert(T const(&arr)[SZ])
static std::string convert(bool b)
static std::string convert(char c)
static std::string convert(char *str)
static std::string convert(char const *str)
static std::string convert(char const *str)
static std::string convert(double value)
static std::string convert(float value)
static std::string convert(int value)
static std::string convert(long value)
static std::string convert(long long value)
static std::string convert(signed char c)
static std::string convert(signed char const *str)
static std::string convert(std::nullptr_t)
static std::string convert(const std::string &str)
static std::string convert(const std::wstring &wstr)
static std::string convert(unsigned char c)
static std::string convert(unsigned char const *str)
static std::string convert(unsigned int value)
static std::string convert(unsigned long value)
static std::string convert(unsigned long long value)
static std::string convert(wchar_t *str)
static std::string convert(wchar_t const *str)
static std::enable_if<::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
static std::enable_if<!::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
auto add() -> std::size_t
std::ostringstream m_referenceStream
std::vector< std::size_t > m_unused
void release(std::size_t index)
std::vector< std::unique_ptr< std::ostringstream > > m_streams
SummaryColumn(std::string _label, Colour::Code _colour)
std::vector< std::string > rows
SummaryColumn addRow(std::size_t count)
TagAlias(std::string const &_tag, SourceLineInfo _lineInfo)
void add(std::string const &spelling)
std::set< std::string > spellings
std::string tagsAsString() const
bool expectedToFail() const
TestCaseInfo(std::string const &_name, std::string const &_className, std::string const &_description, std::vector< std::string > const &_tags, SourceLineInfo const &_lineInfo)
std::vector< std::string > tags
SpecialProperties properties
TestCaseStats(TestCaseInfo const &_testInfo, Totals const &_totals, std::string const &_stdOut, std::string const &_stdErr, bool _aborting)
virtual bool isSuccessfullyCompleted() const =0
NameAndLocation(std::string const &_name, SourceLineInfo const &_location)
bool assertionEnded(AssertionStats const &) override
static std::set< Verbosity > getSupportedVerbosities()
void assertionStarting(AssertionInfo const &) override
TestEventListenerBase(ReporterConfig const &_config)
virtual ~TestGroupStats()
TestGroupStats(GroupInfo const &_groupInfo, Totals const &_totals, bool _aborting)
TestRunInfo(std::string const &_name)
TestRunStats(TestRunInfo const &_runInfo, Totals const &_totals, bool _aborting)
Totals delta(Totals const &prevTotals) const
Totals operator-(Totals const &other) const
Totals & operator+=(Totals const &other)
unsigned int const buildNumber
char const *const branchName
Version & operator=(Version const &)=delete
unsigned int const minorVersion
friend std::ostream & operator<<(std::ostream &os, Version const &version)
unsigned int const majorVersion
unsigned int const patchNumber
Version(Version const &)=delete
typename append< L1< E1..., E2... >, Rest... >::type type
auto operator|=(ExeName const &exeName) -> Parser &
std::vector< Opt > m_options
auto operator|(T const &other) const -> Parser
auto validate() const -> Result override
void writeToStream(std::ostream &os) const
friend auto operator<<(std::ostream &os, Parser const &parser) -> std::ostream &
std::vector< Arg > m_args
auto operator+(T const &other) const -> Parser
auto parse(std::string const &exeName, TokenStream const &tokens) const -> InternalParseResult override
auto getHelpColumns() const -> std::vector< HelpColumns >
auto operator+=(T const &other) -> Parser &
typename append< Final<>, typename rewrap< Containers, Types... >::type... >::type type
pluralise(std::size_t count, std::string const &label)
typename append< TypeList< Container< Elems... > >, typename rewrap< Container, Elements... >::type >::type type
FILE * TempFile(char *filename)
void inc(const Operand &op)
void setp(const Operand &op)
yubihsm_pkcs11_object_template template
yh_object_descriptor object
memcpy((char *) pInfo->slotDescription, s, l)
c_gkp_out sizeof(template))