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 13
18 #define CATCH_VERSION_PATCH 8
21 # pragma clang system_header
22 #elif defined __GNUC__
23 # pragma GCC system_header
30 # pragma warning(push)
31 # pragma warning(disable: 161 1682)
33 # pragma clang diagnostic push
34 # pragma clang diagnostic ignored "-Wpadded"
35 # pragma clang diagnostic ignored "-Wswitch-enum"
36 # pragma clang diagnostic ignored "-Wcovered-switch-default"
38 #elif defined __GNUC__
42 # pragma GCC diagnostic ignored "-Wparentheses"
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)
72 # include <TargetConditionals.h>
73 # if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \
74 (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
75 # define CATCH_PLATFORM_MAC
76 # elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
77 # define CATCH_PLATFORM_IPHONE
80 #elif defined(linux) || defined(__linux) || defined(__linux__)
81 # define CATCH_PLATFORM_LINUX
83 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
84 # define CATCH_PLATFORM_WINDOWS
90 # ifndef CLARA_CONFIG_MAIN
91 # define CLARA_CONFIG_MAIN_NOT_DEFINED
92 # define CLARA_CONFIG_MAIN
128 # if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
129 # define CATCH_CPP14_OR_GREATER
132 # if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
133 # define CATCH_CPP17_OR_GREATER
140 #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)
141 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
142 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" )
144 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
148 #if defined(__clang__)
150 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
151 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" )
164 # if !defined(__ibmxl__) && !defined(__CUDACC__)
165 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
168 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
169 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
170 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
172 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
173 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
175 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
176 _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
178 # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
179 _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
181 # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
182 _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
188 #if !defined(CATCH_PLATFORM_WINDOWS)
189 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
194 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__ghs) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
195 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
199 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
200 # define CATCH_CONFIG_COLOUR_NONE
205 #if defined(__ANDROID__)
206 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
207 # define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
212 #if defined(__MINGW32__)
213 # define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
218 #if defined(__ORBIS__)
219 # define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
231 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
232 && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
234 # define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
241 #if defined(_MSC_VER)
245 # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
246 # define CATCH_CONFIG_COLOUR_NONE
248 # define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
251 # if !defined(__clang__)
256 # if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
257 # define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
261 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
262 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) )
267 #if defined(_REENTRANT) || defined(_MSC_VER)
269 # define CATCH_INTERNAL_CONFIG_USE_ASYNC
274 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
275 # define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
281 # define CATCH_INTERNAL_CONFIG_NO_WCHAR
286 #if defined(__BORLANDC__)
287 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
297 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
298 #define CATCH_INTERNAL_CONFIG_COUNTER
306 #if defined(UNDER_RTSS) || defined(RTX64_BUILD)
307 #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
308 #define CATCH_INTERNAL_CONFIG_NO_ASYNC
309 #define CATCH_CONFIG_COLOUR_NONE
312 #if !defined(_GLIBCXX_USE_C99_MATH_TR1)
313 #define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
317 #if defined(__has_include)
319 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
320 # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
324 # if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
325 # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
329 # if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
331 # if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)
332 # define CATCH_INTERNAL_CONFIG_CPP17_BYTE
337 # if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
338 # if defined(__clang__) && (__clang_major__ < 8)
342 # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
343 # define CATCH_CONFIG_NO_CPP17_VARIANT
345 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
348 # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
353 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
354 # define CATCH_CONFIG_COUNTER
356 #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)
357 # define CATCH_CONFIG_WINDOWS_SEH
360 #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)
361 # define CATCH_CONFIG_POSIX_SIGNALS
364 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
365 # define CATCH_CONFIG_WCHAR
368 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
369 # define CATCH_CONFIG_CPP11_TO_STRING
372 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
373 # define CATCH_CONFIG_CPP17_OPTIONAL
376 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
377 # define CATCH_CONFIG_CPP17_STRING_VIEW
380 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
381 # define CATCH_CONFIG_CPP17_VARIANT
384 #if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
385 # define CATCH_CONFIG_CPP17_BYTE
388 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
389 # define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
392 #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)
393 # define CATCH_CONFIG_NEW_CAPTURE
396 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
397 # define CATCH_CONFIG_DISABLE_EXCEPTIONS
400 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
401 # define CATCH_CONFIG_POLYFILL_ISNAN
404 #if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
405 # define CATCH_CONFIG_USE_ASYNC
408 #if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE)
409 # define CATCH_CONFIG_ANDROID_LOGWRITE
412 #if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
413 # define CATCH_CONFIG_GLOBAL_NEXTAFTER
418 #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
419 # define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
421 #if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
422 # define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
424 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
425 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
427 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
428 # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
430 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
431 # define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
433 #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
434 # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
439 #if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
440 # define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
443 #if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
444 # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
445 #elif defined(__clang__) && (__clang_major__ < 5)
446 # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
449 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)
450 # define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
453 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
454 #define CATCH_TRY if ((true))
455 #define CATCH_CATCH_ALL if ((false))
456 #define CATCH_CATCH_ANON(type) if ((false))
458 #define CATCH_TRY try
459 #define CATCH_CATCH_ALL catch (...)
460 #define CATCH_CATCH_ANON(type) catch (type)
463 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
464 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
468 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
469 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
470 #ifdef CATCH_CONFIG_COUNTER
471 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
473 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
543 #define CATCH_INTERNAL_LINEINFO \
544 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
555 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
556 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
557 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
558 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
559 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
612 static constexpr
char const*
const s_empty =
"";
614 char const* m_start = s_empty;
623 : m_start( rawChars ),
628 : m_start( stdString.c_str() ),
629 m_size( stdString.size() )
639 return !(*
this ==
other);
644 return m_start[
index];
669 return m_start[m_size] ==
'\0';
680 constexpr
auto operator "" _sr(
char const* rawChars, std::size_t
size ) noexcept ->
StringRef {
693 #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
694 #define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
695 #define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
696 #define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
697 #define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
698 #define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
700 #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
701 #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
703 #define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
704 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
706 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__)
709 #define CATCH_REC_END(...)
710 #define CATCH_REC_OUT
712 #define CATCH_EMPTY()
713 #define CATCH_DEFER(id) id CATCH_EMPTY()
715 #define CATCH_REC_GET_END2() 0, CATCH_REC_END
716 #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
717 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
718 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
719 #define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
720 #define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
722 #define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
723 #define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
724 #define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
726 #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__ )
727 #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__ )
728 #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__ )
733 #define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
735 #define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
737 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
738 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
739 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
740 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
741 #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
742 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
743 #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
744 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
747 #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
748 #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
749 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
752 #define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
753 #define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
755 #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
757 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
758 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())
759 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
761 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()))
762 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
765 #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\
766 CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__)
768 #define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)
769 #define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)
770 #define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)
771 #define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3)
772 #define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4)
773 #define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5)
774 #define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6)
775 #define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7)
776 #define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8)
777 #define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9)
778 #define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10)
780 #define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
782 #define INTERNAL_CATCH_TYPE_GEN\
783 template<typename...> struct TypeList {};\
784 template<typename...Ts>\
785 constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
786 template<template<typename...> class...> struct TemplateTypeList{};\
787 template<template<typename...> class...Cs>\
788 constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\
789 template<typename...>\
791 template<typename...>\
793 template<template<typename...> class, typename...>\
795 template<template<typename...> class, typename>\
798 template<typename T> \
799 struct append<T> { using type = T; };\
800 template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
801 struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
802 template< template<typename...> class L1, typename...E1, typename...Rest>\
803 struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
805 template< template<typename...> class Container, template<typename...> class List, typename...elems>\
806 struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
807 template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
808 struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
810 template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
811 struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
812 template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
813 struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
815 #define INTERNAL_CATCH_NTTP_1(signature, ...)\
816 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
817 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
818 constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
819 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
820 template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
821 constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
823 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
824 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
825 template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
826 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\
827 template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
828 struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };
830 #define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
831 #define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
832 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
833 static void TestName()
834 #define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\
835 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
836 static void TestName()
838 #define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)
839 #define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\
840 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
841 static void TestName()
842 #define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\
843 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
844 static void TestName()
846 #define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\
847 template<typename Type>\
848 void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\
850 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
853 #define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\
854 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
855 void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
857 Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
860 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\
861 template<typename Type>\
862 void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
864 Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
867 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\
868 template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
869 void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
871 Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
874 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)
875 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\
876 template<typename TestType> \
877 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \
881 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\
882 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
883 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \
887 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)
888 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\
889 template<typename TestType> \
890 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test()
891 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\
892 template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
893 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()
895 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
896 #define INTERNAL_CATCH_NTTP_0
897 #define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__),INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_0)
898 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)
899 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)
900 #define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)
901 #define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)
902 #define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)
903 #define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)
904 #define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)
906 #define INTERNAL_CATCH_NTTP_0(signature)
907 #define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1,INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_0)( __VA_ARGS__))
908 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__))
909 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__))
910 #define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__))
911 #define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__))
912 #define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__))
913 #define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__))
914 #define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__))
921 #include <type_traits>
929 template <
typename Fun,
typename...
Args>
931 template <
typename...>
932 std::false_type
static test(...);
935 template <
typename T>
938 template <
typename Fun,
typename...
Args>
939 struct is_callable<Fun(
Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
941 #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
944 template <
typename Func,
typename...
U>
945 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func,
U...>>>;
948 template <
typename Func,
typename...
U>
963 void (
C::*m_testAsMethod)();
969 (
obj.*m_testAsMethod)();
993 #if defined(CATCH_CONFIG_DISABLE)
994 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
995 static void TestName()
996 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
998 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
1002 void TestName::test()
1003 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... ) \
1004 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1005 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
1007 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
1008 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
1011 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1013 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1014 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
1015 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_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, typename TestType, __VA_ARGS__ )
1017 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
1018 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_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, typename TestType, __VA_ARGS__ ) )
1021 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1022 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
1023 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_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, Signature, __VA_ARGS__ )
1025 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
1026 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_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, Signature, __VA_ARGS__ ) )
1029 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1030 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
1031 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_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, typename T, __VA_ARGS__ )
1033 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
1034 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_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, typename T, __VA_ARGS__ ) )
1037 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1038 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
1039 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_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, Signature, __VA_ARGS__ )
1041 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
1042 INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_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, Signature, __VA_ARGS__ ) )
1047 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
1048 static void TestName(); \
1049 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1050 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1051 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } \
1052 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1053 static void TestName()
1054 #define INTERNAL_CATCH_TESTCASE( ... ) \
1055 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), __VA_ARGS__ )
1058 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
1059 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1060 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1061 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); }
\
1062 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
1065 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
1066 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1067 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1069 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
1072 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); \
1074 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1075 void TestName::test()
1076 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
1077 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), ClassName, __VA_ARGS__ )
1080 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
1081 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1082 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1083 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); \
1084 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
1087 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
1088 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1089 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1090 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1091 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1092 INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
1094 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
1095 INTERNAL_CATCH_TYPE_GEN\
1096 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1097 INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1098 template<typename...Types> \
1102 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
1103 using expander = int[];\
1104 (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };
\
1107 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1108 TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
1113 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1114 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
1116 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1117 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
1118 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, typename TestType, __VA_ARGS__ )
1120 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
1121 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, typename TestType, __VA_ARGS__ ) )
1124 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1125 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
1126 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, Signature, __VA_ARGS__ )
1128 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
1129 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, Signature, __VA_ARGS__ ) )
1132 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
1133 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1134 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1135 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1136 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1137 template<typename TestType> static void TestFuncName(); \
1139 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) { \
1140 INTERNAL_CATCH_TYPE_GEN \
1141 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
1142 template<typename... Types> \
1144 void reg_tests() { \
1146 using expander = int[]; \
1147 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
1148 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
1149 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
1150 (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++)... };
\
1153 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
1154 using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
1161 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1162 template<typename TestType> \
1163 static void TestFuncName()
1165 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1166 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
1167 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, typename T,__VA_ARGS__)
1169 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
1170 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, typename T, __VA_ARGS__ ) )
1173 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1174 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
1175 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, Signature, __VA_ARGS__)
1177 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
1178 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, Signature, __VA_ARGS__ ) )
1181 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
1182 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1183 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1184 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1185 template<typename TestType> static void TestFunc(); \
1187 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
1188 INTERNAL_CATCH_TYPE_GEN\
1189 template<typename... Types> \
1191 void reg_tests() { \
1193 using expander = int[]; \
1194 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };
\
1197 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
1198 using TestInit = typename convert<TestName, TmplList>::type; \
1204 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1205 template<typename TestType> \
1206 static void TestFunc()
1208 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
1209 INTERNAL_CATCH_TEMPLATE_LIST_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, TmplList )
1211 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
1212 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1213 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1214 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1215 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1217 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
1218 INTERNAL_CATCH_TYPE_GEN\
1219 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1220 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
1221 INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1222 template<typename...Types> \
1223 struct TestNameClass{\
1226 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
1227 using expander = int[];\
1228 (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };
\
1231 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1232 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
1237 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1238 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1240 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1241 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
1242 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, typename T, __VA_ARGS__ )
1244 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
1245 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, typename T, __VA_ARGS__ ) )
1248 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1249 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
1250 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, Signature, __VA_ARGS__ )
1252 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
1253 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, Signature, __VA_ARGS__ ) )
1256 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
1257 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1258 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1259 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1260 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1261 template<typename TestType> \
1262 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
1266 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\
1267 INTERNAL_CATCH_TYPE_GEN \
1268 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1269 template<typename...Types>\
1270 struct TestNameClass{\
1273 using expander = int[];\
1274 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
1275 constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
1276 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
1277 (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++)... };
\
1280 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1281 using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\
1288 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1289 template<typename TestType> \
1290 void TestName<TestType>::test()
1292 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1293 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
1294 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, typename T, __VA_ARGS__ )
1296 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
1297 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, typename T,__VA_ARGS__ ) )
1300 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1301 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
1302 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, Signature, __VA_ARGS__ )
1304 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
1305 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, Signature,__VA_ARGS__ ) )
1308 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
1309 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1310 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1311 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1312 template<typename TestType> \
1313 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
1317 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
1318 INTERNAL_CATCH_TYPE_GEN\
1319 template<typename...Types>\
1320 struct TestNameClass{\
1323 using expander = int[];\
1324 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };
\
1327 static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1328 using TestInit = typename convert<TestNameClass, TmplList>::type;\
1334 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1335 template<typename TestType> \
1336 void TestName<TestType>::test()
1338 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
1339 INTERNAL_CATCH_TEMPLATE_LIST_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, TmplList )
1417 #include <type_traits>
1441 std::size_t m_index;
1442 std::ostream* m_oss;
1449 template<typename
T>
1454 auto get() -> std::ostream& {
return *m_oss; }
1481 template<
typename E>
1483 static_assert(
sizeof(
int) >=
sizeof(E),
"Cannot serialize enum to int");
1484 std::vector<int> intValues;
1485 intValues.reserve(
values.size() );
1487 intValues.push_back(
static_cast<int>(
enumValue ) );
1496 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1497 #include <string_view>
1503 #import <Foundation/Foundation.h>
1505 #ifdef __has_feature
1506 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1508 #define CATCH_ARC_ENABLED 0
1511 void arcSafeRelease( NSObject*
obj );
1512 id performOptionalSelector(
id obj,
SEL sel );
1514 #if !CATCH_ARC_ENABLED
1515 inline void arcSafeRelease( NSObject*
obj ) {
1518 inline id performOptionalSelector(
id obj,
SEL sel ) {
1519 if( [
obj respondsToSelector: sel] )
1520 return [
obj performSelector: sel];
1523 #define CATCH_UNSAFE_UNRETAINED
1524 #define CATCH_ARC_STRONG
1526 inline void arcSafeRelease( NSObject* ){}
1527 inline id performOptionalSelector(
id obj,
SEL sel ) {
1529 #pragma clang diagnostic push
1530 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1532 if( [
obj respondsToSelector: sel] )
1533 return [
obj performSelector: sel];
1535 #pragma clang diagnostic pop
1539 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1540 #define CATCH_ARC_STRONG __strong
1547 #pragma warning(push)
1548 #pragma warning(disable:4180)
1558 template<
typename T>
1563 template<
typename T>
1565 template<
typename Stream,
typename U>
1566 static auto test(
int)
1567 -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
1569 template<
typename,
typename>
1570 static auto test(...)->std::false_type;
1573 static const bool value = decltype(test<std::ostream, const T&>(0))::
value;
1576 template<
typename E>
1579 template<
typename T>
1580 typename std::enable_if<
1585 template<
typename T>
1586 typename std::enable_if<
1592 template<
typename T>
1593 typename std::enable_if<
1599 #if defined(_MANAGED)
1601 template<
typename T>
1605 auto bytes = System::Text::Encoding::UTF8->GetBytes(
ref->ToString());
1606 cli::pin_ptr<System::Byte>
p = &bytes[0];
1607 return std::string(
reinterpret_cast<char const *
>(
p), bytes->Length);
1614 template <
typename T,
typename =
void>
1616 template <
typename Fake = T>
1623 rss.operator<<(
value);
1627 template <
typename Fake = T>
1631 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
1634 return CATCH_CONFIG_FALLBACK_STRINGIFIER(
value);
1643 template <
typename T>
1648 template<
typename E>
1653 #if defined(_MANAGED)
1654 template <
typename T>
1669 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1685 #ifdef CATCH_CONFIG_WCHAR
1691 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1729 #if defined(CATCH_CONFIG_CPP17_BYTE)
1731 struct StringMaker<
std::byte> {
1795 template <
typename T>
1797 template <
typename U>
1807 template <
typename R,
typename C>
1818 #if defined(_MANAGED)
1819 template <
typename T>
1820 struct StringMaker<
T^> {
1822 return ::Catch::Detail::clrReferenceToString(
ref);
1828 template<
typename InputIterator,
typename Sentinel = InputIterator>
1832 if (
first != last) {
1844 struct StringMaker<NSString*> {
1852 struct StringMaker<NSObject*> {
1872 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
1873 # define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
1874 # define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
1875 # define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
1876 # define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
1877 # define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
1881 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
1884 template<
typename T1,
typename T2>
1885 struct StringMaker<
std::pair<T1, T2> > {
1887 ReusableStringStream rss;
1899 #if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
1902 template<
typename T>
1903 struct StringMaker<
std::optional<T> > {
1905 ReusableStringStream rss;
1906 if (optional.has_value()) {
1918 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
1927 struct TupleElementPrinter {
1928 static void print(
const Tuple& tuple, std::ostream& os) {
1929 os << (
N ?
", " :
" ")
1931 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
1939 struct TupleElementPrinter<Tuple,
N,
false> {
1940 static void print(
const Tuple&, std::ostream&) {}
1945 template<
typename ...Types>
1946 struct StringMaker<
std::tuple<Types...>> {
1948 ReusableStringStream rss;
1950 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
1958 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
1962 struct StringMaker<
std::monostate> {
1968 template<
typename... Elements>
1969 struct StringMaker<
std::
variant<Elements...>> {
1971 if (
variant.valueless_by_exception()) {
1972 return "{valueless variant}";
1975 [](
const auto&
value) {
1992 template <
typename...>
1997 template <
typename T,
typename =
void>
2001 template <
typename T>
2006 template <
typename T>
2010 #if defined(_MANAGED)
2011 template <
typename T>
2013 static const bool value =
false;
2017 template<
typename Range>
2023 template<
typename Allocator>
2039 template<
typename R>
2040 struct StringMaker<
R, typename
std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>
::type> {
2046 template <
typename T,
int SZ>
2056 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
2063 template <
class Ratio>
2064 struct ratio_string {
2068 template <
class Ratio>
2072 << Ratio::den <<
']';
2076 struct ratio_string<
std::atto> {
2080 struct ratio_string<
std::femto> {
2084 struct ratio_string<
std::pico> {
2088 struct ratio_string<
std::nano> {
2092 struct ratio_string<
std::micro> {
2096 struct ratio_string<
std::milli> {
2102 template<
typename Value,
typename Ratio>
2103 struct StringMaker<
std::chrono::duration<Value, Ratio>> {
2105 ReusableStringStream rss;
2106 rss << duration.count() <<
' ' << ratio_string<Ratio>::symbol() <<
's';
2110 template<
typename Value>
2111 struct StringMaker<
std::chrono::duration<Value, std::ratio<1>>> {
2113 ReusableStringStream rss;
2114 rss << duration.count() <<
" s";
2118 template<
typename Value>
2119 struct StringMaker<
std::chrono::duration<Value, std::ratio<60>>> {
2121 ReusableStringStream rss;
2122 rss << duration.count() <<
" m";
2126 template<
typename Value>
2127 struct StringMaker<
std::chrono::duration<Value, std::ratio<3600>>> {
2129 ReusableStringStream rss;
2130 rss << duration.count() <<
" h";
2138 template<
typename Clock,
typename Duration>
2139 struct StringMaker<
std::chrono::time_point<Clock, Duration>> {
2140 static std::string convert(std::chrono::time_point<Clock, Duration>
const& time_point) {
2145 template<
typename Duration>
2146 struct StringMaker<
std::chrono::time_point<std::chrono::system_clock, Duration>> {
2147 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration>
const& time_point) {
2148 auto converted = std::chrono::system_clock::to_time_t(time_point);
2151 std::tm timeInfo = {};
2152 gmtime_s(&timeInfo, &converted);
2154 std::tm* timeInfo = std::gmtime(&converted);
2157 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
2158 char timeStamp[timeStampSize];
2159 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
2162 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
2164 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
2172 #define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
2174 template<> struct StringMaker<enumName> { \
2175 static std::string convert( enumName value ) { \
2176 static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
2177 return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
2182 #define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
2185 #pragma warning(pop)
2192 #pragma warning(push)
2193 #pragma warning(disable:4389)
2194 #pragma warning(disable:4018)
2195 #pragma warning(disable:4312)
2196 #pragma warning(disable:4180)
2197 #pragma warning(disable:4800)
2223 template<
typename LhsT,
typename RhsT>
2229 void streamReconstructedExpression( std::ostream &os )
const override {
2242 template<
typename T>
2245 "chained comparisons are not supported inside assertions, "
2246 "wrap the expression inside parentheses, or decompose it");
2249 template<
typename T>
2252 "chained comparisons are not supported inside assertions, "
2253 "wrap the expression inside parentheses, or decompose it");
2256 template<
typename T>
2259 "chained comparisons are not supported inside assertions, "
2260 "wrap the expression inside parentheses, or decompose it");
2263 template<
typename T>
2266 "chained comparisons are not supported inside assertions, "
2267 "wrap the expression inside parentheses, or decompose it");
2270 template<
typename T>
2273 "chained comparisons are not supported inside assertions, "
2274 "wrap the expression inside parentheses, or decompose it");
2277 template<
typename T>
2280 "chained comparisons are not supported inside assertions, "
2281 "wrap the expression inside parentheses, or decompose it");
2284 template<
typename T>
2287 "chained comparisons are not supported inside assertions, "
2288 "wrap the expression inside parentheses, or decompose it");
2291 template<
typename T>
2294 "chained comparisons are not supported inside assertions, "
2295 "wrap the expression inside parentheses, or decompose it");
2299 template<
typename LhsT>
2303 void streamReconstructedExpression( std::ostream &os )
const override {
2315 template<
typename LhsT,
typename RhsT>
2317 template<
typename T>
2319 template<
typename T>
2321 template<
typename T>
2323 template<
typename T>
2326 template<
typename LhsT,
typename RhsT>
2328 template<
typename T>
2330 template<
typename T>
2332 template<
typename T>
2334 template<
typename T>
2337 template<
typename LhsT>
2343 template<
typename RhsT>
2348 return { m_lhs ==
rhs, m_lhs,
"==",
rhs };
2351 template<
typename RhsT>
2356 return { m_lhs !=
rhs, m_lhs,
"!=",
rhs };
2359 template<
typename RhsT>
2361 return {
static_cast<bool>(m_lhs >
rhs), m_lhs,
">",
rhs };
2363 template<
typename RhsT>
2365 return {
static_cast<bool>(m_lhs <
rhs), m_lhs,
"<",
rhs };
2367 template<
typename RhsT>
2369 return {
static_cast<bool>(m_lhs >=
rhs), m_lhs,
">=",
rhs };
2371 template<
typename RhsT>
2373 return {
static_cast<bool>(m_lhs <=
rhs), m_lhs,
"<=",
rhs };
2375 template <
typename RhsT>
2377 return {
static_cast<bool>(m_lhs |
rhs), m_lhs,
"|",
rhs };
2379 template <
typename RhsT>
2381 return {
static_cast<bool>(m_lhs &
rhs), m_lhs,
"&",
rhs };
2383 template <
typename RhsT>
2385 return {
static_cast<bool>(m_lhs ^
rhs), m_lhs,
"^",
rhs };
2388 template<
typename RhsT>
2391 "operator&& is not supported inside assertions, "
2392 "wrap the expression inside parentheses, or decompose it");
2395 template<
typename RhsT>
2398 "operator|| is not supported inside assertions, "
2399 "wrap the expression inside parentheses, or decompose it");
2409 template<
typename T>
2415 template<
typename T>
2428 #pragma warning(pop)
2439 class AssertionResult;
2440 struct AssertionInfo;
2442 struct SectionEndInfo;
2444 struct MessageBuilder;
2446 struct AssertionReaction;
2447 struct SourceLineInfo;
2449 struct ITransientExpression;
2450 struct IGeneratorTracker;
2452 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
2453 struct BenchmarkInfo;
2454 template <
typename Duration = std::chrono::duration<
double, std::nano>>
2455 struct BenchmarkStats;
2463 Counts& assertions ) = 0;
2469 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
2471 virtual void benchmarkStarting( BenchmarkInfo
const&
info ) = 0;
2472 virtual void benchmarkEnded( BenchmarkStats<>
const& stats ) = 0;
2522 struct AssertionResultData;
2538 explicit operator bool()
const;
2551 bool m_completed =
false;
2561 if ( !m_completed ) {
2566 template<
typename T>
2613 static unsigned int globalCount;
2618 template<
typename T>
2632 template<
typename T>
2653 std::vector<MessageInfo> m_messages;
2655 size_t m_captured = 0;
2662 template<
typename T>
2667 template<
typename T,
typename... Ts>
2677 #if !defined(CATCH_CONFIG_DISABLE)
2679 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
2680 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
2682 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
2685 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
2690 #define INTERNAL_CATCH_TRY
2691 #define INTERNAL_CATCH_CATCH( capturer )
2695 #define INTERNAL_CATCH_TRY try
2696 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
2700 #define INTERNAL_CATCH_REACT( handler ) handler.complete();
2703 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
2705 CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
2706 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
2707 INTERNAL_CATCH_TRY { \
2708 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
2709 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2710 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
2711 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
2712 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
2713 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2714 } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) )
2717 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
2718 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
2719 if( Catch::getResultCapture().lastAssertionPassed() )
2722 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
2723 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
2724 if( !Catch::getResultCapture().lastAssertionPassed() )
2727 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
2729 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
2731 static_cast<void>(__VA_ARGS__); \
2732 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
2735 catchAssertionHandler.handleUnexpectedInflightException(); \
2737 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2741 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
2743 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
2744 if( catchAssertionHandler.allowThrows() ) \
2746 static_cast<void>(__VA_ARGS__); \
2747 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2750 catchAssertionHandler.handleExceptionThrownAsExpected(); \
2753 catchAssertionHandler.handleThrowingCallSkipped(); \
2754 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2758 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
2760 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
2761 if( catchAssertionHandler.allowThrows() ) \
2763 static_cast<void>(expr); \
2764 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2766 catch( exceptionType const& ) { \
2767 catchAssertionHandler.handleExceptionThrownAsExpected(); \
2770 catchAssertionHandler.handleUnexpectedInflightException(); \
2773 catchAssertionHandler.handleThrowingCallSkipped(); \
2774 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2778 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
2780 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
2781 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
2782 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2786 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
2787 auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
2788 varName.captureValues( 0, __VA_ARGS__ )
2791 #define INTERNAL_CATCH_INFO( macroName, log ) \
2792 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
2795 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
2796 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
2800 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
2802 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
2803 if( catchAssertionHandler.allowThrows() ) \
2805 static_cast<void>(__VA_ARGS__); \
2806 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2809 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \
2812 catchAssertionHandler.handleThrowingCallSkipped(); \
2813 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2837 std::size_t passed = 0;
2838 std::size_t failed = 0;
2839 std::size_t failedButOk = 0;
2895 uint64_t m_nanoseconds = 0;
2917 explicit operator bool()
const;
2924 bool m_sectionIncluded;
2930 #define INTERNAL_CATCH_SECTION( ... ) \
2931 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
2932 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
2933 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
2934 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
2936 #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
2937 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
2938 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
2939 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
2940 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
2953 struct ITestCaseRegistry;
2954 struct IExceptionTranslatorRegistry;
2955 struct IExceptionTranslator;
2956 struct IReporterRegistry;
2957 struct IReporterFactory;
2958 struct ITagAliasRegistry;
2959 struct IMutableEnumValuesRegistry;
2961 class StartupExceptionRegistry;
2995 #if defined(CATCH_CONFIG_DISABLE)
2996 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
2997 static std::string translatorName( signature )
3000 #include <exception>
3022 template<
typename T>
3026 ExceptionTranslator(
std::string(*translateFunction)(
T& ) )
3027 : m_translateFunction( translateFunction )
3031 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
3036 std::rethrow_exception(std::current_exception());
3038 return (*it)->translate(
it+1, itEnd );
3041 return m_translateFunction( ex );
3051 template<
typename T>
3054 (
new ExceptionTranslator<T>( translateFunction ) );
3060 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
3061 static std::string translatorName( signature ); \
3062 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
3063 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
3064 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
3065 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
3066 static std::string translatorName( signature )
3068 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
3073 #include <type_traits>
3080 bool equalityComparisonImpl(
double other)
const;
3083 void setMargin(
double margin);
3086 void setEpsilon(
double epsilon);
3098 approx.m_epsilon = m_epsilon;
3099 approx.m_margin = m_margin;
3100 approx.m_scale = m_scale;
3110 auto lhs_v =
static_cast<double>(lhs);
3111 return rhs.equalityComparisonImpl(lhs_v);
3131 return static_cast<double>(lhs) <
rhs.m_value || lhs ==
rhs;
3136 return lhs.m_value <
static_cast<double>(
rhs) || lhs ==
rhs;
3141 return static_cast<double>(lhs) >
rhs.m_value || lhs ==
rhs;
3146 return lhs.m_value >
static_cast<double>(
rhs) || lhs ==
rhs;
3151 double epsilonAsDouble =
static_cast<double>(newEpsilon);
3152 setEpsilon(epsilonAsDouble);
3158 double marginAsDouble =
static_cast<double>(newMargin);
3159 setMargin(marginAsDouble);
3165 m_scale =
static_cast<double>(newScale);
3179 namespace literals {
3227 #ifndef CATCH_CONFIG_DISABLE_MATCHERS
3236 namespace Matchers {
3257 # pragma clang diagnostic push
3258 # pragma clang diagnostic ignored "-Wnon-virtual-dtor"
3261 template<
typename ObjectT>
3266 #if defined(__OBJC__)
3271 virtual bool match( NSString*
arg )
const = 0;
3276 # pragma clang diagnostic pop
3279 template<
typename T>
3287 template<
typename ArgT>
3290 for(
auto matcher : m_matchers ) {
3291 if (!matcher->match(
arg))
3298 description.reserve( 4 + m_matchers.size()*32 );
3299 description +=
"( ";
3301 for(
auto matcher : m_matchers ) {
3305 description +=
" and ";
3306 description += matcher->toString();
3308 description +=
" )";
3314 copy.m_matchers.push_back( &
other );
3320 template<
typename ArgT>
3324 for(
auto matcher : m_matchers ) {
3325 if (matcher->match(
arg))
3332 description.reserve( 4 + m_matchers.size()*32 );
3333 description +=
"( ";
3335 for(
auto matcher : m_matchers ) {
3339 description +=
" or ";
3340 description += matcher->toString();
3342 description +=
" )";
3348 copy.m_matchers.push_back( &
other );
3355 template<
typename ArgT>
3361 return !m_underlyingMatcher.match(
arg );
3365 return "not " + m_underlyingMatcher.toString();
3370 template<
typename T>
3374 template<
typename T>
3378 template<
typename T>
3387 using namespace Matchers;
3396 namespace Matchers {
3397 namespace Exception {
3407 bool match(std::exception
const& ex)
const override;
3423 namespace Matchers {
3425 namespace Floating {
3427 enum class FloatingPointKind : uint8_t;
3431 bool match(
double const& matchee)
const override;
3440 bool match(
double const& matchee)
const override;
3445 FloatingPointKind m_type;
3456 bool match(
double const& matchee)
const override;
3483 #include <functional>
3487 namespace Matchers {
3494 template <
typename T>
3501 :m_predicate(
std::move(elem)),
3506 return m_predicate(
item);
3510 return m_description;
3520 template<
typename T>
3534 namespace Matchers {
3536 namespace StdString {
3600 #include <algorithm>
3603 namespace Matchers {
3606 template<
typename T,
typename Alloc>
3611 bool match(std::vector<T, Alloc>
const &
v)
const override {
3612 for (
auto const&
el :
v) {
3613 if (
el == m_comparator) {
3627 template<
typename T,
typename AllocComp,
typename AllocMatch>
3630 ContainsMatcher(std::vector<T, AllocComp>
const &comparator) : m_comparator( comparator ) {}
3632 bool match(std::vector<T, AllocMatch>
const &
v)
const override {
3634 if (m_comparator.size() >
v.size())
3636 for (
auto const& comparator : m_comparator) {
3637 auto present =
false;
3638 for (
const auto&
el :
v) {
3639 if (
el == comparator) {
3657 template<
typename T,
typename AllocComp,
typename AllocMatch>
3660 EqualsMatcher(std::vector<T, AllocComp>
const &comparator) : m_comparator( comparator ) {}
3662 bool match(std::vector<T, AllocMatch>
const &
v)
const override {
3667 if (m_comparator.size() !=
v.size())
3669 for (std::size_t
i = 0;
i <
v.size(); ++
i)
3670 if (m_comparator[
i] !=
v[
i])
3680 template<
typename T,
typename AllocComp,
typename AllocMatch>
3683 ApproxMatcher(std::vector<T, AllocComp>
const& comparator) : m_comparator( comparator ) {}
3685 bool match(std::vector<T, AllocMatch>
const &
v)
const override {
3686 if (m_comparator.size() !=
v.size())
3688 for (std::size_t
i = 0;
i <
v.size(); ++
i)
3689 if (m_comparator[
i] != approx(
v[
i]))
3703 approx.
margin(newMargin);
3708 approx.
scale(newScale);
3716 template<
typename T,
typename AllocComp,
typename AllocMatch>
3719 bool match(std::vector<T, AllocMatch>
const&
vec)
const override {
3720 if (m_target.size() !=
vec.size()) {
3723 return std::is_permutation(m_target.begin(), m_target.end(),
vec.begin());
3730 std::vector<T, AllocComp>
const& m_target;
3738 template<
typename T,
typename AllocComp = std::allocator<T>,
typename AllocMatch = AllocComp>
3743 template<
typename T,
typename Alloc = std::allocator<T>>
3748 template<
typename T,
typename AllocComp = std::allocator<T>,
typename AllocMatch = AllocComp>
3753 template<
typename T,
typename AllocComp = std::allocator<T>,
typename AllocMatch = AllocComp>
3758 template<
typename T,
typename AllocComp = std::allocator<T>,
typename AllocMatch = AllocComp>
3769 template<
typename ArgT,
typename MatcherT>
3778 m_matcher( matcher ),
3779 m_matcherString( matcherString )
3783 auto matcherAsString = m_matcher.toString();
3786 os << m_matcherString;
3788 os << matcherAsString;
3796 template<
typename ArgT,
typename MatcherT>
3804 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
3806 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3807 INTERNAL_CATCH_TRY { \
3808 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \
3809 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
3810 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3814 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
3816 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3817 if( catchAssertionHandler.allowThrows() ) \
3819 static_cast<void>(__VA_ARGS__ ); \
3820 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
3822 catch( exceptionType const& ex ) { \
3823 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \
3826 catchAssertionHandler.handleUnexpectedInflightException(); \
3829 catchAssertionHandler.handleThrowingCallSkipped(); \
3830 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3871 #include <exception>
3874 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
3875 template <
typename Ex>
3894 #define CATCH_MAKE_MSG(...) \
3895 (Catch::ReusableStringStream() << __VA_ARGS__).str()
3897 #define CATCH_INTERNAL_ERROR(...) \
3898 Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))
3900 #define CATCH_ERROR(...) \
3901 Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
3903 #define CATCH_RUNTIME_ERROR(...) \
3904 Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
3906 #define CATCH_ENFORCE( condition, ... ) \
3907 do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
3915 #include <exception>
3920 const char*
const m_msg =
"";
3930 namespace Generators {
3934 template<
typename T,
typename...
Args>
3936 return std::unique_ptr<T>(
new T(std::forward<Args>(
args)...));
3940 template<
typename T>
3952 template<
typename T>
3966 template<
typename T>
3969 "FixedValuesGenerator does not support bools because of std::vector<bool>"
3970 "specialization, use SingleValue Generator instead.");
3971 std::vector<T> m_values;
3977 return m_values[m_idx];
3981 return m_idx < m_values.size();
3985 template <
typename T>
3987 std::unique_ptr<IGenerator<T>> m_generator;
3993 return m_generator->get();
3996 return m_generator->next();
4000 template <
typename T>
4004 template <
typename T>
4009 template<
typename T>
4011 std::vector<GeneratorWrapper<T>> m_generators;
4012 size_t m_current = 0;
4015 m_generators.emplace_back(std::move(
generator));
4018 m_generators.emplace_back(
value(std::forward<T>(
val)));
4020 template<
typename U>
4024 template<
typename U,
typename... Gs>
4025 void populate(
U&& valueOrGenerator, Gs &&... moreGenerators) {
4026 populate(std::forward<U>(valueOrGenerator));
4027 populate(std::forward<Gs>(moreGenerators)...);
4031 template <
typename... Gs>
4033 m_generators.reserve(
sizeof...(Gs));
4034 populate(std::forward<Gs>(moreGenerators)...);
4038 return m_generators[m_current].get();
4042 if (m_current >= m_generators.size()) {
4045 const bool current_status = m_generators[m_current].next();
4046 if (!current_status) {
4049 return m_current < m_generators.size();
4053 template<
typename... Ts>
4055 return values<std::tuple<Ts...>>( tuples );
4059 template <
typename T>
4062 template<
typename T,
typename... Gs>
4066 template<
typename T>
4070 template<
typename T,
typename... Gs>
4074 template<
typename T,
typename U,
typename... Gs>
4081 template<
typename L>
4086 using UnderlyingType =
typename decltype(generatorExpression())::
type;
4100 #define GENERATE( ... ) \
4101 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
4102 CATCH_INTERNAL_LINEINFO, \
4103 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
4104 #define GENERATE_COPY( ... ) \
4105 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
4106 CATCH_INTERNAL_LINEINFO, \
4107 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
4108 #define GENERATE_REF( ... ) \
4109 Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
4110 CATCH_INTERNAL_LINEINFO, \
4111 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
4117 namespace Generators {
4119 template <
typename T>
4122 size_t m_returned = 0;
4129 assert(
target != 0 &&
"Empty generators are not allowed");
4132 return m_generator.
get();
4136 if (m_returned >= m_target) {
4140 const auto success = m_generator.
next();
4144 m_returned = m_target;
4150 template <
typename T>
4155 template <
typename T,
typename Predicate>
4160 template <
typename P = Predicate>
4163 m_predicate(
std::forward<
P>(pred))
4165 if (!m_predicate(m_generator.
get())) {
4168 auto has_initial_value = nextImpl();
4169 if (!has_initial_value) {
4176 return m_generator.
get();
4185 bool success = m_generator.
next();
4189 while (!m_predicate(m_generator.
get()) && (success = m_generator.
next()) ==
true);
4194 template <
typename T,
typename Predicate>
4199 template <
typename T>
4202 "RepeatGenerator currently does not support bools"
4203 "because of std::vector<bool> specialization");
4205 mutable std::vector<T> m_returned;
4206 size_t m_target_repeats;
4207 size_t m_current_repeat = 0;
4208 size_t m_repeat_index = 0;
4212 m_target_repeats(repeats)
4214 assert(m_target_repeats > 0 &&
"Repeat generator must repeat at least once");
4218 if (m_current_repeat == 0) {
4219 m_returned.push_back(m_generator.
get());
4220 return m_returned.back();
4222 return m_returned[m_repeat_index];
4232 if (m_current_repeat == 0) {
4233 const auto success = m_generator.
next();
4237 return m_current_repeat < m_target_repeats;
4242 if (m_repeat_index == m_returned.size()) {
4246 return m_current_repeat < m_target_repeats;
4250 template <
typename T>
4255 template <
typename T,
typename U,
typename Func>
4263 template <
typename F2 = Func>
4267 m_cache(m_function(m_generator.
get()))
4274 const auto success = m_generator.
next();
4276 m_cache = m_function(m_generator.
get());
4282 template <
typename Func,
typename U,
typename T = FunctionReturnType<Func, U>>
4289 template <
typename T,
typename U,
typename Func>
4290 GeneratorWrapper<T>
map(Func&&
function, GeneratorWrapper<U>&&
generator) {
4291 return GeneratorWrapper<T>(
4296 template <
typename T>
4298 std::vector<T> m_chunk;
4299 size_t m_chunk_size;
4301 bool m_used_up =
false;
4306 m_chunk.reserve(m_chunk_size);
4307 if (m_chunk_size != 0) {
4308 m_chunk.push_back(m_generator.
get());
4309 for (
size_t i = 1;
i < m_chunk_size; ++
i) {
4310 if (!m_generator.
next()) {
4313 m_chunk.push_back(m_generator.
get());
4317 std::vector<T>
const&
get()
const override {
4322 for (
size_t idx = 0;
idx < m_chunk_size; ++
idx) {
4323 if (!m_generator.
next()) {
4326 m_chunk.push_back(m_generator.
get());
4332 template <
typename T>
4335 pf::make_unique<ChunkGenerator<T>>(
size, std::move(
generator))
4351 struct IResultCapture;
4354 struct IMutableContext;
4378 static void createContext();
4383 if( !IMutableContext::currentContext )
4384 IMutableContext::createContext();
4386 return *IMutableContext::currentContext;
4408 template<
typename T>
4413 : nullableValue( new(
storage )
T( _value ) )
4424 if( &_other !=
this ) {
4427 nullableValue =
new(
storage )
T( *_other );
4433 nullableValue =
new(
storage )
T( _value );
4439 nullableValue->~T();
4440 nullableValue =
nullptr;
4449 return nullableValue ? *nullableValue : defaultValue;
4452 bool some()
const {
return nullableValue !=
nullptr; }
4453 bool none()
const {
return nullableValue ==
nullptr; }
4456 explicit operator bool()
const {
4462 alignas(
alignof(
T))
char storage[
sizeof(
T)];
4484 NoAssertions = 0x01,
4507 BeforeStartAndExit = BeforeStart | BeforeExit
4543 using IConfigPtr = std::shared_ptr<IConfig const>;
4559 using state_type = std::uint64_t;
4586 std::uint64_t m_state;
4591 static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
4600 namespace Generators {
4602 template <
typename Float>
4605 std::uniform_real_distribution<Float> m_dist;
4606 Float m_current_number;
4612 static_cast<void>(
next());
4616 return m_current_number;
4619 m_current_number = m_dist(m_rng);
4624 template <
typename Integer>
4627 std::uniform_int_distribution<Integer> m_dist;
4628 Integer m_current_number;
4634 static_cast<void>(
next());
4637 Integer
const&
get()
const override {
4638 return m_current_number;
4641 m_current_number = m_dist(m_rng);
4648 template <
typename T>
4650 GeneratorWrapper<T>>
::type
4657 template <
typename T>
4659 GeneratorWrapper<T>>
::type
4666 template <
typename T>
4678 m_positive(m_step >
T(0))
4680 assert(m_current != m_end &&
"Range start and end cannot be equal");
4681 assert(m_step !=
T(0) &&
"Step size cannot be zero");
4682 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) &&
"Step moves away from end");
4694 m_current += m_step;
4695 return (m_positive) ? (m_current < m_end) : (m_current > m_end);
4699 template <
typename T>
4705 template <
typename T>
4711 template <
typename T>
4714 "IteratorGenerator currently does not support bools"
4715 "because of std::vector<bool> specialization");
4717 std::vector<T> m_elems;
4718 size_t m_current = 0;
4720 template <
typename InputIterator,
typename InputSentinel>
4722 if (m_elems.empty()) {
4728 return m_elems[m_current];
4733 return m_current != m_elems.size();
4737 template <
typename InputIterator,
4738 typename InputSentinel,
4764 #pragma clang diagnostic push
4765 #pragma clang diagnostic ignored "-Wpadded"
4770 struct ITestInvoker;
4776 ShouldFail = 1 << 2,
4779 NonPortable = 1 << 5,
4786 std::vector<std::string>
const& _tags,
4792 bool throws()
const;
4822 std::shared_ptr<ITestInvoker> test;
4832 #pragma clang diagnostic pop
4851 #import <objc/runtime.h>
4873 class OcMethod :
public ITestInvoker {
4876 OcMethod(
Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
4878 virtual void invoke()
const {
4879 id obj = [[m_cls alloc] init];
4881 performOptionalSelector(
obj,
@selector(setUp) );
4882 performOptionalSelector(
obj, m_sel );
4883 performOptionalSelector(
obj,
@selector(tearDown) );
4885 arcSafeRelease(
obj );
4888 virtual ~OcMethod() {}
4899 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
4900 SEL sel = NSSelectorFromString( selStr );
4901 arcSafeRelease( selStr );
4902 id value = performOptionalSelector( cls, sel );
4904 return [(NSString*)value UTF8String];
4909 inline std::size_t registerTestMethods() {
4910 std::size_t noTestMethods = 0;
4911 int noClasses = objc_getClassList(
nullptr, 0 );
4913 Class* classes = (CATCH_UNSAFE_UNRETAINED
Class *)malloc(
sizeof(
Class) * noClasses);
4914 objc_getClassList( classes, noClasses );
4916 for(
int c = 0;
c < noClasses;
c++ ) {
4917 Class cls = classes[c];
4920 Method* methods = class_copyMethodList( cls, &
count );
4921 for( u_int
m = 0;
m <
count ;
m++ ) {
4922 SEL selector = method_getName(methods[
m]);
4924 if(
startsWith( methodName,
"Catch_TestCase_" ) ) {
4925 std::string testCaseName = methodName.substr( 15 );
4926 std::string name = Detail::getAnnotation( cls,
"Name", testCaseName );
4927 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
4928 const char*
className = class_getName( cls );
4937 return noTestMethods;
4940 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
4942 namespace Matchers {
4944 namespace NSStringMatchers {
4946 struct StringHolder : MatcherBase<NSString*>{
4947 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
4948 StringHolder( StringHolder
const&
other ) : m_substr( [
other.m_substr copy] ){}
4950 arcSafeRelease( m_substr );
4953 bool match( NSString*
str )
const override {
4957 NSString* CATCH_ARC_STRONG m_substr;
4960 struct Equals : StringHolder {
4961 Equals( NSString* substr ) : StringHolder( substr ){}
4963 bool match( NSString*
str )
const override {
4964 return (
str != nil || m_substr == nil ) &&
4965 [str isEqualToString:m_substr];
4969 return "equals string: " +
Catch::Detail::stringify( m_substr );
4974 Contains( NSString* substr ) : StringHolder( substr ){}
4976 bool match( NSString*
str )
const override {
4977 return (
str != nil || m_substr == nil ) &&
4978 [str rangeOfString:m_substr].location != NSNotFound;
4982 return "contains string: " +
Catch::Detail::stringify( m_substr );
4987 StartsWith( NSString* substr ) : StringHolder( substr ){}
4989 bool match( NSString*
str )
const override {
4990 return (
str != nil || m_substr == nil ) &&
4991 [str rangeOfString:m_substr].location == 0;
4995 return "starts with: " +
Catch::Detail::stringify( m_substr );
4999 EndsWith( NSString* substr ) : StringHolder( substr ){}
5001 bool match( NSString*
str )
const override {
5002 return (
str != nil || m_substr == nil ) &&
5003 [str rangeOfString:m_substr].location == [str length] - [m_substr
length];
5007 return "ends with: " +
Catch::Detail::stringify( m_substr );
5028 using namespace Matchers;
5035 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix
5036 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \
5037 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \
5041 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \
5045 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )
5047 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )
5053 #if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5065 #pragma clang diagnostic push
5066 #pragma clang diagnostic ignored "-Wpadded"
5072 #pragma clang diagnostic push
5073 #pragma clang diagnostic ignored "-Wpadded"
5080 class WildcardPattern {
5081 enum WildcardPosition {
5083 WildcardAtStart = 1,
5085 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
5091 virtual ~WildcardPattern() =
default;
5097 WildcardPosition m_wildcard = NoWildcard;
5116 virtual bool matches( TestCaseInfo
const& testCase )
const = 0;
5121 using PatternPtr = std::shared_ptr<Pattern>;
5123 class NamePattern :
public Pattern {
5126 bool matches( TestCaseInfo
const& testCase )
const override;
5128 WildcardPattern m_wildcardPattern;
5131 class TagPattern :
public Pattern {
5134 bool matches( TestCaseInfo
const& testCase )
const override;
5139 class ExcludedPattern :
public Pattern {
5141 explicit ExcludedPattern( PatternPtr
const& underlyingPattern );
5142 bool matches( TestCaseInfo
const& testCase )
const override;
5144 PatternPtr m_underlyingPattern;
5148 std::vector<PatternPtr> m_patterns;
5150 bool matches( TestCaseInfo
const& testCase )
const;
5155 struct FilterMatch {
5157 std::vector<TestCase const*>
tests;
5159 using Matches = std::vector<FilterMatch>;
5160 using vectorStrings = std::vector<std::string>;
5162 bool hasFilters()
const;
5163 bool matches( TestCaseInfo
const& testCase )
const;
5164 Matches matchesByFilter( std::vector<TestCase>
const& testCases, IConfig
const&
config )
const;
5165 const vectorStrings & getInvalidArgs()
const;
5168 std::vector<Filter> m_filters;
5169 std::vector<std::string> m_invalidArgs;
5170 friend class TestSpecParser;
5175 #pragma clang diagnostic pop
5187 struct ITagAliasRegistry {
5188 virtual ~ITagAliasRegistry();
5193 static ITagAliasRegistry
const&
get();
5201 class TestSpecParser {
5205 bool m_exclusion =
false;
5206 std::size_t m_pos = 0;
5207 std::size_t m_realPatternPos = 0;
5211 std::vector<std::size_t> m_escapeChars;
5212 TestSpec::Filter m_currentFilter;
5213 TestSpec m_testSpec;
5214 ITagAliasRegistry
const* m_tagAliases =
nullptr;
5217 TestSpecParser( ITagAliasRegistry
const& tagAliases );
5220 TestSpec testSpec();
5223 bool visitChar(
char c );
5225 bool processNoneChar(
char c );
5226 void processNameChar(
char c );
5227 bool processOtherChar(
char c );
5230 bool isControlChar(
char c )
const;
5231 void saveLastMode();
5232 void revertBackToLastMode();
5239 void addNamePattern();
5241 void addTagPattern();
5243 inline void addCharToPattern(
char c) {
5255 #pragma clang diagnostic pop
5265 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
5266 #define CATCH_CONFIG_CONSOLE_WIDTH 80
5274 bool listTests =
false;
5275 bool listTags =
false;
5276 bool listReporters =
false;
5277 bool listTestNamesOnly =
false;
5279 bool showSuccessfulTests =
false;
5280 bool shouldDebugBreak =
false;
5281 bool noThrow =
false;
5282 bool showHelp =
false;
5283 bool showInvisibles =
false;
5284 bool filenamesAsTags =
false;
5285 bool libIdentify =
false;
5287 int abortAfter = -1;
5290 bool benchmarkNoAnalysis =
false;
5291 unsigned int benchmarkSamples = 100;
5292 double benchmarkConfidenceInterval = 0.95;
5293 unsigned int benchmarkResamples = 100000;
5294 std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
5299 double minDuration = -1;
5307 #ifndef CATCH_CONFIG_DEFAULT_REPORTER
5308 #define CATCH_CONFIG_DEFAULT_REPORTER "console"
5310 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
5311 #undef CATCH_CONFIG_DEFAULT_REPORTER
5313 std::vector<std::string> testsOrTags;
5314 std::vector<std::string> sectionsToRun;
5317 class Config :
public IConfig {
5322 virtual ~
Config() =
default;
5326 bool listTests()
const;
5327 bool listTestNamesOnly()
const;
5328 bool listTags()
const;
5329 bool listReporters()
const;
5334 std::vector<std::string>
const& getTestsOrTags()
const override;
5335 std::vector<std::string>
const& getSectionsToRun()
const override;
5337 TestSpec
const& testSpec()
const override;
5338 bool hasTestFilters()
const override;
5340 bool showHelp()
const;
5344 std::ostream&
stream()
const override;
5346 bool includeSuccessfulResults()
const override;
5347 bool warnAboutMissingAssertions()
const override;
5348 bool warnAboutNoTests()
const override;
5350 double minDuration()
const override;
5352 unsigned int rngSeed()
const override;
5354 bool shouldDebugBreak()
const override;
5355 int abortAfter()
const override;
5356 bool showInvisibles()
const override;
5358 bool benchmarkNoAnalysis()
const override;
5359 int benchmarkSamples()
const override;
5360 double benchmarkConfidenceInterval()
const override;
5361 unsigned int benchmarkResamples()
const override;
5362 std::chrono::milliseconds benchmarkWarmupTime()
const override;
5366 IStream
const* openStream();
5369 std::unique_ptr<IStream const> m_stream;
5370 TestSpec m_testSpec;
5371 bool m_hasTestFilters =
false;
5383 struct AssertionResultData
5385 AssertionResultData() =
delete;
5387 AssertionResultData(
ResultWas::OfType _resultType, LazyExpression
const& _lazyExpression );
5391 LazyExpression lazyExpression;
5397 class AssertionResult {
5399 AssertionResult() =
delete;
5400 AssertionResult( AssertionInfo
const&
info, AssertionResultData
const&
data );
5403 bool succeeded()
const;
5405 bool hasExpression()
const;
5406 bool hasMessage()
const;
5409 bool hasExpandedExpression()
const;
5412 SourceLineInfo getSourceInfo()
const;
5413 StringRef getTestMacroName()
const;
5416 AssertionInfo m_info;
5417 AssertionResultData m_resultData;
5423 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5431 template <
typename Duration>
5434 Duration lower_bound;
5435 Duration upper_bound;
5436 double confidence_interval;
5438 template <
typename Duration2>
5439 operator Estimate<Duration2>()
const {
5440 return { point, lower_bound, upper_bound, confidence_interval };
5453 struct OutlierClassification {
5454 int samples_seen = 0;
5458 int high_severe = 0;
5461 return low_severe + low_mild + high_mild + high_severe;
5477 #include <algorithm>
5481 struct ReporterConfig {
5482 explicit ReporterConfig(
IConfigPtr const& _fullConfig );
5484 ReporterConfig(
IConfigPtr const& _fullConfig, std::ostream& _stream );
5486 std::ostream&
stream()
const;
5490 std::ostream* m_stream;
5494 struct ReporterPreferences {
5495 bool shouldRedirectStdOut =
false;
5496 bool shouldReportAllAssertions =
false;
5499 template<
typename T>
5501 LazyStat& operator=(
T const& _value ) {
5513 struct TestRunInfo {
5519 std::size_t _groupIndex,
5520 std::size_t _groupsCount );
5523 std::size_t groupIndex;
5524 std::size_t groupsCounts;
5527 struct AssertionStats {
5528 AssertionStats( AssertionResult
const& _assertionResult,
5529 std::vector<MessageInfo>
const& _infoMessages,
5530 Totals
const& _totals );
5532 AssertionStats( AssertionStats
const& ) =
default;
5533 AssertionStats( AssertionStats && ) =
default;
5534 AssertionStats& operator = ( AssertionStats
const& ) =
delete;
5535 AssertionStats& operator = ( AssertionStats && ) =
delete;
5536 virtual ~AssertionStats();
5538 AssertionResult assertionResult;
5539 std::vector<MessageInfo> infoMessages;
5543 struct SectionStats {
5544 SectionStats( SectionInfo
const& _sectionInfo,
5545 Counts
const& _assertions,
5546 double _durationInSeconds,
5547 bool _missingAssertions );
5548 SectionStats( SectionStats
const& ) =
default;
5549 SectionStats( SectionStats && ) =
default;
5550 SectionStats& operator = ( SectionStats
const& ) =
default;
5551 SectionStats& operator = ( SectionStats && ) =
default;
5552 virtual ~SectionStats();
5554 SectionInfo sectionInfo;
5556 double durationInSeconds;
5557 bool missingAssertions;
5560 struct TestCaseStats {
5561 TestCaseStats( TestCaseInfo
const& _testInfo,
5562 Totals
const& _totals,
5567 TestCaseStats( TestCaseStats
const& ) =
default;
5568 TestCaseStats( TestCaseStats && ) =
default;
5569 TestCaseStats& operator = ( TestCaseStats
const& ) =
default;
5570 TestCaseStats& operator = ( TestCaseStats && ) =
default;
5571 virtual ~TestCaseStats();
5573 TestCaseInfo testInfo;
5580 struct TestGroupStats {
5581 TestGroupStats( GroupInfo
const& _groupInfo,
5582 Totals
const& _totals,
5584 TestGroupStats( GroupInfo
const& _groupInfo );
5586 TestGroupStats( TestGroupStats
const& ) =
default;
5587 TestGroupStats( TestGroupStats && ) =
default;
5588 TestGroupStats& operator = ( TestGroupStats
const& ) =
default;
5589 TestGroupStats& operator = ( TestGroupStats && ) =
default;
5590 virtual ~TestGroupStats();
5592 GroupInfo groupInfo;
5597 struct TestRunStats {
5598 TestRunStats( TestRunInfo
const& _runInfo,
5599 Totals
const& _totals,
5602 TestRunStats( TestRunStats
const& ) =
default;
5603 TestRunStats( TestRunStats && ) =
default;
5604 TestRunStats& operator = ( TestRunStats
const& ) =
default;
5605 TestRunStats& operator = ( TestRunStats && ) =
default;
5606 virtual ~TestRunStats();
5608 TestRunInfo runInfo;
5613 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5614 struct BenchmarkInfo {
5616 double estimatedDuration;
5619 unsigned int resamples;
5620 double clockResolution;
5624 template <
class Duration>
5625 struct BenchmarkStats {
5628 std::vector<Duration>
samples;
5629 Benchmark::Estimate<Duration> mean;
5630 Benchmark::Estimate<Duration> standardDeviation;
5631 Benchmark::OutlierClassification outliers;
5632 double outlierVariance;
5634 template <
typename Duration2>
5635 operator BenchmarkStats<Duration2>()
const {
5636 std::vector<Duration2> samples2;
5637 samples2.reserve(
samples.size());
5641 std::move(samples2),
5651 struct IStreamingReporter {
5652 virtual ~IStreamingReporter() =
default;
5658 virtual ReporterPreferences getPreferences()
const = 0;
5660 virtual void noMatchingTestCases(
std::string const& spec ) = 0;
5662 virtual void reportInvalidArguments(
std::string const&) {}
5664 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
5665 virtual void testGroupStarting( GroupInfo
const& groupInfo ) = 0;
5667 virtual void testCaseStarting( TestCaseInfo
const& testInfo ) = 0;
5668 virtual void sectionStarting( SectionInfo
const& sectionInfo ) = 0;
5670 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5671 virtual void benchmarkPreparing(
std::string const& ) {}
5672 virtual void benchmarkStarting( BenchmarkInfo
const& ) {}
5673 virtual void benchmarkEnded( BenchmarkStats<>
const& ) {}
5674 virtual void benchmarkFailed(
std::string const& ) {}
5677 virtual void assertionStarting( AssertionInfo
const& assertionInfo ) = 0;
5680 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
5682 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
5683 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
5684 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
5685 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
5687 virtual void skipTest( TestCaseInfo
const& testInfo ) = 0;
5690 virtual void fatalErrorEncountered( StringRef
name );
5692 virtual bool isMulti()
const;
5694 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
5696 struct IReporterFactory {
5697 virtual ~IReporterFactory();
5698 virtual IStreamingReporterPtr
create( ReporterConfig
const&
config )
const = 0;
5703 struct IReporterRegistry {
5704 using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
5705 using Listeners = std::vector<IReporterFactoryPtr>;
5707 virtual ~IReporterRegistry();
5709 virtual FactoryMap
const& getFactories()
const = 0;
5710 virtual Listeners
const& getListeners()
const = 0;
5716 #include <algorithm>
5725 void prepareExpandedExpression(AssertionResult&
result);
5728 std::string getFormattedDuration(
double duration );
5731 bool shouldShowDuration( IConfig
const&
config,
double duration );
5733 std::string serializeFilters( std::vector<std::string>
const& container );
5735 template<
typename DerivedT>
5736 struct StreamingReporterBase : IStreamingReporter {
5738 StreamingReporterBase( ReporterConfig
const& _config )
5739 : m_config( _config.fullConfig() ),
5742 m_reporterPrefs.shouldRedirectStdOut =
false;
5743 if( !DerivedT::getSupportedVerbosities().
count( m_config->verbosity() ) )
5744 CATCH_ERROR(
"Verbosity level not supported by this reporter" );
5747 ReporterPreferences getPreferences()
const override {
5748 return m_reporterPrefs;
5751 static std::set<Verbosity> getSupportedVerbosities() {
5755 ~StreamingReporterBase()
override =
default;
5757 void noMatchingTestCases(
std::string const&)
override {}
5759 void reportInvalidArguments(
std::string const&)
override {}
5761 void testRunStarting(TestRunInfo
const& _testRunInfo)
override {
5762 currentTestRunInfo = _testRunInfo;
5765 void testGroupStarting(GroupInfo
const& _groupInfo)
override {
5766 currentGroupInfo = _groupInfo;
5769 void testCaseStarting(TestCaseInfo
const& _testInfo)
override {
5770 currentTestCaseInfo = _testInfo;
5772 void sectionStarting(SectionInfo
const& _sectionInfo)
override {
5773 m_sectionStack.push_back(_sectionInfo);
5776 void sectionEnded(SectionStats
const& )
override {
5777 m_sectionStack.pop_back();
5779 void testCaseEnded(TestCaseStats
const& )
override {
5780 currentTestCaseInfo.reset();
5782 void testGroupEnded(TestGroupStats
const& )
override {
5783 currentGroupInfo.reset();
5785 void testRunEnded(TestRunStats
const& )
override {
5786 currentTestCaseInfo.reset();
5787 currentGroupInfo.reset();
5788 currentTestRunInfo.reset();
5791 void skipTest(TestCaseInfo
const&)
override {
5799 LazyStat<TestRunInfo> currentTestRunInfo;
5800 LazyStat<GroupInfo> currentGroupInfo;
5801 LazyStat<TestCaseInfo> currentTestCaseInfo;
5803 std::vector<SectionInfo> m_sectionStack;
5804 ReporterPreferences m_reporterPrefs;
5807 template<
typename DerivedT>
5808 struct CumulativeReporterBase : IStreamingReporter {
5809 template<
typename T,
typename ChildNodeT>
5811 explicit Node(
T const& _value ) :
value( _value ) {}
5814 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
5816 ChildNodes children;
5818 struct SectionNode {
5819 explicit SectionNode(SectionStats
const& _stats) : stats(_stats) {}
5820 virtual ~SectionNode() =
default;
5823 return stats.sectionInfo.lineInfo ==
other.stats.sectionInfo.lineInfo;
5830 using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
5831 using Assertions = std::vector<AssertionStats>;
5832 ChildSections childSections;
5833 Assertions assertions;
5838 struct BySectionInfo {
5839 BySectionInfo( SectionInfo
const&
other ) : m_other(
other ) {}
5840 BySectionInfo( BySectionInfo
const&
other ) : m_other(
other.m_other ) {}
5841 bool operator() (std::shared_ptr<SectionNode>
const&
node)
const {
5842 return ((
node->stats.sectionInfo.name == m_other.name) &&
5843 (
node->stats.sectionInfo.lineInfo == m_other.lineInfo));
5845 void operator=(BySectionInfo
const&) =
delete;
5848 SectionInfo
const& m_other;
5855 CumulativeReporterBase( ReporterConfig
const& _config )
5856 : m_config( _config.fullConfig() ),
5859 m_reporterPrefs.shouldRedirectStdOut =
false;
5860 if( !DerivedT::getSupportedVerbosities().
count( m_config->verbosity() ) )
5861 CATCH_ERROR(
"Verbosity level not supported by this reporter" );
5863 ~CumulativeReporterBase()
override =
default;
5865 ReporterPreferences getPreferences()
const override {
5866 return m_reporterPrefs;
5869 static std::set<Verbosity> getSupportedVerbosities() {
5873 void testRunStarting( TestRunInfo
const& )
override {}
5874 void testGroupStarting( GroupInfo
const& )
override {}
5876 void testCaseStarting( TestCaseInfo
const& )
override {}
5878 void sectionStarting( SectionInfo
const& sectionInfo )
override {
5879 SectionStats incompleteStats( sectionInfo, Counts(), 0,
false );
5880 std::shared_ptr<SectionNode>
node;
5881 if( m_sectionStack.empty() ) {
5882 if( !m_rootSection )
5883 m_rootSection = std::make_shared<SectionNode>( incompleteStats );
5884 node = m_rootSection;
5887 SectionNode& parentNode = *m_sectionStack.back();
5889 std::find_if( parentNode.childSections.begin(),
5890 parentNode.childSections.end(),
5891 BySectionInfo( sectionInfo ) );
5892 if(
it == parentNode.childSections.end() ) {
5893 node = std::make_shared<SectionNode>( incompleteStats );
5894 parentNode.childSections.push_back(
node );
5899 m_sectionStack.push_back(
node );
5900 m_deepestSection = std::move(
node);
5903 void assertionStarting(AssertionInfo
const&)
override {}
5905 bool assertionEnded(AssertionStats
const& assertionStats)
override {
5906 assert(!m_sectionStack.empty());
5912 prepareExpandedExpression(
const_cast<AssertionResult&
>( assertionStats.assertionResult ) );
5913 SectionNode& sectionNode = *m_sectionStack.back();
5914 sectionNode.assertions.push_back(assertionStats);
5917 void sectionEnded(SectionStats
const& sectionStats)
override {
5918 assert(!m_sectionStack.empty());
5919 SectionNode&
node = *m_sectionStack.back();
5920 node.stats = sectionStats;
5921 m_sectionStack.pop_back();
5923 void testCaseEnded(TestCaseStats
const& testCaseStats)
override {
5924 auto node = std::make_shared<TestCaseNode>(testCaseStats);
5925 assert(m_sectionStack.size() == 0);
5926 node->children.push_back(m_rootSection);
5927 m_testCases.push_back(
node);
5928 m_rootSection.reset();
5930 assert(m_deepestSection);
5931 m_deepestSection->stdOut = testCaseStats.stdOut;
5932 m_deepestSection->stdErr = testCaseStats.stdErr;
5934 void testGroupEnded(TestGroupStats
const& testGroupStats)
override {
5935 auto node = std::make_shared<TestGroupNode>(testGroupStats);
5937 m_testGroups.push_back(
node);
5939 void testRunEnded(TestRunStats
const& testRunStats)
override {
5940 auto node = std::make_shared<TestRunNode>(testRunStats);
5942 m_testRuns.push_back(
node);
5943 testRunEndedCumulative();
5945 virtual void testRunEndedCumulative() = 0;
5947 void skipTest(TestCaseInfo
const&)
override {}
5951 std::vector<AssertionStats> m_assertions;
5952 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
5953 std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
5954 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
5956 std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
5958 std::shared_ptr<SectionNode> m_rootSection;
5959 std::shared_ptr<SectionNode> m_deepestSection;
5960 std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
5961 ReporterPreferences m_reporterPrefs;
5965 char const* getLineOfChars() {
5966 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
5968 std::memset(
line,
C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
5969 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
5974 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
5975 TestEventListenerBase( ReporterConfig
const& _config );
5977 static std::set<Verbosity> getSupportedVerbosities();
5979 void assertionStarting(AssertionInfo
const&)
override;
5980 bool assertionEnded(AssertionStats
const&)
override;
6004 BrightRed = Bright |
Red,
6005 BrightGreen = Bright |
Green,
6006 LightGrey = Bright | Grey,
6007 BrightWhite = Bright |
White,
6008 BrightYellow = Bright |
Yellow,
6011 FileName = LightGrey,
6013 ResultError = BrightRed,
6014 ResultSuccess = BrightGreen,
6015 ResultExpectedFailure =
Warning,
6020 OriginalExpression =
Cyan,
6021 ReconstructedExpression = BrightYellow,
6023 SecondaryText = LightGrey,
6028 Colour(
Code _colourCode );
6029 Colour( Colour&&
other ) noexcept;
6030 Colour& operator=( Colour&&
other ) noexcept;
6034 static void use(
Code _colourCode );
6037 bool m_moved =
false;
6040 std::ostream&
operator << ( std::ostream& os, Colour
const& );
6050 template<
typename T>
6051 class ReporterRegistrar {
6053 class ReporterFactory :
public IReporterFactory {
6055 IStreamingReporterPtr
create( ReporterConfig
const&
config )
const override {
6056 return std::unique_ptr<T>(
new T(
config ) );
6060 return T::getDescription();
6071 template<
typename T>
6072 class ListenerRegistrar {
6074 class ListenerFactory :
public IReporterFactory {
6076 IStreamingReporterPtr
create( ReporterConfig
const&
config )
const override {
6077 return std::unique_ptr<T>(
new T(
config ) );
6086 ListenerRegistrar() {
6092 #if !defined(CATCH_CONFIG_DISABLE)
6094 #define CATCH_REGISTER_REPORTER( name, reporterType ) \
6095 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6096 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6097 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
6098 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
6100 #define CATCH_REGISTER_LISTENER( listenerType ) \
6101 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6102 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6103 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
6104 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
6107 #define CATCH_REGISTER_REPORTER(name, reporterType)
6108 #define CATCH_REGISTER_LISTENER(listenerType)
6118 struct CompactReporter : StreamingReporterBase<CompactReporter> {
6120 using StreamingReporterBase::StreamingReporterBase;
6122 ~CompactReporter()
override;
6126 void noMatchingTestCases(
std::string const& spec)
override;
6128 void assertionStarting(AssertionInfo
const&)
override;
6130 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
6132 void sectionEnded(SectionStats
const& _sectionStats)
override;
6134 void testRunEnded(TestRunStats
const& _testRunStats)
override;
6143 #if defined(_MSC_VER)
6144 #pragma warning(push)
6145 #pragma warning(disable:4061)
6152 struct SummaryColumn;
6155 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
6156 std::unique_ptr<TablePrinter> m_tablePrinter;
6158 ConsoleReporter(ReporterConfig
const&
config);
6159 ~ConsoleReporter()
override;
6162 void noMatchingTestCases(
std::string const& spec)
override;
6166 void assertionStarting(AssertionInfo
const&)
override;
6168 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
6170 void sectionStarting(SectionInfo
const& _sectionInfo)
override;
6171 void sectionEnded(SectionStats
const& _sectionStats)
override;
6173 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
6175 void benchmarkStarting(BenchmarkInfo
const&
info)
override;
6176 void benchmarkEnded(BenchmarkStats<>
const& stats)
override;
6180 void testCaseEnded(TestCaseStats
const& _testCaseStats)
override;
6181 void testGroupEnded(TestGroupStats
const& _testGroupStats)
override;
6182 void testRunEnded(TestRunStats
const& _testRunStats)
override;
6183 void testRunStarting(TestRunInfo
const& _testRunInfo)
override;
6188 void lazyPrintWithoutClosingBenchmarkTable();
6189 void lazyPrintRunInfo();
6190 void lazyPrintGroupInfo();
6191 void printTestCaseAndSectionHeader();
6198 void printHeaderString(
std::string const& _string, std::size_t indent = 0);
6200 void printTotals(Totals
const& totals);
6201 void printSummaryRow(
std::string const&
label, std::vector<SummaryColumn>
const& cols, std::size_t
row);
6203 void printTotalsDivider(Totals
const& totals);
6204 void printSummaryDivider();
6205 void printTestFilters();
6208 bool m_headerPrinted =
false;
6213 #if defined(_MSC_VER)
6214 #pragma warning(pop)
6225 enum class XmlFormatting {
6231 XmlFormatting
operator | (XmlFormatting lhs, XmlFormatting
rhs);
6232 XmlFormatting
operator & (XmlFormatting lhs, XmlFormatting
rhs);
6236 enum ForWhat { ForTextNodes, ForAttributes };
6238 XmlEncode(
std::string const&
str, ForWhat forWhat = ForTextNodes );
6240 void encodeTo( std::ostream& os )
const;
6242 friend std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode );
6252 class ScopedElement {
6254 ScopedElement(
XmlWriter* writer, XmlFormatting fmt );
6256 ScopedElement( ScopedElement&&
other ) noexcept;
6257 ScopedElement& operator=( ScopedElement&&
other ) noexcept;
6261 ScopedElement& writeText(
std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent );
6263 template<
typename T>
6271 XmlFormatting m_fmt;
6280 XmlWriter& startElement(
std::string const&
name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6282 ScopedElement scopedElement(
std::string const&
name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6284 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6290 template<
typename T>
6292 ReusableStringStream rss;
6294 return writeAttribute(
name, rss.str() );
6297 XmlWriter& writeText(
std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6299 XmlWriter& writeComment(
std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6305 void ensureTagClosed();
6309 void applyFormatting(XmlFormatting fmt);
6311 void writeDeclaration();
6313 void newlineIfNecessary();
6315 bool m_tagIsOpen =
false;
6316 bool m_needsNewline =
false;
6317 std::vector<std::string> m_tags;
6327 class JunitReporter :
public CumulativeReporterBase<JunitReporter> {
6329 JunitReporter(ReporterConfig
const& _config);
6331 ~JunitReporter()
override;
6335 void noMatchingTestCases(
std::string const& )
override;
6337 void testRunStarting(TestRunInfo
const& runInfo)
override;
6339 void testGroupStarting(GroupInfo
const& groupInfo)
override;
6341 void testCaseStarting(TestCaseInfo
const& testCaseInfo)
override;
6342 bool assertionEnded(AssertionStats
const& assertionStats)
override;
6344 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
6346 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
6348 void testRunEndedCumulative()
override;
6350 void writeGroup(TestGroupNode
const& groupNode,
double suiteTime);
6352 void writeTestCase(TestCaseNode
const& testCaseNode);
6356 SectionNode
const& sectionNode,
6357 bool testOkToFail );
6359 void writeAssertions(SectionNode
const& sectionNode);
6360 void writeAssertion(AssertionStats
const& stats);
6366 unsigned int unexpectedExceptions = 0;
6367 bool m_okToFail =
false;
6376 class XmlReporter :
public StreamingReporterBase<XmlReporter> {
6378 XmlReporter(ReporterConfig
const& _config);
6380 ~XmlReporter()
override;
6386 void writeSourceInfo(SourceLineInfo
const& sourceInfo);
6390 void noMatchingTestCases(
std::string const&
s)
override;
6392 void testRunStarting(TestRunInfo
const& testInfo)
override;
6394 void testGroupStarting(GroupInfo
const& groupInfo)
override;
6396 void testCaseStarting(TestCaseInfo
const& testInfo)
override;
6398 void sectionStarting(SectionInfo
const& sectionInfo)
override;
6400 void assertionStarting(AssertionInfo
const&)
override;
6402 bool assertionEnded(AssertionStats
const& assertionStats)
override;
6404 void sectionEnded(SectionStats
const& sectionStats)
override;
6406 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
6408 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
6410 void testRunEnded(TestRunStats
const& testRunStats)
override;
6412 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
6414 void benchmarkStarting(BenchmarkInfo
const&)
override;
6415 void benchmarkEnded(BenchmarkStats<>
const&)
override;
6416 void benchmarkFailed(
std::string const&)
override;
6420 Timer m_testCaseTimer;
6422 int m_sectionDepth = 0;
6432 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
6458 template <
typename Clock>
6459 using ClockDuration =
typename Clock::duration;
6460 template <
typename Clock>
6461 using FloatDuration = std::chrono::duration<double, typename Clock::period>;
6463 template <
typename Clock>
6464 using TimePoint =
typename Clock::time_point;
6466 using default_clock = std::chrono::steady_clock;
6468 template <
typename Clock>
6475 using fp_seconds = std::chrono::duration<double, std::ratio<1>>;
6485 #if defined(_MSC_VER)
6491 #if defined(__GNUC__) || defined(__clang__)
6492 template <
typename T>
6493 inline void keep_memory(
T*
p) {
6494 asm volatile(
"" : :
"g"(
p) :
"memory");
6496 inline void keep_memory() {
6497 asm volatile(
"" : : :
"memory");
6501 inline void optimizer_barrier() { keep_memory(); }
6503 #elif defined(_MSC_VER)
6505 #pragma optimize("", off)
6506 template <
typename T>
6507 inline void keep_memory(
T*
p) {
6509 *
reinterpret_cast<char volatile*
>(
p) = *
reinterpret_cast<char const volatile*
>(
p);
6512 #pragma optimize("", on)
6515 inline void optimizer_barrier() {
6516 std::atomic_thread_fence(std::memory_order_seq_cst);
6522 template <
typename T>
6523 inline void deoptimize_value(
T&&
x) {
6527 template <
typename Fn,
typename...
Args>
6529 deoptimize_value(std::forward<Fn>(
fn) (std::forward<Args...>(
args...)));
6532 template <
typename Fn,
typename...
Args>
6534 std::forward<Fn>(
fn) (std::forward<
Args...>(
args...));
6545 #include <type_traits>
6551 template <
typename T>
6552 struct CompleteType {
using type =
T; };
6554 struct CompleteType<
void> {
struct type {}; };
6556 template <
typename T>
6559 template <
typename Result>
6560 struct CompleteInvoker {
6561 template <
typename Fun,
typename...
Args>
6563 return std::forward<Fun>(
fun)(std::forward<Args>(
args)...);
6567 struct CompleteInvoker<
void> {
6568 template <
typename Fun,
typename...
Args>
6569 static CompleteType_t<void> invoke(Fun&&
fun,
Args&&...
args) {
6570 std::forward<Fun>(
fun)(std::forward<Args>(
args)...);
6576 template <
typename Fun,
typename...
Args>
6581 const std::string benchmarkErrorMsg =
"a benchmark failed to run successfully";
6584 template <
typename Fun>
6585 Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&&
fun) {
6587 return Detail::complete_invoke(std::forward<Fun>(
fun));
6600 struct ChronometerConcept {
6601 virtual void start() = 0;
6602 virtual void finish() = 0;
6603 virtual ~ChronometerConcept() =
default;
6605 template <
typename Clock>
6606 struct ChronometerModel
final :
public ChronometerConcept {
6608 void finish()
override { finished =
Clock::now(); }
6610 ClockDuration<Clock> elapsed()
const {
return finished - started; }
6612 TimePoint<Clock> started;
6613 TimePoint<Clock> finished;
6617 struct Chronometer {
6619 template <
typename Fun>
6620 void measure(Fun&&
fun) { measure(std::forward<Fun>(
fun), is_callable<Fun(
int)>()); }
6622 int runs()
const {
return k; }
6624 Chronometer(Detail::ChronometerConcept& meter,
int k)
6629 template <
typename Fun>
6630 void measure(Fun&&
fun, std::false_type) {
6631 measure([&
fun](
int) {
return fun(); }, std::true_type());
6634 template <
typename Fun>
6635 void measure(Fun&&
fun, std::true_type) {
6636 Detail::optimizer_barrier();
6638 for (
int i = 0;
i < k; ++
i) invoke_deoptimized(
fun,
i);
6640 Detail::optimizer_barrier();
6643 Detail::ChronometerConcept* impl;
6657 template <
typename Duration>
6658 struct EnvironmentEstimate {
6660 OutlierClassification outliers;
6662 template <
typename Duration2>
6663 operator EnvironmentEstimate<Duration2>()
const {
6664 return { mean, outliers };
6667 template <
typename Clock>
6668 struct Environment {
6669 using clock_type = Clock;
6670 EnvironmentEstimate<FloatDuration<Clock>> clock_resolution;
6671 EnvironmentEstimate<FloatDuration<Clock>> clock_cost;
6688 #include <type_traits>
6695 template <
typename T>
6697 template <
typename T,
typename U>
6699 : std::is_same<Decay<T>, Decay<U>> {};
6708 struct BenchmarkFunction {
6711 virtual void call(Chronometer meter)
const = 0;
6712 virtual callable* clone()
const = 0;
6713 virtual ~callable() =
default;
6715 template <
typename Fun>
6716 struct model :
public callable {
6720 model<Fun>* clone()
const override {
return new model<Fun>(*
this); }
6722 void call(Chronometer meter)
const override {
6723 call(meter, is_callable<Fun(Chronometer)>());
6725 void call(Chronometer meter, std::true_type)
const {
6728 void call(Chronometer meter, std::false_type)
const {
6735 struct do_nothing {
void operator()()
const {} };
6737 template <
typename T>
6738 BenchmarkFunction(model<T>*
c) :
f(
c) {}
6742 :
f(new
model<do_nothing>{ {} }) {}
6744 template <
typename Fun,
6746 BenchmarkFunction(Fun&&
fun)
6749 BenchmarkFunction(BenchmarkFunction&& that)
6750 :
f(
std::move(that.
f)) {}
6752 BenchmarkFunction(BenchmarkFunction
const& that)
6753 :
f(that.
f->clone()) {}
6755 BenchmarkFunction& operator=(BenchmarkFunction&& that) {
6756 f = std::move(that.f);
6760 BenchmarkFunction& operator=(BenchmarkFunction
const& that) {
6761 f.reset(that.f->clone());
6765 void operator()(Chronometer meter)
const {
f->call(meter); }
6768 std::unique_ptr<callable>
f;
6780 #include <type_traits>
6786 template <
typename Fun>
6789 for (
int i = 0;
i < k; ++
i) {
6795 template <
typename Fun>
6797 return { std::forward<Fun>(
fun) };
6820 #include <type_traits>
6824 template <
typename Duration,
typename Result>
6830 template <
typename Clock,
typename Func,
typename...
Args>
6831 using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<
FunctionReturnType<Func,
Args...>>>;
6841 template <
typename Clock,
typename Fun,
typename...
Args>
6844 auto&&
r = Detail::complete_invoke(
fun, std::forward<Args>(
args)...);
6847 return { delta, std::forward<decltype(r)>(
r), 1 };
6855 #include <type_traits>
6860 template <
typename Clock,
typename Fun>
6861 TimingOf<Clock, Fun, int> measure_one(Fun&&
fun,
int iters, std::false_type) {
6862 return Detail::measure<Clock>(
fun, iters);
6864 template <
typename Clock,
typename Fun>
6865 TimingOf<Clock, Fun, Chronometer> measure_one(Fun&&
fun,
int iters, std::true_type) {
6866 Detail::ChronometerModel<Clock> meter;
6867 auto&&
result = Detail::complete_invoke(
fun, Chronometer(meter, iters));
6869 return { meter.elapsed(), std::move(
result), iters };
6872 template <
typename Clock,
typename Fun>
6873 using run_for_at_least_argument_t =
typename std::conditional<is_callable<Fun(Chronometer)>
::value, Chronometer,
int>
::type;
6875 struct optimized_away_error : std::exception {
6876 const char* what()
const noexcept
override {
6877 return "could not measure benchmark, maybe it was optimized away";
6881 template <
typename Clock,
typename Fun>
6882 TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>> run_for_at_least(ClockDuration<Clock> how_long,
int seed, Fun&&
fun) {
6884 while (iters < (1 << 30)) {
6885 auto&& Timing = measure_one<Clock>(
fun, iters, is_callable<Fun(Chronometer)>());
6887 if (Timing.elapsed >= how_long) {
6888 return { Timing.elapsed, std::move(Timing.result), iters };
6899 #include <algorithm>
6904 template <
typename Duration>
6905 struct ExecutionPlan {
6906 int iterations_per_sample;
6907 Duration estimated_duration;
6908 Detail::BenchmarkFunction benchmark;
6909 Duration warmup_time;
6910 int warmup_iterations;
6912 template <
typename Duration2>
6913 operator ExecutionPlan<Duration2>()
const {
6914 return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations };
6917 template <
typename Clock>
6918 std::vector<FloatDuration<Clock>>
run(
const IConfig &cfg, Environment<FloatDuration<Clock>> env)
const {
6920 Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations,
Detail::repeat(now<Clock>{}));
6922 std::vector<FloatDuration<Clock>> times;
6923 times.reserve(cfg.benchmarkSamples());
6924 std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [
this, env] {
6925 Detail::ChronometerModel<Clock> model;
6926 this->benchmark(Chronometer(model, iterations_per_sample));
6927 auto sample_time = model.elapsed() - env.clock_cost.mean;
6928 if (sample_time < FloatDuration<Clock>::zero()) sample_time = FloatDuration<Clock>::zero();
6929 return sample_time / iterations_per_sample;
6948 #include <algorithm>
6949 #include <functional>
6962 using sample = std::vector<double>;
6966 template <
typename Iterator>
6967 OutlierClassification classify_outliers(Iterator
first, Iterator last) {
6968 std::vector<double> copy(
first, last);
6970 auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end());
6971 auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end());
6973 auto los = q1 - (iqr * 3.);
6974 auto lom = q1 - (iqr * 1.5);
6975 auto him = q3 + (iqr * 1.5);
6976 auto his = q3 + (iqr * 3.);
6978 OutlierClassification
o;
6981 if (
t < los) ++
o.low_severe;
6982 else if (
t < lom) ++
o.low_mild;
6983 else if (
t > his) ++
o.high_severe;
6984 else if (
t > him) ++
o.high_mild;
6990 template <
typename Iterator>
6991 double mean(Iterator
first, Iterator last) {
6997 template <
typename URng,
typename Iterator,
typename Estimator>
6998 sample resample(URng&
rng,
int resamples, Iterator
first, Iterator last, Estimator& estimator) {
7000 std::uniform_int_distribution<decltype(
n)>
dist(0,
n - 1);
7003 out.reserve(resamples);
7004 std::generate_n(std::back_inserter(
out), resamples, [
n,
first, &estimator, &
dist, &
rng] {
7005 std::vector<double> resampled;
7006 resampled.reserve(
n);
7007 std::generate_n(std::back_inserter(resampled),
n, [
first, &
dist, &
rng] {
return first[dist(rng)]; });
7008 return estimator(resampled.begin(), resampled.end());
7010 std::sort(
out.begin(),
out.end());
7014 template <
typename Estimator,
typename Iterator>
7015 sample jackknife(Estimator&& estimator, Iterator
first, Iterator last) {
7029 inline double normal_cdf(
double x) {
7030 return std::erfc(-
x / std::sqrt(2.0)) / 2.0;
7033 double erfc_inv(
double x);
7035 double normal_quantile(
double p);
7037 template <
typename Iterator,
typename Estimator>
7038 Estimate<double> bootstrap(
double confidence_level, Iterator
first, Iterator last, sample
const& resample, Estimator&& estimator) {
7039 auto n_samples = last -
first;
7041 double point = estimator(
first, last);
7043 if (n_samples == 1)
return { point, point, point, confidence_level };
7045 sample jack = jackknife(estimator,
first, last);
7046 double jack_mean = mean(jack.begin(), jack.end());
7047 double sum_squares, sum_cubes;
7048 std::tie(sum_squares, sum_cubes) =
std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.), [jack_mean](std::pair<double, double> sqcb,
double x) -> std::pair<double, double> {
7049 auto d = jack_mean - x;
7052 return { sqcb.first + d2, sqcb.second + d3 };
7055 double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));
7056 int n =
static_cast<int>(resample.size());
7057 double prob_n = std::count_if(resample.begin(), resample.end(), [point](
double x) { return x < point; }) / (double)
n;
7059 if (prob_n == 0)
return { point, point, point, confidence_level };
7061 double bias = normal_quantile(prob_n);
7062 double z1 = normal_quantile((1. - confidence_level) / 2.);
7064 auto cumn = [n](
double x) ->
int {
7065 return std::lround(normal_cdf(
x) *
n); };
7066 auto a = [bias, accel](
double b) {
return bias +
b / (1. - accel *
b); };
7067 double b1 =
bias + z1;
7068 double b2 =
bias - z1;
7071 auto lo = (std::max)(cumn(
a1), 0);
7072 auto hi = (std::min)(cumn(
a2),
n - 1);
7074 return { point, resample[lo], resample[hi], confidence_level };
7077 double outlier_variance(Estimate<double> mean, Estimate<double> stddev,
int n);
7079 struct bootstrap_analysis {
7080 Estimate<double> mean;
7081 Estimate<double> standard_deviation;
7082 double outlier_variance;
7091 #include <algorithm>
7100 template <
typename Clock>
7101 std::vector<double> resolution(
int k) {
7102 std::vector<TimePoint<Clock>> times;
7103 times.reserve(k + 1);
7104 std::generate_n(std::back_inserter(times), k + 1, now<Clock>{});
7106 std::vector<double> deltas;
7109 std::back_inserter(deltas),
7110 [](TimePoint<Clock>
a, TimePoint<Clock>
b) { return static_cast<double>((a - b).count()); });
7115 const auto warmup_iterations = 10000;
7116 const auto warmup_time = std::chrono::milliseconds(100);
7117 const auto minimum_ticks = 1000;
7118 const auto warmup_seed = 10000;
7119 const auto clock_resolution_estimation_time = std::chrono::milliseconds(500);
7120 const auto clock_cost_estimation_time_limit = std::chrono::seconds(1);
7121 const auto clock_cost_estimation_tick_limit = 100000;
7122 const auto clock_cost_estimation_time = std::chrono::milliseconds(10);
7123 const auto clock_cost_estimation_iterations = 10000;
7125 template <
typename Clock>
7127 return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>)
7130 template <
typename Clock>
7131 EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(
int iterations) {
7132 auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time),
iterations, &resolution<Clock>)
7135 FloatDuration<Clock>(mean(
r.begin(),
r.end())),
7136 classify_outliers(
r.begin(),
r.end()),
7139 template <
typename Clock>
7140 EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {
7141 auto time_limit = (std::min)(
7142 resolution * clock_cost_estimation_tick_limit,
7143 FloatDuration<Clock>(clock_cost_estimation_time_limit));
7144 auto time_clock = [](
int k) {
7145 return Detail::measure<Clock>([k] {
7146 for (
int i = 0;
i < k; ++
i) {
7153 int iters = clock_cost_estimation_iterations;
7154 auto&&
r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock);
7155 std::vector<double> times;
7156 int nsamples =
static_cast<int>(std::ceil(time_limit /
r.elapsed));
7157 times.reserve(nsamples);
7158 std::generate_n(std::back_inserter(times), nsamples, [time_clock, &
r] {
7159 return static_cast<double>((time_clock(
r.iterations) /
r.iterations).
count());
7162 FloatDuration<Clock>(mean(times.begin(), times.end())),
7163 classify_outliers(times.begin(), times.end()),
7167 template <
typename Clock>
7168 Environment<FloatDuration<Clock>> measure_environment() {
7169 static Environment<FloatDuration<Clock>>* env =
nullptr;
7174 auto iters = Detail::warmup<Clock>();
7175 auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
7176 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
7178 env =
new Environment<FloatDuration<Clock>>{ resolution, cost };
7196 #include <algorithm>
7203 template <
typename Duration>
7204 struct SampleAnalysis {
7205 std::vector<Duration>
samples;
7206 Estimate<Duration> mean;
7207 Estimate<Duration> standard_deviation;
7208 OutlierClassification outliers;
7209 double outlier_variance;
7211 template <
typename Duration2>
7212 operator SampleAnalysis<Duration2>()
const {
7213 std::vector<Duration2> samples2;
7214 samples2.reserve(
samples.size());
7217 std::move(samples2),
7229 #include <algorithm>
7236 template <
typename Duration,
typename Iterator>
7237 SampleAnalysis<Duration> analyse(
const IConfig &cfg, Environment<Duration>, Iterator
first, Iterator last) {
7238 if (!cfg.benchmarkNoAnalysis()) {
7243 auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(),
samples.begin(),
samples.end());
7244 auto outliers = Catch::Benchmark::Detail::classify_outliers(
samples.begin(),
samples.end());
7246 auto wrap_estimate = [](Estimate<double>
e) {
7247 return Estimate<Duration> {
7249 Duration(
e.lower_bound),
7250 Duration(
e.upper_bound),
7251 e.confidence_interval,
7254 std::vector<Duration> samples2;
7255 samples2.reserve(
samples.size());
7258 std::move(samples2),
7259 wrap_estimate(analysis.mean),
7260 wrap_estimate(analysis.standard_deviation),
7262 analysis.outlier_variance,
7265 std::vector<Duration>
samples;
7268 Duration mean = Duration(0);
7272 mean += Duration(*
it);
7278 Estimate<Duration>{mean, mean, mean, 0.0},
7279 Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0},
7280 OutlierClassification{},
7290 #include <algorithm>
7291 #include <functional>
7302 template <
class FUN>
7306 template <
typename Clock>
7307 ExecutionPlan<FloatDuration<Clock>> prepare(
const IConfig &cfg, Environment<FloatDuration<Clock>> env)
const {
7308 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
7309 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
7310 auto&&
test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1,
fun);
7311 int new_iters =
static_cast<int>(std::ceil(min_time *
test.iterations /
test.elapsed));
7312 return { new_iters,
test.elapsed /
test.iterations * new_iters * cfg.benchmarkSamples(),
fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
7315 template <
typename Clock = default_clock>
7319 auto env = Detail::measure_environment<Clock>();
7323 auto plan = user_code([&] {
7324 return prepare<Clock>(*cfg, env);
7327 BenchmarkInfo
info {
7329 plan.estimated_duration.count(),
7330 plan.iterations_per_sample,
7331 cfg->benchmarkSamples(),
7332 cfg->benchmarkResamples(),
7333 env.clock_resolution.mean.count(),
7334 env.clock_cost.mean.count()
7339 auto samples = user_code([&] {
7340 return plan.template run<Clock>(*cfg, env);
7343 auto analysis = Detail::analyse(*cfg, env,
samples.begin(),
samples.end());
7344 BenchmarkStats<FloatDuration<Clock>> stats{
info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
7349 std::rethrow_exception(std::current_exception());
7354 template <
typename Fun,
7357 fun = Detail::BenchmarkFunction(
func);
7362 explicit operator bool() {
7367 Detail::BenchmarkFunction
fun;
7373 #define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1
7374 #define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2
7376 #define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\
7377 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
7378 BenchmarkName = [&](int benchmarkIndex)
7380 #define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\
7381 if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
7390 #include <type_traits>
7395 template <
typename T,
bool Destruct>
7396 struct ObjectStorage
7400 ObjectStorage() :
data() {}
7402 ObjectStorage(
const ObjectStorage&
other)
7407 ObjectStorage(ObjectStorage&&
other)
7409 new(&
data)
T(std::move(
other.stored_object()));
7412 ~ObjectStorage() { destruct_on_exit<T>(); }
7414 template <
typename...
Args>
7417 new (&
data)
T(std::forward<Args>(
args)...);
7420 template <
bool AllowManualDestruction = !Destruct>
7423 stored_object().~T();
7428 template <
typename U>
7431 template <
typename U>
7434 T& stored_object() {
7435 return *
static_cast<T*
>(
static_cast<void*
>(&
data));
7438 T const& stored_object()
const {
7439 return *
static_cast<T*
>(
static_cast<void*
>(&
data));
7446 template <
typename T>
7447 using storage_for = Detail::ObjectStorage<T, true>;
7449 template <
typename T>
7450 using destructable_object = Detail::ObjectStorage<T, false>;
7464 #pragma clang diagnostic push
7465 #pragma clang diagnostic ignored "-Wweak-vtables"
7476 namespace TestCaseTracking {
7478 struct NameAndLocation {
7482 NameAndLocation(
std::string const& _name, SourceLineInfo
const& _location );
7483 friend bool operator==(NameAndLocation
const& lhs, NameAndLocation
const&
rhs) {
7484 return lhs.name ==
rhs.name
7485 && lhs.location ==
rhs.location;
7491 using ITrackerPtr = std::shared_ptr<ITracker>;
7494 NameAndLocation m_nameAndLocation;
7497 ITracker(NameAndLocation
const& nameAndLoc) :
7498 m_nameAndLocation(nameAndLoc)
7502 NameAndLocation
const& nameAndLocation()
const {
7503 return m_nameAndLocation;
7506 virtual ~ITracker();
7509 virtual bool isComplete()
const = 0;
7510 virtual bool isSuccessfullyCompleted()
const = 0;
7511 virtual bool isOpen()
const = 0;
7512 virtual bool hasChildren()
const = 0;
7513 virtual bool hasStarted()
const = 0;
7515 virtual ITracker&
parent() = 0;
7518 virtual void close() = 0;
7519 virtual void fail() = 0;
7520 virtual void markAsNeedingAnotherRun() = 0;
7522 virtual void addChild( ITrackerPtr
const&
child ) = 0;
7523 virtual ITrackerPtr findChild( NameAndLocation
const& nameAndLocation ) = 0;
7524 virtual void openChild() = 0;
7527 virtual bool isSectionTracker()
const = 0;
7528 virtual bool isGeneratorTracker()
const = 0;
7531 class TrackerContext {
7539 ITrackerPtr m_rootTracker;
7540 ITracker* m_currentTracker =
nullptr;
7541 RunState m_runState = NotStarted;
7545 ITracker& startRun();
7549 void completeCycle();
7551 bool completedCycle()
const;
7552 ITracker& currentTracker();
7553 void setCurrentTracker( ITracker* tracker );
7556 class TrackerBase :
public ITracker {
7563 CompletedSuccessfully,
7567 using Children = std::vector<ITrackerPtr>;
7568 TrackerContext& m_ctx;
7570 Children m_children;
7571 CycleState m_runState = NotStarted;
7574 TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker*
parent );
7576 bool isComplete()
const override;
7577 bool isSuccessfullyCompleted()
const override;
7578 bool isOpen()
const override;
7579 bool hasChildren()
const override;
7580 bool hasStarted()
const override {
7581 return m_runState != NotStarted;
7584 void addChild( ITrackerPtr
const&
child )
override;
7586 ITrackerPtr findChild( NameAndLocation
const& nameAndLocation )
override;
7587 ITracker&
parent()
override;
7589 void openChild()
override;
7591 bool isSectionTracker()
const override;
7592 bool isGeneratorTracker()
const override;
7596 void close()
override;
7597 void fail()
override;
7598 void markAsNeedingAnotherRun()
override;
7601 void moveToParent();
7605 class SectionTracker :
public TrackerBase {
7606 std::vector<std::string> m_filters;
7609 SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker*
parent );
7611 bool isSectionTracker()
const override;
7613 bool isComplete()
const override;
7615 static SectionTracker&
acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation );
7619 void addInitialFilters( std::vector<std::string>
const&
filters );
7620 void addNextFilters( std::vector<std::string>
const&
filters );
7622 std::vector<std::string>
const& getFilters()
const;
7629 using TestCaseTracking::ITracker;
7630 using TestCaseTracking::TrackerContext;
7631 using TestCaseTracking::SectionTracker;
7641 struct LeakDetector {
7653 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
7658 #if defined(CATCH_CONFIG_USE_ASYNC)
7663 double erf_inv(
double x) {
7667 w = -log((1.0 -
x) * (1.0 +
x));
7671 p = -3.6444120640178196996
e-21;
7672 p = -1.685059138182016589
e-19 +
p *
w;
7673 p = 1.2858480715256400167e-18 +
p *
w;
7674 p = 1.115787767802518096e-17 +
p *
w;
7675 p = -1.333171662854620906
e-16 +
p *
w;
7676 p = 2.0972767875968561637e-17 +
p *
w;
7677 p = 6.6376381343583238325e-15 +
p *
w;
7678 p = -4.0545662729752068639
e-14 +
p *
w;
7679 p = -8.1519341976054721522
e-14 +
p *
w;
7680 p = 2.6335093153082322977e-12 +
p *
w;
7681 p = -1.2975133253453532498
e-11 +
p *
w;
7682 p = -5.4154120542946279317
e-11 +
p *
w;
7683 p = 1.051212273321532285e-09 +
p *
w;
7684 p = -4.1126339803469836976
e-09 +
p *
w;
7685 p = -2.9070369957882005086
e-08 +
p *
w;
7686 p = 4.2347877827932403518e-07 +
p *
w;
7687 p = -1.3654692000834678645
e-06 +
p *
w;
7688 p = -1.3882523362786468719
e-05 +
p *
w;
7689 p = 0.0001867342080340571352 +
p *
w;
7690 p = -0.00074070253416626697512 +
p *
w;
7691 p = -0.0060336708714301490533 +
p *
w;
7692 p = 0.24015818242558961693 +
p *
w;
7693 p = 1.6536545626831027356 +
p *
w;
7694 }
else if (
w < 16.000000) {
7695 w = sqrt(
w) - 3.250000;
7696 p = 2.2137376921775787049e-09;
7697 p = 9.0756561938885390979e-08 +
p *
w;
7698 p = -2.7517406297064545428
e-07 +
p *
w;
7699 p = 1.8239629214389227755e-08 +
p *
w;
7700 p = 1.5027403968909827627e-06 +
p *
w;
7701 p = -4.013867526981545969
e-06 +
p *
w;
7702 p = 2.9234449089955446044e-06 +
p *
w;
7703 p = 1.2475304481671778723e-05 +
p *
w;
7704 p = -4.7318229009055733981
e-05 +
p *
w;
7705 p = 6.8284851459573175448e-05 +
p *
w;
7706 p = 2.4031110387097893999e-05 +
p *
w;
7707 p = -0.0003550375203628474796 +
p *
w;
7708 p = 0.00095328937973738049703 +
p *
w;
7709 p = -0.0016882755560235047313 +
p *
w;
7710 p = 0.0024914420961078508066 +
p *
w;
7711 p = -0.0037512085075692412107 +
p *
w;
7712 p = 0.005370914553590063617 +
p *
w;
7713 p = 1.0052589676941592334 +
p *
w;
7714 p = 3.0838856104922207635 +
p *
w;
7716 w = sqrt(
w) - 5.000000;
7717 p = -2.7109920616438573243
e-11;
7718 p = -2.5556418169965252055
e-10 +
p *
w;
7719 p = 1.5076572693500548083e-09 +
p *
w;
7720 p = -3.7894654401267369937
e-09 +
p *
w;
7721 p = 7.6157012080783393804e-09 +
p *
w;
7722 p = -1.4960026627149240478
e-08 +
p *
w;
7723 p = 2.9147953450901080826e-08 +
p *
w;
7724 p = -6.7711997758452339498
e-08 +
p *
w;
7725 p = 2.2900482228026654717e-07 +
p *
w;
7726 p = -9.9298272942317002539
e-07 +
p *
w;
7727 p = 4.5260625972231537039e-06 +
p *
w;
7728 p = -1.9681778105531670567
e-05 +
p *
w;
7729 p = 7.5995277030017761139e-05 +
p *
w;
7730 p = -0.00021503011930044477347 +
p *
w;
7731 p = -0.00013871931833623122026 +
p *
w;
7732 p = 1.0103004648645343977 +
p *
w;
7733 p = 4.8499064014085844221 +
p *
w;
7739 auto m = Catch::Benchmark::Detail::mean(
first, last);
7741 double diff =
b -
m;
7742 return a + diff * diff;
7743 }) / (last -
first);
7744 return std::sqrt(variance);
7755 double idx = (
count - 1) * k / static_cast<double>(
q);
7756 int j =
static_cast<int>(
idx);
7760 if (
g == 0)
return xj;
7762 auto xj1 = *std::min_element(
first + (
j + 1), last);
7763 return xj +
g * (xj1 - xj);
7766 double erfc_inv(
double x) {
7767 return erf_inv(1.0 -
x);
7770 double normal_quantile(
double p) {
7771 static const double ROOT_TWO = std::sqrt(2.0);
7786 double outlier_variance(Estimate<double> mean, Estimate<double> stddev,
int n) {
7787 double sb = stddev.point;
7788 double mn = mean.point /
n;
7789 double mg_min = mn / 2.;
7790 double sg = (std::min)(mg_min / 4., sb / std::sqrt(
n));
7791 double sg2 = sg * sg;
7792 double sb2 = sb * sb;
7794 auto c_max = [n, mn, sb2, sg2](
double x) ->
double {
7798 double k0 = -
n * nd;
7799 double k1 = sb2 -
n * sg2 + nd;
7800 double det =
k1 *
k1 - 4 * sg2 *
k0;
7801 return (
int)(-2. *
k0 / (
k1 +
std::sqrt(det)));
7804 auto var_out = [n, sb2, sg2](
double c) {
7806 return (nc /
n) * (sb2 - nc * sg2);
7809 return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2;
7815 static std::random_device entropy;
7818 auto n =
static_cast<int>(last -
first);
7821 auto stddev = &standard_deviation;
7823 #if defined(CATCH_CONFIG_USE_ASYNC)
7825 auto seed = entropy();
7826 return std::async(std::launch::async, [=] {
7827 std::mt19937
rng(seed);
7828 auto resampled = resample(
rng, n_resamples,
first, last,
f);
7829 return bootstrap(confidence_level,
first, last, resampled,
f);
7833 auto mean_future = Estimate(mean);
7834 auto stddev_future = Estimate(stddev);
7836 auto mean_estimate = mean_future.get();
7837 auto stddev_estimate = stddev_future.get();
7840 auto seed = entropy();
7841 std::mt19937
rng(seed);
7842 auto resampled = resample(
rng, n_resamples,
first, last,
f);
7843 return bootstrap(confidence_level,
first, last, resampled,
f);
7846 auto mean_estimate = Estimate(mean);
7847 auto stddev_estimate = Estimate(stddev);
7850 double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate,
n);
7852 return { mean_estimate, stddev_estimate, outlier_variance };
7869 bool marginComparison(
double lhs,
double rhs,
double margin) {
7870 return (lhs + margin >=
rhs) && (
rhs + margin >= lhs);
7879 : m_epsilon(
std::numeric_limits<float>::
epsilon()*100 ),
7885 Approx Approx::custom() {
7891 temp.m_value = -temp.m_value;
7896 ReusableStringStream rss;
7901 bool Approx::equalityComparisonImpl(
const double other)
const {
7904 return marginComparison(m_value,
other, m_margin)
7905 || marginComparison(m_value,
other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value)));
7908 void Approx::setMargin(
double newMargin) {
7910 "Invalid Approx::margin: " << newMargin <<
'.'
7911 <<
" Approx::Margin has to be non-negative.");
7912 m_margin = newMargin;
7915 void Approx::setEpsilon(
double newEpsilon) {
7917 "Invalid Approx::epsilon: " << newEpsilon <<
'.'
7918 <<
" Approx::epsilon has to be in [0, 1]");
7919 m_epsilon = newEpsilon;
7924 namespace literals {
7934 return value.toString();
7944 bool isDebuggerActive();
7947 #ifdef CATCH_PLATFORM_MAC
7949 #if defined(__i386__) || defined(__x86_64__)
7950 #define CATCH_TRAP() __asm__("int $3\n" : : )
7951 #elif defined(__aarch64__)
7952 #define CATCH_TRAP() __asm__(".inst 0xd4200000")
7955 #elif defined(CATCH_PLATFORM_IPHONE)
7958 #if defined(__i386__) || defined(__x86_64__)
7959 #define CATCH_TRAP() __asm__("int $3")
7960 #elif defined(__aarch64__)
7961 #define CATCH_TRAP() __asm__(".inst 0xd4200000")
7962 #elif defined(__arm__) && !defined(__thumb__)
7963 #define CATCH_TRAP() __asm__(".inst 0xe7f001f0")
7964 #elif defined(__arm__) && defined(__thumb__)
7965 #define CATCH_TRAP() __asm__(".inst 0xde01")
7968 #elif defined(CATCH_PLATFORM_LINUX)
7972 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
7973 #define CATCH_TRAP() asm volatile ("int $3")
7977 #define CATCH_TRAP() raise(SIGTRAP)
7979 #elif defined(_MSC_VER)
7980 #define CATCH_TRAP() __debugbreak()
7981 #elif defined(__MINGW32__)
7982 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
7983 #define CATCH_TRAP() DebugBreak()
7986 #ifndef CATCH_BREAK_INTO_DEBUGGER
7988 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
7990 #define CATCH_BREAK_INTO_DEBUGGER() []{}()
8011 class FatalConditionHandler {
8012 bool m_started =
false;
8017 void engage_platform();
8018 void disengage_platform();
8021 FatalConditionHandler();
8022 ~FatalConditionHandler();
8025 assert(!m_started &&
"Handler cannot be installed twice.");
8031 assert(m_started &&
"Handler cannot be uninstalled without being installed first");
8033 disengage_platform();
8038 class FatalConditionHandlerGuard {
8039 FatalConditionHandler* m_handler;
8041 FatalConditionHandlerGuard(FatalConditionHandler* handler):
8042 m_handler(handler) {
8043 m_handler->engage();
8045 ~FatalConditionHandlerGuard() {
8046 m_handler->disengage();
8057 struct IMutableContext;
8061 class RunContext :
public IResultCapture,
public IRunner {
8064 RunContext( RunContext
const& ) =
delete;
8065 RunContext& operator =( RunContext
const& ) =
delete;
8067 explicit RunContext(
IConfigPtr const& _config, IStreamingReporterPtr&& reporter );
8069 ~RunContext()
override;
8071 void testGroupStarting(
std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
8072 void testGroupEnded(
std::string const& testSpec, Totals
const& totals, std::size_t groupIndex, std::size_t groupsCount );
8074 Totals
runTest(TestCase
const& testCase);
8077 IStreamingReporter& reporter()
const;
8083 ( AssertionInfo
const&
info,
8084 ITransientExpression
const& expr,
8085 AssertionReaction& reaction )
override;
8087 ( AssertionInfo
const&
info,
8090 AssertionReaction& reaction )
override;
8091 void handleUnexpectedExceptionNotThrown
8092 ( AssertionInfo
const&
info,
8093 AssertionReaction& reaction )
override;
8094 void handleUnexpectedInflightException
8095 ( AssertionInfo
const&
info,
8097 AssertionReaction& reaction )
override;
8098 void handleIncomplete
8099 ( AssertionInfo
const&
info )
override;
8101 ( AssertionInfo
const &
info,
8103 AssertionReaction &reaction )
override;
8105 bool sectionStarted( SectionInfo
const& sectionInfo, Counts& assertions )
override;
8107 void sectionEnded( SectionEndInfo
const& endInfo )
override;
8108 void sectionEndedEarly( SectionEndInfo
const& endInfo )
override;
8110 auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo
const& lineInfo ) -> IGeneratorTracker&
override;
8112 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
8114 void benchmarkStarting( BenchmarkInfo
const&
info )
override;
8115 void benchmarkEnded( BenchmarkStats<>
const& stats )
override;
8119 void pushScopedMessage( MessageInfo
const&
message )
override;
8120 void popScopedMessage( MessageInfo
const&
message )
override;
8122 void emplaceUnscopedMessage( MessageBuilder
const& builder )
override;
8126 const AssertionResult* getLastResult()
const override;
8128 void exceptionEarlyReported()
override;
8130 void handleFatalErrorCondition( StringRef
message )
override;
8132 bool lastAssertionPassed()
override;
8134 void assertionPassed()
override;
8142 void runCurrentTest(
std::
string& redirectedCout,
std::
string& redirectedCerr );
8143 void invokeActiveTestCase();
8145 void resetAssertionInfo();
8146 bool testForMissingAssertions( Counts& assertions );
8148 void assertionEnded( AssertionResult
const&
result );
8151 ResultWas::OfType resultType,
8152 ITransientExpression
const *expr,
8155 void populateReaction( AssertionReaction& reaction );
8159 void handleUnfinishedSections();
8161 TestRunInfo m_runInfo;
8162 IMutableContext& m_context;
8163 TestCase
const* m_activeTestCase =
nullptr;
8164 ITracker* m_testCaseTracker =
nullptr;
8165 Option<AssertionResult> m_lastResult;
8169 IStreamingReporterPtr m_reporter;
8171 std::
vector<ScopedMessage> m_messageScopes;
8172 AssertionInfo m_lastAssertionInfo;
8173 std::
vector<SectionEndInfo> m_unfinishedSections;
8174 std::
vector<ITracker*> m_activeSections;
8175 TrackerContext m_trackerContext;
8176 FatalConditionHandler m_fatalConditionhandler;
8177 bool m_lastAssertionPassed =
false;
8178 bool m_shouldReportUnexpected =
true;
8179 bool m_includeSuccessfulResults;
8190 auto operator <<( std::ostream& os, ITransientExpression
const& expr ) -> std::ostream& {
8191 expr.streamReconstructedExpression( os );
8197 : m_isNegated( isNegated )
8202 LazyExpression::operator bool()
const {
8203 return m_transientExpression !=
nullptr;
8206 auto operator << ( std::ostream& os, LazyExpression
const& lazyExpr ) -> std::ostream& {
8207 if( lazyExpr.m_isNegated )
8211 if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
8212 os <<
"(" << *lazyExpr.m_transientExpression <<
")";
8214 os << *lazyExpr.m_transientExpression;
8217 os <<
"{** error - unchecked empty expression requested **}";
8223 ( StringRef
const& macroName,
8224 SourceLineInfo
const& lineInfo,
8225 StringRef capturedExpression,
8227 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
8232 m_resultCapture.
handleExpr( m_assertionInfo, expr, m_reaction );
8250 CATCH_BREAK_INTO_DEBUGGER();
8253 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
8256 CATCH_ERROR(
"Test failure requires aborting test!" );
8294 AssertionResultData::AssertionResultData(
ResultWas::OfType _resultType, LazyExpression
const & _lazyExpression):
8295 lazyExpression(_lazyExpression),
8296 resultType(_resultType) {}
8298 std::string AssertionResultData::reconstructExpression()
const {
8300 if( reconstructedExpression.empty() ) {
8301 if( lazyExpression ) {
8302 ReusableStringStream rss;
8303 rss << lazyExpression;
8304 reconstructedExpression = rss.str();
8307 return reconstructedExpression;
8310 AssertionResult::AssertionResult( AssertionInfo
const&
info, AssertionResultData
const&
data )
8312 m_resultData(
data )
8316 bool AssertionResult::succeeded()
const {
8326 return m_resultData.resultType;
8329 bool AssertionResult::hasExpression()
const {
8330 return !m_info.capturedExpression.empty();
8333 bool AssertionResult::hasMessage()
const {
8334 return !m_resultData.message.empty();
8337 std::string AssertionResult::getExpression()
const {
8339 std::string expr; expr.reserve(m_info.capturedExpression.size() + 3);
8343 expr += m_info.capturedExpression;
8350 std::string AssertionResult::getExpressionInMacro()
const {
8352 if( m_info.macroName.empty() )
8353 expr =
static_cast<std::string>(m_info.capturedExpression);
8355 expr.reserve( m_info.macroName.size() + m_info.capturedExpression.
size() + 4 );
8356 expr += m_info.macroName;
8358 expr += m_info.capturedExpression;
8364 bool AssertionResult::hasExpandedExpression()
const {
8365 return hasExpression() && getExpandedExpression() != getExpression();
8368 std::string AssertionResult::getExpandedExpression()
const {
8369 std::string expr = m_resultData.reconstructExpression();
8376 return m_resultData.message;
8378 SourceLineInfo AssertionResult::getSourceInfo()
const {
8379 return m_info.lineInfo;
8382 StringRef AssertionResult::getTestMacroName()
const {
8383 return m_info.macroName;
8392 using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
8399 MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
8400 handler.handleExpr( expr );
8412 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
8413 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8414 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8417 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
8421 #pragma clang diagnostic push
8422 #pragma clang diagnostic ignored "-Wweak-vtables"
8423 #pragma clang diagnostic ignored "-Wexit-time-destructors"
8424 #pragma clang diagnostic ignored "-Wshadow"
8438 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
8439 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
8442 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8443 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
8446 #ifndef CLARA_CONFIG_OPTIONAL_TYPE
8447 #ifdef __has_include
8448 #if __has_include(<optional>) && __cplusplus >= 201703L
8450 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional
8472 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8473 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
8478 namespace TextFlow {
8480 inline auto isWhitespace(
char c) ->
bool {
8482 return chars.find(
c) != std::string::npos;
8484 inline auto isBreakableBefore(
char c) ->
bool {
8486 return chars.find(
c) != std::string::npos;
8488 inline auto isBreakableAfter(
char c) ->
bool {
8490 return chars.find(
c) != std::string::npos;
8496 std::vector<std::string> m_strings;
8497 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
8498 size_t m_indent = 0;
8499 size_t m_initialIndent = std::string::npos;
8506 size_t m_stringIndex = 0;
8511 bool m_suffix =
false;
8515 m_stringIndex(stringIndex) {}
8517 auto line()
const ->
std::
string const& {
return m_column.m_strings[m_stringIndex]; }
8519 auto isBoundary(
size_t at)
const ->
bool {
8524 (isWhitespace(
line()[
at]) && !isWhitespace(
line()[
at - 1])) ||
8525 isBreakableBefore(
line()[at]) ||
8526 isBreakableAfter(
line()[at - 1]);
8530 assert(m_stringIndex < m_column.m_strings.size());
8533 auto width = m_column.m_width - indent();
8535 if (
line()[m_pos] ==
'\n') {
8541 if (m_end < m_pos +
width) {
8542 m_len = m_end - m_pos;
8545 while (
len > 0 && !isBoundary(m_pos +
len))
8547 while (
len > 0 && isWhitespace(
line()[m_pos +
len - 1]))
8559 auto indent()
const ->
size_t {
8560 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
8561 return initial == std::string::npos ? m_column.m_indent : initial;
8565 return std::string(indent(),
' ') + (m_suffix ? plain + "-" : plain);
8569 using difference_type = std::ptrdiff_t;
8573 using iterator_category = std::forward_iterator_tag;
8576 assert(m_column.m_width > m_column.m_indent);
8577 assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
8584 assert(m_stringIndex < m_column.m_strings.size());
8586 return addIndentAndSuffix(
line().substr(m_pos, m_len));
8594 while (m_pos <
line().
size() && isWhitespace(
line()[m_pos]))
8601 if (m_stringIndex < m_column.m_strings.size())
8605 auto operator ++(
int) ->
iterator {
8613 m_pos ==
other.m_pos &&
8614 m_stringIndex ==
other.m_stringIndex &&
8615 &m_column == &
other.m_column;
8630 auto indent(
size_t newIndent) ->
Column& {
8631 m_indent = newIndent;
8634 auto initialIndent(
size_t newIndent) ->
Column& {
8635 m_initialIndent = newIndent;
8639 auto width()
const ->
size_t {
return m_width; }
8645 for (
auto line : col) {
8658 std::ostringstream oss;
8664 class Spacer :
public Column {
8667 explicit Spacer(
size_t spaceWidth) :
Column(
"") {
8673 std::vector<Column> m_columns;
8681 std::vector<Column>
const& m_columns;
8682 std::vector<Column::iterator> m_iterators;
8683 size_t m_activeIterators;
8686 : m_columns(columns.m_columns),
8687 m_activeIterators(0) {
8688 m_iterators.reserve(m_columns.size());
8690 for (
auto const& col : m_columns)
8691 m_iterators.push_back(col.end());
8695 using difference_type = std::ptrdiff_t;
8699 using iterator_category = std::forward_iterator_tag;
8702 : m_columns(columns.m_columns),
8703 m_activeIterators(m_columns.
size()) {
8704 m_iterators.reserve(m_columns.size());
8706 for (
auto const& col : m_columns)
8707 m_iterators.push_back(col.begin());
8711 return m_iterators ==
other.m_iterators;
8714 return m_iterators !=
other.m_iterators;
8719 for (
size_t i = 0;
i < m_columns.size(); ++
i) {
8720 auto width = m_columns[i].width();
8721 if (m_iterators[
i] != m_columns[
i].
end()) {
8723 row += padding + col;
8724 if (col.size() <
width)
8729 padding +=
std::string(
width, ' ');
8735 for (
size_t i = 0;
i < m_columns.size(); ++
i) {
8736 if (m_iterators[
i] != m_columns[
i].
end())
8741 auto operator ++(
int) ->
iterator {
8753 m_columns.push_back(col);
8765 for (
auto line : cols) {
8776 std::ostringstream oss;
8800 #include <algorithm>
8802 #if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
8803 #define CATCH_PLATFORM_WINDOWS
8806 namespace Catch {
namespace clara {
8810 template<
typename L>
8811 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
8813 template<
typename ClassT,
typename ReturnT,
typename...
Args>
8814 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... )
const> {
8815 static const bool isValid =
false;
8818 template<
typename ClassT,
typename ReturnT,
typename ArgT>
8819 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT )
const> {
8820 static const bool isValid =
true;
8822 using ReturnType = ReturnT;
8831 std::vector<std::string> m_args;
8834 Args(
int argc,
char const*
const* argv )
8835 : m_exeName(argv[0]),
8836 m_args(argv + 1, argv + argc) {}
8838 Args( std::initializer_list<std::string>
args )
8843 auto exeName()
const ->
std::
string {
8858 inline auto isOptPrefix(
char c ) ->
bool {
8860 #ifdef CATCH_PLATFORM_WINDOWS
8871 std::vector<Token> m_tokenBuffer;
8874 m_tokenBuffer.resize( 0 );
8877 while(
it != itEnd &&
it->empty() )
8882 if( isOptPrefix(
next[0] ) ) {
8883 auto delimiterPos =
next.find_first_of(
" :=" );
8884 if( delimiterPos != std::string::npos ) {
8885 m_tokenBuffer.push_back( { TokenType::Option,
next.substr( 0, delimiterPos ) } );
8886 m_tokenBuffer.push_back( { TokenType::Argument,
next.substr( delimiterPos + 1 ) } );
8888 if(
next[1] !=
'-' &&
next.size() > 2 ) {
8890 for(
size_t i = 1;
i <
next.size(); ++
i ) {
8892 m_tokenBuffer.push_back( { TokenType::Option,
opt } );
8895 m_tokenBuffer.push_back( { TokenType::Option,
next } );
8899 m_tokenBuffer.push_back( { TokenType::Argument,
next } );
8911 explicit operator bool()
const {
8912 return !m_tokenBuffer.empty() ||
it != itEnd;
8915 auto count()
const ->
size_t {
return m_tokenBuffer.size() + (itEnd -
it); }
8918 assert( !m_tokenBuffer.empty() );
8919 return m_tokenBuffer.front();
8923 assert( !m_tokenBuffer.empty() );
8924 return &m_tokenBuffer.front();
8928 if( m_tokenBuffer.size() >= 2 ) {
8929 m_tokenBuffer.erase( m_tokenBuffer.begin() );
8942 Ok, LogicError, RuntimeError
8947 virtual ~ResultBase() =
default;
8949 virtual void enforceOk()
const = 0;
8954 template<
typename T>
8955 class ResultValueBase :
public ResultBase {
8965 ResultValueBase( ResultValueBase
const &
other ) : ResultBase(
other ) {
8967 new( &m_value )
T(
other.m_value );
8970 ResultValueBase(
Type,
T const &
value ) : ResultBase(
Ok ) {
8971 new( &m_value )
T(
value );
8974 auto operator=( ResultValueBase
const &
other ) -> ResultValueBase & {
8977 ResultBase::operator=(
other);
8979 new( &m_value )
T(
other.m_value );
8983 ~ResultValueBase()
override {
8994 class ResultValueBase<
void> :
public ResultBase {
8996 using ResultBase::ResultBase;
8999 template<
typename T =
void>
9000 class BasicResult :
public ResultValueBase<
T> {
9002 template<
typename U>
9003 explicit BasicResult( BasicResult<U>
const &
other )
9005 m_errorMessage(
other.errorMessage() )
9010 template<
typename U>
9016 explicit operator bool()
const {
return m_type ==
ResultBase::Ok; }
9018 auto errorMessage()
const ->
std::
string {
return m_errorMessage; }
9021 void enforceOk()
const override {
9025 assert( m_type != ResultBase::LogicError );
9026 assert( m_type != ResultBase::RuntimeError );
9034 : ResultValueBase<
T>(
type),
9040 using ResultValueBase<T>::ResultValueBase;
9041 using ResultBase::m_type;
9044 enum class ParseResultType {
9045 Matched,
NoMatch, ShortCircuitAll, ShortCircuitSame
9051 ParseState( ParseResultType
type,
TokenStream const &remainingTokens )
9053 m_remainingTokens( remainingTokens )
9056 auto type()
const -> ParseResultType {
return m_type; }
9060 ParseResultType m_type;
9064 using Result = BasicResult<void>;
9065 using ParserResult = BasicResult<ParseResultType>;
9066 using InternalParseResult = BasicResult<ParseState>;
9068 struct HelpColumns {
9073 template<
typename T>
9075 std::stringstream ss;
9079 return ParserResult::runtimeError(
"Unable to convert '" +
source +
"' to destination type" );
9089 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), [](
unsigned char c ) { return static_cast<char>( std::tolower(c) ); } );
9090 if (srcLC ==
"y" || srcLC ==
"1" || srcLC ==
"true" || srcLC ==
"yes" || srcLC ==
"on")
9092 else if (srcLC ==
"n" || srcLC ==
"0" || srcLC ==
"false" || srcLC ==
"no" || srcLC ==
"off")
9095 return ParserResult::runtimeError(
"Expected a boolean value but did not recognise: '" +
source +
"'" );
9098 #ifdef CLARA_CONFIG_OPTIONAL_TYPE
9099 template<
typename T>
9104 target = std::move(temp);
9109 struct NonCopyable {
9110 NonCopyable() =
default;
9111 NonCopyable( NonCopyable
const & ) =
delete;
9112 NonCopyable( NonCopyable && ) =
delete;
9113 NonCopyable &operator=( NonCopyable
const & ) =
delete;
9114 NonCopyable &operator=( NonCopyable && ) =
delete;
9117 struct BoundRef : NonCopyable {
9118 virtual ~BoundRef() =
default;
9119 virtual auto isContainer()
const ->
bool {
return false; }
9120 virtual auto isFlag()
const ->
bool {
return false; }
9122 struct BoundValueRefBase : BoundRef {
9125 struct BoundFlagRefBase : BoundRef {
9126 virtual auto setFlag(
bool flag ) -> ParserResult = 0;
9127 virtual auto isFlag()
const ->
bool {
return true; }
9130 template<
typename T>
9131 struct BoundValueRef : BoundValueRefBase {
9134 explicit BoundValueRef(
T &
ref ) : m_ref(
ref ) {}
9137 return convertInto(
arg, m_ref );
9141 template<
typename T>
9142 struct BoundValueRef<
std::
vector<
T>> : BoundValueRefBase {
9143 std::vector<T> &m_ref;
9145 explicit BoundValueRef( std::vector<T> &
ref ) : m_ref(
ref ) {}
9147 auto isContainer()
const ->
bool override {
return true; }
9153 m_ref.push_back( temp );
9158 struct BoundFlagRef : BoundFlagRefBase {
9161 explicit BoundFlagRef(
bool &
ref ) : m_ref(
ref ) {}
9163 auto setFlag(
bool flag ) -> ParserResult
override {
9169 template<
typename ReturnType>
9170 struct LambdaInvoker {
9173 template<
typename L,
typename ArgType>
9174 static auto invoke(
L const &lambda, ArgType
const &
arg ) -> ParserResult {
9175 return lambda(
arg );
9180 struct LambdaInvoker<
void> {
9181 template<
typename L,
typename ArgType>
9182 static auto invoke(
L const &lambda, ArgType
const &
arg ) -> ParserResult {
9188 template<
typename ArgType,
typename L>
9189 inline auto invokeLambda(
L const &lambda,
std::string const &
arg ) -> ParserResult {
9194 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
9197 template<
typename L>
9198 struct BoundLambda : BoundValueRefBase {
9201 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
9202 explicit BoundLambda(
L const &lambda ) : m_lambda( lambda ) {}
9205 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda,
arg );
9209 template<
typename L>
9210 struct BoundFlagLambda : BoundFlagRefBase {
9213 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
9214 static_assert( std::is_same<
typename UnaryLambdaTraits<L>::ArgType,
bool>::
value,
"flags must be boolean" );
9216 explicit BoundFlagLambda(
L const &lambda ) : m_lambda( lambda ) {}
9218 auto setFlag(
bool flag ) -> ParserResult
override {
9219 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
9223 enum class Optionality { Optional,
Required };
9229 virtual ~ParserBase() =
default;
9232 virtual auto cardinality()
const ->
size_t {
return 1; }
9234 auto parse(
Args const &
args )
const -> InternalParseResult {
9239 template<
typename DerivedT>
9240 class ComposableParserImpl :
public ParserBase {
9242 template<
typename T>
9245 template<
typename T>
9250 template<
typename DerivedT>
9251 class ParserRefImpl :
public ComposableParserImpl<DerivedT> {
9253 Optionality m_optionality = Optionality::Optional;
9254 std::shared_ptr<BoundRef> m_ref;
9258 explicit ParserRefImpl( std::shared_ptr<BoundRef>
const &
ref ) : m_ref(
ref ) {}
9261 template<
typename T>
9263 : m_ref(
std::make_shared<BoundValueRef<
T>>(
ref ) ),
9267 template<
typename LambdaT>
9269 : m_ref(
std::make_shared<BoundLambda<LambdaT>>(
ref ) ),
9274 m_description = description;
9275 return static_cast<DerivedT &
>( *this );
9278 auto optional() -> DerivedT & {
9279 m_optionality = Optionality::Optional;
9280 return static_cast<DerivedT &
>( *this );
9285 return static_cast<DerivedT &
>( *this );
9288 auto isOptional()
const ->
bool {
9289 return m_optionality == Optionality::Optional;
9292 auto cardinality()
const ->
size_t override {
9293 if( m_ref->isContainer() )
9299 auto hint()
const ->
std::
string {
return m_hint; }
9302 class ExeName :
public ComposableParserImpl<ExeName> {
9303 std::shared_ptr<std::string> m_name;
9304 std::shared_ptr<BoundValueRefBase> m_ref;
9306 template<
typename LambdaT>
9307 static auto makeRef(LambdaT
const &lambda) -> std::shared_ptr<BoundValueRefBase> {
9308 return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
9312 ExeName() : m_name(
std::make_shared<
std::
string>(
"<executable>" ) ) {}
9315 m_ref = std::make_shared<BoundValueRef<std::string>>(
ref );
9318 template<
typename LambdaT>
9319 explicit ExeName( LambdaT
const& lambda ) : ExeName() {
9320 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );
9331 auto lastSlash = newName.find_last_of(
"\\/" );
9332 auto filename = ( lastSlash == std::string::npos )
9334 : newName.substr( lastSlash+1 );
9338 return m_ref->setValue(
filename );
9344 class Arg :
public ParserRefImpl<Arg> {
9346 using ParserRefImpl::ParserRefImpl;
9349 auto validationResult = validate();
9350 if( !validationResult )
9351 return InternalParseResult( validationResult );
9353 auto remainingTokens = tokens;
9354 auto const &
token = *remainingTokens;
9355 if(
token.type != TokenType::Argument )
9358 assert( !m_ref->isFlag() );
9359 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.get() );
9361 auto result = valueRef->setValue( remainingTokens->token );
9363 return InternalParseResult(
result );
9370 #ifdef CATCH_PLATFORM_WINDOWS
9371 if( optName[0] ==
'/' )
9372 return "-" + optName.substr( 1 );
9378 class Opt :
public ParserRefImpl<Opt> {
9380 std::vector<std::string> m_optNames;
9383 template<
typename LambdaT>
9384 explicit Opt( LambdaT
const &
ref ) : ParserRefImpl(
std::make_shared<BoundFlagLambda<LambdaT>>(
ref ) ) {}
9386 explicit Opt(
bool &
ref ) : ParserRefImpl(
std::make_shared<BoundFlagRef>(
ref ) ) {}
9388 template<
typename LambdaT>
9389 Opt( LambdaT
const &
ref,
std::string const &hint ) : ParserRefImpl(
ref, hint ) {}
9391 template<
typename T>
9394 auto operator[](
std::string const &optName ) -> Opt & {
9395 m_optNames.push_back( optName );
9400 std::ostringstream oss;
9402 for(
auto const &
opt : m_optNames ) {
9409 if( !m_hint.empty() )
9410 oss <<
" <" << m_hint <<
">";
9411 return { { oss.str(), m_description } };
9414 auto isMatch(
std::string const &optToken )
const ->
bool {
9415 auto normalisedToken = normaliseOpt( optToken );
9416 for(
auto const &
name : m_optNames ) {
9417 if( normaliseOpt(
name ) == normalisedToken )
9426 auto validationResult = validate();
9427 if( !validationResult )
9428 return InternalParseResult( validationResult );
9430 auto remainingTokens = tokens;
9431 if( remainingTokens && remainingTokens->type == TokenType::Option ) {
9432 auto const &
token = *remainingTokens;
9433 if( isMatch(
token.token ) ) {
9434 if( m_ref->isFlag() ) {
9435 auto flagRef =
static_cast<detail::BoundFlagRefBase*
>( m_ref.get() );
9436 auto result = flagRef->setFlag(
true );
9438 return InternalParseResult(
result );
9439 if(
result.value() == ParseResultType::ShortCircuitAll )
9442 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.get() );
9444 if( !remainingTokens )
9445 return InternalParseResult::runtimeError(
"Expected argument following " +
token.token );
9446 auto const &argToken = *remainingTokens;
9447 if( argToken.type != TokenType::Argument )
9448 return InternalParseResult::runtimeError(
"Expected argument following " +
token.token );
9449 auto result = valueRef->setValue( argToken.token );
9451 return InternalParseResult(
result );
9452 if(
result.value() == ParseResultType::ShortCircuitAll )
9461 auto validate()
const -> Result
override {
9462 if( m_optNames.empty() )
9463 return Result::logicError(
"No options supplied to Opt" );
9464 for(
auto const &
name : m_optNames ) {
9466 return Result::logicError(
"Option name cannot be empty" );
9467 #ifdef CATCH_PLATFORM_WINDOWS
9468 if(
name[0] !=
'-' &&
name[0] !=
'/' )
9469 return Result::logicError(
"Option name must begin with '-' or '/'" );
9471 if(
name[0] !=
'-' )
9472 return Result::logicError(
"Option name must begin with '-'" );
9475 return ParserRefImpl::validate();
9480 Help(
bool &showHelpFlag )
9481 : Opt([&]( bool flag ) {
9482 showHelpFlag = flag;
9486 static_cast<Opt &
>( *this )
9487 (
"display usage information")
9488 [
"-?"][
"-h"][
"--help"]
9493 struct Parser : ParserBase {
9495 mutable ExeName m_exeName;
9497 std::vector<Arg> m_args;
9500 m_exeName = exeName;
9505 m_args.push_back(
arg);
9516 m_args.insert(m_args.end(),
other.m_args.begin(),
other.m_args.end());
9520 template<
typename T>
9526 template<
typename T>
9528 template<
typename T>
9532 std::vector<HelpColumns> cols;
9534 auto childCols =
o.getHelpColumns();
9535 cols.insert( cols.end(), childCols.begin(), childCols.end() );
9540 void writeToStream( std::ostream &os )
const {
9541 if (!m_exeName.name().empty()) {
9542 os <<
"usage:\n" <<
" " << m_exeName.name() <<
" ";
9544 for(
auto const &
arg : m_args ) {
9553 os <<
"<" <<
arg.hint() <<
">";
9554 if(
arg.cardinality() == 0 )
9561 os <<
"\n\nwhere options are:" <<
std::endl;
9564 auto rows = getHelpColumns();
9566 size_t optWidth = 0;
9567 for(
auto const &cols : rows )
9568 optWidth = (std::max)(optWidth, cols.left.size() + 2);
9570 optWidth = (std::min)(optWidth, consoleWidth/2);
9572 for(
auto const &cols : rows ) {
9575 TextFlow::Spacer(4) +
9576 TextFlow::Column( cols.
right ).width( consoleWidth - 7 - optWidth );
9582 parser.writeToStream( os );
9586 auto validate()
const -> Result
override {
9592 for(
auto const &
arg : m_args ) {
9605 ParserBase
const*
parser =
nullptr;
9608 const size_t totalParsers =
m_options.size() + m_args.
size();
9609 assert( totalParsers < 512 );
9611 ParserInfo parseInfos[512];
9616 for (
auto const &
arg : m_args) parseInfos[i++].parser = &
arg;
9619 m_exeName.set( exeName );
9622 while(
result.value().remainingTokens() ) {
9623 bool tokenParsed =
false;
9625 for(
size_t i = 0;
i < totalParsers; ++
i ) {
9626 auto& parseInfo = parseInfos[i];
9627 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
9628 result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
9631 if (result.value().type() != ParseResultType::NoMatch) {
9639 if(
result.value().type() == ParseResultType::ShortCircuitAll )
9642 return InternalParseResult::runtimeError(
"Unrecognised token: " +
result.value().remainingTokens()->token );
9649 template<
typename DerivedT>
9650 template<
typename T>
9652 return Parser() |
static_cast<DerivedT
const &
>( *this ) |
other;
9657 using detail::Parser;
9669 using detail::ExeName;
9675 using detail::ParseResultType;
9678 using detail::ParserResult;
9684 #pragma clang diagnostic pop
9688 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
9689 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
9690 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
9696 clara::Parser makeCommandLineParser( ConfigData&
config );
9706 clara::Parser makeCommandLineParser( ConfigData&
config ) {
9708 using namespace clara;
9710 auto const setWarning = [&](
std::string const& warning ) {
9711 auto warningSet = [&]() {
9712 if( warning ==
"NoAssertions" )
9715 if ( warning ==
"NoTests" )
9722 return ParserResult::runtimeError(
"Unrecognised warning: '" + warning +
"'" );
9729 return ParserResult::runtimeError(
"Unable to load input file: '" +
filename +
"'" );
9732 while( std::getline(
f,
line ) ) {
9738 config.testsOrTags.emplace_back(
"," );
9742 if(!
config.testsOrTags.empty())
9743 config.testsOrTags.erase(
config.testsOrTags.end()-1 );
9755 return clara::ParserResult::runtimeError(
"Unrecognised ordering: '" +
order +
"'" );
9758 auto const setRngSeed = [&](
std::string const& seed ) {
9759 if( seed !=
"time" )
9760 return clara::detail::convertInto( seed,
config.rngSeed );
9764 auto const setColourUsage = [&](
std::string const& useColour ) {
9769 else if(
mode ==
"no" )
9771 else if(
mode ==
"auto" )
9774 return ParserResult::runtimeError(
"colour mode must be one of: auto, yes or no. '" + useColour +
"' not recognised" );
9777 auto const setWaitForKeypress = [&](
std::string const& keypress ) {
9778 auto keypressLc =
toLower( keypress );
9779 if (keypressLc ==
"never")
9781 else if( keypressLc ==
"start" )
9783 else if( keypressLc ==
"exit" )
9785 else if( keypressLc ==
"both" )
9788 return ParserResult::runtimeError(
"keypress argument must be one of: never, start, exit or both. '" + keypress +
"' not recognised" );
9791 auto const setVerbosity = [&](
std::string const& verbosity ) {
9792 auto lcVerbosity =
toLower( verbosity );
9793 if( lcVerbosity ==
"quiet" )
9795 else if( lcVerbosity ==
"normal" )
9797 else if( lcVerbosity ==
"high" )
9800 return ParserResult::runtimeError(
"Unrecognised verbosity, '" + verbosity +
"'" );
9803 auto const setReporter = [&](
std::string const& reporter ) {
9806 auto lcReporter =
toLower( reporter );
9807 auto result = factories.find( lcReporter );
9809 if( factories.end() !=
result )
9810 config.reporterName = lcReporter;
9812 return ParserResult::runtimeError(
"Unrecognized reporter, '" + reporter +
"'. Check available with --list-reporters" );
9817 = ExeName(
config.processName )
9818 | Help(
config.showHelp )
9819 | Opt(
config.listTests )
9820 ["-l"]["--list-tests"]
9821 (
"list all/matching test cases" )
9823 ["-t"]["--list-tags"]
9824 (
"list all/matching tags" )
9825 | Opt(
config.showSuccessfulTests )
9827 (
"include successful tests in output" )
9828 | Opt(
config.shouldDebugBreak )
9830 (
"break into debugger on failure" )
9833 (
"skip exception tests" )
9834 | Opt(
config.showInvisibles )
9835 ["-i"]["--invisibles"]
9836 (
"show invisibles (tabs, newlines)" )
9837 | Opt(
config.outputFilename,
"filename" )
9839 (
"output filename" )
9840 | Opt( setReporter,
"name" )
9841 ["-r"]["--reporter"]
9842 (
"reporter to use (defaults to console)" )
9843 | Opt(
config.name,
"name" )
9846 | Opt( [&](
bool ){
config.abortAfter = 1; } )
9848 (
"abort at first failure" )
9849 | Opt( [&](
int x ){
config.abortAfter =
x; },
"no. failures" )
9851 (
"abort after x failures" )
9852 | Opt( setWarning,
"warning name" )
9854 (
"enable warnings" )
9856 [
"-d"][
"--durations"]
9857 (
"show test durations" )
9858 | Opt(
config.minDuration,
"seconds" )
9859 ["-D"]["--min-duration"]
9860 (
"show test durations for tests taking at least the given number of seconds" )
9861 | Opt( loadTestNamesFromFile,
"filename" )
9862 ["-f"]["--input-file"]
9863 (
"load test names to run from a file" )
9864 | Opt(
config.filenamesAsTags )
9865 ["-#"]["--filenames-as-tags"]
9866 (
"adds a tag for the filename" )
9867 | Opt(
config.sectionsToRun,
"section name" )
9869 (
"specify section to run" )
9870 | Opt( setVerbosity,
"quiet|normal|high" )
9871 ["-v"]["--verbosity"]
9872 (
"set output verbosity" )
9873 | Opt(
config.listTestNamesOnly )
9874 ["--list-test-names-only"]
9875 (
"list all/matching test cases names only" )
9876 | Opt(
config.listReporters )
9877 ["--list-reporters"]
9878 (
"list all reporters" )
9879 | Opt( setTestOrder,
"decl|lex|rand" )
9881 (
"test case order (defaults to decl)" )
9882 | Opt( setRngSeed,
"'time'|number" )
9884 (
"set a specific seed for random numbers" )
9885 | Opt( setColourUsage,
"yes|no" )
9887 (
"should output be colourised" )
9888 | Opt(
config.libIdentify )
9890 (
"report name and version according to libidentify standard" )
9891 | Opt( setWaitForKeypress,
"never|start|exit|both" )
9892 ["--wait-for-keypress"]
9893 (
"waits for a keypress before exiting" )
9894 | Opt(
config.benchmarkSamples,
"samples" )
9895 ["--benchmark-samples"]
9896 (
"number of samples to collect (default: 100)" )
9897 | Opt(
config.benchmarkResamples,
"resamples" )
9898 ["--benchmark-resamples"]
9899 (
"number of resamples for the bootstrap (default: 100000)" )
9900 | Opt(
config.benchmarkConfidenceInterval,
"confidence interval" )
9901 ["--benchmark-confidence-interval"]
9902 (
"confidence interval for the bootstrap (between 0 and 1, default: 0.95)" )
9903 | Opt(
config.benchmarkNoAnalysis )
9904 ["--benchmark-no-analysis"]
9905 (
"perform only measurements; do not perform any analysis" )
9906 | Opt(
config.benchmarkWarmupTime,
"benchmarkWarmupTime" )
9907 ["--benchmark-warmup-time"]
9908 (
"amount of time in milliseconds spent on warming up each test (default: 100)" )
9909 | Arg(
config.testsOrTags,
"test name|pattern|tags" )
9910 (
"which test or tests to use" );
9933 std::ostream&
operator << ( std::ostream& os, SourceLineInfo
const&
info ) {
9935 os <<
info.file <<
'(' <<
info.line <<
')';
9937 os <<
info.file <<
':' <<
info.line;
9957 m_stream( openStream() )
9963 for (
auto& elem : m_data.testsOrTags) {
9966 for (
auto& elem : m_data.sectionsToRun) {
9971 if (!m_data.testsOrTags.empty()) {
9972 m_hasTestFilters =
true;
9973 for (
auto const& testOrTags : m_data.testsOrTags) {
9974 parser.parse(testOrTags);
9977 m_testSpec =
parser.testSpec();
9981 return m_data.outputFilename ;
9984 bool Config::listTests()
const {
return m_data.listTests; }
9985 bool Config::listTestNamesOnly()
const {
return m_data.listTestNamesOnly; }
9986 bool Config::listTags()
const {
return m_data.listTags; }
9987 bool Config::listReporters()
const {
return m_data.listReporters; }
9989 std::string Config::getProcessName()
const {
return m_data.processName; }
9990 std::string const& Config::getReporterName()
const {
return m_data.reporterName; }
9992 std::vector<std::string>
const& Config::getTestsOrTags()
const {
return m_data.testsOrTags; }
9993 std::vector<std::string>
const& Config::getSectionsToRun()
const {
return m_data.sectionsToRun; }
9995 TestSpec
const& Config::testSpec()
const {
return m_testSpec; }
9996 bool Config::hasTestFilters()
const {
return m_hasTestFilters; }
9998 bool Config::showHelp()
const {
return m_data.showHelp; }
10001 bool Config::allowThrows()
const {
return !m_data.noThrow; }
10002 std::ostream&
Config::stream()
const {
return m_stream->stream(); }
10004 bool Config::includeSuccessfulResults()
const {
return m_data.showSuccessfulTests; }
10006 bool Config::warnAboutNoTests()
const {
return !!(m_data.warnings &
WarnAbout::NoTests); }
10008 double Config::minDuration()
const {
return m_data.minDuration; }
10012 bool Config::shouldDebugBreak()
const {
return m_data.shouldDebugBreak; }
10013 int Config::abortAfter()
const {
return m_data.abortAfter; }
10014 bool Config::showInvisibles()
const {
return m_data.showInvisibles; }
10015 Verbosity Config::verbosity()
const {
return m_data.verbosity; }
10017 bool Config::benchmarkNoAnalysis()
const {
return m_data.benchmarkNoAnalysis; }
10018 int Config::benchmarkSamples()
const {
return m_data.benchmarkSamples; }
10019 double Config::benchmarkConfidenceInterval()
const {
return m_data.benchmarkConfidenceInterval; }
10020 unsigned int Config::benchmarkResamples()
const {
return m_data.benchmarkResamples; }
10021 std::chrono::milliseconds Config::benchmarkWarmupTime()
const {
return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }
10023 IStream
const* Config::openStream() {
10031 #if defined(__clang__)
10032 # pragma clang diagnostic push
10033 # pragma clang diagnostic ignored "-Wexit-time-destructors"
10054 #if defined(CATCH_PLATFORM_WINDOWS)
10056 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
10057 # define CATCH_DEFINED_NOMINMAX
10060 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
10061 # define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
10062 # define WIN32_LEAN_AND_MEAN
10066 #include <AfxWin.h>
10071 #ifdef CATCH_DEFINED_NOMINMAX
10074 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
10075 # undef WIN32_LEAN_AND_MEAN
10086 struct IColourImpl {
10087 virtual ~IColourImpl() =
default;
10091 struct NoColourImpl : IColourImpl {
10094 static IColourImpl* instance() {
10103 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
10104 # ifdef CATCH_PLATFORM_WINDOWS
10105 # define CATCH_CONFIG_COLOUR_WINDOWS
10107 # define CATCH_CONFIG_COLOUR_ANSI
10111 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS )
10116 class Win32ColourImpl :
public IColourImpl {
10118 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
10120 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
10121 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
10122 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
10123 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
10127 switch( _colourCode ) {
10128 case Colour::None:
return setTextAttribute( originalForegroundAttributes );
10129 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
10130 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
10131 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
10132 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
10133 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
10134 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
10135 case Colour::Grey:
return setTextAttribute( 0 );
10137 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
10138 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
10139 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
10140 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
10141 case Colour::BrightYellow:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
10151 void setTextAttribute( WORD _textAttribute ) {
10152 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
10155 WORD originalForegroundAttributes;
10156 WORD originalBackgroundAttributes;
10159 IColourImpl* platformColourInstance() {
10170 : NoColourImpl::instance();
10176 #elif defined( CATCH_CONFIG_COLOUR_ANSI )
10178 #include <unistd.h>
10187 class PosixColourImpl :
public IColourImpl {
10190 switch( _colourCode ) {
10198 case Colour::Grey:
return setColour(
"[1;30m" );
10200 case Colour::LightGrey:
return setColour(
"[0;37m" );
10201 case Colour::BrightRed:
return setColour(
"[1;31m" );
10202 case Colour::BrightGreen:
return setColour(
"[1;32m" );
10203 case Colour::BrightWhite:
return setColour(
"[1;37m" );
10204 case Colour::BrightYellow:
return setColour(
"[1;33m" );
10210 static IColourImpl* instance() {
10216 void setColour(
const char* _escapeCode ) {
10218 <<
'\033' << _escapeCode;
10222 bool useColourOnPlatform() {
10224 #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
10225 !isDebuggerActive() &&
10227 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
10234 IColourImpl* platformColourInstance() {
10241 colourMode = useColourOnPlatform()
10245 ? PosixColourImpl::instance()
10246 : NoColourImpl::instance();
10256 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
10264 Colour::Colour(
Code _colourCode ) { use( _colourCode ); }
10265 Colour::Colour( Colour&&
other ) noexcept {
10266 m_moved =
other.m_moved;
10267 other.m_moved =
true;
10269 Colour& Colour::operator=( Colour&&
other ) noexcept {
10270 m_moved =
other.m_moved;
10271 other.m_moved =
true;
10275 Colour::~Colour(){
if( !m_moved ) use( None ); }
10277 void Colour::use(
Code _colourCode ) {
10278 static IColourImpl* impl = platformColourInstance();
10283 if (impl !=
nullptr) {
10284 impl->use( _colourCode );
10288 std::ostream&
operator << ( std::ostream& os, Colour
const& ) {
10294 #if defined(__clang__)
10295 # pragma clang diagnostic pop
10303 class Context :
public IMutableContext, NonCopyable {
10307 return m_resultCapture;
10309 IRunner* getRunner()
override {
10313 IConfigPtr const& getConfig()
const override {
10317 ~Context()
override;
10320 void setResultCapture( IResultCapture* resultCapture )
override {
10321 m_resultCapture = resultCapture;
10323 void setRunner( IRunner* runner )
override {
10334 IRunner* m_runner =
nullptr;
10335 IResultCapture* m_resultCapture =
nullptr;
10338 IMutableContext *IMutableContext::currentContext =
nullptr;
10340 void IMutableContext::createContext()
10342 currentContext =
new Context();
10346 delete IMutableContext::currentContext;
10347 IMutableContext::currentContext =
nullptr;
10351 Context::~Context() =
default;
10353 SimplePcg32&
rng() {
10354 static SimplePcg32 s_rng;
10367 void writeToDebugConsole(
std::string const& text );
10371 #if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
10372 #include <android/log.h>
10375 void writeToDebugConsole(
std::string const& text ) {
10376 __android_log_write( ANDROID_LOG_DEBUG,
"Catch",
text.c_str() );
10380 #elif defined(CATCH_PLATFORM_WINDOWS)
10383 void writeToDebugConsole(
std::string const& text ) {
10384 ::OutputDebugStringA(
text.c_str() );
10391 void writeToDebugConsole(
std::string const& text ) {
10401 #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
10403 # include <cassert>
10404 # include <sys/types.h>
10405 # include <unistd.h>
10406 # include <cstddef>
10407 # include <ostream>
10409 #ifdef __apple_build_version__
10412 # include <sys/sysctl.h>
10416 #ifdef __apple_build_version__
10422 bool isDebuggerActive(){
10424 struct kinfo_proc
info;
10430 info.kp_proc.p_flag = 0;
10436 mib[1] = KERN_PROC;
10437 mib[2] = KERN_PROC_PID;
10443 if( sysctl(mib,
sizeof(mib) /
sizeof(*mib), &
info, &
size,
nullptr, 0) != 0 ) {
10444 Catch::cerr() <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" <<
std::endl;
10450 return ( (
info.kp_proc.p_flag & P_TRACED) != 0 );
10453 bool isDebuggerActive() {
10460 #elif defined(CATCH_PLATFORM_LINUX)
10472 bool isDebuggerActive(){
10476 std::ifstream
in(
"/proc/self/status");
10478 static const int PREFIX_LEN = 11;
10479 if(
line.
compare(0, PREFIX_LEN,
"TracerPid:\t") == 0 ) {
10490 #elif defined(_MSC_VER)
10491 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
10493 bool isDebuggerActive() {
10494 return IsDebuggerPresent() != 0;
10497 #elif defined(__MINGW32__)
10498 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
10500 bool isDebuggerActive() {
10501 return IsDebuggerPresent() != 0;
10506 bool isDebuggerActive() {
return false; }
10517 if( lhs.size() +
rhs.size() < 40 &&
10518 lhs.find(
'\n') == std::string::npos &&
10519 rhs.find(
'\n') == std::string::npos )
10520 os << lhs <<
" " <<
op <<
" " <<
rhs;
10522 os << lhs <<
"\n" <<
op <<
"\n" <<
rhs;
10528 #include <stdexcept>
10531 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
10534 Catch::cerr() <<
"Catch will terminate because it needed to throw an exception.\n"
10535 <<
"The message was: " <<
e.what() <<
'\n';
10567 std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int>
const&
values );
10569 class EnumValuesRegistry :
public IMutableEnumValuesRegistry {
10571 std::vector<std::unique_ptr<EnumInfo>> m_enumInfos;
10573 EnumInfo
const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int>
const&
values)
override;
10576 std::vector<StringRef> parseEnums( StringRef
enums );
10596 StringRef extractInstanceName(StringRef enumInstance) {
10598 size_t name_start = enumInstance.size();
10599 while (name_start > 0 && enumInstance[name_start - 1] !=
':') {
10602 return enumInstance.substr(name_start, enumInstance.size() - name_start);
10606 std::vector<StringRef> parseEnums( StringRef
enums ) {
10608 std::vector<StringRef> parsed;
10609 parsed.reserve( enumValues.size() );
10610 for(
auto const&
enumValue : enumValues ) {
10619 for(
auto const& valueToName :
m_values ) {
10620 if( valueToName.first ==
value )
10621 return valueToName.second;
10623 return "{** unexpected enum value **}"_sr;
10626 std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int>
const&
values ) {
10627 std::unique_ptr<EnumInfo> enumInfo(
new EnumInfo );
10628 enumInfo->m_name = enumName;
10629 enumInfo->m_values.reserve(
values.size() );
10631 const auto valueNames = Catch::Detail::parseEnums( allValueNames );
10635 enumInfo->m_values.emplace_back(
value, valueNames[
i++]);
10640 EnumInfo
const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int>
const&
values ) {
10641 m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames,
values));
10642 return *m_enumInfos.back();
10654 ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
10655 ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
10668 class ExceptionTranslatorRegistry :
public IExceptionTranslatorRegistry {
10670 ~ExceptionTranslatorRegistry();
10671 virtual void registerTranslator(
const IExceptionTranslator* translator );
10676 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
10682 #import "Foundation/Foundation.h"
10687 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
10690 void ExceptionTranslatorRegistry::registerTranslator(
const IExceptionTranslator* translator ) {
10691 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
10694 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
10700 return tryTranslators();
10702 @catch (NSException *exception) {
10714 if (std::current_exception() ==
nullptr) {
10715 return "Non C++ exception. Possibly a CLR exception.";
10717 return tryTranslators();
10720 catch( TestFailureException& ) {
10721 std::rethrow_exception(std::current_exception());
10723 catch( std::exception& ex ) {
10729 catch(
const char*
msg ) {
10733 return "Unknown exception";
10737 std::string ExceptionTranslatorRegistry::tryTranslators()
const {
10738 if (m_translators.empty()) {
10739 std::rethrow_exception(std::current_exception());
10741 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
10747 CATCH_INTERNAL_ERROR(
"Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
10750 std::string ExceptionTranslatorRegistry::tryTranslators()
const {
10751 CATCH_INTERNAL_ERROR(
"Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
10759 #include <algorithm>
10761 #if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS )
10767 void FatalConditionHandler::engage_platform() {}
10768 void FatalConditionHandler::disengage_platform() {}
10769 FatalConditionHandler::FatalConditionHandler() =
default;
10770 FatalConditionHandler::~FatalConditionHandler() =
default;
10776 #if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS )
10777 #error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"
10780 #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
10784 void reportFatal(
char const *
const message ) {
10791 constexpr std::size_t minStackSizeForErrors = 32 * 1024;
10796 #if defined( CATCH_CONFIG_WINDOWS_SEH )
10800 struct SignalDefs { DWORD
id;
const char*
name; };
10805 static SignalDefs signalDefs[] = {
10806 {
static_cast<DWORD
>(EXCEPTION_ILLEGAL_INSTRUCTION),
"SIGILL - Illegal instruction signal" },
10807 {
static_cast<DWORD
>(EXCEPTION_STACK_OVERFLOW),
"SIGSEGV - Stack overflow" },
10808 {
static_cast<DWORD
>(EXCEPTION_ACCESS_VIOLATION),
"SIGSEGV - Segmentation violation signal" },
10809 {
static_cast<DWORD
>(EXCEPTION_INT_DIVIDE_BY_ZERO),
"Divide by zero error" },
10812 static LONG
CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
10813 for (
auto const& def : signalDefs) {
10814 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
10815 reportFatal(def.name);
10820 return EXCEPTION_CONTINUE_SEARCH;
10826 static PVOID exceptionHandlerHandle =
nullptr;
10830 FatalConditionHandler::FatalConditionHandler() {
10831 ULONG guaranteeSize =
static_cast<ULONG
>(minStackSizeForErrors);
10832 if (!SetThreadStackGuarantee(&guaranteeSize)) {
10836 <<
"Failed to reserve piece of stack."
10837 <<
" Stack overflows will not be reported successfully.";
10843 FatalConditionHandler::~FatalConditionHandler() =
default;
10845 void FatalConditionHandler::engage_platform() {
10847 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
10848 if (!exceptionHandlerHandle) {
10853 void FatalConditionHandler::disengage_platform() {
10854 if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {
10857 exceptionHandlerHandle =
nullptr;
10864 #if defined( CATCH_CONFIG_POSIX_SIGNALS )
10866 #include <signal.h>
10870 struct SignalDefs {
10875 static SignalDefs signalDefs[] = {
10876 { SIGINT,
"SIGINT - Terminal interrupt signal" },
10877 { SIGILL,
"SIGILL - Illegal instruction signal" },
10878 { SIGFPE,
"SIGFPE - Floating point error signal" },
10879 { SIGSEGV,
"SIGSEGV - Segmentation violation signal" },
10880 { SIGTERM,
"SIGTERM - Termination request signal" },
10881 { SIGABRT,
"SIGABRT - Abort (abnormal termination) signal" }
10887 #if defined(__GNUC__)
10888 # pragma GCC diagnostic push
10889 # pragma GCC diagnostic ignored "-Wmissing-field-initializers"
10892 static char* altStackMem =
nullptr;
10893 static std::size_t altStackSize = 0;
10894 static stack_t oldSigStack{};
10895 static struct sigaction oldSigActions[
sizeof(signalDefs) /
sizeof(SignalDefs)]{};
10897 static void restorePreviousSignalHandlers() {
10902 for (std::size_t
i = 0;
i <
sizeof(signalDefs) /
sizeof(SignalDefs); ++
i) {
10903 sigaction(signalDefs[
i].
id, &oldSigActions[
i],
nullptr);
10906 sigaltstack(&oldSigStack,
nullptr);
10909 static void handleSignal(
int sig ) {
10910 char const *
name =
"<unknown signal>";
10911 for (
auto const& def : signalDefs) {
10912 if (sig == def.id) {
10920 restorePreviousSignalHandlers();
10921 reportFatal(
name );
10925 FatalConditionHandler::FatalConditionHandler() {
10926 assert(!altStackMem &&
"Cannot initialize POSIX signal handler when one already exists");
10927 if (altStackSize == 0) {
10928 altStackSize = std::max(
static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
10930 altStackMem =
new char[altStackSize]();
10933 FatalConditionHandler::~FatalConditionHandler() {
10934 delete[] altStackMem;
10937 altStackMem =
nullptr;
10940 void FatalConditionHandler::engage_platform() {
10942 sigStack.ss_sp = altStackMem;
10943 sigStack.ss_size = altStackSize;
10944 sigStack.ss_flags = 0;
10945 sigaltstack(&sigStack, &oldSigStack);
10946 struct sigaction sa = { };
10948 sa.sa_handler = handleSignal;
10949 sa.sa_flags = SA_ONSTACK;
10950 for (std::size_t
i = 0;
i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++
i) {
10951 sigaction(signalDefs[
i].
id, &sa, &oldSigActions[
i]);
10955 #if defined(__GNUC__)
10956 # pragma GCC diagnostic pop
10959 void FatalConditionHandler::disengage_platform() {
10960 restorePreviousSignalHandlers();
10980 namespace Generators {
10984 auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo
const& lineInfo ) -> IGeneratorTracker& {
11023 class ListeningReporter :
public IStreamingReporter {
11024 using Reporters = std::vector<IStreamingReporterPtr>;
11025 Reporters m_listeners;
11026 IStreamingReporterPtr m_reporter =
nullptr;
11027 ReporterPreferences m_preferences;
11030 ListeningReporter();
11032 void addListener( IStreamingReporterPtr&& listener );
11033 void addReporter( IStreamingReporterPtr&& reporter );
11037 ReporterPreferences getPreferences()
const override;
11039 void noMatchingTestCases(
std::string const& spec )
override;
11043 static std::set<Verbosity> getSupportedVerbosities();
11045 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
11047 void benchmarkStarting( BenchmarkInfo
const& benchmarkInfo )
override;
11048 void benchmarkEnded( BenchmarkStats<>
const& benchmarkStats )
override;
11049 void benchmarkFailed(
std::string const&)
override;
11052 void testRunStarting( TestRunInfo
const& testRunInfo )
override;
11053 void testGroupStarting( GroupInfo
const& groupInfo )
override;
11054 void testCaseStarting( TestCaseInfo
const& testInfo )
override;
11055 void sectionStarting( SectionInfo
const& sectionInfo )
override;
11056 void assertionStarting( AssertionInfo
const& assertionInfo )
override;
11059 bool assertionEnded( AssertionStats
const& assertionStats )
override;
11060 void sectionEnded( SectionStats
const& sectionStats )
override;
11061 void testCaseEnded( TestCaseStats
const& testCaseStats )
override;
11062 void testGroupEnded( TestGroupStats
const& testGroupStats )
override;
11063 void testRunEnded( TestRunStats
const& testRunStats )
override;
11065 void skipTest( TestCaseInfo
const& testInfo )
override;
11066 bool isMulti()
const override;
11075 ReporterConfig::ReporterConfig(
IConfigPtr const& _fullConfig )
11076 : m_stream( &_fullConfig->
stream() ), m_fullConfig( _fullConfig ) {}
11078 ReporterConfig::ReporterConfig(
IConfigPtr const& _fullConfig, std::ostream& _stream )
11079 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
11082 IConfigPtr ReporterConfig::fullConfig()
const {
return m_fullConfig; }
11084 TestRunInfo::TestRunInfo(
std::string const& _name ) :
name( _name ) {}
11087 std::size_t _groupIndex,
11088 std::size_t _groupsCount )
11090 groupIndex( _groupIndex ),
11091 groupsCounts( _groupsCount )
11094 AssertionStats::AssertionStats( AssertionResult
const& _assertionResult,
11095 std::vector<MessageInfo>
const& _infoMessages,
11096 Totals
const& _totals )
11097 : assertionResult( _assertionResult ),
11098 infoMessages( _infoMessages ),
11101 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
11103 if( assertionResult.hasMessage() ) {
11106 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
11107 builder << assertionResult.getMessage();
11108 builder.m_info.message = builder.m_stream.str();
11110 infoMessages.push_back( builder.m_info );
11114 AssertionStats::~AssertionStats() =
default;
11116 SectionStats::SectionStats( SectionInfo
const& _sectionInfo,
11117 Counts
const& _assertions,
11118 double _durationInSeconds,
11119 bool _missingAssertions )
11120 : sectionInfo( _sectionInfo ),
11121 assertions( _assertions ),
11122 durationInSeconds( _durationInSeconds ),
11123 missingAssertions( _missingAssertions )
11126 SectionStats::~SectionStats() =
default;
11128 TestCaseStats::TestCaseStats( TestCaseInfo
const& _testInfo,
11129 Totals
const& _totals,
11133 : testInfo( _testInfo ),
11137 aborting( _aborting )
11140 TestCaseStats::~TestCaseStats() =
default;
11142 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo,
11143 Totals
const& _totals,
11145 : groupInfo( _groupInfo ),
11147 aborting( _aborting )
11150 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo )
11151 : groupInfo( _groupInfo ),
11155 TestGroupStats::~TestGroupStats() =
default;
11157 TestRunStats::TestRunStats( TestRunInfo
const& _runInfo,
11158 Totals
const& _totals,
11160 : runInfo( _runInfo ),
11162 aborting( _aborting )
11165 TestRunStats::~TestRunStats() =
default;
11167 void IStreamingReporter::fatalErrorEncountered( StringRef ) {}
11168 bool IStreamingReporter::isMulti()
const {
return false; }
11170 IReporterFactory::~IReporterFactory() =
default;
11171 IReporterRegistry::~IReporterRegistry() =
default;
11190 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG
11191 #include <crtdbg.h>
11195 LeakDetector::LeakDetector() {
11196 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
11197 flag |= _CRTDBG_LEAK_CHECK_DF;
11198 flag |= _CRTDBG_ALLOC_MEM_DF;
11199 _CrtSetDbgFlag(flag);
11200 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
11201 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
11203 _CrtSetBreakAlloc(-1);
11209 Catch::LeakDetector::LeakDetector() {}
11213 Catch::LeakDetector::~LeakDetector() {
11227 std::size_t listTestsNamesOnly(
Config const&
config );
11233 std::set<std::string> spellings;
11234 std::size_t
count = 0;
11239 std::size_t listReporters();
11249 using namespace clara::TextFlow;
11254 #include <algorithm>
11260 TestSpec
const& testSpec =
config.testSpec();
11261 if(
config.hasTestFilters() )
11268 for(
auto const& testCaseInfo : matchedTestCases ) {
11270 ? Colour::SecondaryText
11272 Colour colourGuard( colour );
11274 Catch::cout() <<
Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) <<
"\n";
11277 std::string description = testCaseInfo.description;
11278 if( description.empty() )
11279 description =
"(NO DESCRIPTION)";
11282 if( !testCaseInfo.tags.empty() )
11286 if( !
config.hasTestFilters() )
11289 Catch::cout() << pluralise( matchedTestCases.size(),
"matching test case" ) <<
'\n' <<
std::endl;
11290 return matchedTestCases.size();
11293 std::size_t listTestsNamesOnly(
Config const&
config ) {
11294 TestSpec
const& testSpec =
config.testSpec();
11295 std::size_t matchedTests = 0;
11297 for(
auto const& testCaseInfo : matchedTestCases ) {
11300 Catch::cout() <<
'"' << testCaseInfo.name <<
'"';
11307 return matchedTests;
11312 spellings.insert( spelling );
11317 for (
auto const& spelling : spellings) {
11323 for (
auto const& spelling : spellings) {
11332 TestSpec
const& testSpec =
config.testSpec();
11333 if(
config.hasTestFilters() )
11334 Catch::cout() <<
"Tags for matching test cases:\n";
11339 std::map<std::string, TagInfo> tagCounts;
11342 for(
auto const& testCase : matchedTestCases ) {
11343 for(
auto const& tagName : testCase.getTestCaseInfo().tags ) {
11345 auto countIt = tagCounts.find( lcaseTagName );
11346 if( countIt == tagCounts.end() )
11347 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
11348 countIt->second.add( tagName );
11352 for(
auto const& tagCount : tagCounts ) {
11353 ReusableStringStream rss;
11354 rss <<
" " << std::setw(2) << tagCount.second.count <<
" ";
11355 auto str = rss.str();
11357 .initialIndent( 0 )
11359 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
11363 return tagCounts.size();
11366 std::size_t listReporters() {
11369 std::size_t maxNameLen = 0;
11370 for(
auto const& factoryKvp : factories )
11371 maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );
11373 for(
auto const& factoryKvp : factories ) {
11375 <<
Column( factoryKvp.first +
":" )
11377 .width( 5+maxNameLen )
11378 +
Column( factoryKvp.second->getDescription() )
11381 .
width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
11385 return factories.size();
11391 if(
config->listTests() )
11392 listedCount = listedCount.valueOr(0) + listTests( *
config );
11393 if(
config->listTestNamesOnly() )
11394 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *
config );
11395 if(
config->listTags() )
11396 listedCount = listedCount.valueOr(0) + listTags( *
config );
11397 if(
config->listReporters() )
11398 listedCount = listedCount.valueOr(0) + listReporters();
11399 return listedCount;
11407 namespace Matchers {
11421 using namespace Matchers;
11422 using Matchers::Impl::MatcherBase;
11429 namespace Matchers {
11430 namespace Exception {
11433 return ex.what() == m_message;
11437 return "exception message matches \"" + m_message + "\"";
11442 return Exception::ExceptionMessageMatcher(
message);
11454 bool isnan(
float f);
11455 bool isnan(
double d);
11464 template <
typename T>
11466 #if defined(CATCH_CONFIG_CPP11_TO_STRING)
11469 ReusableStringStream rss;
11477 #include <algorithm>
11483 #include <type_traits>
11491 static_assert(
sizeof(
float) ==
sizeof(int32_t),
"Important ULP matcher assumption violated");
11493 std::memcpy(&
i, &
f,
sizeof(
f));
11498 static_assert(
sizeof(
double) ==
sizeof(int64_t),
"Important ULP matcher assumption violated");
11500 std::memcpy(&
i, &
d,
sizeof(
d));
11504 template <
typename FP>
11505 bool almostEqualUlps(FP lhs, FP
rhs, uint64_t maxUlpDiff) {
11508 if (Catch::isnan(lhs) || Catch::isnan(
rhs)) {
11515 if ((lc < 0) != (rc < 0)) {
11521 auto ulpDiff = std::abs(
static_cast<FP
>(lc - rc));
11522 return static_cast<uint64_t
>(ulpDiff) <= maxUlpDiff;
11525 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
11527 float nextafter(
float x,
float y) {
11528 return ::nextafterf(
x,
y);
11531 double nextafter(
double x,
double y) {
11532 return ::nextafter(
x,
y);
11537 template <
typename FP>
11539 for (uint64_t
i = 0;
i < steps; ++
i) {
11540 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
11551 bool marginComparison(
double lhs,
double rhs,
double margin) {
11552 return (lhs + margin >=
rhs) && (
rhs + margin >= lhs);
11555 template <
typename FloatingPo
int>
11556 void write(std::ostream&
out, FloatingPoint
num) {
11558 << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1)
11564 namespace Matchers {
11565 namespace Floating {
11567 enum class FloatingPointKind : uint8_t {
11572 WithinAbsMatcher::WithinAbsMatcher(
double target,
double margin)
11573 :m_target{
target }, m_margin{ margin } {
11574 CATCH_ENFORCE(margin >= 0,
"Invalid margin: " << margin <<
'.'
11575 <<
" Margin has to be non-negative.");
11580 bool WithinAbsMatcher::match(
double const& matchee)
const {
11581 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
11585 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
11588 WithinUlpsMatcher::WithinUlpsMatcher(
double target, uint64_t ulps, FloatingPointKind baseType)
11589 :m_target{
target }, m_ulps{ ulps }, m_type{ baseType } {
11591 || m_ulps < (std::numeric_limits<uint32_t>::max)(),
11592 "Provided ULP is impossibly large for a float comparison.");
11595 #if defined(__clang__)
11596 #pragma clang diagnostic push
11598 #pragma clang diagnostic ignored "-Wunreachable-code"
11601 bool WithinUlpsMatcher::match(
double const& matchee)
const {
11604 return almostEqualUlps<float>(
static_cast<float>(matchee),
static_cast<float>(m_target), m_ulps);
11606 return almostEqualUlps<double>(matchee, m_target, m_ulps);
11612 #if defined(__clang__)
11613 #pragma clang diagnostic pop
11616 std::string WithinUlpsMatcher::describe()
const {
11617 std::stringstream
ret;
11619 ret <<
"is within " << m_ulps <<
" ULPs of ";
11622 write(
ret,
static_cast<float>(m_target));
11630 write(
ret,
step(m_target,
static_cast<double>(-INFINITY), m_ulps));
11632 write(
ret,
step(m_target,
static_cast<double>( INFINITY), m_ulps));
11635 write(
ret,
step(
static_cast<float>(m_target),
static_cast<float>(-INFINITY), m_ulps));
11637 write(
ret,
step(
static_cast<float>(m_target),
static_cast<float>( INFINITY), m_ulps));
11644 WithinRelMatcher::WithinRelMatcher(
double target,
double epsilon):
11647 CATCH_ENFORCE(m_epsilon >= 0.,
"Relative comparison with epsilon < 0 does not make sense.");
11648 CATCH_ENFORCE(m_epsilon < 1., "Relative comparison with epsilon >= 1 does not
make sense.
");
11651 bool WithinRelMatcher::match(double const& matchee) const {
11652 const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));
11653 return marginComparison(matchee, m_target,
11654 std::isinf(relMargin)? 0 : relMargin);
11657 std::string WithinRelMatcher::describe() const {
11658 Catch::ReusableStringStream sstr;
11659 sstr << "and
" << m_target << " are within
" << m_epsilon * 100. << "% of each
other";
11663 }// namespace Floating
11665 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
11666 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
11669 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
11670 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
11673 Floating::WithinAbsMatcher WithinAbs(double target, double margin) {
11674 return Floating::WithinAbsMatcher(target, margin);
11677 Floating::WithinRelMatcher WithinRel(double target, double eps) {
11678 return Floating::WithinRelMatcher(target, eps);
11681 Floating::WithinRelMatcher WithinRel(double target) {
11682 return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
11685 Floating::WithinRelMatcher WithinRel(float target, float eps) {
11686 return Floating::WithinRelMatcher(target, eps);
11689 Floating::WithinRelMatcher WithinRel(float target) {
11690 return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
11693 } // namespace Matchers
11694 } // namespace Catch
11695 // end catch_matchers_floating.cpp
11696 // start catch_matchers_generic.cpp
11698 std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {
11699 if (desc.empty()) {
11700 return "matches undescribed
predicate";
11702 return "matches
predicate: \
"" + desc +
'"';
11711 namespace Matchers {
11713 namespace StdString {
11716 : m_caseSensitivity( caseSensitivity ),
11717 m_str( adjustString(
str ) )
11724 std::string CasedString::caseSensitivitySuffix()
const {
11726 ?
" (case insensitive)"
11730 StringMatcherBase::StringMatcherBase(
std::string const& operation, CasedString
const& comparator )
11731 : m_comparator( comparator ),
11732 m_operation( operation ) {
11735 std::string StringMatcherBase::describe()
const {
11737 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
11738 m_comparator.caseSensitivitySuffix().size());
11739 description += m_operation;
11740 description += ": \"";
11741 description += m_comparator.m_str;
11742 description += "\"";
11743 description += m_comparator.caseSensitivitySuffix();
11744 return description;
11747 EqualsMatcher::EqualsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"equals", comparator ) {}
11750 return m_comparator.adjustString(
source ) == m_comparator.m_str;
11753 ContainsMatcher::ContainsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"contains", comparator ) {}
11756 return contains( m_comparator.adjustString(
source ), m_comparator.m_str );
11759 StartsWithMatcher::StartsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"starts with", comparator ) {}
11762 return startsWith( m_comparator.adjustString(
source ), m_comparator.m_str );
11765 EndsWithMatcher::EndsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"ends with", comparator ) {}
11768 return endsWith( m_comparator.adjustString(
source ), m_comparator.m_str );
11773 bool RegexMatcher::match(
std::string const& matchee)
const {
11774 auto flags = std::regex::ECMAScript;
11775 if (m_caseSensitivity == CaseSensitive::Choice::No) {
11776 flags |= std::regex::icase;
11778 auto reg = std::regex(m_regex,
flags);
11779 return std::regex_match(matchee, reg);
11783 return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity ==
CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");
11788 StdString::EqualsMatcher
Equals(
std::string const&
str, CaseSensitive::Choice caseSensitivity ) {
11789 return StdString::EqualsMatcher( StdString::CasedString(
str, caseSensitivity) );
11792 return StdString::ContainsMatcher( StdString::CasedString(
str, caseSensitivity) );
11795 return StdString::EndsWithMatcher( StdString::CasedString(
str, caseSensitivity) );
11798 return StdString::StartsWithMatcher( StdString::CasedString(
str, caseSensitivity) );
11801 StdString::RegexMatcher
Matches(
std::string const& regex, CaseSensitive::Choice caseSensitivity) {
11802 return StdString::RegexMatcher(regex, caseSensitivity);
11813 bool uncaught_exceptions();
11823 SourceLineInfo
const& _lineInfo,
11825 : macroName( _macroName ),
11826 lineInfo( _lineInfo ),
11828 sequence( ++globalCount )
11840 unsigned int MessageInfo::globalCount = 0;
11845 SourceLineInfo
const& lineInfo,
11847 :m_info(macroName, lineInfo,
type) {}
11852 : m_info( builder.m_info ), m_moved()
11854 m_info.message = builder.m_stream.str();
11859 : m_info( old.m_info ), m_moved()
11861 old.m_moved =
true;
11865 if ( !uncaught_exceptions() && !
m_moved ){
11875 while (
names[
end] ==
',' || isspace(
static_cast<unsigned char>(
names[
end]))) {
11880 auto skipq = [&] (
size_t start,
char quote) {
11891 std::stack<char> openings;
11914 if (
start !=
pos && openings.empty()) {
11915 m_messages.emplace_back(macroName, lineInfo, resultType);
11917 m_messages.back().message += " := ";
11922 assert(openings.empty() &&
"Mismatched openings");
11923 m_messages.emplace_back(macroName, lineInfo, resultType);
11925 m_messages.back().message += " := ";
11927 Capturer::~Capturer() {
11928 if ( !uncaught_exceptions() ){
11929 assert( m_captured == m_messages.size() );
11930 for(
size_t i = 0;
i < m_captured; ++
i )
11931 m_resultCapture.popScopedMessage( m_messages[
i] );
11937 m_messages[index].message +=
value;
11947 #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
11948 #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
11956 class RedirectedStream {
11957 std::ostream& m_originalStream;
11958 std::ostream& m_redirectionStream;
11959 std::streambuf* m_prevBuf;
11962 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
11963 ~RedirectedStream();
11966 class RedirectedStdOut {
11967 ReusableStringStream m_rss;
11968 RedirectedStream m_cout;
11970 RedirectedStdOut();
11977 class RedirectedStdErr {
11978 ReusableStringStream m_rss;
11979 RedirectedStream m_cerr;
11980 RedirectedStream m_clog;
11982 RedirectedStdErr();
11986 class RedirectedStreams {
11988 RedirectedStreams(RedirectedStreams
const&) =
delete;
11989 RedirectedStreams& operator=(RedirectedStreams
const&) =
delete;
11990 RedirectedStreams(RedirectedStreams&&) =
delete;
11991 RedirectedStreams& operator=(RedirectedStreams&&) =
delete;
11994 ~RedirectedStreams();
11998 RedirectedStdOut m_redirectedStdOut;
11999 RedirectedStdErr m_redirectedStdErr;
12002 #if defined(CATCH_CONFIG_NEW_CAPTURE)
12018 std::FILE* getFile();
12022 std::FILE* m_file =
nullptr;
12023 #if defined(_MSC_VER)
12024 char m_buffer[L_tmpnam] = { 0 };
12028 class OutputRedirect {
12030 OutputRedirect(OutputRedirect
const&) =
delete;
12031 OutputRedirect& operator=(OutputRedirect
const&) =
delete;
12032 OutputRedirect(OutputRedirect&&) =
delete;
12033 OutputRedirect& operator=(OutputRedirect&&) =
delete;
12039 int m_originalStdout = -1;
12040 int m_originalStderr = -1;
12057 #include <stdexcept>
12059 #if defined(CATCH_CONFIG_NEW_CAPTURE)
12060 #if defined(_MSC_VER)
12064 #define fileno _fileno
12066 #include <unistd.h>
12072 RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
12073 : m_originalStream( originalStream ),
12074 m_redirectionStream( redirectionStream ),
12075 m_prevBuf( m_originalStream.rdbuf() )
12077 m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
12080 RedirectedStream::~RedirectedStream() {
12081 m_originalStream.rdbuf( m_prevBuf );
12084 RedirectedStdOut::RedirectedStdOut() : m_cout(
Catch::
cout(), m_rss.
get() ) {}
12087 RedirectedStdErr::RedirectedStdErr()
12094 : m_redirectedCout(redirectedCout),
12095 m_redirectedCerr(redirectedCerr)
12098 RedirectedStreams::~RedirectedStreams() {
12099 m_redirectedCout += m_redirectedStdOut.
str();
12100 m_redirectedCerr += m_redirectedStdErr.
str();
12103 #if defined(CATCH_CONFIG_NEW_CAPTURE)
12105 #if defined(_MSC_VER)
12107 if (tmpnam_s(m_buffer)) {
12110 if (fopen_s(&m_file, m_buffer,
"w+")) {
12112 if (strerror_s(
buffer, errno)) {
12120 m_file = std::tmpfile();
12130 std::fclose(m_file);
12133 #if defined(_MSC_VER)
12138 FILE* TempFile::getFile() {
12143 std::stringstream sstr;
12145 std::rewind(m_file);
12153 m_originalStdout(dup(1)),
12154 m_originalStderr(dup(2)),
12155 m_stdoutDest(stdout_dest),
12156 m_stderrDest(stderr_dest) {
12157 dup2(fileno(m_stdoutFile.getFile()), 1);
12158 dup2(fileno(m_stderrFile.getFile()), 2);
12161 OutputRedirect::~OutputRedirect() {
12170 dup2(m_originalStdout, 1);
12171 dup2(m_originalStderr, 2);
12173 m_stdoutDest += m_stdoutFile.getContents();
12174 m_stderrDest += m_stderrFile.getContents();
12181 #if defined(CATCH_CONFIG_NEW_CAPTURE)
12182 #if defined(_MSC_VER)
12195 #if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
12196 bool isnan(
float f) {
12197 return std::isnan(
f);
12199 bool isnan(
double d) {
12200 return std::isnan(
d);
12204 bool isnan(
float f) {
12205 return std::_isnan(
f);
12207 bool isnan(
double d) {
12208 return std::_isnan(
d);
12220 #if defined(_MSC_VER)
12221 #pragma warning(push)
12222 #pragma warning(disable:4146)
12225 uint32_t rotate_right(uint32_t
val, uint32_t
count) {
12226 const uint32_t
mask = 31;
12231 #if defined(_MSC_VER)
12232 #pragma warning(pop)
12251 for (uint64_t
s = 0;
s < skip; ++
s) {
12252 static_cast<void>((*this)());
12258 const uint32_t xorshifted =
static_cast<uint32_t
>(((m_state >> 18u) ^ m_state) >> 27u);
12259 const auto output = rotate_right(xorshifted, m_state >> 59u);
12262 m_state = m_state * 6364136223846793005ULL + s_inc;
12267 bool operator==(SimplePcg32
const& lhs, SimplePcg32
const&
rhs) {
12268 return lhs.m_state ==
rhs.m_state;
12271 bool operator!=(SimplePcg32
const& lhs, SimplePcg32
const&
rhs) {
12272 return lhs.m_state !=
rhs.m_state;
12282 #include <algorithm>
12290 std::vector<TestCase> sortTests( IConfig
const&
config, std::vector<TestCase>
const& unsortedTestCases );
12293 bool matchTest( TestCase
const& testCase, TestSpec
const& testSpec, IConfig
const&
config );
12295 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions );
12297 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const&
config );
12300 class TestRegistry :
public ITestCaseRegistry {
12302 virtual ~TestRegistry() =
default;
12304 virtual void registerTest( TestCase
const& testCase );
12306 std::vector<TestCase>
const& getAllTests()
const override;
12307 std::vector<TestCase>
const& getAllTestsSorted( IConfig
const&
config )
const override;
12310 std::vector<TestCase> m_functions;
12312 mutable std::vector<TestCase> m_sortedFunctions;
12313 std::size_t m_unnamedCount = 0;
12314 std::ios_base::Init m_ostreamInit;
12319 class TestInvokerAsFunction :
public ITestInvoker {
12320 void(*m_testAsFunction)();
12322 TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept;
12327 std::
string extractClassName( StringRef
const& classOrQualifiedMethodName );
12340 class ReporterRegistry :
public IReporterRegistry {
12344 ~ReporterRegistry()
override;
12351 FactoryMap
const& getFactories()
const override;
12352 Listeners
const& getListeners()
const override;
12355 FactoryMap m_factories;
12356 Listeners m_listeners;
12370 TagAlias(
std::string const& _tag, SourceLineInfo _lineInfo);
12373 SourceLineInfo lineInfo;
12383 class TagAliasRegistry :
public ITagAliasRegistry {
12385 ~TagAliasRegistry()
override;
12391 std::map<std::string, TagAlias> m_registry;
12400 #include <exception>
12404 class StartupExceptionRegistry {
12405 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
12407 void add(std::exception_ptr
const& exception) noexcept;
12408 std::vector<std::exception_ptr>
const& getExceptions()
const noexcept;
12421 struct ISingleton {
12422 virtual ~ISingleton();
12425 void addSingleton( ISingleton* singleton );
12426 void cleanupSingletons();
12428 template<
typename SingletonImplT,
typename InterfaceT = SingletonImplT,
typename MutableInterfaceT = InterfaceT>
12429 class Singleton : SingletonImplT,
public ISingleton {
12431 static auto getInternal() -> Singleton* {
12441 static auto get() -> InterfaceT
const& {
12442 return *getInternal();
12444 static auto getMutable() -> MutableInterfaceT& {
12445 return *getInternal();
12456 class RegistryHub :
public IRegistryHub,
public IMutableRegistryHub,
12457 private NonCopyable {
12460 RegistryHub() =
default;
12461 IReporterRegistry
const& getReporterRegistry()
const override {
12462 return m_reporterRegistry;
12464 ITestCaseRegistry
const& getTestCaseRegistry()
const override {
12465 return m_testCaseRegistry;
12467 IExceptionTranslatorRegistry
const& getExceptionTranslatorRegistry()
const override {
12468 return m_exceptionTranslatorRegistry;
12470 ITagAliasRegistry
const& getTagAliasRegistry()
const override {
12471 return m_tagAliasRegistry;
12473 StartupExceptionRegistry
const& getStartupExceptionRegistry()
const override {
12474 return m_exceptionRegistry;
12479 m_reporterRegistry.registerReporter(
name,
factory );
12482 m_reporterRegistry.registerListener(
factory );
12484 void registerTest( TestCase
const& testInfo )
override {
12485 m_testCaseRegistry.registerTest( testInfo );
12487 void registerTranslator(
const IExceptionTranslator* translator )
override {
12488 m_exceptionTranslatorRegistry.registerTranslator( translator );
12491 m_tagAliasRegistry.add( alias,
tag, lineInfo );
12493 void registerStartupException() noexcept
override {
12494 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
12495 m_exceptionRegistry.add(std::current_exception());
12497 CATCH_INTERNAL_ERROR(
"Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
12500 IMutableEnumValuesRegistry& getMutableEnumValuesRegistry()
override {
12501 return m_enumValuesRegistry;
12505 TestRegistry m_testCaseRegistry;
12506 ReporterRegistry m_reporterRegistry;
12507 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
12508 TagAliasRegistry m_tagAliasRegistry;
12509 StartupExceptionRegistry m_exceptionRegistry;
12510 Detail::EnumValuesRegistry m_enumValuesRegistry;
12514 using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
12520 return RegistryHubSingleton::getMutable();
12523 cleanupSingletons();
12536 ReporterRegistry::~ReporterRegistry() =
default;
12539 auto it = m_factories.find(
name );
12540 if(
it == m_factories.end() )
12542 return it->second->create( ReporterConfig(
config ) );
12549 m_listeners.push_back(
factory );
12552 IReporterRegistry::FactoryMap
const& ReporterRegistry::getFactories()
const {
12553 return m_factories;
12555 IReporterRegistry::Listeners
const& ReporterRegistry::getListeners()
const {
12556 return m_listeners;
12584 #include <algorithm>
12589 namespace Generators {
12590 struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
12593 GeneratorTracker( TestCaseTracking::NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker*
parent )
12594 : TrackerBase( nameAndLocation, ctx,
parent )
12596 ~GeneratorTracker();
12598 static GeneratorTracker&
acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation
const& nameAndLocation ) {
12599 std::shared_ptr<GeneratorTracker> tracker;
12601 ITracker& currentTracker = ctx.currentTracker();
12613 if (currentTracker.nameAndLocation() == nameAndLocation) {
12614 auto thisTracker = currentTracker.parent().findChild(nameAndLocation);
12616 assert(thisTracker->isGeneratorTracker());
12617 tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker);
12618 }
else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
12620 assert( childTracker->isGeneratorTracker() );
12621 tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
12623 tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, ¤tTracker );
12624 currentTracker.addChild( tracker );
12627 if( !tracker->isComplete() ) {
12635 bool isGeneratorTracker()
const override {
return true; }
12636 auto hasGenerator()
const ->
bool override {
12637 return !!m_generator;
12639 void close()
override {
12640 TrackerBase::close();
12648 const bool should_wait_for_child = [&]() {
12650 if ( m_children.empty() ) {
12655 m_children.begin(),
12657 []( TestCaseTracking::ITrackerPtr tracker ) {
12658 return tracker->hasStarted();
12659 } ) != m_children.end() ) {
12666 auto*
parent = m_parent;
12669 while ( !
parent->isSectionTracker() ) {
12673 "Missing root (test case) level section" );
12675 auto const& parentSection =
12676 static_cast<SectionTracker&
>( *parent );
12677 auto const&
filters = parentSection.getFilters();
12683 for (
auto const&
child : m_children ) {
12684 if (
child->isSectionTracker() &&
12687 static_cast<SectionTracker&
>( *
child )
12688 .trimmedName() ) !=
12700 if ( should_wait_for_child ||
12701 ( m_runState == CompletedSuccessfully &&
12702 m_generator->next() ) ) {
12703 m_children.clear();
12704 m_runState = Executing;
12710 return m_generator;
12716 GeneratorTracker::~GeneratorTracker() {}
12719 RunContext::RunContext(
IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
12720 : m_runInfo(_config->
name()),
12723 m_reporter(
std::move(reporter)),
12724 m_lastAssertionInfo{ StringRef(), SourceLineInfo(
"",0), StringRef(), ResultDisposition::
Normal },
12725 m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
12727 m_context.setRunner(
this);
12728 m_context.setConfig(m_config);
12729 m_context.setResultCapture(
this);
12730 m_reporter->testRunStarting(m_runInfo);
12733 RunContext::~RunContext() {
12734 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
12737 void RunContext::testGroupStarting(
std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
12738 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
12741 void RunContext::testGroupEnded(
std::string const& testSpec, Totals
const& totals, std::size_t groupIndex, std::size_t groupsCount) {
12742 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
12746 Totals prevTotals = m_totals;
12751 auto const& testInfo = testCase.getTestCaseInfo();
12753 m_reporter->testCaseStarting(testInfo);
12755 m_activeTestCase = &testCase;
12757 ITracker& rootTracker = m_trackerContext.startRun();
12758 assert(rootTracker.isSectionTracker());
12759 static_cast<SectionTracker&
>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
12761 m_trackerContext.startCycle();
12762 m_testCaseTracker = &
SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
12763 runCurrentTest(redirectedCout, redirectedCerr);
12764 }
while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
12766 Totals deltaTotals = m_totals.delta(prevTotals);
12767 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
12768 deltaTotals.assertions.failed++;
12769 deltaTotals.testCases.passed--;
12770 deltaTotals.testCases.failed++;
12772 m_totals.testCases += deltaTotals.testCases;
12773 m_reporter->testCaseEnded(TestCaseStats(testInfo,
12779 m_activeTestCase =
nullptr;
12780 m_testCaseTracker =
nullptr;
12782 return deltaTotals;
12789 IStreamingReporter& RunContext::reporter()
const {
12790 return *m_reporter;
12793 void RunContext::assertionEnded(AssertionResult
const &
result) {
12795 m_totals.assertions.passed++;
12796 m_lastAssertionPassed =
true;
12797 }
else if (!
result.isOk()) {
12798 m_lastAssertionPassed =
false;
12799 if( m_activeTestCase->getTestCaseInfo().okToFail() )
12800 m_totals.assertions.failedButOk++;
12802 m_totals.assertions.failed++;
12805 m_lastAssertionPassed =
true;
12810 static_cast<void>(m_reporter->assertionEnded(AssertionStats(
result, m_messages, m_totals)));
12813 m_messageScopes.clear();
12816 resetAssertionInfo();
12819 void RunContext::resetAssertionInfo() {
12820 m_lastAssertionInfo.macroName = StringRef();
12821 m_lastAssertionInfo.capturedExpression =
"{Unknown expression after the reported line}"_sr;
12824 bool RunContext::sectionStarted(SectionInfo
const & sectionInfo, Counts & assertions) {
12825 ITracker& sectionTracker =
SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
12826 if (!sectionTracker.isOpen())
12828 m_activeSections.push_back(§ionTracker);
12830 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
12832 m_reporter->sectionStarting(sectionInfo);
12834 assertions = m_totals.assertions;
12839 using namespace Generators;
12841 TestCaseTracking::NameAndLocation(
static_cast<std::string>(generatorName), lineInfo ) );
12842 m_lastAssertionInfo.lineInfo = lineInfo;
12846 bool RunContext::testForMissingAssertions(Counts& assertions) {
12847 if (assertions.total() != 0)
12849 if (!m_config->warnAboutMissingAssertions())
12851 if (m_trackerContext.currentTracker().hasChildren())
12853 m_totals.assertions.failed++;
12854 assertions.failed++;
12858 void RunContext::sectionEnded(SectionEndInfo
const & endInfo) {
12859 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
12860 bool missingAssertions = testForMissingAssertions(assertions);
12862 if (!m_activeSections.empty()) {
12863 m_activeSections.back()->close();
12864 m_activeSections.pop_back();
12867 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
12868 m_messages.clear();
12869 m_messageScopes.clear();
12872 void RunContext::sectionEndedEarly(SectionEndInfo
const & endInfo) {
12873 if (m_unfinishedSections.empty())
12874 m_activeSections.back()->fail();
12876 m_activeSections.back()->close();
12877 m_activeSections.pop_back();
12879 m_unfinishedSections.push_back(endInfo);
12882 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
12884 m_reporter->benchmarkPreparing(
name);
12886 void RunContext::benchmarkStarting( BenchmarkInfo
const&
info ) {
12887 m_reporter->benchmarkStarting(
info );
12889 void RunContext::benchmarkEnded( BenchmarkStats<>
const& stats ) {
12890 m_reporter->benchmarkEnded( stats );
12893 m_reporter->benchmarkFailed(
error);
12897 void RunContext::pushScopedMessage(MessageInfo
const &
message) {
12898 m_messages.push_back(
message);
12901 void RunContext::popScopedMessage(MessageInfo
const &
message) {
12902 m_messages.erase(
std::remove(m_messages.begin(), m_messages.end(),
message), m_messages.end());
12905 void RunContext::emplaceUnscopedMessage( MessageBuilder
const& builder ) {
12906 m_messageScopes.emplace_back( builder );
12909 std::string RunContext::getCurrentTestName()
const {
12910 return m_activeTestCase
12911 ? m_activeTestCase->getTestCaseInfo().name
12915 const AssertionResult * RunContext::getLastResult()
const {
12916 return &(*m_lastResult);
12919 void RunContext::exceptionEarlyReported() {
12920 m_shouldReportUnexpected =
false;
12923 void RunContext::handleFatalErrorCondition( StringRef
message ) {
12925 m_reporter->fatalErrorEncountered(
message);
12931 AssertionResult
result(m_lastAssertionInfo, tempResult);
12935 handleUnfinishedSections();
12938 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
12939 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
12942 assertions.failed = 1;
12943 SectionStats testCaseSectionStats(testCaseSection, assertions, 0,
false);
12944 m_reporter->sectionEnded(testCaseSectionStats);
12946 auto const& testInfo = m_activeTestCase->getTestCaseInfo();
12948 Totals deltaTotals;
12949 deltaTotals.testCases.failed = 1;
12950 deltaTotals.assertions.failed = 1;
12951 m_reporter->testCaseEnded(TestCaseStats(testInfo,
12956 m_totals.testCases.failed++;
12958 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals,
false));
12961 bool RunContext::lastAssertionPassed() {
12962 return m_lastAssertionPassed;
12965 void RunContext::assertionPassed() {
12966 m_lastAssertionPassed =
true;
12967 ++m_totals.assertions.passed;
12968 resetAssertionInfo();
12969 m_messageScopes.clear();
12972 bool RunContext::aborting()
const {
12973 return m_totals.assertions.failed >=
static_cast<std::size_t
>(m_config->abortAfter());
12977 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
12978 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
12979 m_reporter->sectionStarting(testCaseSection);
12980 Counts prevAssertions = m_totals.assertions;
12981 double duration = 0;
12982 m_shouldReportUnexpected =
true;
12985 seedRng(*m_config);
12989 if (m_reporter->getPreferences().shouldRedirectStdOut) {
12990 #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
12991 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
12994 invokeActiveTestCase();
12996 OutputRedirect
r(redirectedCout, redirectedCerr);
12998 invokeActiveTestCase();
13002 invokeActiveTestCase();
13004 duration =
timer.getElapsedSeconds();
13010 if( m_shouldReportUnexpected ) {
13011 AssertionReaction dummyReaction;
13015 Counts assertions = m_totals.assertions - prevAssertions;
13016 bool missingAssertions = testForMissingAssertions(assertions);
13018 m_testCaseTracker->close();
13019 handleUnfinishedSections();
13020 m_messages.clear();
13021 m_messageScopes.clear();
13023 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
13024 m_reporter->sectionEnded(testCaseSectionStats);
13027 void RunContext::invokeActiveTestCase() {
13028 FatalConditionHandlerGuard
_(&m_fatalConditionhandler);
13029 m_activeTestCase->invoke();
13032 void RunContext::handleUnfinishedSections() {
13035 for (
auto it = m_unfinishedSections.rbegin(),
13036 itEnd = m_unfinishedSections.rend();
13040 m_unfinishedSections.clear();
13043 void RunContext::handleExpr(
13044 AssertionInfo
const&
info,
13045 ITransientExpression
const& expr,
13046 AssertionReaction& reaction
13048 m_reporter->assertionStarting(
info );
13051 bool result = expr.getResult() != negated;
13054 if (!m_includeSuccessfulResults) {
13063 populateReaction( reaction );
13066 void RunContext::reportExpr(
13067 AssertionInfo
const &
info,
13069 ITransientExpression
const *expr,
13072 m_lastAssertionInfo =
info;
13073 AssertionResultData
data( resultType, LazyExpression( negated ) );
13075 AssertionResult assertionResult{
info,
data };
13076 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
13078 assertionEnded( assertionResult );
13081 void RunContext::handleMessage(
13082 AssertionInfo
const&
info,
13085 AssertionReaction& reaction
13087 m_reporter->assertionStarting(
info );
13089 m_lastAssertionInfo =
info;
13091 AssertionResultData
data( resultType, LazyExpression(
false ) );
13093 AssertionResult assertionResult{ m_lastAssertionInfo,
data };
13094 assertionEnded( assertionResult );
13095 if( !assertionResult.isOk() )
13096 populateReaction( reaction );
13098 void RunContext::handleUnexpectedExceptionNotThrown(
13099 AssertionInfo
const&
info,
13100 AssertionReaction& reaction
13105 void RunContext::handleUnexpectedInflightException(
13106 AssertionInfo
const&
info,
13108 AssertionReaction& reaction
13110 m_lastAssertionInfo =
info;
13114 AssertionResult assertionResult{
info,
data };
13115 assertionEnded( assertionResult );
13116 populateReaction( reaction );
13119 void RunContext::populateReaction( AssertionReaction& reaction ) {
13120 reaction.shouldDebugBreak = m_config->shouldDebugBreak();
13124 void RunContext::handleIncomplete(
13125 AssertionInfo
const&
info
13127 m_lastAssertionInfo =
info;
13130 data.message =
"Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
13131 AssertionResult assertionResult{
info,
data };
13132 assertionEnded( assertionResult );
13134 void RunContext::handleNonExpr(
13135 AssertionInfo
const &
info,
13137 AssertionReaction &reaction
13139 m_lastAssertionInfo =
info;
13141 AssertionResultData
data( resultType, LazyExpression(
false ) );
13142 AssertionResult assertionResult{
info,
data };
13143 assertionEnded( assertionResult );
13145 if( !assertionResult.isOk() )
13146 populateReaction( reaction );
13156 void seedRng(IConfig
const&
config) {
13157 if (
config.rngSeed() != 0) {
13158 std::srand(
config.rngSeed());
13175 m_sectionIncluded(
getResultCapture().sectionStarted( m_info, m_assertions ) )
13181 if( m_sectionIncluded ) {
13183 if( uncaught_exceptions() )
13191 Section::operator bool()
const {
13192 return m_sectionIncluded;
13202 ( SourceLineInfo
const& _lineInfo,
13205 lineInfo( _lineInfo )
13218 class Session : NonCopyable {
13222 ~Session()
override;
13224 void showHelp()
const;
13225 void libIdentify();
13227 int applyCommandLine(
int argc,
char const *
const * argv );
13228 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
13229 int applyCommandLine(
int argc,
wchar_t const *
const * argv );
13232 void useConfigData( ConfigData
const& configData );
13234 template<
typename CharT>
13235 int run(
int argc, CharT
const *
const argv[]) {
13236 if (m_startupExceptions)
13238 int returnCode = applyCommandLine(argc, argv);
13239 if (returnCode == 0)
13240 returnCode =
run();
13246 clara::Parser
const& cli()
const;
13247 void cli( clara::Parser
const& newParser );
13248 ConfigData& configData();
13253 clara::Parser m_cli;
13254 ConfigData m_configData;
13255 std::shared_ptr<Config> m_config;
13256 bool m_startupExceptions =
false;
13272 Version(
unsigned int _majorVersion,
13273 unsigned int _minorVersion,
13274 unsigned int _patchNumber,
13275 char const *
const _branchName,
13276 unsigned int _buildNumber );
13278 unsigned int const majorVersion;
13279 unsigned int const minorVersion;
13280 unsigned int const patchNumber;
13283 char const *
const branchName;
13284 unsigned int const buildNumber;
13289 Version const& libraryVersion();
13296 #include <iterator>
13301 const int MaxExitCode = 255;
13305 CATCH_ENFORCE(reporter,
"No reporter registered with name: '" << reporterName <<
"'");
13310 IStreamingReporterPtr makeReporter(std::shared_ptr<Config>
const&
config) {
13312 return createReporter(
config->getReporterName(),
config);
13320 auto ret = std::unique_ptr<IStreamingReporter>(
new ListeningReporter);
13321 auto& multi =
static_cast<ListeningReporter&
>(*ret);
13323 for (
auto const& listener : listeners) {
13324 multi.addListener(listener->create(Catch::ReporterConfig(
config)));
13326 multi.addReporter(createReporter(
config->getReporterName(),
config));
13337 m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
13338 auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
13340 if (m_matches.empty() && invalidArgs.empty()) {
13341 for (
auto const& test : allTestCases)
13342 if (!
test.isHidden())
13343 m_tests.emplace(&test);
13345 for (
auto const& match : m_matches)
13346 m_tests.insert(match.tests.begin(), match.tests.end());
13351 auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
13353 m_context.testGroupStarting(m_config->name(), 1, 1);
13354 for (
auto const& testCase : m_tests) {
13355 if (!m_context.aborting())
13356 totals += m_context.
runTest(*testCase);
13358 m_context.reporter().skipTest(*testCase);
13361 for (
auto const& match : m_matches) {
13362 if (match.tests.empty()) {
13363 m_context.reporter().noMatchingTestCases(match.name);
13368 if (!invalidArgs.empty()) {
13369 for (
auto const& invalidArg: invalidArgs)
13370 m_context.reporter().reportInvalidArguments(invalidArg);
13373 m_context.testGroupEnded(m_config->name(), totals, 1, 1);
13378 using Tests = std::set<TestCase const*>;
13380 std::shared_ptr<Config> m_config;
13381 RunContext m_context;
13388 for (
auto& testCase :
tests) {
13389 auto tags = testCase.tags;
13392 auto lastSlash =
filename.find_last_of(
"\\/");
13393 if (lastSlash != std::string::npos) {
13398 auto lastDot =
filename.find_last_of(
'.');
13399 if (lastDot != std::string::npos) {
13403 tags.push_back(std::move(
filename));
13404 setTags(testCase, tags);
13410 Session::Session() {
13411 static bool alreadyInstantiated =
false;
13412 if( alreadyInstantiated ) {
13418 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
13420 if ( !exceptions.empty() ) {
13424 m_startupExceptions =
true;
13426 Catch::cerr() <<
"Errors occurred during startup!" <<
'\n';
13428 for (
const auto& ex_ptr : exceptions ) {
13430 std::rethrow_exception(ex_ptr);
13431 }
catch ( std::exception
const& ex ) {
13438 alreadyInstantiated =
true;
13439 m_cli = makeCommandLineParser( m_configData );
13441 Session::~Session() {
13445 void Session::showHelp()
const {
13447 <<
"\nCatch v" << libraryVersion() <<
"\n"
13449 <<
"For more detailed usage please see the project docs\n" <<
std::endl;
13451 void Session::libIdentify() {
13453 <<
std::left << std::setw(16) <<
"description: " <<
"A Catch2 test executable\n"
13454 <<
std::left << std::setw(16) <<
"category: " <<
"testframework\n"
13455 <<
std::left << std::setw(16) <<
"framework: " <<
"Catch Test\n"
13459 int Session::applyCommandLine(
int argc,
char const *
const * argv ) {
13460 if( m_startupExceptions )
13463 auto result = m_cli.parse( clara::Args( argc, argv ) );
13469 <<
"\nError(s) in input:\n"
13473 return MaxExitCode;
13476 if( m_configData.showHelp )
13478 if( m_configData.libIdentify )
13484 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
13485 int Session::applyCommandLine(
int argc,
wchar_t const *
const * argv ) {
13487 char **utf8Argv =
new char *[ argc ];
13489 for (
int i = 0;
i < argc; ++
i ) {
13490 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[
i], -1,
nullptr, 0,
nullptr,
nullptr );
13492 utf8Argv[ i ] =
new char[ bufSize ];
13494 WideCharToMultiByte( CP_UTF8, 0, argv[
i], -1, utf8Argv[
i],
bufSize,
nullptr,
nullptr );
13497 int returnCode = applyCommandLine( argc, utf8Argv );
13499 for (
int i = 0;
i < argc; ++
i )
13500 delete [] utf8Argv[
i ];
13502 delete [] utf8Argv;
13508 void Session::useConfigData( ConfigData
const& configData ) {
13509 m_configData = configData;
13514 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
13516 static_cast<void>(std::getchar());
13518 int exitCode = runInternal();
13519 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
13520 Catch::cout() <<
"...waiting for enter/ return before exiting, with code: " << exitCode <<
std::endl;
13521 static_cast<void>(std::getchar());
13526 clara::Parser
const& Session::cli()
const {
13529 void Session::cli( clara::Parser
const& newParser ) {
13532 ConfigData& Session::configData() {
13533 return m_configData;
13537 m_config = std::make_shared<Config>( m_configData );
13541 int Session::runInternal() {
13542 if( m_startupExceptions )
13545 if (m_configData.showHelp || m_configData.libIdentify) {
13552 seedRng( *m_config );
13554 if( m_configData.filenamesAsTags )
13555 applyFilenamesAsTags( *m_config );
13559 return static_cast<int>( *listed );
13562 auto const totals =
tests.execute();
13564 if( m_config->warnAboutNoTests() && totals.error == -1 )
13570 return (std::min) (MaxExitCode, (std::max) (totals.error,
static_cast<int>(totals.assertions.failed)));
13572 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
13573 catch( std::exception& ex ) {
13575 return MaxExitCode;
13589 static auto getSingletons() -> std::vector<ISingleton*>*& {
13590 static std::vector<ISingleton*>* g_singletons =
nullptr;
13591 if( !g_singletons )
13592 g_singletons =
new std::vector<ISingleton*>();
13593 return g_singletons;
13597 ISingleton::~ISingleton() {}
13599 void addSingleton(ISingleton* singleton ) {
13600 getSingletons()->push_back( singleton );
13602 void cleanupSingletons() {
13603 auto& singletons = getSingletons();
13604 for(
auto singleton : *singletons )
13607 singletons =
nullptr;
13614 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
13618 m_exceptions.push_back(exception);
13625 std::vector<std::exception_ptr>
const& StartupExceptionRegistry::getExceptions()
const noexcept {
13626 return m_exceptions;
13635 #include <iostream>
13645 namespace Detail {
namespace {
13646 template<
typename WriterF, std::
size_t bufferSize=256>
13647 class StreamBufImpl :
public std::streambuf {
13648 char data[bufferSize];
13656 ~StreamBufImpl() noexcept {
13657 StreamBufImpl::sync();
13661 int overflow(
int c )
override {
13665 if( pbase() == epptr() )
13668 sputc(
static_cast<char>(
c ) );
13673 int sync()
override {
13674 if( pbase() != pptr() ) {
13675 m_writer(
std::string( pbase(),
static_cast<std::string::size_type
>( pptr() - pbase() ) ) );
13676 setp( pbase(), epptr() );
13684 struct OutputDebugWriter {
13687 writeToDebugConsole(
str );
13693 class FileStream :
public IStream {
13694 mutable std::ofstream m_ofs;
13696 FileStream( StringRef
filename ) {
13700 ~FileStream()
override =
default;
13702 std::ostream&
stream()
const override {
13709 class CoutStream :
public IStream {
13710 mutable std::ostream m_os;
13714 CoutStream() : m_os(
Catch::
cout().rdbuf() ) {}
13715 ~CoutStream()
override =
default;
13718 std::ostream&
stream()
const override {
return m_os; }
13723 class DebugOutStream :
public IStream {
13724 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
13725 mutable std::ostream m_os;
13728 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
13729 m_os( m_streamBuf.
get() )
13732 ~DebugOutStream()
override =
default;
13735 std::ostream&
stream()
const override {
return m_os; }
13744 return new Detail::CoutStream();
13747 return new Detail::DebugOutStream();
13752 return new Detail::FileStream(
filename );
13756 struct StringStreams {
13757 std::vector<std::unique_ptr<std::ostringstream>> m_streams;
13758 std::vector<std::size_t> m_unused;
13759 std::ostringstream m_referenceStream;
13761 auto add() -> std::size_t {
13762 if( m_unused.empty() ) {
13763 m_streams.push_back( std::unique_ptr<std::ostringstream>(
new std::ostringstream ) );
13764 return m_streams.size()-1;
13767 auto index = m_unused.back();
13768 m_unused.pop_back();
13774 m_streams[index]->copyfmt( m_referenceStream );
13775 m_unused.push_back(
index);
13780 : m_index( Singleton<StringStreams>::getMutable().
add() ),
13781 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].
get() )
13785 static_cast<std::ostringstream*
>( m_oss )->
str(
"");
13787 Singleton<StringStreams>::getMutable().release( m_index );
13791 return static_cast<std::ostringstream*
>( m_oss )->
str();
13796 #ifndef CATCH_CONFIG_NOSTDOUT
13805 #include <algorithm>
13814 char toLowerCh(
char c) {
13815 return static_cast<char>( std::tolower(
static_cast<unsigned char>(
c) ) );
13820 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(),
s.begin());
13823 return !
s.empty() &&
s[0] == prefix;
13826 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(),
s.rbegin());
13829 return !
s.empty() &&
s[s.size()-1] == suffix;
13832 return s.find( infix ) != std::string::npos;
13843 static char const* whitespaceChars =
"\n\r\t ";
13844 std::string::size_type
start =
str.find_first_not_of( whitespaceChars );
13845 std::string::size_type
end =
str.find_last_not_of( whitespaceChars );
13850 StringRef
trim(StringRef
ref) {
13851 const auto is_ws = [](
char c) {
13852 return c ==
' ' ||
c ==
'\t' ||
c ==
'\n' ||
c ==
'\r';
13854 size_t real_begin = 0;
13855 while (real_begin <
ref.size() && is_ws(
ref[real_begin])) { ++real_begin; }
13856 size_t real_end =
ref.size();
13857 while (real_end > real_begin && is_ws(
ref[real_end - 1])) { --real_end; }
13859 return ref.substr(real_begin, real_end - real_begin);
13863 bool replaced =
false;
13864 std::size_t
i =
str.find( replaceThis );
13865 while(
i != std::string::npos ) {
13867 str =
str.substr( 0,
i ) + withThis +
str.substr(
i+replaceThis.
size() );
13868 if(
i <
str.
size()-withThis.size() )
13869 i =
str.find( replaceThis,
i+withThis.size() );
13871 i = std::string::npos;
13877 std::vector<StringRef> subStrings;
13878 std::size_t
start = 0;
13880 if(
str[
pos] == delimiter ) {
13892 : m_count(
count ),
13896 std::ostream&
operator << ( std::ostream& os, pluralise
const& pluraliser ) {
13897 os << pluraliser.m_count <<
' ' << pluraliser.m_label;
13898 if( pluraliser.m_count != 1 )
13907 #include <algorithm>
13926 if (
start < m_size) {
13927 return StringRef(m_start +
start, (std::min)(m_size -
start,
size));
13929 return StringRef();
13933 return m_size ==
other.m_size
13934 && (std::memcmp( m_start,
other.m_start, m_size ) == 0);
13937 auto operator << ( std::ostream& os, StringRef
const&
str ) -> std::ostream& {
13942 lhs.append(
rhs.data(),
rhs.size());
13951 TagAlias::TagAlias(
std::string const & _tag, SourceLineInfo _lineInfo):
tag(_tag), lineInfo(_lineInfo) {}
13975 TagAliasRegistry::~TagAliasRegistry() {}
13978 auto it = m_registry.find( alias );
13979 if(
it != m_registry.end() )
13980 return &(
it->second);
13986 std::string expandedTestSpec = unexpandedTestSpec;
13987 for(
auto const& registryKvp : m_registry ) {
13988 std::size_t
pos = expandedTestSpec.find( registryKvp.first );
13989 if(
pos != std::string::npos ) {
13990 expandedTestSpec = expandedTestSpec.substr( 0,
pos ) +
13991 registryKvp.second.
tag +
13992 expandedTestSpec.substr(
pos + registryKvp.
first.
size() );
13995 return expandedTestSpec;
14000 "error: tag alias, '" << alias <<
"' is not of the form [@alias name].\n" << lineInfo );
14002 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(
tag, lineInfo))).second,
14003 "error: tag alias, '" << alias <<
"' already registered.\n"
14004 <<
"\tFirst seen at: " <<
find(alias)->lineInfo <<
"\n"
14005 <<
"\tRedefined at: " << lineInfo );
14008 ITagAliasRegistry::~ITagAliasRegistry() {}
14019 #include <exception>
14020 #include <algorithm>
14030 else if(
tag ==
"!throws" )
14032 else if(
tag ==
"!shouldfail" )
14034 else if(
tag ==
"!mayfail" )
14036 else if(
tag ==
"!nonportable" )
14038 else if(
tag ==
"!benchmark" )
14046 void enforceNotReservedTag(
std::string const&
tag, SourceLineInfo
const& _lineInfo ) {
14048 "Tag name: [" <<
tag <<
"] is not allowed.\n"
14049 <<
"Tag names starting with non alphanumeric characters are reserved\n"
14056 NameAndTags
const& nameAndTags,
14057 SourceLineInfo
const& _lineInfo )
14059 bool isHidden =
false;
14062 std::vector<std::string> tags;
14064 bool inTag =
false;
14065 for (
char c : nameAndTags.tags) {
14078 enforceNotReservedTag(
tag, _lineInfo );
14086 tags.push_back(
tag );
14096 tags.insert( tags.end(), {
".",
"!hide" } );
14099 TestCaseInfo
info(
static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo );
14100 return TestCase( _testCase, std::move(
info) );
14103 void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
14104 std::sort(
begin(tags),
end(tags));
14105 tags.erase(std::unique(
begin(tags),
end(tags)),
end(tags));
14106 testCaseInfo.lcaseTags.clear();
14108 for(
auto const&
tag : tags ) {
14111 testCaseInfo.lcaseTags.push_back( lcaseTag );
14113 testCaseInfo.tags = std::move(tags);
14119 std::vector<std::string>
const& _tags,
14120 SourceLineInfo
const& _lineInfo )
14123 description( _description ),
14124 lineInfo( _lineInfo ),
14127 setTags( *
this, _tags );
14146 std::size_t full_size = 2 *
tags.size();
14147 for (
const auto&
tag :
tags) {
14150 ret.reserve(full_size);
14151 for (
const auto&
tag :
tags) {
14152 ret.push_back(
'[');
14154 ret.push_back(
']');
14164 other.name = _newName;
14173 return test.get() ==
other.test.get() &&
14191 #include <algorithm>
14197 struct TestHasher {
14198 using hash_t = uint64_t;
14200 explicit TestHasher( hash_t hashSuffix ):
14201 m_hashSuffix{ hashSuffix } {}
14205 const hash_t prime = 1099511628211u;
14206 hash_t
hash = 14695981039346656037u;
14207 for (
const char c :
t.name ) {
14211 hash ^= m_hashSuffix;
14213 const uint32_t low{
static_cast<uint32_t
>(
hash ) };
14214 const uint32_t high{
static_cast<uint32_t
>(
hash >> 32 ) };
14219 hash_t m_hashSuffix;
14223 std::vector<TestCase> sortTests( IConfig
const&
config, std::vector<TestCase>
const& unsortedTestCases ) {
14224 switch(
config.runOrder() ) {
14230 std::vector<TestCase>
sorted = unsortedTestCases;
14237 TestHasher
h{
config.rngSeed() };
14239 using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>;
14240 std::vector<hashedTest> indexed_tests;
14241 indexed_tests.reserve( unsortedTestCases.size() );
14243 for (
auto const& testCase : unsortedTestCases) {
14244 indexed_tests.emplace_back(
h(testCase), &testCase);
14247 std::sort(indexed_tests.begin(), indexed_tests.end(),
14248 [](hashedTest
const& lhs, hashedTest
const&
rhs) {
14249 if (lhs.first == rhs.first) {
14250 return lhs.second->name < rhs.second->name;
14252 return lhs.first <
rhs.first;
14255 std::vector<TestCase>
sorted;
14256 sorted.reserve( indexed_tests.size() );
14258 for (
auto const& hashed : indexed_tests) {
14259 sorted.emplace_back(*hashed.second);
14265 return unsortedTestCases;
14269 return !testCase.throws() ||
config.allowThrows();
14272 bool matchTest( TestCase
const& testCase, TestSpec
const& testSpec, IConfig
const&
config ) {
14276 void enforceNoDuplicateTestCases( std::vector<TestCase>
const& functions ) {
14277 std::set<TestCase> seenFunctions;
14278 for(
auto const&
function : functions ) {
14279 auto prev = seenFunctions.insert(
function );
14281 "error: TEST_CASE( \"" <<
function.name <<
"\" ) already defined.\n"
14282 <<
"\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo <<
"\n"
14283 <<
"\tRedefined at " <<
function.getTestCaseInfo().lineInfo );
14287 std::vector<TestCase>
filterTests( std::vector<TestCase>
const& testCases, TestSpec
const& testSpec, IConfig
const&
config ) {
14289 filtered.reserve( testCases.size() );
14290 for (
auto const& testCase : testCases) {
14291 if ((!testSpec.hasFilters() && !testCase.isHidden()) ||
14302 void TestRegistry::registerTest( TestCase
const& testCase ) {
14304 if(
name.empty() ) {
14305 ReusableStringStream rss;
14306 rss <<
"Anonymous test case " << ++m_unnamedCount;
14307 return registerTest( testCase.withName( rss.str() ) );
14309 m_functions.push_back( testCase );
14312 std::vector<TestCase>
const& TestRegistry::getAllTests()
const {
14313 return m_functions;
14315 std::vector<TestCase>
const& TestRegistry::getAllTestsSorted( IConfig
const&
config )
const {
14316 if( m_sortedFunctions.empty() )
14317 enforceNoDuplicateTestCases( m_functions );
14319 if( m_currentSortOrder !=
config.runOrder() || m_sortedFunctions.empty() ) {
14320 m_sortedFunctions = sortTests(
config, m_functions );
14321 m_currentSortOrder =
config.runOrder();
14323 return m_sortedFunctions;
14327 TestInvokerAsFunction::TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
14329 void TestInvokerAsFunction::invoke()
const {
14330 m_testAsFunction();
14333 std::string extractClassName( StringRef
const& classOrQualifiedMethodName ) {
14337 std::size_t lastColons =
className.rfind(
"::" );
14338 std::size_t penultimateColons =
className.rfind(
"::", lastColons-1 );
14339 if( penultimateColons == std::string::npos )
14340 penultimateColons = 1;
14350 #include <algorithm>
14352 #include <stdexcept>
14356 #if defined(__clang__)
14357 # pragma clang diagnostic push
14358 # pragma clang diagnostic ignored "-Wexit-time-destructors"
14362 namespace TestCaseTracking {
14364 NameAndLocation::NameAndLocation(
std::string const& _name, SourceLineInfo
const& _location )
14369 ITracker::~ITracker() =
default;
14371 ITracker& TrackerContext::startRun() {
14372 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation(
"{root}",
CATCH_INTERNAL_LINEINFO ), *
this,
nullptr );
14373 m_currentTracker =
nullptr;
14374 m_runState = Executing;
14375 return *m_rootTracker;
14378 void TrackerContext::endRun() {
14379 m_rootTracker.reset();
14380 m_currentTracker =
nullptr;
14381 m_runState = NotStarted;
14384 void TrackerContext::startCycle() {
14385 m_currentTracker = m_rootTracker.get();
14386 m_runState = Executing;
14388 void TrackerContext::completeCycle() {
14389 m_runState = CompletedCycle;
14392 bool TrackerContext::completedCycle()
const {
14393 return m_runState == CompletedCycle;
14395 ITracker& TrackerContext::currentTracker() {
14396 return *m_currentTracker;
14398 void TrackerContext::setCurrentTracker( ITracker* tracker ) {
14399 m_currentTracker = tracker;
14402 TrackerBase::TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker*
parent ):
14403 ITracker(nameAndLocation),
14408 bool TrackerBase::isComplete()
const {
14409 return m_runState == CompletedSuccessfully || m_runState == Failed;
14411 bool TrackerBase::isSuccessfullyCompleted()
const {
14412 return m_runState == CompletedSuccessfully;
14415 return m_runState != NotStarted && !isComplete();
14417 bool TrackerBase::hasChildren()
const {
14418 return !m_children.empty();
14421 void TrackerBase::addChild( ITrackerPtr
const&
child ) {
14422 m_children.push_back(
child );
14425 ITrackerPtr TrackerBase::findChild( NameAndLocation
const& nameAndLocation ) {
14426 auto it = std::find_if( m_children.begin(), m_children.end(),
14427 [&nameAndLocation]( ITrackerPtr
const& tracker ){
14429 tracker->nameAndLocation().location == nameAndLocation.location &&
14430 tracker->nameAndLocation().name == nameAndLocation.name;
14432 return(
it != m_children.end() )
14441 void TrackerBase::openChild() {
14442 if( m_runState != ExecutingChildren ) {
14443 m_runState = ExecutingChildren;
14445 m_parent->openChild();
14449 bool TrackerBase::isSectionTracker()
const {
return false; }
14450 bool TrackerBase::isGeneratorTracker()
const {
return false; }
14453 m_runState = Executing;
14456 m_parent->openChild();
14459 void TrackerBase::close() {
14462 while( &m_ctx.currentTracker() !=
this )
14463 m_ctx.currentTracker().close();
14465 switch( m_runState ) {
14466 case NeedsAnotherRun:
14470 m_runState = CompletedSuccessfully;
14472 case ExecutingChildren:
14473 if(
std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr
const&
t){ return t->isComplete(); }) )
14474 m_runState = CompletedSuccessfully;
14478 case CompletedSuccessfully:
14486 m_ctx.completeCycle();
14488 void TrackerBase::fail() {
14489 m_runState = Failed;
14491 m_parent->markAsNeedingAnotherRun();
14493 m_ctx.completeCycle();
14495 void TrackerBase::markAsNeedingAnotherRun() {
14496 m_runState = NeedsAnotherRun;
14499 void TrackerBase::moveToParent() {
14501 m_ctx.setCurrentTracker( m_parent );
14503 void TrackerBase::moveToThis() {
14504 m_ctx.setCurrentTracker(
this );
14507 SectionTracker::SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker*
parent )
14508 : TrackerBase( nameAndLocation, ctx,
parent ),
14509 m_trimmed_name(
trim(nameAndLocation.
name))
14512 while( !
parent->isSectionTracker() )
14515 SectionTracker& parentSection =
static_cast<SectionTracker&
>( *parent );
14516 addNextFilters( parentSection.m_filters );
14520 bool SectionTracker::isComplete()
const {
14521 bool complete =
true;
14523 if (m_filters.empty()
14524 || m_filters[0] ==
""
14525 ||
std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
14526 complete = TrackerBase::isComplete();
14531 bool SectionTracker::isSectionTracker()
const {
return true; }
14534 std::shared_ptr<SectionTracker> section;
14536 ITracker& currentTracker = ctx.currentTracker();
14537 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
14539 assert( childTracker->isSectionTracker() );
14540 section = std::static_pointer_cast<SectionTracker>( childTracker );
14543 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, ¤tTracker );
14544 currentTracker.addChild( section );
14546 if( !ctx.completedCycle() )
14547 section->tryOpen();
14551 void SectionTracker::tryOpen() {
14552 if( !isComplete() )
14556 void SectionTracker::addInitialFilters( std::vector<std::string>
const&
filters ) {
14558 m_filters.reserve( m_filters.size() +
filters.size() + 2 );
14559 m_filters.emplace_back(
"");
14560 m_filters.emplace_back(
"");
14561 m_filters.insert( m_filters.end(),
filters.begin(),
filters.end() );
14564 void SectionTracker::addNextFilters( std::vector<std::string>
const&
filters ) {
14566 m_filters.insert( m_filters.end(),
filters.begin()+1,
filters.end() );
14569 std::vector<std::string>
const& SectionTracker::getFilters()
const {
14573 std::string const& SectionTracker::trimmedName()
const {
14574 return m_trimmed_name;
14579 using TestCaseTracking::ITracker;
14580 using TestCaseTracking::TrackerContext;
14581 using TestCaseTracking::SectionTracker;
14585 #if defined(__clang__)
14586 # pragma clang diagnostic pop
14593 auto makeTestInvoker(
void(*testAsFunction)() ) noexcept -> ITestInvoker* {
14594 return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
14599 AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo
const& lineInfo, StringRef
const& classOrMethod, NameAndTags
const& nameAndTags ) noexcept {
14605 extractClassName( classOrMethod ),
14619 #include <algorithm>
14630 TestSpec::Pattern::~Pattern() =
default;
14637 : Pattern( filterString )
14641 bool TestSpec::NamePattern::matches( TestCaseInfo
const& testCase )
const {
14642 return m_wildcardPattern.matches( testCase.name );
14646 : Pattern( filterString )
14650 bool TestSpec::TagPattern::matches( TestCaseInfo
const& testCase )
const {
14652 end(testCase.lcaseTags),
14653 m_tag) !=
end(testCase.lcaseTags);
14656 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr
const& underlyingPattern )
14657 : Pattern( underlyingPattern->
name() )
14658 , m_underlyingPattern( underlyingPattern )
14661 bool TestSpec::ExcludedPattern::matches( TestCaseInfo
const& testCase )
const {
14662 return !m_underlyingPattern->matches( testCase );
14665 bool TestSpec::Filter::matches( TestCaseInfo
const& testCase )
const {
14666 return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr
const&
p ){ return p->matches( testCase ); } );
14671 for(
auto const&
p : m_patterns )
14676 bool TestSpec::hasFilters()
const {
14677 return !m_filters.empty();
14680 bool TestSpec::matches( TestCaseInfo
const& testCase )
const {
14681 return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter
const&
f ){ return f.matches( testCase ); } );
14684 TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase>
const& testCases, IConfig
const&
config )
const
14686 Matches matches( m_filters.size() );
14687 std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter
const&
filter ){
14688 std::vector<TestCase const*> currentMatches;
14689 for( auto const& test : testCases )
14690 if( isThrowSafe( test, config ) && filter.matches( test ) )
14691 currentMatches.emplace_back( &test );
14692 return FilterMatch{ filter.name(), currentMatches };
14697 const TestSpec::vectorStrings& TestSpec::getInvalidArgs()
const{
14698 return (m_invalidArgs);
14707 TestSpecParser::TestSpecParser( ITagAliasRegistry
const& tagAliases ) : m_tagAliases( &tagAliases ) {}
14711 m_exclusion =
false;
14712 m_arg = m_tagAliases->expandAliases(
arg );
14713 m_escapeChars.clear();
14714 m_substring.reserve(m_arg.size());
14715 m_patternName.reserve(m_arg.size());
14716 m_realPatternPos = 0;
14718 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
14720 if( !visitChar( m_arg[m_pos] ) ){
14721 m_testSpec.m_invalidArgs.push_back(
arg);
14727 TestSpec TestSpecParser::testSpec() {
14731 bool TestSpecParser::visitChar(
char c ) {
14732 if( (m_mode != EscapedName) && (
c ==
'\\') ) {
14734 addCharToPattern(
c);
14736 }
else if((m_mode != EscapedName) && (
c ==
',') ) {
14742 if( processNoneChar(
c ) )
14746 processNameChar(
c );
14750 addCharToPattern(
c);
14755 if( processOtherChar(
c ) )
14761 if( !isControlChar(
c ) ) {
14762 m_patternName +=
c;
14763 m_realPatternPos++;
14769 bool TestSpecParser::processNoneChar(
char c ) {
14774 m_exclusion =
true;
14777 startNewMode(
Tag );
14780 startNewMode( QuotedName );
14783 startNewMode(
Name );
14787 void TestSpecParser::processNameChar(
char c ) {
14789 if( m_substring ==
"exclude:" )
14790 m_exclusion =
true;
14793 startNewMode(
Tag );
14796 bool TestSpecParser::processOtherChar(
char c ) {
14797 if( !isControlChar(
c ) )
14803 void TestSpecParser::startNewMode(
Mode mode ) {
14806 void TestSpecParser::endMode() {
14810 return addNamePattern();
14812 return addTagPattern();
14814 revertBackToLastMode();
14818 return startNewMode(
None );
14823 m_mode = EscapedName;
14824 m_escapeChars.push_back(m_realPatternPos);
14826 bool TestSpecParser::isControlChar(
char c )
const {
14839 return c ==
'[' ||
c ==
']';
14843 void TestSpecParser::addFilter() {
14844 if( !m_currentFilter.m_patterns.empty() ) {
14845 m_testSpec.m_filters.push_back( m_currentFilter );
14846 m_currentFilter = TestSpec::Filter();
14850 void TestSpecParser::saveLastMode() {
14854 void TestSpecParser::revertBackToLastMode() {
14858 bool TestSpecParser::separate() {
14859 if( (m_mode==QuotedName) || (m_mode==
Tag) ){
14862 m_pos = m_arg.size();
14863 m_substring.clear();
14864 m_patternName.clear();
14865 m_realPatternPos = 0;
14873 std::string TestSpecParser::preprocessPattern() {
14875 for (std::size_t
i = 0;
i < m_escapeChars.size(); ++
i)
14877 m_escapeChars.clear();
14879 m_exclusion =
true;
14883 m_patternName.clear();
14884 m_realPatternPos = 0;
14889 void TestSpecParser::addNamePattern() {
14890 auto token = preprocessPattern();
14892 if (!
token.empty()) {
14893 TestSpec::PatternPtr
pattern = std::make_shared<TestSpec::NamePattern>(
token, m_substring);
14896 m_currentFilter.m_patterns.push_back(
pattern);
14898 m_substring.clear();
14899 m_exclusion =
false;
14903 void TestSpecParser::addTagPattern() {
14904 auto token = preprocessPattern();
14906 if (!
token.empty()) {
14911 TestSpec::PatternPtr
pattern = std::make_shared<TestSpec::TagPattern>(
".", m_substring);
14915 m_currentFilter.m_patterns.push_back(
pattern);
14918 TestSpec::PatternPtr
pattern = std::make_shared<TestSpec::TagPattern>(
token, m_substring);
14923 m_currentFilter.m_patterns.push_back(
pattern);
14925 m_substring.clear();
14926 m_exclusion =
false;
14940 static const uint64_t nanosecondsInSecond = 1000000000;
14949 auto estimateClockResolution() -> uint64_t {
14961 }
while( ticks == baseTicks );
14963 auto delta = ticks - baseTicks;
14969 if (ticks > startTime + 3 * nanosecondsInSecond) {
14970 return sum / (
i + 1
u );
14980 static auto s_resolution = estimateClockResolution();
14981 return s_resolution;
14987 auto Timer::getElapsedNanoseconds()
const -> uint64_t {
14990 auto Timer::getElapsedMicroseconds()
const -> uint64_t {
14991 return getElapsedNanoseconds()/1000;
14993 auto Timer::getElapsedMilliseconds()
const ->
unsigned int {
14994 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
14996 auto Timer::getElapsedSeconds()
const ->
double {
14997 return getElapsedMicroseconds()/1000000.0;
15004 #if defined(__clang__)
15005 # pragma clang diagnostic push
15006 # pragma clang diagnostic ignored "-Wexit-time-destructors"
15007 # pragma clang diagnostic ignored "-Wglobal-constructors"
15011 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
15012 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
15025 const int hexThreshold = 255;
15027 struct Endianness {
15028 enum Arch {
Big, Little };
15030 static Arch which() {
15034 auto value = *
reinterpret_cast<char*
>(&one);
15042 int i = 0,
end =
static_cast<int>(
size ), inc = 1;
15043 if( Endianness::which() == Endianness::Little ) {
15048 unsigned char const *bytes =
static_cast<unsigned char const *
>(
object);
15049 ReusableStringStream rss;
15050 rss <<
"0x" << std::setfill(
'0') <<
std::hex;
15051 for( ;
i !=
end;
i += inc )
15052 rss <<
std::setw(2) << static_cast<unsigned>(bytes[
i]);
15057 template<
typename T>
15059 if (Catch::isnan(
value)) {
15063 ReusableStringStream rss;
15068 std::size_t
i =
d.find_last_not_of(
'0' );
15069 if(
i != std::string::npos &&
i !=
d.size()-1 ) {
15072 d =
d.substr( 0,
i+1 );
15085 return '"' +
str + '"';
15089 for (
char c :
str) {
15106 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
15116 return{
"{null string}" };
15123 return{
"{null string}" };
15127 #ifdef CATCH_CONFIG_WCHAR
15130 s.reserve(wstr.size());
15131 for (
auto c : wstr) {
15132 s += (
c <= 0xff) ? static_cast<char>(
c) : '?';
15137 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW
15147 return{
"{null string}" };
15154 return{
"{null string}" };
15159 #if defined(CATCH_CONFIG_CPP17_BYTE)
15173 ReusableStringStream rss;
15175 if (
value > Detail::hexThreshold) {
15188 ReusableStringStream rss;
15190 if (
value > Detail::hexThreshold) {
15197 return b ?
"true" :
"false";
15201 if (
value ==
'\r') {
15203 }
else if (
value ==
'\f') {
15205 }
else if (
value ==
'\n') {
15207 }
else if (
value ==
'\t') {
15212 char chstr[] =
"' '";
15240 std::string ratio_string<std::atto>::symbol() {
return "a"; }
15241 std::string ratio_string<std::femto>::symbol() {
return "f"; }
15242 std::string ratio_string<std::pico>::symbol() {
return "p"; }
15243 std::string ratio_string<std::nano>::symbol() {
return "n"; }
15244 std::string ratio_string<std::micro>::symbol() {
return "u"; }
15245 std::string ratio_string<std::milli>::symbol() {
return "m"; }
15249 #if defined(__clang__)
15250 # pragma clang diagnostic pop
15297 Totals diff = *
this - prevTotals;
15298 if( diff.assertions.failed > 0 )
15300 else if( diff.assertions.failedButOk > 0 )
15320 #ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
15321 #define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
15323 #if defined(_MSC_VER)
15324 # if _MSC_VER >= 1900
15325 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
15329 #include <exception>
15331 #if defined(__cpp_lib_uncaught_exceptions) \
15332 && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
15334 # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
15337 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \
15338 && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \
15339 && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
15341 # define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
15346 #include <exception>
15349 bool uncaught_exceptions() {
15350 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
15352 #elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
15353 return std::uncaught_exceptions() > 0;
15355 return std::uncaught_exception();
15367 (
unsigned int _majorVersion,
15368 unsigned int _minorVersion,
15369 unsigned int _patchNumber,
15370 char const *
const _branchName,
15371 unsigned int _buildNumber )
15372 : majorVersion( _majorVersion ),
15373 minorVersion( _minorVersion ),
15374 patchNumber( _patchNumber ),
15375 branchName( _branchName ),
15376 buildNumber( _buildNumber )
15380 os <<
version.majorVersion <<
'.'
15381 <<
version.minorVersion <<
'.'
15385 os <<
'-' <<
version.branchName
15386 <<
'.' <<
version.buildNumber;
15391 Version const& libraryVersion() {
15404 : m_caseSensitivity( caseSensitivity ),
15405 m_pattern( normaliseString(
pattern ) )
15408 m_pattern = m_pattern.substr( 1 );
15409 m_wildcard = WildcardAtStart;
15411 if(
endsWith( m_pattern,
'*' ) ) {
15412 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
15413 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
15418 switch( m_wildcard ) {
15420 return m_pattern == normaliseString(
str );
15421 case WildcardAtStart:
15422 return endsWith( normaliseString(
str ), m_pattern );
15423 case WildcardAtEnd:
15425 case WildcardAtBothEnds:
15426 return contains( normaliseString(
str ), m_pattern );
15440 #include <type_traits>
15446 size_t trailingBytes(
unsigned char c) {
15447 if ((
c & 0xE0) == 0xC0) {
15450 if ((
c & 0xF0) == 0xE0) {
15453 if ((
c & 0xF8) == 0xF0) {
15459 uint32_t headerValue(
unsigned char c) {
15460 if ((
c & 0xE0) == 0xC0) {
15463 if ((
c & 0xF0) == 0xE0) {
15466 if ((
c & 0xF8) == 0xF0) {
15472 void hexEscapeChar(std::ostream& os,
unsigned char c) {
15473 std::ios_base::fmtflags
f(os.flags());
15475 << std::uppercase <<
std::hex << std::setfill(
'0') << std::setw(2)
15476 <<
static_cast<int>(
c);
15480 bool shouldNewline(XmlFormatting fmt) {
15484 bool shouldIndent(XmlFormatting fmt) {
15490 XmlFormatting
operator | (XmlFormatting lhs, XmlFormatting
rhs) {
15491 return static_cast<XmlFormatting
>(
15497 XmlFormatting
operator & (XmlFormatting lhs, XmlFormatting
rhs) {
15498 return static_cast<XmlFormatting
>(
15506 m_forWhat( forWhat )
15509 void XmlEncode::encodeTo( std::ostream& os )
const {
15513 for( std::size_t
idx = 0;
idx < m_str.size(); ++
idx ) {
15514 unsigned char c = m_str[idx];
15516 case '<': os <<
"<";
break;
15517 case '&': os <<
"&";
break;
15521 if (
idx > 2 && m_str[
idx - 1] ==
']' && m_str[
idx - 2] ==
']')
15528 if (m_forWhat == ForAttributes)
15539 if (
c < 0x09 || (
c > 0x0D &&
c < 0x20) ||
c == 0x7F) {
15540 hexEscapeChar(os,
c);
15558 hexEscapeChar(os,
c);
15562 auto encBytes = trailingBytes(
c);
15564 if (
idx + encBytes - 1 >= m_str.size()) {
15565 hexEscapeChar(os,
c);
15572 uint32_t
value = headerValue(
c);
15573 for (std::size_t
n = 1;
n < encBytes; ++
n) {
15574 unsigned char nc = m_str[idx + n];
15575 valid &= ((nc & 0xC0) == 0x80);
15587 (
value >= 0x110000)
15589 hexEscapeChar(os,
c);
15594 for (std::size_t
n = 0;
n < encBytes; ++
n) {
15595 os << m_str[idx + n];
15597 idx += encBytes - 1;
15603 std::ostream&
operator << ( std::ostream& os, XmlEncode
const& xmlEncode ) {
15604 xmlEncode.encodeTo( os );
15608 XmlWriter::ScopedElement::ScopedElement(
XmlWriter* writer, XmlFormatting fmt )
15609 : m_writer( writer ),
15613 XmlWriter::ScopedElement::ScopedElement( ScopedElement&&
other ) noexcept
15614 : m_writer(
other.m_writer ),
15617 other.m_writer =
nullptr;
15620 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&&
other ) noexcept {
15622 m_writer->endElement();
15624 m_writer =
other.m_writer;
15625 other.m_writer =
nullptr;
15626 m_fmt =
other.m_fmt;
15631 XmlWriter::ScopedElement::~ScopedElement() {
15633 m_writer->endElement(m_fmt);
15637 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText(
std::string const& text, XmlFormatting fmt ) {
15638 m_writer->writeText( text, fmt );
15644 writeDeclaration();
15647 XmlWriter::~XmlWriter() {
15648 while (!m_tags.empty()) {
15651 newlineIfNecessary();
15656 newlineIfNecessary();
15657 if (shouldIndent(fmt)) {
15661 m_os <<
'<' <<
name;
15662 m_tags.push_back(
name );
15663 m_tagIsOpen =
true;
15664 applyFormatting(fmt);
15668 XmlWriter::ScopedElement XmlWriter::scopedElement(
std::string const&
name, XmlFormatting fmt ) {
15669 ScopedElement scoped(
this, fmt );
15670 startElement(
name, fmt );
15674 XmlWriter& XmlWriter::endElement(XmlFormatting fmt) {
15675 m_indent = m_indent.substr(0, m_indent.size() - 2);
15677 if( m_tagIsOpen ) {
15679 m_tagIsOpen =
false;
15681 newlineIfNecessary();
15682 if (shouldIndent(fmt)) {
15685 m_os <<
"</" << m_tags.back() <<
">";
15688 applyFormatting(fmt);
15695 m_os <<
' ' <<
name <<
"=\"" << XmlEncode(
attribute, XmlEncode::ForAttributes ) <<
'"';
15700 m_os <<
' ' <<
name <<
"=\"" << (
attribute ?
"true" :
"false" ) <<
'"';
15705 if( !
text.empty() ){
15706 bool tagWasOpen = m_tagIsOpen;
15708 if (tagWasOpen && shouldIndent(fmt)) {
15711 m_os << XmlEncode( text );
15712 applyFormatting(fmt);
15719 if (shouldIndent(fmt)) {
15722 m_os <<
"<!--" <<
text <<
"-->";
15723 applyFormatting(fmt);
15728 m_os <<
"<?xml-stylesheet type=\"text/xsl\" href=\"" <<
url <<
"\"?>\n";
15731 XmlWriter& XmlWriter::writeBlankLine() {
15737 void XmlWriter::ensureTagClosed() {
15738 if( m_tagIsOpen ) {
15739 m_os << '>
' << std::flush;
15740 newlineIfNecessary();
15741 m_tagIsOpen = false;
15745 void XmlWriter::applyFormatting(XmlFormatting fmt) {
15746 m_needsNewline = shouldNewline(fmt);
15749 void XmlWriter::writeDeclaration() {
15750 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
15753 void XmlWriter::newlineIfNecessary() {
15754 if( m_needsNewline ) {
15756 m_needsNewline = false;
15760 // end catch_xmlwriter.cpp
15761 // start catch_reporter_bases.cpp
15770 void prepareExpandedExpression(AssertionResult& result) {
15771 result.getExpandedExpression();
15774 // Because formatting using c++ streams is stateful, drop down to C is required
15775 // Alternatively we could use stringstream, but its performance is... not good.
15776 std::string getFormattedDuration( double duration ) {
15777 // Max exponent + 1 is required to represent the whole part
15778 // + 1 for decimal point
15779 // + 3 for the 3 decimal places
15780 // + 1 for null terminator
15781 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
15782 char buffer[maxDoubleSize];
15784 // Save previous errno, to prevent sprintf from overwriting it
15787 sprintf_s(buffer, "%.3f", duration);
15789 std::sprintf(buffer, "%.3f", duration);
15791 return std::string(buffer);
15794 bool shouldShowDuration( IConfig const& config, double duration ) {
15795 if ( config.showDurations() == ShowDurations::Always ) {
15798 if ( config.showDurations() == ShowDurations::Never ) {
15801 const double min = config.minDuration();
15802 return min >= 0 && duration >= min;
15805 std::string serializeFilters( std::vector<std::string> const& container ) {
15806 ReusableStringStream oss;
15808 for (auto&& filter : container)
15820 TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
15821 :StreamingReporterBase(_config) {}
15823 std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() {
15824 return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High };
15827 void TestEventListenerBase::assertionStarting(AssertionInfo const &) {}
15829 bool TestEventListenerBase::assertionEnded(AssertionStats const &) {
15833 } // end namespace Catch
15834 // end catch_reporter_bases.cpp
15835 // start catch_reporter_compact.cpp
15839 #ifdef CATCH_PLATFORM_MAC
15840 const char* failedString() { return "FAILED"; }
15841 const char* passedString() { return "PASSED"; }
15843 const char* failedString() { return "failed"; }
15844 const char* passedString() { return "passed"; }
15847 // Colour::LightGrey
15848 Catch::Colour::Code dimColour() { return Catch::Colour::FileName; }
15850 std::string bothOrAll( std::size_t count ) {
15851 return count == 1 ? std::string() :
15852 count == 2 ? "both " : "all " ;
15855 } // anon namespace
15859 // Colour, message variants:
15860 // - white: No tests ran.
15861 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
15862 // - white: Passed [both/all] N test cases (no assertions).
15863 // - red: Failed N tests cases, failed M assertions.
15864 // - green: Passed [both/all] N tests cases with M assertions.
15865 void printTotals(std::ostream& out, const Totals& totals) {
15866 if (totals.testCases.total() == 0) {
15867 out << "No tests ran.";
15868 } else if (totals.testCases.failed == totals.testCases.total()) {
15869 Colour colour(Colour::ResultError);
15870 const std::string qualify_assertions_failed =
15871 totals.assertions.failed == totals.assertions.total() ?
15872 bothOrAll(totals.assertions.failed) : std::string();
15874 "Failed " << bothOrAll(totals.testCases.failed)
15875 << pluralise(totals.testCases.failed, "test case") << ", "
15876 "failed " << qualify_assertions_failed <<
15877 pluralise(totals.assertions.failed, "assertion") << '.
';
15878 } else if (totals.assertions.total() == 0) {
15880 "Passed " << bothOrAll(totals.testCases.total())
15881 << pluralise(totals.testCases.total(), "test case")
15882 << " (no assertions).";
15883 } else if (totals.assertions.failed) {
15884 Colour colour(Colour::ResultError);
15886 "Failed " << pluralise(totals.testCases.failed, "test case") << ", "
15887 "failed " << pluralise(totals.assertions.failed, "assertion") << '.
';
15889 Colour colour(Colour::ResultSuccess);
15891 "Passed " << bothOrAll(totals.testCases.passed)
15892 << pluralise(totals.testCases.passed, "test case") <<
15893 " with " << pluralise(totals.assertions.passed, "assertion") << '.
';
15897 // Implementation of CompactReporter formatting
15898 class AssertionPrinter {
15900 AssertionPrinter& operator= (AssertionPrinter const&) = delete;
15901 AssertionPrinter(AssertionPrinter const&) = delete;
15902 AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
15904 , result(_stats.assertionResult)
15905 , messages(_stats.infoMessages)
15906 , itMessage(_stats.infoMessages.begin())
15907 , printInfoMessages(_printInfoMessages) {}
15912 itMessage = messages.begin();
15914 switch (result.getResultType()) {
15915 case ResultWas::Ok:
15916 printResultType(Colour::ResultSuccess, passedString());
15917 printOriginalExpression();
15918 printReconstructedExpression();
15919 if (!result.hasExpression())
15920 printRemainingMessages(Colour::None);
15922 printRemainingMessages();
15924 case ResultWas::ExpressionFailed:
15926 printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok"));
15928 printResultType(Colour::Error, failedString());
15929 printOriginalExpression();
15930 printReconstructedExpression();
15931 printRemainingMessages();
15933 case ResultWas::ThrewException:
15934 printResultType(Colour::Error, failedString());
15935 printIssue("unexpected exception with message:");
15937 printExpressionWas();
15938 printRemainingMessages();
15940 case ResultWas::FatalErrorCondition:
15941 printResultType(Colour::Error, failedString());
15942 printIssue("fatal error condition with message:");
15944 printExpressionWas();
15945 printRemainingMessages();
15947 case ResultWas::DidntThrowException:
15948 printResultType(Colour::Error, failedString());
15949 printIssue("expected exception, got none");
15950 printExpressionWas();
15951 printRemainingMessages();
15953 case ResultWas::Info:
15954 printResultType(Colour::None, "info");
15956 printRemainingMessages();
15958 case ResultWas::Warning:
15959 printResultType(Colour::None, "warning");
15961 printRemainingMessages();
15963 case ResultWas::ExplicitFailure:
15964 printResultType(Colour::Error, failedString());
15965 printIssue("explicitly");
15966 printRemainingMessages(Colour::None);
15968 // These cases are here to prevent compiler warnings
15969 case ResultWas::Unknown:
15970 case ResultWas::FailureBit:
15971 case ResultWas::Exception:
15972 printResultType(Colour::Error, "** internal error **");
15978 void printSourceInfo() const {
15979 Colour colourGuard(Colour::FileName);
15980 stream << result.getSourceInfo() << ':
';
15983 void printResultType(Colour::Code colour, std::string const& passOrFail) const {
15984 if (!passOrFail.empty()) {
15986 Colour colourGuard(colour);
15987 stream << ' ' << passOrFail;
15993 void printIssue(std::string const& issue) const {
15994 stream << ' ' << issue;
15997 void printExpressionWas() {
15998 if (result.hasExpression()) {
16001 Colour colour(dimColour());
16002 stream << " expression was:";
16004 printOriginalExpression();
16008 void printOriginalExpression() const {
16009 if (result.hasExpression()) {
16010 stream << ' ' << result.getExpression();
16014 void printReconstructedExpression() const {
16015 if (result.hasExpandedExpression()) {
16017 Colour colour(dimColour());
16018 stream << " for: ";
16020 stream << result.getExpandedExpression();
16024 void printMessage() {
16025 if (itMessage != messages.end()) {
16026 stream << " '" << itMessage->message << '\'';
16031 void printRemainingMessages(Colour::Code colour = dimColour()) {
16032 if (itMessage == messages.end())
16035 const auto itEnd = messages.cend();
16036 const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
16039 Colour colourGuard(colour);
16040 stream << " with
" << pluralise(N, "message") << ':';
16043 while (itMessage != itEnd) {
16044 // If this assertion is a warning ignore any INFO messages
16045 if (printInfoMessages || itMessage->type != ResultWas::Info) {
16047 if (itMessage != itEnd) {
16048 Colour colourGuard(dimColour());
16058 std::ostream& stream;
16059 AssertionResult const& result;
16060 std::vector<MessageInfo> messages;
16061 std::vector<MessageInfo>::const_iterator itMessage;
16062 bool printInfoMessages;
16065 } // anon namespace
16067 std::string CompactReporter::getDescription() {
16071 void CompactReporter::noMatchingTestCases( std::string const& spec ) {
16072 stream << "No
test cases matched
'" << spec << '\
'' <<
std::endl;
16075 void CompactReporter::assertionStarting( AssertionInfo
const& ) {}
16077 bool CompactReporter::assertionEnded( AssertionStats
const& _assertionStats ) {
16078 AssertionResult
const&
result = _assertionStats.assertionResult;
16080 bool printInfoMessages =
true;
16083 if( !m_config->includeSuccessfulResults() &&
result.isOk() ) {
16086 printInfoMessages =
false;
16089 AssertionPrinter printer(
stream, _assertionStats, printInfoMessages );
16096 void CompactReporter::sectionEnded(SectionStats
const& _sectionStats) {
16097 double dur = _sectionStats.durationInSeconds;
16098 if ( shouldShowDuration( *m_config, dur ) ) {
16099 stream << getFormattedDuration( dur ) <<
" s: " << _sectionStats.sectionInfo.name <<
std::endl;
16103 void CompactReporter::testRunEnded( TestRunStats
const& _testRunStats ) {
16104 printTotals(
stream, _testRunStats.totals );
16106 StreamingReporterBase::testRunEnded( _testRunStats );
16109 CompactReporter::~CompactReporter() {}
16111 CATCH_REGISTER_REPORTER(
"compact", CompactReporter )
16120 #if defined(_MSC_VER)
16121 #pragma warning(push)
16122 #pragma warning(disable:4061)
16126 #if defined(__clang__)
16127 # pragma clang diagnostic push
16129 # pragma clang diagnostic ignored "-Wunused-function"
16137 class ConsoleAssertionPrinter {
16139 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter
const&) =
delete;
16140 ConsoleAssertionPrinter(ConsoleAssertionPrinter
const&) =
delete;
16141 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
16144 result(_stats.assertionResult),
16145 colour(Colour::
None),
16148 printInfoMessages(_printInfoMessages) {
16149 switch (
result.getResultType()) {
16152 passOrFail =
"PASSED";
16154 if (_stats.infoMessages.size() == 1)
16155 messageLabel =
"with message";
16156 if (_stats.infoMessages.size() > 1)
16157 messageLabel =
"with messages";
16162 passOrFail =
"FAILED - but was ok";
16165 passOrFail =
"FAILED";
16167 if (_stats.infoMessages.size() == 1)
16168 messageLabel =
"with message";
16169 if (_stats.infoMessages.size() > 1)
16170 messageLabel =
"with messages";
16174 passOrFail =
"FAILED";
16175 messageLabel =
"due to unexpected exception with ";
16176 if (_stats.infoMessages.size() == 1)
16178 if (_stats.infoMessages.size() > 1)
16183 passOrFail =
"FAILED";
16184 messageLabel =
"due to a fatal error condition";
16188 passOrFail =
"FAILED";
16189 messageLabel =
"because no exception was thrown where one was expected";
16192 messageLabel =
"info";
16195 messageLabel =
"warning";
16198 passOrFail =
"FAILED";
16200 if (_stats.infoMessages.size() == 1)
16201 messageLabel =
"explicitly with message";
16202 if (_stats.infoMessages.size() > 1)
16203 messageLabel =
"explicitly with messages";
16209 passOrFail =
"** internal error **";
16215 void print()
const {
16217 if (stats.totals.assertions.total() > 0) {
16219 printOriginalExpression();
16220 printReconstructedExpression();
16228 void printResultType()
const {
16229 if (!passOrFail.empty()) {
16230 Colour colourGuard(colour);
16231 stream << passOrFail <<
":\n";
16234 void printOriginalExpression()
const {
16235 if (
result.hasExpression()) {
16236 Colour colourGuard(Colour::OriginalExpression);
16242 void printReconstructedExpression()
const {
16243 if (
result.hasExpandedExpression()) {
16244 stream <<
"with expansion:\n";
16245 Colour colourGuard(Colour::ReconstructedExpression);
16249 void printMessage()
const {
16250 if (!messageLabel.empty())
16251 stream << messageLabel <<
':' <<
'\n';
16258 void printSourceInfo()
const {
16259 Colour colourGuard(Colour::FileName);
16264 AssertionStats
const& stats;
16265 AssertionResult
const&
result;
16270 std::vector<MessageInfo>
messages;
16271 bool printInfoMessages;
16274 std::size_t makeRatio(std::size_t
number, std::size_t total) {
16275 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH *
number / total : 0;
16276 return (ratio == 0 &&
number > 0) ? 1 : ratio;
16279 std::size_t& findMax(std::size_t&
i, std::size_t&
j, std::size_t& k) {
16280 if (
i >
j &&
i > k)
16288 struct ColumnInfo {
16292 Justification justification;
16294 struct ColumnBreak {};
16295 struct RowBreak {};
16306 static const uint64_t s_nanosecondsInAMicrosecond = 1000;
16307 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
16308 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
16309 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
16311 double m_inNanoseconds;
16316 : m_inNanoseconds(inNanoseconds),
16319 if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
16320 m_units = Unit::Nanoseconds;
16321 else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
16322 m_units = Unit::Microseconds;
16323 else if (m_inNanoseconds < s_nanosecondsInASecond)
16324 m_units = Unit::Milliseconds;
16325 else if (m_inNanoseconds < s_nanosecondsInAMinute)
16326 m_units = Unit::Seconds;
16328 m_units = Unit::Minutes;
16335 case Unit::Microseconds:
16336 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMicrosecond);
16337 case Unit::Milliseconds:
16338 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMillisecond);
16339 case Unit::Seconds:
16340 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInASecond);
16341 case Unit::Minutes:
16342 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMinute);
16344 return m_inNanoseconds;
16347 auto unitsAsString()
const ->
std::
string {
16349 case Unit::Nanoseconds:
16351 case Unit::Microseconds:
16353 case Unit::Milliseconds:
16355 case Unit::Seconds:
16357 case Unit::Minutes:
16360 return "** internal error **";
16364 friend auto operator << (std::ostream& os, Duration
const& duration) -> std::ostream& {
16365 return os << duration.value() <<
' ' << duration.unitsAsString();
16370 class TablePrinter {
16371 std::ostream& m_os;
16372 std::vector<ColumnInfo> m_columnInfos;
16373 std::ostringstream m_oss;
16374 int m_currentColumn = -1;
16375 bool m_isOpen =
false;
16378 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
16380 m_columnInfos(
std::move( columnInfos ) ) {}
16383 return m_columnInfos;
16389 *
this << RowBreak();
16393 for (
auto const&
info : m_columnInfos) {
16395 headerCols += spacer;
16397 m_os << headerCols <<
'\n';
16399 m_os << Catch::getLineOfChars<
'-'>() <<
'\n';
16404 *
this << RowBreak();
16410 template<
typename T>
16416 friend TablePrinter&
operator << (TablePrinter& tp, ColumnBreak) {
16417 auto colStr = tp.m_oss.str();
16418 const auto strSize = colStr.size();
16421 if (tp.m_currentColumn ==
static_cast<int>(tp.m_columnInfos.size() - 1)) {
16422 tp.m_currentColumn = -1;
16425 tp.m_currentColumn++;
16427 auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
16428 auto padding = (strSize + 1 < static_cast<
std::size_t>(colInfo.
width))
16429 ? std::string(colInfo.
width - (strSize + 1), ' ')
16432 tp.m_os << colStr << padding <<
' ';
16434 tp.m_os << padding << colStr <<
' ';
16438 friend TablePrinter&
operator << (TablePrinter& tp, RowBreak) {
16439 if (tp.m_currentColumn > 0) {
16441 tp.m_currentColumn = -1;
16447 ConsoleReporter::ConsoleReporter(ReporterConfig
const&
config)
16448 : StreamingReporterBase(
config),
16451 if (
config.fullConfig()->benchmarkNoAnalysis())
16454 {
"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },
16463 {
"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },
16470 ConsoleReporter::~ConsoleReporter() =
default;
16473 return "Reports test results as plain lines of text";
16476 void ConsoleReporter::noMatchingTestCases(
std::string const& spec) {
16480 void ConsoleReporter::reportInvalidArguments(
std::string const&
arg){
16484 void ConsoleReporter::assertionStarting(AssertionInfo
const&) {}
16486 bool ConsoleReporter::assertionEnded(AssertionStats
const& _assertionStats) {
16487 AssertionResult
const&
result = _assertionStats.assertionResult;
16489 bool includeResults = m_config->includeSuccessfulResults() || !
result.isOk();
16497 ConsoleAssertionPrinter printer(
stream, _assertionStats, includeResults);
16503 void ConsoleReporter::sectionStarting(SectionInfo
const& _sectionInfo) {
16504 m_tablePrinter->close();
16505 m_headerPrinted =
false;
16506 StreamingReporterBase::sectionStarting(_sectionInfo);
16508 void ConsoleReporter::sectionEnded(SectionStats
const& _sectionStats) {
16509 m_tablePrinter->close();
16510 if (_sectionStats.missingAssertions) {
16512 Colour colour(Colour::ResultError);
16513 if (m_sectionStack.size() > 1)
16514 stream <<
"\nNo assertions in section";
16516 stream <<
"\nNo assertions in test case";
16517 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" <<
std::endl;
16519 double dur = _sectionStats.durationInSeconds;
16520 if (shouldShowDuration(*m_config, dur)) {
16521 stream << getFormattedDuration(dur) <<
" s: " << _sectionStats.sectionInfo.name <<
std::endl;
16523 if (m_headerPrinted) {
16524 m_headerPrinted =
false;
16526 StreamingReporterBase::sectionEnded(_sectionStats);
16529 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
16531 lazyPrintWithoutClosingBenchmarkTable();
16533 auto nameCol =
Column(
name).width(
static_cast<std::size_t
>(m_tablePrinter->columnInfos()[0].width - 2));
16535 bool firstLine =
true;
16536 for (
auto line : nameCol) {
16538 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
16542 (*m_tablePrinter) <<
line << ColumnBreak();
16546 void ConsoleReporter::benchmarkStarting(BenchmarkInfo
const&
info) {
16547 (*m_tablePrinter) <<
info.samples << ColumnBreak()
16548 <<
info.iterations << ColumnBreak();
16549 if (!m_config->benchmarkNoAnalysis())
16550 (*m_tablePrinter) << Duration(
info.estimatedDuration) << ColumnBreak();
16552 void ConsoleReporter::benchmarkEnded(BenchmarkStats<>
const& stats) {
16553 if (m_config->benchmarkNoAnalysis())
16555 (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
16559 (*m_tablePrinter) << ColumnBreak()
16560 << Duration(stats.mean.point.count()) << ColumnBreak()
16561 << Duration(stats.mean.lower_bound.count()) << ColumnBreak()
16562 << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()
16563 << Duration(stats.standardDeviation.point.count()) << ColumnBreak()
16564 << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()
16565 << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak();
16572 <<
"Benchmark failed (" <<
error <<
')'
16573 << ColumnBreak() << RowBreak();
16577 void ConsoleReporter::testCaseEnded(TestCaseStats
const& _testCaseStats) {
16578 m_tablePrinter->close();
16579 StreamingReporterBase::testCaseEnded(_testCaseStats);
16580 m_headerPrinted =
false;
16582 void ConsoleReporter::testGroupEnded(TestGroupStats
const& _testGroupStats) {
16583 if (currentGroupInfo.used) {
16584 printSummaryDivider();
16585 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
16586 printTotals(_testGroupStats.totals);
16589 StreamingReporterBase::testGroupEnded(_testGroupStats);
16591 void ConsoleReporter::testRunEnded(TestRunStats
const& _testRunStats) {
16592 printTotalsDivider(_testRunStats.totals);
16593 printTotals(_testRunStats.totals);
16595 StreamingReporterBase::testRunEnded(_testRunStats);
16597 void ConsoleReporter::testRunStarting(TestRunInfo
const& _testInfo) {
16598 StreamingReporterBase::testRunStarting(_testInfo);
16599 printTestFilters();
16602 void ConsoleReporter::lazyPrint() {
16604 m_tablePrinter->close();
16605 lazyPrintWithoutClosingBenchmarkTable();
16608 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
16610 if (!currentTestRunInfo.used)
16611 lazyPrintRunInfo();
16612 if (!currentGroupInfo.used)
16613 lazyPrintGroupInfo();
16615 if (!m_headerPrinted) {
16616 printTestCaseAndSectionHeader();
16617 m_headerPrinted =
true;
16620 void ConsoleReporter::lazyPrintRunInfo() {
16622 Colour colour(Colour::SecondaryText);
16623 stream << currentTestRunInfo->name
16624 <<
" is a Catch v" << libraryVersion() <<
" host application.\n"
16625 <<
"Run with -? for options\n\n";
16627 if (m_config->rngSeed() != 0)
16628 stream <<
"Randomness seeded to: " << m_config->rngSeed() <<
"\n\n";
16630 currentTestRunInfo.used =
true;
16632 void ConsoleReporter::lazyPrintGroupInfo() {
16633 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
16634 printClosedHeader(
"Group: " + currentGroupInfo->name);
16635 currentGroupInfo.used =
true;
16638 void ConsoleReporter::printTestCaseAndSectionHeader() {
16639 assert(!m_sectionStack.empty());
16640 printOpenHeader(currentTestCaseInfo->name);
16642 if (m_sectionStack.size() > 1) {
16643 Colour colourGuard(Colour::Headers);
16646 it = m_sectionStack.begin() + 1,
16647 itEnd = m_sectionStack.
end();
16648 for (;
it != itEnd; ++
it)
16649 printHeaderString(
it->
name, 2);
16652 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
16654 stream << getLineOfChars<
'-'>() <<
'\n';
16655 Colour colourGuard(Colour::FileName);
16656 stream << lineInfo <<
'\n';
16660 void ConsoleReporter::printClosedHeader(
std::string const& _name) {
16661 printOpenHeader(_name);
16662 stream << getLineOfChars<
'.'>() <<
'\n';
16664 void ConsoleReporter::printOpenHeader(
std::string const& _name) {
16665 stream << getLineOfChars<
'-'>() <<
'\n';
16667 Colour colourGuard(Colour::Headers);
16668 printHeaderString(_name);
16674 void ConsoleReporter::printHeaderString(
std::string const& _string, std::size_t indent) {
16675 std::size_t
i = _string.find(
": ");
16676 if (
i != std::string::npos)
16680 stream <<
Column(_string).indent(indent +
i).initialIndent(indent) <<
'\n';
16683 struct SummaryColumn {
16687 colour( _colour ) {}
16689 ReusableStringStream rss;
16692 for (
auto& oldRow : rows) {
16693 while (oldRow.size() <
row.size())
16694 oldRow =
' ' + oldRow;
16695 while (oldRow.size() >
row.size())
16698 rows.push_back(
row);
16704 std::vector<std::string> rows;
16708 void ConsoleReporter::printTotals( Totals
const& totals ) {
16709 if (totals.testCases.total() == 0) {
16710 stream << Colour(Colour::Warning) <<
"No tests ran\n";
16711 }
else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {
16712 stream << Colour(Colour::ResultSuccess) <<
"All tests passed";
16714 << pluralise(totals.assertions.passed,
"assertion") <<
" in "
16715 << pluralise(totals.testCases.passed,
"test case") <<
')'
16719 std::vector<SummaryColumn> columns;
16721 .
addRow(totals.testCases.total())
16722 .addRow(totals.assertions.total()));
16724 .
addRow(totals.testCases.passed)
16725 .addRow(totals.assertions.passed));
16726 columns.push_back(SummaryColumn(
"failed", Colour::ResultError)
16727 .
addRow(totals.testCases.failed)
16728 .addRow(totals.assertions.failed));
16729 columns.push_back(SummaryColumn(
"failed as expected", Colour::ResultExpectedFailure)
16730 .
addRow(totals.testCases.failedButOk)
16731 .addRow(totals.assertions.failedButOk));
16733 printSummaryRow(
"test cases", columns, 0);
16734 printSummaryRow(
"assertions", columns, 1);
16737 void ConsoleReporter::printSummaryRow(
std::string const&
label, std::vector<SummaryColumn>
const& cols, std::size_t
row) {
16738 for (
auto col : cols) {
16740 if (col.label.empty()) {
16745 stream << Colour(Colour::Warning) <<
"- none -";
16746 }
else if (
value !=
"0") {
16747 stream << Colour(Colour::LightGrey) <<
" | ";
16748 stream << Colour(col.colour)
16749 <<
value <<
' ' << col.label;
16755 void ConsoleReporter::printTotalsDivider(Totals
const& totals) {
16756 if (totals.testCases.total() > 0) {
16757 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
16758 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
16759 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
16760 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
16761 findMax(failedRatio, failedButOkRatio, passedRatio)++;
16762 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
16763 findMax(failedRatio, failedButOkRatio, passedRatio)--;
16766 stream << Colour(Colour::ResultExpectedFailure) <<
std::string(failedButOkRatio,
'=');
16767 if (totals.testCases.allPassed())
16772 stream << Colour(Colour::Warning) <<
std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1,
'=');
16776 void ConsoleReporter::printSummaryDivider() {
16777 stream << getLineOfChars<
'-'>() <<
'\n';
16780 void ConsoleReporter::printTestFilters() {
16781 if (m_config->testSpec().hasFilters()) {
16782 Colour guard(Colour::BrightYellow);
16783 stream <<
"Filters: " << serializeFilters(m_config->getTestsOrTags()) <<
'\n';
16787 CATCH_REGISTER_REPORTER(
"console", ConsoleReporter)
16791 #if defined(_MSC_VER)
16792 #pragma warning(pop)
16795 #if defined(__clang__)
16796 # pragma clang diagnostic pop
16804 #include <algorithm>
16815 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
16818 std::tm timeInfo = {};
16819 gmtime_s(&timeInfo, &rawtime);
16822 timeInfo = std::gmtime(&rawtime);
16825 char timeStamp[timeStampSize];
16826 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
16829 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
16831 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
16836 std::string fileNameTag(
const std::vector<std::string> &tags) {
16837 auto it = std::find_if(
begin(tags),
16840 if (
it != tags.end())
16841 return it->substr(1);
16850 ReusableStringStream rss;
16851 rss <<
std::fixed << std::setprecision( 3 ) << seconds;
16857 JunitReporter::JunitReporter( ReporterConfig
const& _config )
16858 : CumulativeReporterBase( _config ),
16861 m_reporterPrefs.shouldRedirectStdOut =
true;
16862 m_reporterPrefs.shouldReportAllAssertions =
true;
16865 JunitReporter::~JunitReporter() {}
16868 return "Reports test results in an XML format that looks like Ant's junitreport target";
16871 void JunitReporter::noMatchingTestCases(
std::string const& ) {}
16873 void JunitReporter::testRunStarting( TestRunInfo
const& runInfo ) {
16874 CumulativeReporterBase::testRunStarting( runInfo );
16875 xml.startElement(
"testsuites" );
16878 void JunitReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
16879 suiteTimer.start();
16880 stdOutForSuite.
clear();
16881 stdErrForSuite.clear();
16882 unexpectedExceptions = 0;
16883 CumulativeReporterBase::testGroupStarting( groupInfo );
16886 void JunitReporter::testCaseStarting( TestCaseInfo
const& testCaseInfo ) {
16887 m_okToFail = testCaseInfo.okToFail();
16890 bool JunitReporter::assertionEnded( AssertionStats
const& assertionStats ) {
16892 unexpectedExceptions++;
16893 return CumulativeReporterBase::assertionEnded( assertionStats );
16896 void JunitReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
16897 stdOutForSuite += testCaseStats.stdOut;
16898 stdErrForSuite += testCaseStats.stdErr;
16899 CumulativeReporterBase::testCaseEnded( testCaseStats );
16902 void JunitReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
16903 double suiteTime = suiteTimer.getElapsedSeconds();
16904 CumulativeReporterBase::testGroupEnded( testGroupStats );
16905 writeGroup( *m_testGroups.back(), suiteTime );
16908 void JunitReporter::testRunEndedCumulative() {
16912 void JunitReporter::writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
16913 XmlWriter::ScopedElement
e =
xml.scopedElement(
"testsuite" );
16915 TestGroupStats
const& stats = groupNode.value;
16916 xml.writeAttribute(
"name", stats.groupInfo.name );
16917 xml.writeAttribute(
"errors", unexpectedExceptions );
16918 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
16919 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
16920 xml.writeAttribute(
"hostname",
"tbd" );
16922 xml.writeAttribute(
"time",
"" );
16924 xml.writeAttribute(
"time", formatDuration( suiteTime ) );
16925 xml.writeAttribute(
"timestamp", getCurrentTimestamp() );
16928 if (m_config->hasTestFilters() || m_config->rngSeed() != 0) {
16930 if (m_config->hasTestFilters()) {
16931 xml.scopedElement(
"property")
16932 .writeAttribute(
"name",
"filters")
16933 .writeAttribute(
"value", serializeFilters(m_config->getTestsOrTags()));
16935 if (m_config->rngSeed() != 0) {
16936 xml.scopedElement(
"property")
16937 .writeAttribute(
"name",
"random-seed")
16938 .writeAttribute(
"value", m_config->rngSeed());
16943 for(
auto const&
child : groupNode.children )
16944 writeTestCase( *
child );
16946 xml.scopedElement(
"system-out" ).writeText(
trim( stdOutForSuite ), XmlFormatting::Newline );
16947 xml.scopedElement(
"system-err" ).writeText(
trim( stdErrForSuite ), XmlFormatting::Newline );
16950 void JunitReporter::writeTestCase( TestCaseNode
const& testCaseNode ) {
16951 TestCaseStats
const& stats = testCaseNode.value;
16955 assert( testCaseNode.children.size() == 1 );
16956 SectionNode
const& rootSection = *testCaseNode.children.front();
16961 className = fileNameTag(stats.testInfo.tags);
16966 if ( !m_config->name().empty() )
16969 writeSection(
className,
"", rootSection, stats.testInfo.okToFail() );
16974 SectionNode
const& sectionNode,
16975 bool testOkToFail) {
16977 if( !rootName.empty() )
16980 if( !sectionNode.assertions.empty() ||
16981 !sectionNode.stdOut.empty() ||
16982 !sectionNode.stdErr.empty() ) {
16983 XmlWriter::ScopedElement
e =
xml.scopedElement(
"testcase" );
16985 xml.writeAttribute(
"classname",
name );
16986 xml.writeAttribute(
"name",
"root" );
16990 xml.writeAttribute(
"name",
name );
16992 xml.writeAttribute(
"time", formatDuration( sectionNode.stats.durationInSeconds ) );
16997 xml.writeAttribute(
"status",
"run" );
16999 if (sectionNode.stats.assertions.failedButOk) {
17000 xml.scopedElement(
"skipped")
17001 .writeAttribute(
"message",
"TEST_CASE tagged with !mayfail");
17004 writeAssertions( sectionNode );
17006 if( !sectionNode.stdOut.empty() )
17007 xml.scopedElement(
"system-out" ).writeText(
trim( sectionNode.stdOut ), XmlFormatting::Newline );
17008 if( !sectionNode.stdErr.empty() )
17009 xml.scopedElement(
"system-err" ).writeText(
trim( sectionNode.stdErr ), XmlFormatting::Newline );
17011 for(
auto const& childNode : sectionNode.childSections )
17013 writeSection(
name,
"", *childNode, testOkToFail );
17018 void JunitReporter::writeAssertions( SectionNode
const& sectionNode ) {
17019 for(
auto const& assertion : sectionNode.assertions )
17020 writeAssertion( assertion );
17023 void JunitReporter::writeAssertion( AssertionStats
const& stats ) {
17024 AssertionResult
const&
result = stats.assertionResult;
17027 switch(
result.getResultType() ) {
17030 elementName =
"error";
17035 elementName =
"failure";
17045 elementName =
"internalError";
17049 XmlWriter::ScopedElement
e =
xml.scopedElement( elementName );
17051 xml.writeAttribute(
"message",
result.getExpression() );
17052 xml.writeAttribute(
"type",
result.getTestMacroName() );
17054 ReusableStringStream rss;
17055 if (stats.totals.assertions.total() > 0) {
17056 rss <<
"FAILED" <<
":\n";
17057 if (
result.hasExpression()) {
17059 rss <<
result.getExpressionInMacro();
17062 if (
result.hasExpandedExpression()) {
17063 rss <<
"with expansion:\n";
17064 rss <<
Column(
result.getExpandedExpression()).indent(2) <<
'\n';
17070 if( !
result.getMessage().empty() )
17071 rss <<
result.getMessage() <<
'\n';
17072 for(
auto const&
msg : stats.infoMessages )
17074 rss <<
msg.message <<
'\n';
17076 rss <<
"at " <<
result.getSourceInfo();
17077 xml.writeText( rss.str(), XmlFormatting::Newline );
17081 CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
17091 ListeningReporter::ListeningReporter() {
17093 m_preferences.shouldReportAllAssertions =
true;
17096 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
17097 m_listeners.push_back( std::move( listener ) );
17100 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
17101 assert(!m_reporter &&
"Listening reporter can wrap only 1 real reporter");
17102 m_reporter = std::move( reporter );
17103 m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;
17106 ReporterPreferences ListeningReporter::getPreferences()
const {
17107 return m_preferences;
17110 std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
17111 return std::set<Verbosity>{ };
17114 void ListeningReporter::noMatchingTestCases(
std::string const& spec ) {
17115 for (
auto const& listener : m_listeners ) {
17116 listener->noMatchingTestCases( spec );
17118 m_reporter->noMatchingTestCases( spec );
17121 void ListeningReporter::reportInvalidArguments(
std::string const&
arg){
17122 for (
auto const& listener : m_listeners ) {
17123 listener->reportInvalidArguments(
arg );
17125 m_reporter->reportInvalidArguments(
arg );
17128 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
17129 void ListeningReporter::benchmarkPreparing(
std::string const&
name ) {
17130 for (
auto const& listener : m_listeners) {
17131 listener->benchmarkPreparing(
name);
17133 m_reporter->benchmarkPreparing(
name);
17135 void ListeningReporter::benchmarkStarting( BenchmarkInfo
const& benchmarkInfo ) {
17136 for (
auto const& listener : m_listeners ) {
17137 listener->benchmarkStarting( benchmarkInfo );
17139 m_reporter->benchmarkStarting( benchmarkInfo );
17141 void ListeningReporter::benchmarkEnded( BenchmarkStats<>
const& benchmarkStats ) {
17142 for (
auto const& listener : m_listeners ) {
17143 listener->benchmarkEnded( benchmarkStats );
17145 m_reporter->benchmarkEnded( benchmarkStats );
17149 for (
auto const& listener : m_listeners) {
17150 listener->benchmarkFailed(
error);
17152 m_reporter->benchmarkFailed(
error);
17156 void ListeningReporter::testRunStarting( TestRunInfo
const& testRunInfo ) {
17157 for (
auto const& listener : m_listeners ) {
17158 listener->testRunStarting( testRunInfo );
17160 m_reporter->testRunStarting( testRunInfo );
17163 void ListeningReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
17164 for (
auto const& listener : m_listeners ) {
17165 listener->testGroupStarting( groupInfo );
17167 m_reporter->testGroupStarting( groupInfo );
17170 void ListeningReporter::testCaseStarting( TestCaseInfo
const& testInfo ) {
17171 for (
auto const& listener : m_listeners ) {
17172 listener->testCaseStarting( testInfo );
17174 m_reporter->testCaseStarting( testInfo );
17177 void ListeningReporter::sectionStarting( SectionInfo
const& sectionInfo ) {
17178 for (
auto const& listener : m_listeners ) {
17179 listener->sectionStarting( sectionInfo );
17181 m_reporter->sectionStarting( sectionInfo );
17184 void ListeningReporter::assertionStarting( AssertionInfo
const& assertionInfo ) {
17185 for (
auto const& listener : m_listeners ) {
17186 listener->assertionStarting( assertionInfo );
17188 m_reporter->assertionStarting( assertionInfo );
17192 bool ListeningReporter::assertionEnded( AssertionStats
const& assertionStats ) {
17193 for(
auto const& listener : m_listeners ) {
17194 static_cast<void>( listener->assertionEnded( assertionStats ) );
17196 return m_reporter->assertionEnded( assertionStats );
17199 void ListeningReporter::sectionEnded( SectionStats
const& sectionStats ) {
17200 for (
auto const& listener : m_listeners ) {
17201 listener->sectionEnded( sectionStats );
17203 m_reporter->sectionEnded( sectionStats );
17206 void ListeningReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
17207 for (
auto const& listener : m_listeners ) {
17208 listener->testCaseEnded( testCaseStats );
17210 m_reporter->testCaseEnded( testCaseStats );
17213 void ListeningReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
17214 for (
auto const& listener : m_listeners ) {
17215 listener->testGroupEnded( testGroupStats );
17217 m_reporter->testGroupEnded( testGroupStats );
17220 void ListeningReporter::testRunEnded( TestRunStats
const& testRunStats ) {
17221 for (
auto const& listener : m_listeners ) {
17222 listener->testRunEnded( testRunStats );
17224 m_reporter->testRunEnded( testRunStats );
17227 void ListeningReporter::skipTest( TestCaseInfo
const& testInfo ) {
17228 for (
auto const& listener : m_listeners ) {
17229 listener->skipTest( testInfo );
17231 m_reporter->skipTest( testInfo );
17234 bool ListeningReporter::isMulti()
const {
17242 #if defined(_MSC_VER)
17243 #pragma warning(push)
17244 #pragma warning(disable:4061)
17250 XmlReporter::XmlReporter( ReporterConfig
const& _config )
17251 : StreamingReporterBase( _config ),
17254 m_reporterPrefs.shouldRedirectStdOut =
true;
17255 m_reporterPrefs.shouldReportAllAssertions =
true;
17258 XmlReporter::~XmlReporter() =
default;
17261 return "Reports test results as an XML document";
17264 std::string XmlReporter::getStylesheetRef()
const {
17268 void XmlReporter::writeSourceInfo( SourceLineInfo
const& sourceInfo ) {
17270 .writeAttribute(
"filename", sourceInfo.file )
17271 .writeAttribute(
"line", sourceInfo.line );
17274 void XmlReporter::noMatchingTestCases(
std::string const&
s ) {
17275 StreamingReporterBase::noMatchingTestCases(
s );
17278 void XmlReporter::testRunStarting( TestRunInfo
const& testInfo ) {
17279 StreamingReporterBase::testRunStarting( testInfo );
17281 if( !stylesheetRef.empty() )
17282 m_xml.writeStylesheetRef( stylesheetRef );
17283 m_xml.startElement(
"Catch" );
17284 if( !m_config->name().empty() )
17285 m_xml.writeAttribute(
"name", m_config->name() );
17286 if (m_config->testSpec().hasFilters())
17287 m_xml.writeAttribute(
"filters", serializeFilters( m_config->getTestsOrTags() ) );
17288 if( m_config->rngSeed() != 0 )
17289 m_xml.scopedElement(
"Randomness" )
17290 .writeAttribute(
"seed", m_config->rngSeed() );
17293 void XmlReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
17294 StreamingReporterBase::testGroupStarting( groupInfo );
17295 m_xml.startElement(
"Group" )
17296 .writeAttribute(
"name", groupInfo.name );
17299 void XmlReporter::testCaseStarting( TestCaseInfo
const& testInfo ) {
17300 StreamingReporterBase::testCaseStarting(testInfo);
17301 m_xml.startElement(
"TestCase" )
17302 .writeAttribute(
"name",
trim( testInfo.name ) )
17303 .writeAttribute(
"description", testInfo.description )
17304 .writeAttribute(
"tags", testInfo.tagsAsString() );
17306 writeSourceInfo( testInfo.lineInfo );
17309 m_testCaseTimer.start();
17310 m_xml.ensureTagClosed();
17313 void XmlReporter::sectionStarting( SectionInfo
const& sectionInfo ) {
17314 StreamingReporterBase::sectionStarting( sectionInfo );
17315 if( m_sectionDepth++ > 0 ) {
17316 m_xml.startElement(
"Section" )
17317 .writeAttribute(
"name",
trim( sectionInfo.name ) );
17318 writeSourceInfo( sectionInfo.lineInfo );
17319 m_xml.ensureTagClosed();
17323 void XmlReporter::assertionStarting( AssertionInfo
const& ) { }
17325 bool XmlReporter::assertionEnded( AssertionStats
const& assertionStats ) {
17327 AssertionResult
const&
result = assertionStats.assertionResult;
17329 bool includeResults = m_config->includeSuccessfulResults() || !
result.isOk();
17333 for(
auto const&
msg : assertionStats.infoMessages ) {
17335 m_xml.scopedElement(
"Info" )
17336 .writeText(
msg.message );
17338 m_xml.scopedElement(
"Warning" )
17339 .writeText(
msg.message );
17349 if(
result.hasExpression() ) {
17350 m_xml.startElement(
"Expression" )
17351 .writeAttribute(
"success",
result.succeeded() )
17352 .writeAttribute(
"type",
result.getTestMacroName() );
17354 writeSourceInfo(
result.getSourceInfo() );
17356 m_xml.scopedElement(
"Original" )
17357 .writeText(
result.getExpression() );
17358 m_xml.scopedElement(
"Expanded" )
17359 .writeText(
result.getExpandedExpression() );
17363 switch(
result.getResultType() ) {
17365 m_xml.startElement(
"Exception" );
17366 writeSourceInfo(
result.getSourceInfo() );
17367 m_xml.writeText(
result.getMessage() );
17368 m_xml.endElement();
17371 m_xml.startElement(
"FatalErrorCondition" );
17372 writeSourceInfo(
result.getSourceInfo() );
17373 m_xml.writeText(
result.getMessage() );
17374 m_xml.endElement();
17377 m_xml.scopedElement(
"Info" )
17378 .writeText(
result.getMessage() );
17384 m_xml.startElement(
"Failure" );
17385 writeSourceInfo(
result.getSourceInfo() );
17386 m_xml.writeText(
result.getMessage() );
17387 m_xml.endElement();
17393 if(
result.hasExpression() )
17394 m_xml.endElement();
17399 void XmlReporter::sectionEnded( SectionStats
const& sectionStats ) {
17400 StreamingReporterBase::sectionEnded( sectionStats );
17401 if( --m_sectionDepth > 0 ) {
17402 XmlWriter::ScopedElement
e = m_xml.scopedElement(
"OverallResults" );
17403 e.writeAttribute(
"successes", sectionStats.assertions.passed );
17404 e.writeAttribute(
"failures", sectionStats.assertions.failed );
17405 e.writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
17408 e.writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
17410 m_xml.endElement();
17414 void XmlReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
17415 StreamingReporterBase::testCaseEnded( testCaseStats );
17416 XmlWriter::ScopedElement
e = m_xml.scopedElement(
"OverallResult" );
17417 e.writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
17420 e.writeAttribute(
"durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
17422 if( !testCaseStats.stdOut.empty() )
17423 m_xml.scopedElement(
"StdOut" ).writeText(
trim( testCaseStats.stdOut ), XmlFormatting::Newline );
17424 if( !testCaseStats.stdErr.empty() )
17425 m_xml.scopedElement(
"StdErr" ).writeText(
trim( testCaseStats.stdErr ), XmlFormatting::Newline );
17427 m_xml.endElement();
17430 void XmlReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
17431 StreamingReporterBase::testGroupEnded( testGroupStats );
17433 m_xml.scopedElement(
"OverallResults" )
17434 .writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
17435 .writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
17436 .writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
17437 m_xml.scopedElement(
"OverallResultsCases")
17438 .writeAttribute(
"successes", testGroupStats.totals.testCases.passed )
17439 .writeAttribute(
"failures", testGroupStats.totals.testCases.failed )
17440 .writeAttribute(
"expectedFailures", testGroupStats.totals.testCases.failedButOk );
17441 m_xml.endElement();
17444 void XmlReporter::testRunEnded( TestRunStats
const& testRunStats ) {
17445 StreamingReporterBase::testRunEnded( testRunStats );
17446 m_xml.scopedElement(
"OverallResults" )
17447 .writeAttribute(
"successes", testRunStats.totals.assertions.passed )
17448 .writeAttribute(
"failures", testRunStats.totals.assertions.failed )
17449 .writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
17450 m_xml.scopedElement(
"OverallResultsCases")
17451 .writeAttribute(
"successes", testRunStats.totals.testCases.passed )
17452 .writeAttribute(
"failures", testRunStats.totals.testCases.failed )
17453 .writeAttribute(
"expectedFailures", testRunStats.totals.testCases.failedButOk );
17454 m_xml.endElement();
17457 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
17459 m_xml.startElement(
"BenchmarkResults")
17460 .writeAttribute(
"name",
name);
17463 void XmlReporter::benchmarkStarting(BenchmarkInfo
const &
info) {
17464 m_xml.writeAttribute(
"samples",
info.samples)
17465 .writeAttribute(
"resamples",
info.resamples)
17466 .writeAttribute(
"iterations",
info.iterations)
17467 .writeAttribute(
"clockResolution",
info.clockResolution)
17468 .writeAttribute(
"estimatedDuration",
info.estimatedDuration)
17469 .writeComment(
"All values in nano seconds");
17472 void XmlReporter::benchmarkEnded(BenchmarkStats<>
const& benchmarkStats) {
17473 m_xml.startElement(
"mean")
17474 .writeAttribute(
"value", benchmarkStats.mean.point.count())
17475 .writeAttribute(
"lowerBound", benchmarkStats.mean.lower_bound.count())
17476 .writeAttribute(
"upperBound", benchmarkStats.mean.upper_bound.count())
17477 .writeAttribute(
"ci", benchmarkStats.mean.confidence_interval);
17478 m_xml.endElement();
17479 m_xml.startElement(
"standardDeviation")
17480 .writeAttribute(
"value", benchmarkStats.standardDeviation.point.count())
17481 .writeAttribute(
"lowerBound", benchmarkStats.standardDeviation.lower_bound.count())
17482 .writeAttribute(
"upperBound", benchmarkStats.standardDeviation.upper_bound.count())
17483 .writeAttribute(
"ci", benchmarkStats.standardDeviation.confidence_interval);
17484 m_xml.endElement();
17485 m_xml.startElement(
"outliers")
17486 .writeAttribute(
"variance", benchmarkStats.outlierVariance)
17487 .writeAttribute(
"lowMild", benchmarkStats.outliers.low_mild)
17488 .writeAttribute(
"lowSevere", benchmarkStats.outliers.low_severe)
17489 .writeAttribute(
"highMild", benchmarkStats.outliers.high_mild)
17490 .writeAttribute(
"highSevere", benchmarkStats.outliers.high_severe);
17491 m_xml.endElement();
17492 m_xml.endElement();
17496 m_xml.scopedElement(
"failed").
17497 writeAttribute(
"message",
error);
17498 m_xml.endElement();
17502 CATCH_REGISTER_REPORTER(
"xml", XmlReporter )
17506 #if defined(_MSC_VER)
17507 #pragma warning(pop)
17512 LeakDetector leakDetector;
17516 #pragma clang diagnostic pop
17522 #ifdef CATCH_CONFIG_MAIN
17527 #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
17529 extern "C" int wmain (
int argc,
wchar_t * argv[],
wchar_t * []) {
17532 int main (
int argc,
char * argv[]) {
17535 return Catch::Session().run( argc, argv );
17541 int main (
int argc,
char *
const argv[]) {
17542 #if !CATCH_ARC_ENABLED
17543 NSAutoreleasePool *
pool = [[NSAutoreleasePool alloc] init];
17546 Catch::registerTestMethods();
17547 int result = Catch::Session().run( argc, (
char**)argv );
17549 #if !CATCH_ARC_ENABLED
17561 #if !defined(CATCH_CONFIG_IMPL_ONLY)
17563 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
17564 # undef CLARA_CONFIG_MAIN
17567 #if !defined(CATCH_CONFIG_DISABLE)
17570 #ifdef CATCH_CONFIG_PREFIX_ALL
17572 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17573 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17575 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17576 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
17577 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
17578 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17579 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
17581 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17583 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17584 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17585 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17586 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17587 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
17589 #define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17590 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
17591 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
17592 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17593 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
17595 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17597 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17598 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
17600 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
17603 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
17604 #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
17605 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
17606 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )
17608 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
17609 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
17610 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
17611 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
17612 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
17613 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
17614 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
17615 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17616 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17618 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
17620 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
17621 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17622 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
17623 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17624 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
17625 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
17626 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
17627 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
17628 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
17630 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
17631 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
17632 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
17633 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
17634 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
17635 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
17636 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
17637 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
17640 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
17641 #define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ )
17642 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
17644 #define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ )
17645 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
17649 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
17650 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
17651 #define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
17652 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
17653 #define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
17654 #define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
17655 #define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
17656 #define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
17658 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
17659 #define CATCH_BENCHMARK(...) \
17660 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
17661 #define CATCH_BENCHMARK_ADVANCED(name) \
17662 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name)
17668 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17669 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17671 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17672 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
17673 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
17674 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17675 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
17677 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17679 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17680 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17681 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17682 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17683 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
17685 #define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17686 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
17687 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
17688 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17689 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
17691 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17693 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17694 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
17696 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
17699 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
17700 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
17701 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
17702 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
17704 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
17705 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
17706 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
17707 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
17708 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
17709 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
17710 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
17711 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17712 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17713 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
17715 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
17716 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17717 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
17718 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17719 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
17720 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
17721 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
17722 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
17723 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
17724 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
17725 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
17727 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
17728 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
17729 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
17730 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
17731 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
17732 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
17733 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
17734 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
17735 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
17736 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
17739 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
17740 #define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
17741 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
17743 #define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ )
17744 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
17749 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
17752 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
17753 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
17755 #define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
17756 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
17757 #define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
17758 #define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
17759 #define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
17760 #define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
17762 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
17763 #define BENCHMARK(...) \
17764 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
17765 #define BENCHMARK_ADVANCED(name) \
17766 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(C_A_T_C_H_B_E_N_C_H_), name)
17775 #ifdef CATCH_CONFIG_PREFIX_ALL
17777 #define CATCH_REQUIRE( ... ) (void)(0)
17778 #define CATCH_REQUIRE_FALSE( ... ) (void)(0)
17780 #define CATCH_REQUIRE_THROWS( ... ) (void)(0)
17781 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
17782 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
17783 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17784 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
17786 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
17788 #define CATCH_CHECK( ... ) (void)(0)
17789 #define CATCH_CHECK_FALSE( ... ) (void)(0)
17790 #define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__)
17791 #define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
17792 #define CATCH_CHECK_NOFAIL( ... ) (void)(0)
17794 #define CATCH_CHECK_THROWS( ... ) (void)(0)
17795 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
17796 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0)
17797 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17798 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
17800 #define CATCH_CHECK_NOTHROW( ... ) (void)(0)
17802 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17803 #define CATCH_CHECK_THAT( arg, matcher ) (void)(0)
17805 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
17808 #define CATCH_INFO( msg ) (void)(0)
17809 #define CATCH_UNSCOPED_INFO( msg ) (void)(0)
17810 #define CATCH_WARN( msg ) (void)(0)
17811 #define CATCH_CAPTURE( msg ) (void)(0)
17813 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
17814 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
17815 #define CATCH_METHOD_AS_TEST_CASE( method, ... )
17816 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
17817 #define CATCH_SECTION( ... )
17818 #define CATCH_DYNAMIC_SECTION( ... )
17819 #define CATCH_FAIL( ... ) (void)(0)
17820 #define CATCH_FAIL_CHECK( ... ) (void)(0)
17821 #define CATCH_SUCCEED( ... ) (void)(0)
17823 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
17825 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
17826 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
17827 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
17828 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
17829 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
17830 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17831 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17832 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17833 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17835 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
17836 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
17837 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
17838 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
17839 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17840 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17841 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17842 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17846 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
17847 #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 )
17848 #define CATCH_GIVEN( desc )
17849 #define CATCH_AND_GIVEN( desc )
17850 #define CATCH_WHEN( desc )
17851 #define CATCH_AND_WHEN( desc )
17852 #define CATCH_THEN( desc )
17853 #define CATCH_AND_THEN( desc )
17855 #define CATCH_STATIC_REQUIRE( ... ) (void)(0)
17856 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
17861 #define REQUIRE( ... ) (void)(0)
17862 #define REQUIRE_FALSE( ... ) (void)(0)
17864 #define REQUIRE_THROWS( ... ) (void)(0)
17865 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
17866 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
17867 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17868 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
17870 #define REQUIRE_NOTHROW( ... ) (void)(0)
17872 #define CHECK( ... ) (void)(0)
17873 #define CHECK_FALSE( ... ) (void)(0)
17874 #define CHECKED_IF( ... ) if (__VA_ARGS__)
17875 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
17876 #define CHECK_NOFAIL( ... ) (void)(0)
17878 #define CHECK_THROWS( ... ) (void)(0)
17879 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
17880 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
17881 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17882 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
17884 #define CHECK_NOTHROW( ... ) (void)(0)
17886 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17887 #define CHECK_THAT( arg, matcher ) (void)(0)
17889 #define REQUIRE_THAT( arg, matcher ) (void)(0)
17892 #define INFO( msg ) (void)(0)
17893 #define UNSCOPED_INFO( msg ) (void)(0)
17894 #define WARN( msg ) (void)(0)
17895 #define CAPTURE( msg ) (void)(0)
17897 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
17898 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
17899 #define METHOD_AS_TEST_CASE( method, ... )
17900 #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
17901 #define SECTION( ... )
17902 #define DYNAMIC_SECTION( ... )
17903 #define FAIL( ... ) (void)(0)
17904 #define FAIL_CHECK( ... ) (void)(0)
17905 #define SUCCEED( ... ) (void)(0)
17906 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ))
17908 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
17909 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
17910 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
17911 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
17912 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
17913 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
17914 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
17915 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17916 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17918 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
17919 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
17920 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
17921 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
17922 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
17923 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
17924 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17925 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17928 #define STATIC_REQUIRE( ... ) (void)(0)
17929 #define STATIC_REQUIRE_FALSE( ... ) (void)(0)
17933 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
17936 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ) )
17937 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( C_A_T_C_H_T_E_S_T_ ), className )
17939 #define GIVEN( desc )
17940 #define AND_GIVEN( desc )
17941 #define WHEN( desc )
17942 #define AND_WHEN( desc )
17943 #define THEN( desc )
17944 #define AND_THEN( desc )
17957 # pragma warning(pop)
17959 # pragma clang diagnostic pop
17961 #elif defined __GNUC__
17962 # pragma GCC diagnostic pop
small capitals from c petite p scientific f u
small capitals from c petite p scientific i
[1]
#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH
#define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
#define CATCH_CATCH_ANON(type)
#define CATCH_RUNTIME_ERROR(...)
#define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
#define CATCH_ENFORCE(condition,...)
#define CATCH_INTERNAL_LINEINFO
#define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
#define CATCH_INTERNAL_ERROR(...)
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)
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)
Approx operator()(T const &value) const
Approx & margin(T const &newMargin)
Approx & scale(T const &newScale)
std::string toString() const
Approx & epsilon(T const &newEpsilon)
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
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 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
FilterGenerator(P &&pred, GeneratorWrapper< T > &&generator)
T const & get() const override
FixedValuesGenerator(std::initializer_list< T > values)
T const & get() const override
GeneratorUntypedBase()=default
virtual ~GeneratorUntypedBase()
GeneratorWrapper(std::unique_ptr< IGenerator< T >> generator)
Generators(Gs &&... moreGenerators)
T const & get() const override
IteratorGenerator(InputIterator first, InputSentinel last)
T const & get() const override
T const & get() const override
MapGenerator(F2 &&function, GeneratorWrapper< U > &&generator)
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)
RepeatGenerator(size_t repeats, GeneratorWrapper< T > &&generator)
T const & get() const override
T const & get() const override
SingleValueGenerator(T &&value)
T const & get() const override
TakeGenerator(size_t target, GeneratorWrapper< T > &&generator)
LazyExpression(bool isNegated)
friend struct AssertionStats
friend auto operator<<(std::ostream &os, LazyExpression const &lazyExpr) -> std::ostream &
LazyExpression(LazyExpression const &other)
LazyExpression & operator=(LazyExpression const &)=delete
void streamReconstructedExpression(std::ostream &os) const override
MatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef const &matcherString)
std::string describe() const override
bool match(std::exception const &ex) const override
ExceptionMessageMatcher(std::string const &message)
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
MatcherUntypedBase()=default
T const & operator*() const
Option & operator=(Option const &_other)
T valueOr(T const &defaultValue) const
const T * operator->() const
Option(Option const &_other)
auto str() const -> std::string
auto get() -> std::ostream &
ScopedMessage(MessageBuilder const &builder)
ScopedMessage(ScopedMessage &duplicate)=delete
ScopedMessage(ScopedMessage &&old)
Section(SectionInfo const &info)
void seed(result_type seed_)
std::uint32_t result_type
friend bool operator==(SimplePcg32 const &lhs, SimplePcg32 const &rhs)
friend bool operator!=(SimplePcg32 const &lhs, SimplePcg32 const &rhs)
void discard(uint64_t skip)
SimplePcg32(result_type seed_)
constexpr auto empty() const noexcept -> bool
auto c_str() const -> char const *
constexpr const_iterator end() const
auto operator[](size_type index) const noexcept -> char
auto substr(size_type start, size_type length) const noexcept -> StringRef
constexpr StringRef() noexcept=default
constexpr auto isNullTerminated() const noexcept -> bool
StringRef(std::string const &stdString) noexcept
auto operator!=(StringRef const &other) const noexcept -> bool
auto operator==(StringRef const &other) const noexcept -> bool
constexpr const_iterator begin() const
auto data() const noexcept -> char const *
const char * const_iterator
constexpr auto size() const noexcept -> size_type
bool operator<(TestCase const &other) const
TestCase withName(std::string const &_newName) const
TestCaseInfo const & getTestCaseInfo() const
bool operator==(TestCase const &other) const
TestCase(ITestInvoker *testCase, TestCaseInfo &&info)
TestInvokerAsMethod(void(C::*testAsMethod)()) noexcept
void invoke() const override
auto getElapsedSeconds() const -> double
auto getElapsedNanoseconds() const -> uint64_t
operator<<(QDataStream &ds, qfloat16 f)
template< typename Enum > bool operator!=(Enum lhs, QFlags< Enum > rhs)
template< typename Enum > bool operator==(Enum lhs, QFlags< Enum > rhs)
void push_back(parameter_type t)
void reserve(qsizetype size)
void swap(QPainterPath &other) noexcept
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
XmlWriter(QTextDocument *document)
QHash< int, QWidget * > hash
[35multi]
constexpr T & operator()(T &v) const
auto it unsigned count const
backing_store_ptr info
[4]
QT_BEGIN_NAMESPACE bool operator<(const QMimeType &t1, const QMimeType &t2)
triState operator!(const triState &rhs)
std::string convertUnknownEnumToString(E e)
std::string rawMemoryToString(const T &object)
const std::string unprintableString
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 rangeToString(InputIterator first, Sentinel last)
std::string stringify(const T &e)
std::unique_ptr< T > make_unique(Args &&... args)
GeneratorWrapper< std::vector< T > > chunk(size_t size, GeneratorWrapper< T > &&generator)
std::unique_ptr< GeneratorUntypedBase > GeneratorBasePtr
GeneratorWrapper< T > repeat(size_t repeats, GeneratorWrapper< T > &&generator)
auto generate(StringRef generatorName, SourceLineInfo const &lineInfo, L const &generatorExpression) -> decltype(std::declval< decltype(generatorExpression())>().get())
GeneratorWrapper< T > value(T &&value)
GeneratorWrapper< T > values(std::initializer_list< T > values)
std::enable_if< std::is_floating_point< T >::value, GeneratorWrapper< T > >::type random(T a, T b)
GeneratorWrapper< T > range(T const &start, T const &end)
GeneratorWrapper< T > take(size_t target, GeneratorWrapper< T > &&generator)
auto makeGenerators(as< T >, U &&val, Gs &&... moreGenerators) -> Generators< T >
auto acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const &lineInfo) -> IGeneratorTracker &
GeneratorWrapper< ResultType > from_range(Container const &cnt)
GeneratorWrapper< T > map(Func &&function, GeneratorWrapper< U > &&generator)
GeneratorWrapper< T > filter(Predicate &&pred, GeneratorWrapper< T > &&generator)
std::string finalizeDescription(const std::string &desc)
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
Exception::ExceptionMessageMatcher Message(std::string const &message)
Floating::WithinRelMatcher WithinRel(float target)
Vector::EqualsMatcher< T, AllocComp, AllocMatch > Equals(std::vector< T, AllocComp > const &comparator)
Floating::WithinAbsMatcher WithinAbs(double target, double margin)
Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff)
Vector::ContainsMatcher< T, AllocComp, AllocMatch > Contains(std::vector< T, AllocComp > const &comparator)
StdString::RegexMatcher Matches(std::string const ®ex, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Vector::ContainsElementMatcher< T, Alloc > VectorContains(T const &comparator)
StdString::StartsWithMatcher StartsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Vector::UnorderedEqualsMatcher< T, AllocComp, AllocMatch > UnorderedEquals(std::vector< T, AllocComp > const &target)
StdString::EndsWithMatcher EndsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Vector::ApproxMatcher< T, AllocComp, AllocMatch > Approx(std::vector< T, AllocComp > const &comparator)
StdString::EqualsMatcher Equals(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
void toLowerInPlace(std::string &s)
std::string trim(std::string const &str)
Returns a new string without whitespace at the start/end.
std::vector< TestCase > const & getAllTestCasesSorted(IConfig const &config)
auto makeMatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef const &matcherString) -> MatchExpr< ArgT, MatcherT >
typename std::remove_reference< typename std::remove_cv< typename std::result_of< Func(U...)>::type >::type >::type FunctionReturnType
std::vector< StringRef > splitStringRef(StringRef str, char delimiter)
void throw_exception(std::exception const &e)
void throw_runtime_error(std::string const &msg)
void formatReconstructedExpression(std::ostream &os, std::string const &lhs, StringRef op, std::string const &rhs)
bool isOk(ResultWas::OfType resultType)
bool isJustInfo(int flags)
TestCase makeTestCase(ITestInvoker *testCase, std::string const &className, NameAndTags const &nameAndTags, SourceLineInfo const &lineInfo)
T const & operator+(T const &value, StreamEndStop)
auto operator+=(std::string &lhs, StringRef const &sr) -> std::string &
IRegistryHub const & getRegistryHub()
void handleExpression(ITransientExpression const &expr)
bool startsWith(std::string const &s, std::string const &prefix)
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
void throw_logic_error(std::string const &msg)
std::vector< std::unique_ptr< IExceptionTranslator const > > ExceptionTranslators
bool shouldContinueOnFailure(int flags)
auto compareNotEqual(LhsT const &lhs, RhsT &&rhs) -> bool
bool isFalseTest(int flags)
auto getCurrentNanosecondsSinceEpoch() -> uint64_t
bool contains(std::string const &s, std::string const &infix)
bool matchTest(TestCase const &testCase, TestSpec const &testSpec, IConfig const &config)
ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
auto makeTestInvoker(void(*testAsFunction)()) noexcept -> ITestInvoker *
std::vector< TestCase > filterTests(std::vector< TestCase > const &testCases, TestSpec const &testSpec, IConfig const &config)
bool shouldSuppressFailure(int flags)
Matchers::Impl::MatcherBase< std::string > StringMatcher
std::string toLower(std::string const &s)
auto getEstimatedClockResolution() -> uint64_t
IMutableRegistryHub & getMutableRegistryHub()
bool startsWith(std::string const &s, char prefix)
std::shared_ptr< IReporterFactory > IReporterFactoryPtr
IContext & getCurrentContext()
bool endsWith(std::string const &s, std::string const &suffix)
std::string translateActiveException()
std::string rangeToString(std::vector< bool, Allocator > const &v)
void throw_domain_error(std::string const &msg)
std::string(*)() exceptionTranslateFunction
void handleExceptionMatchExpr(AssertionHandler &handler, std::string const &str, StringRef const &matcherString)
std::string rangeToString(Range const &range)
bool isThrowSafe(TestCase const &testCase, IConfig const &config)
auto makeStream(StringRef const &filename) -> IStream const *
IMutableContext & getCurrentMutableContext()
auto compareEqual(LhsT const &lhs, RhsT const &rhs) -> bool
std::shared_ptr< IConfig const > IConfigPtr
bool replaceInPlace(std::string &str, std::string const &replaceThis, std::string const &withThis)
IResultCapture & getResultCapture()
typename C::value_type value_type
typename C::const_iterator const_iterator
typename C::iterator iterator
void toString(QString &appendTo, IPv4Address address)
Q_TESTLIB_EXPORT QTestData & addRow(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
Q_DECL_CONST_FUNCTION Q_CORE_EXPORT const Properties *QT_FASTCALL properties(char32_t ucs4) noexcept
QFuture< typename std::decay_t< Sequence >::value_type > filtered(QThreadPool *pool, Sequence &&sequence, KeepFunctor &&keep)
QTextStream & fixed(QTextStream &stream)
QTextStream & endl(QTextStream &stream)
QTextStream & scientific(QTextStream &stream)
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QByteArrayView trimmed(QByteArrayView s) noexcept
typing.Tuple[int, int] test(str binary_directory, *debug=False)
QString enumValue(const QString &value)
constexpr struct q20::ranges::@309 any_of
constexpr struct q20::ranges::@310 all_of
int PRIV() strcmp(PCRE2_SPTR str1, PCRE2_SPTR str2)
PCRE2_SIZE PRIV() strlen(PCRE2_SPTR str)
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d ®2 endm macro vzip8 reg2 vzip d d ®2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
[3]
set set set set set set set macro pixldst1 op
Q_CORE_EXPORT QBitArray operator&(const QBitArray &, const QBitArray &)
SharedPointerFileDialogOptions m_options
constexpr bool operator!=(const timespec &t1, const timespec &t2)
constexpr timespec operator*(const timespec &t1, int mul)
constexpr timespec operator-(const timespec &t1, const timespec &t2)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
EGLOutputLayerEXT EGLint EGLAttrib value
EGLOutputLayerEXT EGLint attribute
bool operator==(const QMakeBaseKey &one, const QMakeBaseKey &two)
GLenum GLuint GLenum GLsizei length
GLenum GLuint GLenum GLsizei const GLchar * message
GLenum GLsizei GLsizei GLint * values
[16]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLuint GLsizei const GLchar * label
[43]
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLsizei GLchar * source
GLenum GLenum GLsizei void GLsizei void * column
GLuint GLenum GLenum transform
GLsizei const void * pointer
GLdouble GLdouble GLdouble GLdouble q
GLenum GLenum GLsizei void * row
GLfixed GLfixed GLint GLint order
GLenum GLenum GLsizei void * table
GLenum GLint GLint * precision
GLsizei const GLchar *const * string
[0]
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
Q_ALWAYS_INLINE QString to_string(QLatin1String s) noexcept
QUrl::FormattingOptions & operator|=(QUrl::FormattingOptions &i, QUrl::ComponentFormattingOptions f)
bool operator<=(const QUuid &lhs, const QUuid &rhs) noexcept
bool operator>=(const QUuid &lhs, const QUuid &rhs) noexcept
const char className[16]
[1]
QSqlQueryModel * model
[16]
QFuture< QSet< QChar > > set
[10]
QRandomGenerator generator(sseq)
std::uniform_real_distribution dist(1, 2.5)
[2]
file open(QIODevice::ReadOnly)
QFileSelector selector
[1]
gzip write("uncompressed data")
settings remove("monkey")
QTextStream out(stdout)
[7]
QUrl url("http://www.example.com/List of holidays.xml")
[0]
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]
QItemEditorFactory * factory
header setValue("Host", "qt-project.org")
http get(QUrl::toPercentEncoding("/index.html"))
ResultDisposition::Flags resultDisposition
StringRef capturedExpression
AutoReg(ITestInvoker *invoker, SourceLineInfo const &lineInfo, StringRef const &classOrMethod, NameAndTags const &nameAndTags) noexcept
Counts & operator+=(Counts const &other)
std::size_t total() const
Counts operator-(Counts const &other) const
auto operator<=(T const &lhs) -> ExprLhs< T const & >
StringRef lookup(int value) const
std::vector< std::pair< int, StringRef > > m_values
virtual T const & get() const =0
virtual ~IGenerator()=default
virtual TestSpec const & testSpec() const =0
virtual RunTests::InWhatOrder runOrder() const =0
virtual double minDuration() const =0
virtual std::vector< std::string > const & getTestsOrTags() const =0
virtual bool includeSuccessfulResults() const =0
virtual bool warnAboutNoTests() const =0
virtual int abortAfter() const =0
virtual unsigned int benchmarkResamples() const =0
virtual bool hasTestFilters() const =0
virtual std::chrono::milliseconds benchmarkWarmupTime() const =0
virtual Verbosity verbosity() const =0
virtual int benchmarkSamples() const =0
virtual bool shouldDebugBreak() const =0
virtual bool warnAboutMissingAssertions() const =0
virtual UseColour::YesOrNo useColour() const =0
virtual std::string name() const =0
virtual bool showInvisibles() const =0
virtual std::ostream & stream() const =0
virtual bool benchmarkNoAnalysis() const =0
virtual bool allowThrows() const =0
virtual ShowDurations::OrNot showDurations() const =0
virtual unsigned int rngSeed() const =0
virtual double benchmarkConfidenceInterval() const =0
virtual std::vector< std::string > const & getSectionsToRun() const =0
virtual IResultCapture * getResultCapture()=0
virtual IConfigPtr const & getConfig() const =0
virtual IRunner * getRunner()=0
virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const =0
virtual ~IExceptionTranslator()
virtual ~IExceptionTranslatorRegistry()
virtual std::string translateActiveException() const =0
virtual ~IGeneratorTracker()
virtual auto getGenerator() const -> Generators::GeneratorBasePtr const &=0
virtual void setGenerator(Generators::GeneratorBasePtr &&generator)=0
virtual auto hasGenerator() const -> bool=0
virtual void setResultCapture(IResultCapture *resultCapture)=0
virtual ~IMutableContext()
virtual void setConfig(IConfigPtr const &config)=0
friend void cleanUpContext()
virtual void setRunner(IRunner *runner)=0
Detail::EnumInfo const & registerEnum(StringRef enumName, StringRef allEnums, std::initializer_list< E > values)
virtual Detail::EnumInfo const & registerEnum(StringRef enumName, StringRef allEnums, std::vector< int > const &values)=0
virtual ~IMutableEnumValuesRegistry()
virtual void registerTest(TestCase const &testInfo)=0
virtual void registerReporter(std::string const &name, IReporterFactoryPtr const &factory)=0
virtual void registerStartupException() noexcept=0
virtual ~IMutableRegistryHub()
virtual void registerListener(IReporterFactoryPtr const &factory)=0
virtual void registerTagAlias(std::string const &alias, std::string const &tag, SourceLineInfo const &lineInfo)=0
virtual void registerTranslator(const IExceptionTranslator *translator)=0
virtual StartupExceptionRegistry const & getStartupExceptionRegistry() const =0
virtual ITagAliasRegistry const & getTagAliasRegistry() const =0
virtual IExceptionTranslatorRegistry const & getExceptionTranslatorRegistry() const =0
virtual IReporterRegistry const & getReporterRegistry() const =0
virtual ITestCaseRegistry const & getTestCaseRegistry() const =0
virtual void handleMessage(AssertionInfo const &info, ResultWas::OfType resultType, StringRef const &message, AssertionReaction &reaction)=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 handleIncomplete(AssertionInfo const &info)=0
virtual auto acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const &lineInfo) -> IGeneratorTracker &=0
virtual void pushScopedMessage(MessageInfo const &message)=0
virtual bool lastAssertionPassed()=0
virtual void assertionPassed()=0
virtual const AssertionResult * getLastResult() const =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 std::vector< TestCase > const & getAllTestsSorted(IConfig const &config) const =0
virtual std::vector< TestCase > const & getAllTests() const =0
virtual ~ITestCaseRegistry()
virtual void invoke() const =0
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
WithinRelMatcher(double target, double epsilon)
bool match(double const &matchee) const override
std::string describe() const override
WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)
bool match(double const &matchee) const override
std::string describe() const override
std::vector< MatcherBase< ArgT > const * > m_matchers
std::string describe() const override
bool match(ArgT const &arg) const override
std::vector< MatcherBase< ArgT > const * > m_matchers
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
MatcherBase< ArgT > const & m_underlyingMatcher
MatchNotOf< T > operator!() const
MatchAnyOf< T > operator||(MatcherBase const &other) const
MatchAllOf< T > operator&&(MatcherBase const &other) const
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)
CaseSensitive::Choice m_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
ApproxMatcher(std::vector< T, AllocComp > const &comparator)
ApproxMatcher & epsilon(T const &newEpsilon)
std::vector< T, AllocComp > const & m_comparator
ApproxMatcher & margin(T const &newMargin)
ApproxMatcher & scale(T const &newScale)
std::string describe() const override
bool match(std::vector< T, AllocMatch > const &v) const override
ContainsElementMatcher(T const &comparator)
std::string describe() const override
bool match(std::vector< T, Alloc > const &v) const override
bool match(std::vector< T, AllocMatch > const &v) const override
ContainsMatcher(std::vector< T, AllocComp > const &comparator)
std::vector< T, AllocComp > const & m_comparator
std::string describe() const override
std::string describe() const override
bool match(std::vector< T, AllocMatch > const &v) const override
std::vector< T, AllocComp > const & m_comparator
EqualsMatcher(std::vector< T, AllocComp > const &comparator)
std::string describe() const override
UnorderedEqualsMatcher(std::vector< T, AllocComp > const &target)
bool match(std::vector< T, AllocMatch > const &vec) const override
MessageBuilder(StringRef const ¯oName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
bool operator<(MessageInfo const &other) const
bool operator==(MessageInfo const &other) const
MessageInfo(StringRef const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
ReusableStringStream m_stream
RegistrarForTagAliases(char const *alias, char const *tag, SourceLineInfo const &lineInfo)
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name, std::string const &)
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name)
bool empty() const noexcept
SourceLineInfo & operator=(SourceLineInfo const &)=default
SourceLineInfo(char const *_file, std::size_t _line) noexcept
SourceLineInfo(SourceLineInfo &&) noexcept=default
SourceLineInfo(SourceLineInfo const &other)=default
bool operator==(SourceLineInfo const &other) const noexcept
bool operator<(SourceLineInfo const &other) const noexcept
std::string operator+() const
static std::string convert(Catch::Detail::Approx const &value)
static std::string convert(R const &range)
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)
friend void setTags(TestCaseInfo &testCaseInfo, std::vector< std::string > tags)
std::vector< std::string > tags
std::string tagsAsString() const
std::vector< std::string > lcaseTags
bool expectedToFail() const
TestCaseInfo(std::string const &_name, std::string const &_className, std::string const &_description, std::vector< std::string > const &_tags, SourceLineInfo const &_lineInfo)
SpecialProperties properties
Totals delta(Totals const &prevTotals) const
Totals & operator+=(Totals const &other)
Totals operator-(Totals const &other) const
static true_given< decltype(std::declval< Fun >)(std::declval< Args >)...))> test(int)
static std::false_type test(...)
pluralise(std::size_t count, std::string const &label)
TempFile(QString filename)
QString escape(const QString &s)
void populate(Container &)
bool run(const QString &name, QString *errorMessage)
LockFileUsageInGlobalDtor s_instance
constexpr const auto messages
Str make(const QString &s)
void add(int &result, const int &sum)
void runTest(const QString &test, const TestLoggers &requestedLoggers)
Catch::Generators::GeneratorWrapper< T > enums()
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent
QDomElement find(const QString &tagName, const QDomElement &e)
XmlOutput::xml_output tag(const QString &name)