3 * Generated: 2021-04-10 23:43:17.560525
4 * ----------------------------------------------------------
5 * This file has been merged from multiple headers. Please don't edit it directly
6 * Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved.
8 * Distributed under the Boost Software License, Version 1.0. (See accompanying
9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
15 #define CATCH_VERSION_MAJOR 2
16 #define CATCH_VERSION_MINOR 13
17 #define CATCH_VERSION_PATCH 5
20 #pragma clang system_header
21 #elif defined __GNUC__
22 #pragma GCC system_header
25 // start catch_suppress_warnings.h
28 #ifdef __ICC // icpc defines the __clang__ macro
30 #pragma warning(disable : 161 1682)
32 #pragma clang diagnostic push
33 #pragma clang diagnostic ignored "-Wpadded"
34 #pragma clang diagnostic ignored "-Wswitch-enum"
35 #pragma clang diagnostic ignored "-Wcovered-switch-default"
37 #elif defined __GNUC__
38 // Because REQUIREs trigger GCC's -Wparentheses, and because still
39 // supported version of g++ have only buggy support for _Pragmas,
40 // Wparentheses have to be suppressed globally.
41 #pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details
43 #pragma GCC diagnostic push
44 #pragma GCC diagnostic ignored "-Wunused-variable"
45 #pragma GCC diagnostic ignored "-Wpadded"
47 // end catch_suppress_warnings.h
48 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
50 #define CATCH_CONFIG_ALL_PARTS
53 // In the impl file, we want to have access to all parts of the headers
54 // Can also be used to sanely support PCHs
55 #if defined(CATCH_CONFIG_ALL_PARTS)
56 #define CATCH_CONFIG_EXTERNAL_INTERFACES
57 #if defined(CATCH_CONFIG_DISABLE_MATCHERS)
58 #undef CATCH_CONFIG_DISABLE_MATCHERS
60 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
61 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
65 #if !defined(CATCH_CONFIG_IMPL_ONLY)
66 // start catch_platform.h
69 // https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html
71 #include <TargetConditionals.h>
72 #if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)
73 #define CATCH_PLATFORM_MAC
74 #elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)
75 #define CATCH_PLATFORM_IPHONE
78 #elif defined(linux) || defined(__linux) || defined(__linux__)
79 #define CATCH_PLATFORM_LINUX
81 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
82 #define CATCH_PLATFORM_WINDOWS
85 // end catch_platform.h
88 #ifndef CLARA_CONFIG_MAIN
89 #define CLARA_CONFIG_MAIN_NOT_DEFINED
90 #define CLARA_CONFIG_MAIN
94 // start catch_user_interfaces.h
97 unsigned int rngSeed();
100 // end catch_user_interfaces.h
101 // start catch_tag_alias_autoregistrar.h
103 // start catch_common.h
105 // start catch_compiler_capabilities.h
107 // Detect a number of compiler features - by compiler
108 // The following features are defined:
110 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
111 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
112 // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
113 // CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
115 // Note to maintainers: if new toggles are added please document them
116 // in configuration.md, too
119 // In general each macro has a _NO_<feature name> form
120 // (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
121 // Many features, at point of detection, define an _INTERNAL_ macro, so they
122 // can be combined, en-mass, with the _NO_ forms later.
126 #if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
127 #define CATCH_CPP14_OR_GREATER
130 #if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
131 #define CATCH_CPP17_OR_GREATER
136 // Only GCC compiler should be used in this block, so other compilers trying to
137 // mask themselves as GCC should be ignored.
138 #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)
139 #define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma("GCC diagnostic push")
140 #define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma("GCC diagnostic pop")
142 #define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
146 #if defined(__clang__)
148 #define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma("clang diagnostic push")
149 #define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma("clang diagnostic pop")
151 // As of this writing, IBM XL's implementation of __builtin_constant_p has a bug
152 // which results in calls to destructors being emitted for each temporary,
153 // without a matching initialization. In practice, this can result in something
154 // like `std::string::~string` being called on an uninitialized value.
156 // For example, this code will likely segfault under IBM XL:
158 // REQUIRE(std::string("12") + "34" == "1234")
161 // Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.
162 #if !defined(__ibmxl__) && !defined(__CUDACC__)
163 #define CATCH_INTERNAL_IGNORE_BUT_WARN(...) \
164 (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */
167 #define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
168 _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \
169 _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"")
171 #define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma("clang diagnostic ignored \"-Wparentheses\"")
173 #define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS _Pragma("clang diagnostic ignored \"-Wunused-variable\"")
175 #define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
176 _Pragma("clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"")
178 #define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS _Pragma("clang diagnostic ignored \"-Wunused-template\"")
182 ////////////////////////////////////////////////////////////////////////////////
183 // Assume that non-Windows platforms support posix signals by default
184 #if !defined(CATCH_PLATFORM_WINDOWS)
185 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
188 ////////////////////////////////////////////////////////////////////////////////
189 // We know some environments not to support full POSIX signals
190 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
191 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
195 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
196 #define CATCH_CONFIG_COLOUR_NONE
199 ////////////////////////////////////////////////////////////////////////////////
200 // Android somehow still does not support std::to_string
201 #if defined(__ANDROID__)
202 #define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
203 #define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
206 ////////////////////////////////////////////////////////////////////////////////
207 // Not all Windows environments support SEH properly
208 #if defined(__MINGW32__)
209 #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
212 ////////////////////////////////////////////////////////////////////////////////
214 #if defined(__ORBIS__)
215 #define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
218 ////////////////////////////////////////////////////////////////////////////////
222 // Required for some versions of Cygwin to declare gettimeofday
223 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
225 // some versions of cygwin (most) do not support std::to_string. Use the libstd check.
226 // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
227 #if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
229 #define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
234 ////////////////////////////////////////////////////////////////////////////////
236 #if defined(_MSC_VER)
238 #define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma(warning(push))
239 #define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma(warning(pop))
241 // Universal Windows platform does not support SEH
242 // Or console colours (or console at all...)
243 #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
244 #define CATCH_CONFIG_COLOUR_NONE
246 #define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
249 // MSVC traditional preprocessor needs some workaround for __VA_ARGS__
250 // _MSVC_TRADITIONAL == 0 means new conformant preprocessor
251 // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
252 #if !defined(__clang__) // Handle Clang masquerading for msvc
253 #if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
254 #define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
255 #endif // MSVC_TRADITIONAL
260 #if defined(_REENTRANT) || defined(_MSC_VER)
261 // Enable async processing, as -pthread is specified or no additional linking is required
262 #define CATCH_INTERNAL_CONFIG_USE_ASYNC
265 ////////////////////////////////////////////////////////////////////////////////
266 // Check if we are compiled with -fno-exceptions or equivalent
267 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
268 #define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
271 ////////////////////////////////////////////////////////////////////////////////
274 #define CATCH_INTERNAL_CONFIG_NO_WCHAR
277 ////////////////////////////////////////////////////////////////////////////////
278 // Embarcadero C++Build
279 #if defined(__BORLANDC__)
280 #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
283 ////////////////////////////////////////////////////////////////////////////////
285 // Use of __COUNTER__ is suppressed during code analysis in
286 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
288 // Otherwise all supported compilers support COUNTER macro,
289 // but user still might want to turn it off
290 #if (!defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L)
291 #define CATCH_INTERNAL_CONFIG_COUNTER
294 ////////////////////////////////////////////////////////////////////////////////
296 // RTX is a special version of Windows that is real time.
297 // This means that it is detected as Windows, but does not provide
298 // the same set of capabilities as real Windows does.
299 #if defined(UNDER_RTSS) || defined(RTX64_BUILD)
300 #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
301 #define CATCH_INTERNAL_CONFIG_NO_ASYNC
302 #define CATCH_CONFIG_COLOUR_NONE
305 #if !defined(_GLIBCXX_USE_C99_MATH_TR1)
306 #define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
309 // Various stdlib support checks that require __has_include
310 #if defined(__has_include)
311 // Check if string_view is available and usable
312 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
313 #define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
316 // Check if optional is available and usable
317 #if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
318 #define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
319 #endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
321 // Check if byte is available and usable
322 #if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
324 #if __cpp_lib_byte > 0
325 #define CATCH_INTERNAL_CONFIG_CPP17_BYTE
327 #endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
329 // Check if variant is available and usable
330 #if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
331 #if defined(__clang__) && (__clang_major__ < 8)
332 // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
333 // fix should be in clang 8, workaround in libstdc++ 8.2
335 #if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
336 #define CATCH_CONFIG_NO_CPP17_VARIANT
338 #define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
339 #endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
341 #define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
342 #endif // defined(__clang__) && (__clang_major__ < 8)
343 #endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
344 #endif // defined(__has_include)
346 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
347 #define CATCH_CONFIG_COUNTER
349 #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && \
350 !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
351 #define CATCH_CONFIG_WINDOWS_SEH
353 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
354 #if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && \
355 !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
356 #define CATCH_CONFIG_POSIX_SIGNALS
358 // This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
359 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
360 #define CATCH_CONFIG_WCHAR
363 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && \
364 !defined(CATCH_CONFIG_CPP11_TO_STRING)
365 #define CATCH_CONFIG_CPP11_TO_STRING
368 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && \
369 !defined(CATCH_CONFIG_CPP17_OPTIONAL)
370 #define CATCH_CONFIG_CPP17_OPTIONAL
373 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && \
374 !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
375 #define CATCH_CONFIG_CPP17_STRING_VIEW
378 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && \
379 !defined(CATCH_CONFIG_CPP17_VARIANT)
380 #define CATCH_CONFIG_CPP17_VARIANT
383 #if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && \
384 !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) && \
393 !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
394 #define CATCH_CONFIG_NEW_CAPTURE
397 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
398 #define CATCH_CONFIG_DISABLE_EXCEPTIONS
401 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && \
402 !defined(CATCH_CONFIG_POLYFILL_ISNAN)
403 #define CATCH_CONFIG_POLYFILL_ISNAN
406 #if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && \
407 !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
408 #define CATCH_CONFIG_USE_ASYNC
411 #if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && \
412 !defined(CATCH_CONFIG_ANDROID_LOGWRITE)
413 #define CATCH_CONFIG_ANDROID_LOGWRITE
416 #if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && \
417 !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
418 #define CATCH_CONFIG_GLOBAL_NEXTAFTER
421 // Even if we do not think the compiler has that warning, we still have
422 // to provide a macro that can be used by the code.
423 #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
424 #define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
426 #if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
427 #define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
429 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
430 #define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
432 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
433 #define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
435 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
436 #define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
438 #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
439 #define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
442 // The goal of this macro is to avoid evaluation of the arguments, but
443 // still have the compiler warn on problems inside...
444 #if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
445 #define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
448 #if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
449 #undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
450 #elif defined(__clang__) && (__clang_major__ < 5)
451 #undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
454 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)
455 #define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
458 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
459 #define CATCH_TRY if ((true))
460 #define CATCH_CATCH_ALL if ((false))
461 #define CATCH_CATCH_ANON(type) if ((false))
463 #define CATCH_TRY try
464 #define CATCH_CATCH_ALL catch (...)
465 #define CATCH_CATCH_ANON(type) catch (type)
468 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && \
469 !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
470 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
473 // end catch_compiler_capabilities.h
474 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2(name, line) name##line
475 #define INTERNAL_CATCH_UNIQUE_NAME_LINE(name, line) INTERNAL_CATCH_UNIQUE_NAME_LINE2(name, line)
476 #ifdef CATCH_CONFIG_COUNTER
477 #define INTERNAL_CATCH_UNIQUE_NAME(name) INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __COUNTER__)
479 #define INTERNAL_CATCH_UNIQUE_NAME(name) INTERNAL_CATCH_UNIQUE_NAME_LINE(name, __LINE__)
486 // We need a dummy global operator<< so we can bring it into Catch namespace later
487 struct Catch_global_namespace_dummy {};
488 std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
492 struct CaseSensitive {
493 enum Choice { Yes, No };
497 NonCopyable(NonCopyable const&) = delete;
498 NonCopyable(NonCopyable&&) = delete;
499 NonCopyable& operator=(NonCopyable const&) = delete;
500 NonCopyable& operator=(NonCopyable&&) = delete;
504 virtual ~NonCopyable();
507 struct SourceLineInfo {
509 SourceLineInfo() = delete;
510 SourceLineInfo(char const* _file, std::size_t _line) noexcept : file(_file), line(_line) {}
512 SourceLineInfo(SourceLineInfo const& other) = default;
513 SourceLineInfo& operator=(SourceLineInfo const&) = default;
514 SourceLineInfo(SourceLineInfo&&) noexcept = default;
515 SourceLineInfo& operator=(SourceLineInfo&&) noexcept = default;
517 bool empty() const noexcept { return file[0] == '\0'; }
518 bool operator==(SourceLineInfo const& other) const noexcept;
519 bool operator<(SourceLineInfo const& other) const noexcept;
525 std::ostream& operator<<(std::ostream& os, SourceLineInfo const& info);
527 // Bring in operator<< from global namespace into Catch namespace
528 // This is necessary because the overload of operator<< above makes
529 // lookup stop at namespace Catch
532 // Use this in variadic streaming macros to allow
535 // >> stuff +StreamEndStop
536 struct StreamEndStop {
537 std::string operator+() const;
539 template <typename T> T const& operator+(T const& value, StreamEndStop)
545 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo(__FILE__, static_cast<std::size_t>(__LINE__))
547 // end catch_common.h
550 struct RegistrarForTagAliases {
551 RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo);
554 } // end namespace Catch
556 #define CATCH_REGISTER_TAG_ALIAS(alias, spec) \
557 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
558 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
560 Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME(AutoRegisterTagAlias)(alias, spec, \
561 CATCH_INTERNAL_LINEINFO); \
563 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
565 // end catch_tag_alias_autoregistrar.h
566 // start catch_test_registry.h
568 // start catch_interfaces_testcase.h
576 struct ITestInvoker {
577 virtual void invoke() const = 0;
578 virtual ~ITestInvoker();
584 struct ITestCaseRegistry {
585 virtual ~ITestCaseRegistry();
586 virtual std::vector<TestCase> const& getAllTests() const = 0;
587 virtual std::vector<TestCase> const& getAllTestsSorted(IConfig const& config) const = 0;
590 bool isThrowSafe(TestCase const& testCase, IConfig const& config);
591 bool matchTest(TestCase const& testCase, TestSpec const& testSpec, IConfig const& config);
592 std::vector<TestCase> filterTests(std::vector<TestCase> const& testCases, TestSpec const& testSpec,
593 IConfig const& config);
594 std::vector<TestCase> const& getAllTestCasesSorted(IConfig const& config);
598 // end catch_interfaces_testcase.h
599 // start catch_stringref.h
608 /// A non-owning string class (similar to the forthcoming std::string_view)
609 /// Note that, because a StringRef may be a substring of another string,
610 /// it may not be null terminated.
613 using size_type = std::size_t;
614 using const_iterator = const char*;
617 static constexpr char const* const s_empty = "";
619 char const* m_start = s_empty;
620 size_type m_size = 0;
622 public: // construction
623 constexpr StringRef() noexcept = default;
625 StringRef(char const* rawChars) noexcept;
627 constexpr StringRef(char const* rawChars, size_type size) noexcept : m_start(rawChars), m_size(size) {}
629 StringRef(std::string const& stdString) noexcept : m_start(stdString.c_str()), m_size(stdString.size()) {}
631 explicit operator std::string() const { return std::string(m_start, m_size); }
634 auto operator==(StringRef const& other) const noexcept -> bool;
635 auto operator!=(StringRef const& other) const noexcept -> bool { return !(*this == other); }
637 auto operator[](size_type index) const noexcept -> char
639 assert(index < m_size);
640 return m_start[index];
643 public: // named queries
644 constexpr auto empty() const noexcept -> bool { return m_size == 0; }
645 constexpr auto size() const noexcept -> size_type { return m_size; }
647 // Returns the current start pointer. If the StringRef is not
648 // null-terminated, throws std::domain_exception
649 auto c_str() const -> char const*;
651 public: // substrings and searches
652 // Returns a substring of [start, start + length).
653 // If start + length > size(), then the substring is [start, size()).
654 // If start > size(), then the substring is empty.
655 auto substr(size_type start, size_type length) const noexcept -> StringRef;
657 // Returns the current start pointer. May not be null-terminated.
658 auto data() const noexcept -> char const*;
660 constexpr auto isNullTerminated() const noexcept -> bool { return m_start[m_size] == '\0'; }
663 constexpr const_iterator begin() const { return m_start; }
664 constexpr const_iterator end() const { return m_start + m_size; }
667 auto operator+=(std::string& lhs, StringRef const& sr) -> std::string&;
668 auto operator<<(std::ostream& os, StringRef const& sr) -> std::ostream&;
670 constexpr auto operator"" _sr(char const* rawChars, std::size_t size) noexcept -> StringRef
672 return StringRef(rawChars, size);
676 constexpr auto operator"" _catch_sr(char const* rawChars, std::size_t size) noexcept -> Catch::StringRef
678 return Catch::StringRef(rawChars, size);
681 // end catch_stringref.h
682 // start catch_preprocessor.hpp
684 #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
685 #define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
686 #define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
687 #define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
688 #define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
689 #define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
691 #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
692 #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
693 // MSVC needs more evaluations
694 #define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
695 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
697 #define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__)
700 #define CATCH_REC_END(...)
701 #define CATCH_REC_OUT
703 #define CATCH_EMPTY()
704 #define CATCH_DEFER(id) id CATCH_EMPTY()
706 #define CATCH_REC_GET_END2() 0, CATCH_REC_END
707 #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
708 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
709 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
710 #define CATCH_REC_NEXT1(test, next) CATCH_DEFER(CATCH_REC_NEXT0)(test, next, 0)
711 #define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
713 #define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1))(f, peek, __VA_ARGS__)
714 #define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST0))(f, peek, __VA_ARGS__)
715 #define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1))(f, peek, __VA_ARGS__)
717 #define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) \
718 , f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD))(f, userdata, peek, __VA_ARGS__)
719 #define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) \
720 , f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD))(f, userdata, peek, __VA_ARGS__)
721 #define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) \
722 f(userdata, x) CATCH_DEFER(CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD))(f, userdata, peek, __VA_ARGS__)
724 // Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
725 // and passes userdata as the first parameter to each invocation,
726 // e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
727 #define CATCH_REC_LIST_UD(f, userdata, ...) \
728 CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
730 #define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
732 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
733 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO##__VA_ARGS__
734 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
735 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
736 #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
737 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
738 #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
739 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
741 // MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
742 #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
743 #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
744 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) \
745 (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
748 #define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
749 #define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
751 #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
753 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
754 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())
755 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
757 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) \
758 INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()))
759 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) \
760 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
763 #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...) CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST, __VA_ARGS__)
765 #define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)
766 #define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) \
767 INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)
768 #define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) \
769 INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)
770 #define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) \
771 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) \
773 INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4)
774 #define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) \
775 INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5)
776 #define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) \
777 INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6)
778 #define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) \
779 INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7)
780 #define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) \
781 INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8)
782 #define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
783 INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9)
784 #define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
785 INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10)
787 #define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
789 #define INTERNAL_CATCH_TYPE_GEN \
790 template <typename...> struct TypeList { \
792 template <typename... Ts> constexpr auto get_wrapper() noexcept->TypeList<Ts...> \
796 template <template <typename...> class...> struct TemplateTypeList { \
798 template <template <typename...> class... Cs> constexpr auto get_wrapper() noexcept->TemplateTypeList<Cs...> \
802 template <typename...> struct append; \
803 template <typename...> struct rewrap; \
804 template <template <typename...> class, typename...> struct create; \
805 template <template <typename...> class, typename> struct convert; \
807 template <typename T> struct append<T> { \
810 template <template <typename...> class L1, typename... E1, template <typename...> class L2, typename... E2, \
812 struct append<L1<E1...>, L2<E2...>, Rest...> { \
813 using type = typename append<L1<E1..., E2...>, Rest...>::type; \
815 template <template <typename...> class L1, typename... E1, typename... Rest> \
816 struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { \
817 using type = L1<E1...>; \
820 template <template <typename...> class Container, template <typename...> class List, typename... elems> \
821 struct rewrap<TemplateTypeList<Container>, List<elems...>> { \
822 using type = TypeList<Container<elems...>>; \
824 template <template <typename...> class Container, template <typename...> class List, class... Elems, \
825 typename... Elements> \
826 struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { \
827 using type = typename append<TypeList<Container<Elems...>>, \
828 typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; \
831 template <template <typename...> class Final, template <typename...> class... Containers, typename... Types> \
832 struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { \
833 using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; \
835 template <template <typename...> class Final, template <typename...> class List, typename... Ts> \
836 struct convert<Final, List<Ts...>> { \
837 using type = typename append<Final<>, TypeList<Ts>...>::type; \
840 #define INTERNAL_CATCH_NTTP_1(signature, ...) \
841 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp { \
843 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> constexpr auto get_wrapper() noexcept->Nttp<__VA_ARGS__> \
847 template <template <INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList { \
849 template <template <INTERNAL_CATCH_REMOVE_PARENS(signature)> class... Cs> \
850 constexpr auto get_wrapper() noexcept->NttpTemplateTypeList<Cs...> \
855 template <template <INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, \
856 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)> \
857 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { \
858 using type = TypeList<Container<__VA_ARGS__>>; \
860 template <template <INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, \
861 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), \
862 typename... Elements> \
863 struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { \
864 using type = typename append<TypeList<Container<__VA_ARGS__>>, \
865 typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; \
867 template <template <typename...> class Final, \
868 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> class... Containers, typename... Types> \
869 struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { \
870 using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; \
873 #define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
874 #define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature) \
875 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> static void TestName()
876 #define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...) \
877 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> static void TestName()
879 #define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)
880 #define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature) \
881 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> static void TestName()
882 #define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature, ...) \
883 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> static void TestName()
885 #define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature) \
886 template <typename Type> void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags) \
888 Catch::AutoReg(Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags); \
891 #define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...) \
892 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags) \
894 Catch::AutoReg(Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), \
898 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...) \
899 template <typename Type> void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags) \
901 Catch::AutoReg(Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags); \
904 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...) \
905 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> \
906 void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags) \
908 Catch::AutoReg(Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, \
912 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)
913 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature) \
914 template <typename TestType> struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \
918 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...) \
919 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> \
920 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \
924 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)
925 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature) \
926 template <typename TestType> void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test()
927 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...) \
928 template <INTERNAL_CATCH_REMOVE_PARENS(signature)> \
929 void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()
931 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
932 #define INTERNAL_CATCH_NTTP_0
933 #define INTERNAL_CATCH_NTTP_GEN(...) \
934 INTERNAL_CATCH_VA_NARGS_IMPL( \
935 __VA_ARGS__, INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), \
936 INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), \
937 INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), \
938 INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_0)
939 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) \
940 INTERNAL_CATCH_VA_NARGS_IMPL("dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, \
941 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, \
942 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, \
943 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, \
944 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, \
945 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0) \
946 (TestName, __VA_ARGS__)
947 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) \
948 INTERNAL_CATCH_VA_NARGS_IMPL("dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, \
949 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, \
950 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, \
951 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, \
952 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, \
953 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0) \
954 (TestName, ClassName, __VA_ARGS__)
955 #define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) \
956 INTERNAL_CATCH_VA_NARGS_IMPL( \
957 "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, \
958 INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, \
959 INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, \
960 INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0) \
961 (TestName, __VA_ARGS__)
962 #define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) \
963 INTERNAL_CATCH_VA_NARGS_IMPL( \
964 "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, \
965 INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, \
966 INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, \
967 INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0) \
968 (TestFunc, __VA_ARGS__)
969 #define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) \
970 INTERNAL_CATCH_VA_NARGS_IMPL( \
971 "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, \
972 INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, \
973 INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, \
974 INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0) \
975 (TestName, __VA_ARGS__)
976 #define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) \
977 INTERNAL_CATCH_VA_NARGS_IMPL( \
978 "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, \
979 INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, \
980 INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, \
981 INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0) \
982 (TestName, __VA_ARGS__)
983 #define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) \
984 INTERNAL_CATCH_VA_NARGS_IMPL( \
985 __VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG, INTERNAL_CATCH_REMOVE_PARENS_10_ARG, \
986 INTERNAL_CATCH_REMOVE_PARENS_9_ARG, INTERNAL_CATCH_REMOVE_PARENS_8_ARG, INTERNAL_CATCH_REMOVE_PARENS_7_ARG, \
987 INTERNAL_CATCH_REMOVE_PARENS_6_ARG, INTERNAL_CATCH_REMOVE_PARENS_5_ARG, INTERNAL_CATCH_REMOVE_PARENS_4_ARG, \
988 INTERNAL_CATCH_REMOVE_PARENS_3_ARG, INTERNAL_CATCH_REMOVE_PARENS_2_ARG, INTERNAL_CATCH_REMOVE_PARENS_1_ARG) \
991 #define INTERNAL_CATCH_NTTP_0(signature)
992 #define INTERNAL_CATCH_NTTP_GEN(...) \
993 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( \
994 __VA_ARGS__, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, \
995 INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, \
996 INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_0)(__VA_ARGS__))
997 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) \
998 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( \
999 "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, \
1000 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, \
1001 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, \
1002 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, \
1003 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, \
1004 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__))
1005 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) \
1006 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( \
1007 "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, \
1008 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, \
1009 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, \
1010 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, \
1011 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, \
1012 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__))
1013 #define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) \
1014 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( \
1015 "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, \
1016 INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, \
1017 INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, \
1018 INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, \
1019 INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__))
1020 #define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) \
1021 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( \
1022 "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, \
1023 INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, \
1024 INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, \
1025 INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__))
1026 #define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) \
1027 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( \
1028 "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, \
1029 INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, \
1030 INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, \
1031 INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST1, \
1032 INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__))
1033 #define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) \
1034 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( \
1035 "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, \
1036 INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, \
1037 INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, \
1038 INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, \
1039 INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__))
1040 #define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) \
1041 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( \
1042 __VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG, INTERNAL_CATCH_REMOVE_PARENS_10_ARG, \
1043 INTERNAL_CATCH_REMOVE_PARENS_9_ARG, INTERNAL_CATCH_REMOVE_PARENS_8_ARG, INTERNAL_CATCH_REMOVE_PARENS_7_ARG, \
1044 INTERNAL_CATCH_REMOVE_PARENS_6_ARG, INTERNAL_CATCH_REMOVE_PARENS_5_ARG, INTERNAL_CATCH_REMOVE_PARENS_4_ARG, \
1045 INTERNAL_CATCH_REMOVE_PARENS_3_ARG, INTERNAL_CATCH_REMOVE_PARENS_2_ARG, \
1046 INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__))
1049 // end catch_preprocessor.hpp
1050 // start catch_meta.hpp
1052 #include <type_traits>
1055 template <typename T> struct always_false : std::false_type {
1058 template <typename> struct true_given : std::true_type {
1060 struct is_callable_tester {
1061 template <typename Fun, typename... Args>
1062 true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int);
1063 template <typename...> std::false_type static test(...);
1066 template <typename T> struct is_callable;
1068 template <typename Fun, typename... Args>
1069 struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {
1072 #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
1073 // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
1074 // replaced with std::invoke_result here.
1075 template <typename Func, typename... U>
1076 using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>;
1078 // Keep ::type here because we still support C++11
1079 template <typename Func, typename... U>
1080 using FunctionReturnType =
1081 typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U...)>::type>::type>::type;
1084 } // namespace Catch
1090 // end catch_meta.hpp
1093 template <typename C> class TestInvokerAsMethod : public ITestInvoker {
1094 void (C::*m_testAsMethod)();
1097 TestInvokerAsMethod(void (C::*testAsMethod)()) noexcept : m_testAsMethod(testAsMethod) {}
1099 void invoke() const override
1102 (obj.*m_testAsMethod)();
1106 auto makeTestInvoker(void (*testAsFunction)()) noexcept -> ITestInvoker*;
1108 template <typename C> auto makeTestInvoker(void (C::*testAsMethod)()) noexcept -> ITestInvoker*
1110 return new (std::nothrow) TestInvokerAsMethod<C>(testAsMethod);
1113 struct NameAndTags {
1114 NameAndTags(StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef()) noexcept;
1119 struct AutoReg : NonCopyable {
1120 AutoReg(ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod,
1121 NameAndTags const& nameAndTags) noexcept;
1125 } // end namespace Catch
1127 #if defined(CATCH_CONFIG_DISABLE)
1128 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(TestName, ...) static void TestName()
1129 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(TestName, ClassName, ...) \
1131 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
1135 void TestName::test()
1136 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2(TestName, TestFunc, Name, Tags, Signature, ...) \
1137 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1138 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2(TestNameClass, TestName, ClassName, Name, Tags, \
1141 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) \
1143 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature)); \
1146 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1148 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1149 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
1150 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( \
1151 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1152 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, \
1153 typename TestType, __VA_ARGS__)
1155 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
1156 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( \
1157 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1158 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, \
1159 typename TestType, __VA_ARGS__))
1162 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1163 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
1164 INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( \
1165 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1166 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, \
1169 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
1170 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( \
1171 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1172 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, \
1176 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1177 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(ClassName, Name, Tags, ...) \
1178 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( \
1179 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____), \
1180 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, \
1183 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(ClassName, Name, Tags, ...) \
1184 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( \
1185 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____), \
1186 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, \
1190 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1191 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(ClassName, Name, Tags, Signature, ...) \
1192 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( \
1193 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____), \
1194 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, \
1197 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(ClassName, Name, Tags, Signature, ...) \
1198 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( \
1199 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____), \
1200 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, \
1205 ///////////////////////////////////////////////////////////////////////////////
1206 #define INTERNAL_CATCH_TESTCASE2(TestName, ...) \
1207 static void TestName(); \
1208 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1209 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1211 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(Catch::makeTestInvoker(&TestName), CATCH_INTERNAL_LINEINFO, \
1212 Catch::StringRef(), Catch::NameAndTags{__VA_ARGS__}); \
1214 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1215 static void TestName()
1216 #define INTERNAL_CATCH_TESTCASE(...) \
1217 INTERNAL_CATCH_TESTCASE2(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____), __VA_ARGS__)
1219 ///////////////////////////////////////////////////////////////////////////////
1220 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE(QualifiedMethod, ...) \
1221 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1222 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1224 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(Catch::makeTestInvoker(&QualifiedMethod), \
1225 CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, \
1226 Catch::NameAndTags{__VA_ARGS__}); \
1228 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
1230 ///////////////////////////////////////////////////////////////////////////////
1231 #define INTERNAL_CATCH_TEST_CASE_METHOD2(TestName, ClassName, ...) \
1232 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1233 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1235 struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
1238 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(Catch::makeTestInvoker(&TestName::test), \
1239 CATCH_INTERNAL_LINEINFO, #ClassName, \
1240 Catch::NameAndTags{__VA_ARGS__}); /* NOLINT */ \
1242 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1243 void TestName::test()
1244 #define INTERNAL_CATCH_TEST_CASE_METHOD(ClassName, ...) \
1245 INTERNAL_CATCH_TEST_CASE_METHOD2(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____), ClassName, __VA_ARGS__)
1247 ///////////////////////////////////////////////////////////////////////////////
1248 #define INTERNAL_CATCH_REGISTER_TESTCASE(Function, ...) \
1249 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1250 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1251 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME(autoRegistrar)(Catch::makeTestInvoker(Function), CATCH_INTERNAL_LINEINFO, \
1252 Catch::StringRef(), \
1253 Catch::NameAndTags{__VA_ARGS__}); /* NOLINT */ \
1254 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
1256 ///////////////////////////////////////////////////////////////////////////////
1257 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ...) \
1258 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1259 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1260 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1261 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1262 INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature)); \
1264 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) \
1266 INTERNAL_CATCH_TYPE_GEN \
1267 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
1268 INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
1269 template <typename... Types> struct TestName { \
1273 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)}; \
1274 using expander = int[]; \
1275 (void)expander{(reg_test(Types{}, Catch::NameAndTags{Name " - " + std::string(tmpl_types[index]), Tags}), \
1276 index++)...}; /* NOLINT */ \
1279 static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \
1280 TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>(); \
1285 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1286 INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1288 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1289 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
1290 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( \
1291 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1292 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, \
1293 typename TestType, __VA_ARGS__)
1295 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
1296 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( \
1297 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1298 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, \
1299 typename TestType, __VA_ARGS__))
1302 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1303 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
1304 INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( \
1305 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1306 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, \
1309 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
1310 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( \
1311 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1312 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, \
1316 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, \
1318 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1319 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1320 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1321 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1322 template <typename TestType> static void TestFuncName(); \
1324 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) \
1326 INTERNAL_CATCH_TYPE_GEN \
1327 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
1328 template <typename... Types> struct TestName { \
1332 using expander = int[]; \
1333 constexpr char const* tmpl_types[] = { \
1334 CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))}; \
1335 constexpr char const* types_list[] = { \
1336 CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))}; \
1337 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]); \
1339 (Catch::AutoReg(Catch::makeTestInvoker(&TestFuncName<Types>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), \
1340 Catch::NameAndTags{Name " - " + std::string(tmpl_types[index / num_types]) + "<" + \
1341 std::string(types_list[index % num_types]) + ">", \
1343 index++)...}; /* NOLINT */ \
1346 static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \
1347 using TestInit = typename create< \
1348 TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), \
1349 TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
1356 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1357 template <typename TestType> static void TestFuncName()
1359 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1360 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...) \
1361 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( \
1362 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1363 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, \
1366 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...) \
1367 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( \
1368 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1369 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, \
1373 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1374 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...) \
1375 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( \
1376 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1377 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, \
1380 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...) \
1381 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( \
1382 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1383 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, \
1387 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList) \
1388 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1389 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1390 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1391 template <typename TestType> static void TestFunc(); \
1393 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) \
1395 INTERNAL_CATCH_TYPE_GEN \
1396 template <typename... Types> struct TestName { \
1400 using expander = int[]; \
1402 (Catch::AutoReg(Catch::makeTestInvoker(&TestFunc<Types>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), \
1403 Catch::NameAndTags{Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + \
1404 std::to_string(index), \
1406 index++)...}; /* NOLINT */ \
1409 static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \
1410 using TestInit = typename convert<TestName, TmplList>::type; \
1417 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1418 template <typename TestType> static void TestFunc()
1420 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
1421 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( \
1422 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1423 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)
1425 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, ...) \
1426 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1427 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1428 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1429 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1431 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) \
1433 INTERNAL_CATCH_TYPE_GEN \
1434 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
1435 INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature)); \
1436 INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
1437 template <typename... Types> struct TestNameClass { \
1441 constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)}; \
1442 using expander = int[]; \
1444 (reg_test(Types{}, #ClassName, Catch::NameAndTags{Name " - " + std::string(tmpl_types[index]), Tags}), \
1445 index++)...}; /* NOLINT */ \
1448 static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \
1449 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>(); \
1454 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1455 INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1457 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1458 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(ClassName, Name, Tags, ...) \
1459 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( \
1460 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____), \
1461 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, \
1464 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(ClassName, Name, Tags, ...) \
1465 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( \
1466 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____), \
1467 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, \
1471 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1472 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(ClassName, Name, Tags, Signature, ...) \
1473 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( \
1474 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____), \
1475 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, \
1478 #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(ClassName, Name, Tags, Signature, ...) \
1479 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( \
1480 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____), \
1481 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, \
1485 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, \
1486 TmplTypes, TypesList) \
1487 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1488 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1489 CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1490 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1491 template <typename TestType> struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName<TestType>) { \
1495 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) \
1497 INTERNAL_CATCH_TYPE_GEN \
1498 INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature)) \
1499 template <typename... Types> struct TestNameClass { \
1503 using expander = int[]; \
1504 constexpr char const* tmpl_types[] = { \
1505 CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))}; \
1506 constexpr char const* types_list[] = { \
1507 CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))}; \
1508 constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]); \
1510 (Catch::AutoReg(Catch::makeTestInvoker(&TestName<Types>::test), CATCH_INTERNAL_LINEINFO, #ClassName, \
1511 Catch::NameAndTags{Name " - " + std::string(tmpl_types[index / num_types]) + "<" + \
1512 std::string(types_list[index % num_types]) + ">", \
1514 index++)...}; /* NOLINT */ \
1517 static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \
1518 using TestInit = typename create< \
1519 TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), \
1520 TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
1527 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1528 template <typename TestType> void TestName<TestType>::test()
1530 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1531 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(ClassName, Name, Tags, ...) \
1532 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( \
1533 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1534 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, \
1535 typename T, __VA_ARGS__)
1537 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(ClassName, Name, Tags, ...) \
1538 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( \
1539 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1540 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, \
1541 typename T, __VA_ARGS__))
1544 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1545 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(ClassName, Name, Tags, Signature, ...) \
1546 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( \
1547 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1548 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, \
1549 Signature, __VA_ARGS__)
1551 #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(ClassName, Name, Tags, Signature, ...) \
1552 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( \
1553 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1554 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, \
1555 Signature, __VA_ARGS__))
1558 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
1559 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1560 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1561 CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1562 template <typename TestType> struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName<TestType>) { \
1566 namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) \
1568 INTERNAL_CATCH_TYPE_GEN \
1569 template <typename... Types> struct TestNameClass { \
1573 using expander = int[]; \
1575 (Catch::AutoReg(Catch::makeTestInvoker(&TestName<Types>::test), CATCH_INTERNAL_LINEINFO, #ClassName, \
1576 Catch::NameAndTags{Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + \
1577 std::to_string(index), \
1579 index++)...}; /* NOLINT */ \
1582 static int INTERNAL_CATCH_UNIQUE_NAME(globalRegistrar) = []() { \
1583 using TestInit = typename convert<TestNameClass, TmplList>::type; \
1590 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1591 template <typename TestType> void TestName<TestType>::test()
1593 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
1594 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( \
1595 INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____), \
1596 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, \
1599 // end catch_test_registry.h
1600 // start catch_capture.hpp
1602 // start catch_assertionhandler.h
1604 // start catch_assertioninfo.h
1606 // start catch_result_type.h
1610 // ResultWas::OfType enum
1620 ExpressionFailed = FailureBit | 1,
1621 ExplicitFailure = FailureBit | 2,
1623 Exception = 0x100 | FailureBit,
1625 ThrewException = Exception | 1,
1626 DidntThrowException = Exception | 2,
1628 FatalErrorCondition = 0x200 | FailureBit
1633 bool isOk(ResultWas::OfType resultType);
1634 bool isJustInfo(int flags);
1636 // ResultDisposition::Flags enum
1637 struct ResultDisposition {
1641 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
1642 FalseTest = 0x04, // Prefix expression with !
1643 SuppressFail = 0x08 // Failures are reported but do not fail the test
1647 ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs);
1649 bool shouldContinueOnFailure(int flags);
1650 inline bool isFalseTest(int flags)
1652 return (flags & ResultDisposition::FalseTest) != 0;
1654 bool shouldSuppressFailure(int flags);
1656 } // end namespace Catch
1658 // end catch_result_type.h
1661 struct AssertionInfo {
1662 StringRef macroName;
1663 SourceLineInfo lineInfo;
1664 StringRef capturedExpression;
1665 ResultDisposition::Flags resultDisposition;
1667 // We want to delete this constructor but a compiler bug in 4.8 means
1668 // the struct is then treated as non-aggregate
1669 // AssertionInfo() = delete;
1672 } // end namespace Catch
1674 // end catch_assertioninfo.h
1675 // start catch_decomposer.h
1677 // start catch_tostring.h
1681 #include <type_traits>
1683 // start catch_stream.h
1691 std::ostream& cout();
1692 std::ostream& cerr();
1693 std::ostream& clog();
1699 virtual std::ostream& stream() const = 0;
1702 auto makeStream(StringRef const& filename) -> IStream const*;
1704 class ReusableStringStream : NonCopyable {
1705 std::size_t m_index;
1706 std::ostream* m_oss;
1709 ReusableStringStream();
1710 ~ReusableStringStream();
1712 auto str() const -> std::string;
1714 template <typename T> auto operator<<(T const& value) -> ReusableStringStream&
1719 auto get() -> std::ostream& { return *m_oss; }
1721 } // namespace Catch
1723 // end catch_stream.h
1724 // start catch_interfaces_enum_values_registry.h
1733 std::vector<std::pair<int, StringRef>> m_values;
1737 StringRef lookup(int value) const;
1739 } // namespace Detail
1741 struct IMutableEnumValuesRegistry {
1742 virtual ~IMutableEnumValuesRegistry();
1744 virtual Detail::EnumInfo const& registerEnum(StringRef enumName, StringRef allEnums,
1745 std::vector<int> const& values) = 0;
1747 template <typename E>
1748 Detail::EnumInfo const& registerEnum(StringRef enumName, StringRef allEnums, std::initializer_list<E> values)
1750 static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
1751 std::vector<int> intValues;
1752 intValues.reserve(values.size());
1753 for (auto enumValue : values)
1754 intValues.push_back(static_cast<int>(enumValue));
1755 return registerEnum(enumName, allEnums, intValues);
1759 } // namespace Catch
1761 // end catch_interfaces_enum_values_registry.h
1763 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1764 #include <string_view>
1768 // start catch_objc_arc.hpp
1770 #import <Foundation/Foundation.h>
1772 #ifdef __has_feature
1773 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1775 #define CATCH_ARC_ENABLED 0
1778 void arcSafeRelease(NSObject* obj);
1779 id performOptionalSelector(id obj, SEL sel);
1781 #if !CATCH_ARC_ENABLED
1782 inline void arcSafeRelease(NSObject* obj)
1786 inline id performOptionalSelector(id obj, SEL sel)
1788 if ([obj respondsToSelector:sel])
1789 return [obj performSelector:sel];
1792 #define CATCH_UNSAFE_UNRETAINED
1793 #define CATCH_ARC_STRONG
1795 inline void arcSafeRelease(NSObject*) {}
1796 inline id performOptionalSelector(id obj, SEL sel)
1799 #pragma clang diagnostic push
1800 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1802 if ([obj respondsToSelector:sel])
1803 return [obj performSelector:sel];
1805 #pragma clang diagnostic pop
1809 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1810 #define CATCH_ARC_STRONG __strong
1813 // end catch_objc_arc.hpp
1817 #pragma warning(push)
1819 disable : 4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
1825 extern const std::string unprintableString;
1827 std::string rawMemoryToString(const void* object, std::size_t size);
1829 template <typename T> std::string rawMemoryToString(const T& object)
1831 return rawMemoryToString(&object, sizeof(object));
1834 template <typename T> class IsStreamInsertable {
1835 template <typename Stream, typename U>
1836 static auto test(int) -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
1838 template <typename, typename> static auto test(...) -> std::false_type;
1841 static const bool value = decltype(test<std::ostream, const T&>(0))::value;
1844 template <typename E> std::string convertUnknownEnumToString(E e);
1846 template <typename T>
1847 typename std::enable_if<!std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value, std::string>::type
1848 convertUnstreamable(T const&)
1850 return Detail::unprintableString;
1852 template <typename T>
1853 typename std::enable_if<!std::is_enum<T>::value && std::is_base_of<std::exception, T>::value, std::string>::type
1854 convertUnstreamable(T const& ex)
1859 template <typename T>
1860 typename std::enable_if<std::is_enum<T>::value, std::string>::type convertUnstreamable(T const& value)
1862 return convertUnknownEnumToString(value);
1865 #if defined(_MANAGED)
1866 //! Convert a CLR string to a utf8 std::string
1867 template <typename T> std::string clrReferenceToString(T ^ ref)
1870 return std::string("null");
1871 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
1872 cli::pin_ptr<System::Byte> p = &bytes[0];
1873 return std::string(reinterpret_cast<char const*>(p), bytes->Length);
1877 } // namespace Detail
1879 // If we decide for C++14, change these to enable_if_ts
1880 template <typename T, typename = void> struct StringMaker {
1881 template <typename Fake = T>
1882 static typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
1883 convert(const Fake& value)
1885 ReusableStringStream rss;
1886 // NB: call using the function-like syntax to avoid ambiguity with
1887 // user-defined templated operator<< under clang.
1888 rss.operator<<(value);
1892 template <typename Fake = T>
1893 static typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
1894 convert(const Fake& value)
1896 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
1897 return Detail::convertUnstreamable(value);
1899 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
1906 // This function dispatches all stringification requests inside of Catch.
1907 // Should be preferably called fully qualified, like ::Catch::Detail::stringify
1908 template <typename T> std::string stringify(const T& e)
1910 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e);
1913 template <typename E> std::string convertUnknownEnumToString(E e)
1915 return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));
1918 #if defined(_MANAGED)
1919 template <typename T> std::string stringify(T ^ e)
1921 return ::Catch::StringMaker<T ^>::convert(e);
1925 } // namespace Detail
1927 // Some predefined specializations
1929 template <> struct StringMaker<std::string> {
1930 static std::string convert(const std::string& str);
1933 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1934 template <> struct StringMaker<std::string_view> {
1935 static std::string convert(std::string_view str);
1939 template <> struct StringMaker<char const*> {
1940 static std::string convert(char const* str);
1942 template <> struct StringMaker<char*> {
1943 static std::string convert(char* str);
1946 #ifdef CATCH_CONFIG_WCHAR
1947 template <> struct StringMaker<std::wstring> {
1948 static std::string convert(const std::wstring& wstr);
1951 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1952 template <> struct StringMaker<std::wstring_view> {
1953 static std::string convert(std::wstring_view str);
1957 template <> struct StringMaker<wchar_t const*> {
1958 static std::string convert(wchar_t const* str);
1960 template <> struct StringMaker<wchar_t*> {
1961 static std::string convert(wchar_t* str);
1965 // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
1966 // while keeping string semantics?
1967 template <int SZ> struct StringMaker<char[SZ]> {
1968 static std::string convert(char const* str) { return ::Catch::Detail::stringify(std::string{str}); }
1970 template <int SZ> struct StringMaker<signed char[SZ]> {
1971 static std::string convert(signed char const* str)
1973 return ::Catch::Detail::stringify(std::string{reinterpret_cast<char const*>(str)});
1976 template <int SZ> struct StringMaker<unsigned char[SZ]> {
1977 static std::string convert(unsigned char const* str)
1979 return ::Catch::Detail::stringify(std::string{reinterpret_cast<char const*>(str)});
1983 #if defined(CATCH_CONFIG_CPP17_BYTE)
1984 template <> struct StringMaker<std::byte> {
1985 static std::string convert(std::byte value);
1987 #endif // defined(CATCH_CONFIG_CPP17_BYTE)
1988 template <> struct StringMaker<int> {
1989 static std::string convert(int value);
1991 template <> struct StringMaker<long> {
1992 static std::string convert(long value);
1994 template <> struct StringMaker<long long> {
1995 static std::string convert(long long value);
1997 template <> struct StringMaker<unsigned int> {
1998 static std::string convert(unsigned int value);
2000 template <> struct StringMaker<unsigned long> {
2001 static std::string convert(unsigned long value);
2003 template <> struct StringMaker<unsigned long long> {
2004 static std::string convert(unsigned long long value);
2007 template <> struct StringMaker<bool> {
2008 static std::string convert(bool b);
2011 template <> struct StringMaker<char> {
2012 static std::string convert(char c);
2014 template <> struct StringMaker<signed char> {
2015 static std::string convert(signed char c);
2017 template <> struct StringMaker<unsigned char> {
2018 static std::string convert(unsigned char c);
2021 template <> struct StringMaker<std::nullptr_t> {
2022 static std::string convert(std::nullptr_t);
2025 template <> struct StringMaker<float> {
2026 static std::string convert(float value);
2027 static int precision;
2030 template <> struct StringMaker<double> {
2031 static std::string convert(double value);
2032 static int precision;
2035 template <typename T> struct StringMaker<T*> {
2036 template <typename U> static std::string convert(U* p)
2039 return ::Catch::Detail::rawMemoryToString(p);
2046 template <typename R, typename C> struct StringMaker<R C::*> {
2047 static std::string convert(R C::*p)
2050 return ::Catch::Detail::rawMemoryToString(p);
2057 #if defined(_MANAGED)
2058 template <typename T> struct StringMaker<T ^> {
2059 static std::string convert(T ^ ref) { return ::Catch::Detail::clrReferenceToString(ref); }
2064 template <typename InputIterator, typename Sentinel = InputIterator>
2065 std::string rangeToString(InputIterator first, Sentinel last)
2067 ReusableStringStream rss;
2069 if (first != last) {
2070 rss << ::Catch::Detail::stringify(*first);
2071 for (++first; first != last; ++first)
2072 rss << ", " << ::Catch::Detail::stringify(*first);
2077 } // namespace Detail
2080 template <> struct StringMaker<NSString*> {
2081 static std::string convert(NSString* nsstring)
2085 return std::string("@") + [nsstring UTF8String];
2088 template <> struct StringMaker<NSObject*> {
2089 static std::string convert(NSObject* nsObject) { return ::Catch::Detail::stringify([nsObject description]); }
2092 inline std::string stringify(NSString* nsstring)
2094 return StringMaker<NSString*>::convert(nsstring);
2097 } // namespace Detail
2100 } // namespace Catch
2102 //////////////////////////////////////////////////////
2103 // Separate std-lib types stringification, so it can be selectively enabled
2104 // This means that we do not bring in
2106 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
2107 #define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
2108 #define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
2109 #define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
2110 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
2111 #define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
2114 // Separate std::pair specialization
2115 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
2118 template <typename T1, typename T2> struct StringMaker<std::pair<T1, T2>> {
2119 static std::string convert(const std::pair<T1, T2>& pair)
2121 ReusableStringStream rss;
2122 rss << "{ " << ::Catch::Detail::stringify(pair.first) << ", " << ::Catch::Detail::stringify(pair.second) << " }";
2126 } // namespace Catch
2127 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
2129 #if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
2132 template <typename T> struct StringMaker<std::optional<T>> {
2133 static std::string convert(const std::optional<T>& optional)
2135 ReusableStringStream rss;
2136 if (optional.has_value()) {
2137 rss << ::Catch::Detail::stringify(*optional);
2144 } // namespace Catch
2145 #endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
2147 // Separate std::tuple specialization
2148 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
2152 template <typename Tuple, std::size_t N = 0, bool = (N < std::tuple_size<Tuple>::value)> struct TupleElementPrinter {
2153 static void print(const Tuple& tuple, std::ostream& os)
2155 os << (N ? ", " : " ") << ::Catch::Detail::stringify(std::get<N>(tuple));
2156 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
2160 template <typename Tuple, std::size_t N> struct TupleElementPrinter<Tuple, N, false> {
2161 static void print(const Tuple&, std::ostream&) {}
2164 } // namespace Detail
2166 template <typename... Types> struct StringMaker<std::tuple<Types...>> {
2167 static std::string convert(const std::tuple<Types...>& tuple)
2169 ReusableStringStream rss;
2171 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
2176 } // namespace Catch
2177 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
2179 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
2182 template <> struct StringMaker<std::monostate> {
2183 static std::string convert(const std::monostate&) { return "{ }"; }
2186 template <typename... Elements> struct StringMaker<std::variant<Elements...>> {
2187 static std::string convert(const std::variant<Elements...>& variant)
2189 if (variant.valueless_by_exception()) {
2190 return "{valueless variant}";
2192 return std::visit([](const auto& value) { return ::Catch::Detail::stringify(value); }, variant);
2196 } // namespace Catch
2197 #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
2200 // Import begin/ end from std here
2205 template <typename...> struct void_type {
2209 template <typename T, typename = void> struct is_range_impl : std::false_type {
2212 template <typename T>
2213 struct is_range_impl<T, typename void_type<decltype(begin(std::declval<T>()))>::type> : std::true_type {
2215 } // namespace detail
2217 template <typename T> struct is_range : detail::is_range_impl<T> {
2220 #if defined(_MANAGED) // Managed types are never ranges
2221 template <typename T> struct is_range<T ^> {
2222 static const bool value = false;
2226 template <typename Range> std::string rangeToString(Range const& range)
2228 return ::Catch::Detail::rangeToString(begin(range), end(range));
2231 // Handle vector<bool> specially
2232 template <typename Allocator> std::string rangeToString(std::vector<bool, Allocator> const& v)
2234 ReusableStringStream rss;
2242 rss << ::Catch::Detail::stringify(b);
2248 template <typename R>
2250 R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
2251 static std::string convert(R const& range) { return rangeToString(range); }
2254 template <typename T, int SZ> struct StringMaker<T[SZ]> {
2255 static std::string convert(T const (&arr)[SZ]) { return rangeToString(arr); }
2258 } // namespace Catch
2260 // Separate std::chrono::duration specialization
2261 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
2268 template <class Ratio> struct ratio_string {
2269 static std::string symbol();
2272 template <class Ratio> std::string ratio_string<Ratio>::symbol()
2274 Catch::ReusableStringStream rss;
2275 rss << '[' << Ratio::num << '/' << Ratio::den << ']';
2278 template <> struct ratio_string<std::atto> {
2279 static std::string symbol();
2281 template <> struct ratio_string<std::femto> {
2282 static std::string symbol();
2284 template <> struct ratio_string<std::pico> {
2285 static std::string symbol();
2287 template <> struct ratio_string<std::nano> {
2288 static std::string symbol();
2290 template <> struct ratio_string<std::micro> {
2291 static std::string symbol();
2293 template <> struct ratio_string<std::milli> {
2294 static std::string symbol();
2298 // std::chrono::duration specializations
2299 template <typename Value, typename Ratio> struct StringMaker<std::chrono::duration<Value, Ratio>> {
2300 static std::string convert(std::chrono::duration<Value, Ratio> const& duration)
2302 ReusableStringStream rss;
2303 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
2307 template <typename Value> struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
2308 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration)
2310 ReusableStringStream rss;
2311 rss << duration.count() << " s";
2315 template <typename Value> struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
2316 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration)
2318 ReusableStringStream rss;
2319 rss << duration.count() << " m";
2323 template <typename Value> struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
2324 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration)
2326 ReusableStringStream rss;
2327 rss << duration.count() << " h";
2333 // std::chrono::time_point specialization
2334 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
2335 template <typename Clock, typename Duration> struct StringMaker<std::chrono::time_point<Clock, Duration>> {
2336 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point)
2338 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
2341 // std::chrono::time_point<system_clock> specialization
2342 template <typename Duration> struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
2343 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point)
2345 auto converted = std::chrono::system_clock::to_time_t(time_point);
2348 std::tm timeInfo = {};
2349 gmtime_s(&timeInfo, &converted);
2351 std::tm* timeInfo = std::gmtime(&converted);
2354 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
2355 char timeStamp[timeStampSize];
2356 const char* const fmt = "%Y-%m-%dT%H:%M:%SZ";
2359 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
2361 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
2363 return std::string(timeStamp);
2366 } // namespace Catch
2367 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
2369 #define INTERNAL_CATCH_REGISTER_ENUM(enumName, ...) \
2371 template <> struct StringMaker<enumName> { \
2372 static std::string convert(enumName value) \
2374 static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( \
2375 #enumName, #__VA_ARGS__, {__VA_ARGS__}); \
2376 return static_cast<std::string>(enumInfo.lookup(static_cast<int>(value))); \
2381 #define CATCH_REGISTER_ENUM(enumName, ...) INTERNAL_CATCH_REGISTER_ENUM(enumName, __VA_ARGS__)
2384 #pragma warning(pop)
2387 // end catch_tostring.h
2391 #pragma warning(push)
2392 #pragma warning(disable : 4389) // '==' : signed/unsigned mismatch
2393 #pragma warning(disable : 4018) // more "signed/unsigned mismatch"
2394 #pragma warning(disable : 4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
2395 #pragma warning(disable : 4180) // qualifier applied to function type has no meaning
2396 #pragma warning(disable : 4800) // Forcing result to true or false
2401 struct ITransientExpression {
2402 auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
2403 auto getResult() const -> bool { return m_result; }
2404 virtual void streamReconstructedExpression(std::ostream& os) const = 0;
2406 ITransientExpression(bool isBinaryExpression, bool result)
2407 : m_isBinaryExpression(isBinaryExpression), m_result(result)
2411 // We don't actually need a virtual destructor, but many static analysers
2412 // complain if it's not here :-(
2413 virtual ~ITransientExpression();
2415 bool m_isBinaryExpression;
2419 void formatReconstructedExpression(std::ostream& os, std::string const& lhs, StringRef op, std::string const& rhs);
2421 template <typename LhsT, typename RhsT> class BinaryExpr : public ITransientExpression {
2426 void streamReconstructedExpression(std::ostream& os) const override
2428 formatReconstructedExpression(os, Catch::Detail::stringify(m_lhs), m_op, Catch::Detail::stringify(m_rhs));
2432 BinaryExpr(bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs)
2433 : ITransientExpression{true, comparisonResult}, m_lhs(lhs), m_op(op), m_rhs(rhs)
2437 template <typename T> auto operator&&(T) const -> BinaryExpr<LhsT, RhsT const&> const
2439 static_assert(always_false<T>::value, "chained comparisons are not supported inside assertions, "
2440 "wrap the expression inside parentheses, or decompose it");
2443 template <typename T> auto operator||(T) const -> BinaryExpr<LhsT, RhsT const&> const
2445 static_assert(always_false<T>::value, "chained comparisons are not supported inside assertions, "
2446 "wrap the expression inside parentheses, or decompose it");
2449 template <typename T> auto operator==(T) const -> BinaryExpr<LhsT, RhsT const&> const
2451 static_assert(always_false<T>::value, "chained comparisons are not supported inside assertions, "
2452 "wrap the expression inside parentheses, or decompose it");
2455 template <typename T> auto operator!=(T) const -> BinaryExpr<LhsT, RhsT const&> const
2457 static_assert(always_false<T>::value, "chained comparisons are not supported inside assertions, "
2458 "wrap the expression inside parentheses, or decompose it");
2461 template <typename T> auto operator>(T) const -> BinaryExpr<LhsT, RhsT const&> const
2463 static_assert(always_false<T>::value, "chained comparisons are not supported inside assertions, "
2464 "wrap the expression inside parentheses, or decompose it");
2467 template <typename T> auto operator<(T) const -> BinaryExpr<LhsT, RhsT const&> const
2469 static_assert(always_false<T>::value, "chained comparisons are not supported inside assertions, "
2470 "wrap the expression inside parentheses, or decompose it");
2473 template <typename T> auto operator>=(T) const -> BinaryExpr<LhsT, RhsT const&> const
2475 static_assert(always_false<T>::value, "chained comparisons are not supported inside assertions, "
2476 "wrap the expression inside parentheses, or decompose it");
2479 template <typename T> auto operator<=(T) const -> BinaryExpr<LhsT, RhsT const&> const
2481 static_assert(always_false<T>::value, "chained comparisons are not supported inside assertions, "
2482 "wrap the expression inside parentheses, or decompose it");
2486 template <typename LhsT> class UnaryExpr : public ITransientExpression {
2489 void streamReconstructedExpression(std::ostream& os) const override { os << Catch::Detail::stringify(m_lhs); }
2492 explicit UnaryExpr(LhsT lhs) : ITransientExpression{false, static_cast<bool>(lhs)}, m_lhs(lhs) {}
2495 // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
2496 template <typename LhsT, typename RhsT> auto compareEqual(LhsT const& lhs, RhsT const& rhs) -> bool
2498 return static_cast<bool>(lhs == rhs);
2500 template <typename T> auto compareEqual(T* const& lhs, int rhs) -> bool
2502 return lhs == reinterpret_cast<void const*>(rhs);
2504 template <typename T> auto compareEqual(T* const& lhs, long rhs) -> bool
2506 return lhs == reinterpret_cast<void const*>(rhs);
2508 template <typename T> auto compareEqual(int lhs, T* const& rhs) -> bool
2510 return reinterpret_cast<void const*>(lhs) == rhs;
2512 template <typename T> auto compareEqual(long lhs, T* const& rhs) -> bool
2514 return reinterpret_cast<void const*>(lhs) == rhs;
2517 template <typename LhsT, typename RhsT> auto compareNotEqual(LhsT const& lhs, RhsT&& rhs) -> bool
2519 return static_cast<bool>(lhs != rhs);
2521 template <typename T> auto compareNotEqual(T* const& lhs, int rhs) -> bool
2523 return lhs != reinterpret_cast<void const*>(rhs);
2525 template <typename T> auto compareNotEqual(T* const& lhs, long rhs) -> bool
2527 return lhs != reinterpret_cast<void const*>(rhs);
2529 template <typename T> auto compareNotEqual(int lhs, T* const& rhs) -> bool
2531 return reinterpret_cast<void const*>(lhs) != rhs;
2533 template <typename T> auto compareNotEqual(long lhs, T* const& rhs) -> bool
2535 return reinterpret_cast<void const*>(lhs) != rhs;
2538 template <typename LhsT> class ExprLhs {
2542 explicit ExprLhs(LhsT lhs) : m_lhs(lhs) {}
2544 template <typename RhsT> auto operator==(RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const
2546 return {compareEqual(m_lhs, rhs), m_lhs, "==", rhs};
2548 auto operator==(bool rhs) -> BinaryExpr<LhsT, bool> const { return {m_lhs == rhs, m_lhs, "==", rhs}; }
2550 template <typename RhsT> auto operator!=(RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const
2552 return {compareNotEqual(m_lhs, rhs), m_lhs, "!=", rhs};
2554 auto operator!=(bool rhs) -> BinaryExpr<LhsT, bool> const { return {m_lhs != rhs, m_lhs, "!=", rhs}; }
2556 template <typename RhsT> auto operator>(RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const
2558 return {static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs};
2560 template <typename RhsT> auto operator<(RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const
2562 return {static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs};
2564 template <typename RhsT> auto operator>=(RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const
2566 return {static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs};
2568 template <typename RhsT> auto operator<=(RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const
2570 return {static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs};
2572 template <typename RhsT> auto operator|(RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const
2574 return {static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs};
2576 template <typename RhsT> auto operator&(RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const
2578 return {static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs};
2580 template <typename RhsT> auto operator^(RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const
2582 return {static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs};
2585 template <typename RhsT> auto operator&&(RhsT const&) -> BinaryExpr<LhsT, RhsT const&> const
2587 static_assert(always_false<RhsT>::value, "operator&& is not supported inside assertions, "
2588 "wrap the expression inside parentheses, or decompose it");
2591 template <typename RhsT> auto operator||(RhsT const&) -> BinaryExpr<LhsT, RhsT const&> const
2593 static_assert(always_false<RhsT>::value, "operator|| is not supported inside assertions, "
2594 "wrap the expression inside parentheses, or decompose it");
2597 auto makeUnaryExpr() const -> UnaryExpr<LhsT> { return UnaryExpr<LhsT>{m_lhs}; }
2600 void handleExpression(ITransientExpression const& expr);
2602 template <typename T> void handleExpression(ExprLhs<T> const& expr)
2604 handleExpression(expr.makeUnaryExpr());
2608 template <typename T> auto operator<=(T const& lhs) -> ExprLhs<T const&> { return ExprLhs<T const&>{lhs}; }
2610 auto operator<=(bool value) -> ExprLhs<bool> { return ExprLhs<bool>{value}; }
2613 } // end namespace Catch
2616 #pragma warning(pop)
2619 // end catch_decomposer.h
2620 // start catch_interfaces_capture.h
2627 class AssertionResult;
2628 struct AssertionInfo;
2630 struct SectionEndInfo;
2632 struct MessageBuilder;
2634 struct AssertionReaction;
2635 struct SourceLineInfo;
2637 struct ITransientExpression;
2638 struct IGeneratorTracker;
2640 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
2641 struct BenchmarkInfo;
2642 template <typename Duration = std::chrono::duration<double, std::nano>> struct BenchmarkStats;
2643 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
2645 struct IResultCapture {
2647 virtual ~IResultCapture();
2649 virtual bool sectionStarted(SectionInfo const& sectionInfo, Counts& assertions) = 0;
2650 virtual void sectionEnded(SectionEndInfo const& endInfo) = 0;
2651 virtual void sectionEndedEarly(SectionEndInfo const& endInfo) = 0;
2653 virtual auto acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo)
2654 -> IGeneratorTracker& = 0;
2656 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
2657 virtual void benchmarkPreparing(std::string const& name) = 0;
2658 virtual void benchmarkStarting(BenchmarkInfo const& info) = 0;
2659 virtual void benchmarkEnded(BenchmarkStats<> const& stats) = 0;
2660 virtual void benchmarkFailed(std::string const& error) = 0;
2661 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
2663 virtual void pushScopedMessage(MessageInfo const& message) = 0;
2664 virtual void popScopedMessage(MessageInfo const& message) = 0;
2666 virtual void emplaceUnscopedMessage(MessageBuilder const& builder) = 0;
2668 virtual void handleFatalErrorCondition(StringRef message) = 0;
2670 virtual void handleExpr(AssertionInfo const& info, ITransientExpression const& expr, AssertionReaction& reaction) = 0;
2671 virtual void handleMessage(AssertionInfo const& info, ResultWas::OfType resultType, StringRef const& message,
2672 AssertionReaction& reaction) = 0;
2673 virtual void handleUnexpectedExceptionNotThrown(AssertionInfo const& info, AssertionReaction& reaction) = 0;
2674 virtual void handleUnexpectedInflightException(AssertionInfo const& info, std::string const& message,
2675 AssertionReaction& reaction) = 0;
2676 virtual void handleIncomplete(AssertionInfo const& info) = 0;
2677 virtual void handleNonExpr(AssertionInfo const& info, ResultWas::OfType resultType, AssertionReaction& reaction) = 0;
2679 virtual bool lastAssertionPassed() = 0;
2680 virtual void assertionPassed() = 0;
2682 // Deprecated, do not use:
2683 virtual std::string getCurrentTestName() const = 0;
2684 virtual const AssertionResult* getLastResult() const = 0;
2685 virtual void exceptionEarlyReported() = 0;
2688 IResultCapture& getResultCapture();
2689 } // namespace Catch
2691 // end catch_interfaces_capture.h
2694 struct TestFailureException {};
2695 struct AssertionResultData;
2696 struct IResultCapture;
2699 class LazyExpression {
2700 friend class AssertionHandler;
2701 friend struct AssertionStats;
2702 friend class RunContext;
2704 ITransientExpression const* m_transientExpression = nullptr;
2708 LazyExpression(bool isNegated);
2709 LazyExpression(LazyExpression const& other);
2710 LazyExpression& operator=(LazyExpression const&) = delete;
2712 explicit operator bool() const;
2714 friend auto operator<<(std::ostream& os, LazyExpression const& lazyExpr) -> std::ostream&;
2717 struct AssertionReaction {
2718 bool shouldDebugBreak = false;
2719 bool shouldThrow = false;
2722 class AssertionHandler {
2723 AssertionInfo m_assertionInfo;
2724 AssertionReaction m_reaction;
2725 bool m_completed = false;
2726 IResultCapture& m_resultCapture;
2729 AssertionHandler(StringRef const& macroName, SourceLineInfo const& lineInfo, StringRef capturedExpression,
2730 ResultDisposition::Flags resultDisposition);
2734 m_resultCapture.handleIncomplete(m_assertionInfo);
2738 template <typename T> void handleExpr(ExprLhs<T> const& expr) { handleExpr(expr.makeUnaryExpr()); }
2739 void handleExpr(ITransientExpression const& expr);
2741 void handleMessage(ResultWas::OfType resultType, StringRef const& message);
2743 void handleExceptionThrownAsExpected();
2744 void handleUnexpectedExceptionNotThrown();
2745 void handleExceptionNotThrownAsExpected();
2746 void handleThrowingCallSkipped();
2747 void handleUnexpectedInflightException();
2750 void setCompleted();
2753 auto allowThrows() const -> bool;
2756 void handleExceptionMatchExpr(AssertionHandler& handler, std::string const& str, StringRef const& matcherString);
2758 } // namespace Catch
2760 // end catch_assertionhandler.h
2761 // start catch_message.h
2768 struct MessageInfo {
2769 MessageInfo(StringRef const& _macroName, SourceLineInfo const& _lineInfo, ResultWas::OfType _type);
2771 StringRef macroName;
2772 std::string message;
2773 SourceLineInfo lineInfo;
2774 ResultWas::OfType type;
2775 unsigned int sequence;
2777 bool operator==(MessageInfo const& other) const;
2778 bool operator<(MessageInfo const& other) const;
2781 static unsigned int globalCount;
2784 struct MessageStream {
2786 template <typename T> MessageStream& operator<<(T const& value)
2792 ReusableStringStream m_stream;
2795 struct MessageBuilder : MessageStream {
2796 MessageBuilder(StringRef const& macroName, SourceLineInfo const& lineInfo, ResultWas::OfType type);
2798 template <typename T> MessageBuilder& operator<<(T const& value)
2807 class ScopedMessage {
2809 explicit ScopedMessage(MessageBuilder const& builder);
2810 ScopedMessage(ScopedMessage& duplicate) = delete;
2811 ScopedMessage(ScopedMessage&& old);
2819 std::vector<MessageInfo> m_messages;
2820 IResultCapture& m_resultCapture = getResultCapture();
2821 size_t m_captured = 0;
2824 Capturer(StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names);
2827 void captureValue(size_t index, std::string const& value);
2829 template <typename T> void captureValues(size_t index, T const& value)
2831 captureValue(index, Catch::Detail::stringify(value));
2834 template <typename T, typename... Ts> void captureValues(size_t index, T const& value, Ts const&... values)
2836 captureValue(index, Catch::Detail::stringify(value));
2837 captureValues(index + 1, values...);
2841 } // end namespace Catch
2843 // end catch_message.h
2844 #if !defined(CATCH_CONFIG_DISABLE)
2846 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
2847 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
2849 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
2852 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
2854 ///////////////////////////////////////////////////////////////////////////////
2855 // Another way to speed-up compilation is to omit local try-catch for REQUIRE*
2857 #define INTERNAL_CATCH_TRY
2858 #define INTERNAL_CATCH_CATCH(capturer)
2860 #else // CATCH_CONFIG_FAST_COMPILE
2862 #define INTERNAL_CATCH_TRY try
2863 #define INTERNAL_CATCH_CATCH(handler) \
2866 handler.handleUnexpectedInflightException(); \
2871 #define INTERNAL_CATCH_REACT(handler) handler.complete();
2873 ///////////////////////////////////////////////////////////////////////////////
2874 #define INTERNAL_CATCH_TEST(macroName, resultDisposition, ...) \
2876 CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
2877 Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \
2878 CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
2879 INTERNAL_CATCH_TRY \
2881 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
2882 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2883 catchAssertionHandler.handleExpr(Catch::Decomposer() <= __VA_ARGS__); \
2884 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
2886 INTERNAL_CATCH_CATCH(catchAssertionHandler) \
2887 INTERNAL_CATCH_REACT(catchAssertionHandler) \
2888 } while ((void)0, (false) && static_cast<bool>(!!(__VA_ARGS__)))
2890 ///////////////////////////////////////////////////////////////////////////////
2891 #define INTERNAL_CATCH_IF(macroName, resultDisposition, ...) \
2892 INTERNAL_CATCH_TEST(macroName, resultDisposition, __VA_ARGS__); \
2893 if (Catch::getResultCapture().lastAssertionPassed())
2895 ///////////////////////////////////////////////////////////////////////////////
2896 #define INTERNAL_CATCH_ELSE(macroName, resultDisposition, ...) \
2897 INTERNAL_CATCH_TEST(macroName, resultDisposition, __VA_ARGS__); \
2898 if (!Catch::getResultCapture().lastAssertionPassed())
2900 ///////////////////////////////////////////////////////////////////////////////
2901 #define INTERNAL_CATCH_NO_THROW(macroName, resultDisposition, ...) \
2903 Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \
2904 CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
2906 static_cast<void>(__VA_ARGS__); \
2907 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
2909 catchAssertionHandler.handleUnexpectedInflightException(); \
2911 INTERNAL_CATCH_REACT(catchAssertionHandler) \
2914 ///////////////////////////////////////////////////////////////////////////////
2915 #define INTERNAL_CATCH_THROWS(macroName, resultDisposition, ...) \
2917 Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \
2918 CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
2919 if (catchAssertionHandler.allowThrows()) \
2921 static_cast<void>(__VA_ARGS__); \
2922 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2924 catchAssertionHandler.handleExceptionThrownAsExpected(); \
2927 catchAssertionHandler.handleThrowingCallSkipped(); \
2928 INTERNAL_CATCH_REACT(catchAssertionHandler) \
2931 ///////////////////////////////////////////////////////////////////////////////
2932 #define INTERNAL_CATCH_THROWS_AS(macroName, exceptionType, resultDisposition, expr) \
2934 Catch::AssertionHandler catchAssertionHandler( \
2935 macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \
2936 CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition); \
2937 if (catchAssertionHandler.allowThrows()) \
2939 static_cast<void>(expr); \
2940 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2941 } catch (exceptionType const&) { \
2942 catchAssertionHandler.handleExceptionThrownAsExpected(); \
2944 catchAssertionHandler.handleUnexpectedInflightException(); \
2947 catchAssertionHandler.handleThrowingCallSkipped(); \
2948 INTERNAL_CATCH_REACT(catchAssertionHandler) \
2951 ///////////////////////////////////////////////////////////////////////////////
2952 #define INTERNAL_CATCH_MSG(macroName, messageType, resultDisposition, ...) \
2954 Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), \
2955 resultDisposition); \
2956 catchAssertionHandler.handleMessage( \
2957 messageType, (Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop()).m_stream.str()); \
2958 INTERNAL_CATCH_REACT(catchAssertionHandler) \
2961 ///////////////////////////////////////////////////////////////////////////////
2962 #define INTERNAL_CATCH_CAPTURE(varName, macroName, ...) \
2963 auto varName = Catch::Capturer(macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__); \
2964 varName.captureValues(0, __VA_ARGS__)
2966 ///////////////////////////////////////////////////////////////////////////////
2967 #define INTERNAL_CATCH_INFO(macroName, log) \
2968 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME(scopedMessage)( \
2969 Catch::MessageBuilder(macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info) << log);
2971 ///////////////////////////////////////////////////////////////////////////////
2972 #define INTERNAL_CATCH_UNSCOPED_INFO(macroName, log) \
2973 Catch::getResultCapture().emplaceUnscopedMessage( \
2974 Catch::MessageBuilder(macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info) << log)
2976 ///////////////////////////////////////////////////////////////////////////////
2977 // Although this is matcher-based, it can be used with just a string
2978 #define INTERNAL_CATCH_THROWS_STR_MATCHES(macroName, resultDisposition, matcher, ...) \
2980 Catch::AssertionHandler catchAssertionHandler( \
2981 macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \
2982 CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition); \
2983 if (catchAssertionHandler.allowThrows()) \
2985 static_cast<void>(__VA_ARGS__); \
2986 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2988 Catch::handleExceptionMatchExpr(catchAssertionHandler, matcher, #matcher##_catch_sr); \
2991 catchAssertionHandler.handleThrowingCallSkipped(); \
2992 INTERNAL_CATCH_REACT(catchAssertionHandler) \
2995 #endif // CATCH_CONFIG_DISABLE
2997 // end catch_capture.hpp
2998 // start catch_section.h
3000 // start catch_section_info.h
3002 // start catch_totals.h
3009 Counts operator-(Counts const& other) const;
3010 Counts& operator+=(Counts const& other);
3012 std::size_t total() const;
3013 bool allPassed() const;
3016 std::size_t passed = 0;
3017 std::size_t failed = 0;
3018 std::size_t failedButOk = 0;
3023 Totals operator-(Totals const& other) const;
3024 Totals& operator+=(Totals const& other);
3026 Totals delta(Totals const& prevTotals) const;
3032 } // namespace Catch
3034 // end catch_totals.h
3039 struct SectionInfo {
3040 SectionInfo(SourceLineInfo const& _lineInfo, std::string const& _name);
3043 SectionInfo(SourceLineInfo const& _lineInfo, std::string const& _name, std::string const&)
3044 : SectionInfo(_lineInfo, _name)
3049 std::string description; // !Deprecated: this will always be empty
3050 SourceLineInfo lineInfo;
3053 struct SectionEndInfo {
3054 SectionInfo sectionInfo;
3055 Counts prevAssertions;
3056 double durationInSeconds;
3059 } // end namespace Catch
3061 // end catch_section_info.h
3062 // start catch_timer.h
3068 auto getCurrentNanosecondsSinceEpoch() -> uint64_t;
3069 auto getEstimatedClockResolution() -> uint64_t;
3072 uint64_t m_nanoseconds = 0;
3076 auto getElapsedNanoseconds() const -> uint64_t;
3077 auto getElapsedMicroseconds() const -> uint64_t;
3078 auto getElapsedMilliseconds() const -> unsigned int;
3079 auto getElapsedSeconds() const -> double;
3082 } // namespace Catch
3084 // end catch_timer.h
3089 class Section : NonCopyable {
3091 Section(SectionInfo const& info);
3094 // This indicates whether the section should be executed or not
3095 explicit operator bool() const;
3101 Counts m_assertions;
3102 bool m_sectionIncluded;
3106 } // end namespace Catch
3108 #define INTERNAL_CATCH_SECTION(...) \
3109 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
3110 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
3111 if (Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME(catch_internal_Section) = \
3112 Catch::SectionInfo(CATCH_INTERNAL_LINEINFO, __VA_ARGS__)) \
3113 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
3115 #define INTERNAL_CATCH_DYNAMIC_SECTION(...) \
3116 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
3117 CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
3118 if (Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME(catch_internal_Section) = \
3119 Catch::SectionInfo(CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str())) \
3120 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
3122 // end catch_section.h
3123 // start catch_interfaces_exception.h
3125 // start catch_interfaces_registry_hub.h
3133 struct ITestCaseRegistry;
3134 struct IExceptionTranslatorRegistry;
3135 struct IExceptionTranslator;
3136 struct IReporterRegistry;
3137 struct IReporterFactory;
3138 struct ITagAliasRegistry;
3139 struct IMutableEnumValuesRegistry;
3141 class StartupExceptionRegistry;
3143 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
3145 struct IRegistryHub {
3146 virtual ~IRegistryHub();
3148 virtual IReporterRegistry const& getReporterRegistry() const = 0;
3149 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
3150 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
3151 virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
3153 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
3156 struct IMutableRegistryHub {
3157 virtual ~IMutableRegistryHub();
3158 virtual void registerReporter(std::string const& name, IReporterFactoryPtr const& factory) = 0;
3159 virtual void registerListener(IReporterFactoryPtr const& factory) = 0;
3160 virtual void registerTest(TestCase const& testInfo) = 0;
3161 virtual void registerTranslator(const IExceptionTranslator* translator) = 0;
3162 virtual void registerTagAlias(std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo) = 0;
3163 virtual void registerStartupException() noexcept = 0;
3164 virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
3167 IRegistryHub const& getRegistryHub();
3168 IMutableRegistryHub& getMutableRegistryHub();
3170 std::string translateActiveException();
3172 } // namespace Catch
3174 // end catch_interfaces_registry_hub.h
3175 #if defined(CATCH_CONFIG_DISABLE)
3176 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG(translatorName, signature) \
3177 static std::string translatorName(signature)
3180 #include <exception>
3185 using exceptionTranslateFunction = std::string (*)();
3187 struct IExceptionTranslator;
3188 using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;
3190 struct IExceptionTranslator {
3191 virtual ~IExceptionTranslator();
3192 virtual std::string translate(ExceptionTranslators::const_iterator it,
3193 ExceptionTranslators::const_iterator itEnd) const = 0;
3196 struct IExceptionTranslatorRegistry {
3197 virtual ~IExceptionTranslatorRegistry();
3199 virtual std::string translateActiveException() const = 0;
3202 class ExceptionTranslatorRegistrar {
3203 template <typename T> class ExceptionTranslator : public IExceptionTranslator {
3205 ExceptionTranslator(std::string (*translateFunction)(T&)) : m_translateFunction(translateFunction) {}
3207 std::string translate(ExceptionTranslators::const_iterator it,
3208 ExceptionTranslators::const_iterator itEnd) const override
3210 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
3215 std::rethrow_exception(std::current_exception());
3217 return (*it)->translate(it + 1, itEnd);
3219 return m_translateFunction(ex);
3225 std::string (*m_translateFunction)(T&);
3229 template <typename T> ExceptionTranslatorRegistrar(std::string (*translateFunction)(T&))
3231 getMutableRegistryHub().registerTranslator(new ExceptionTranslator<T>(translateFunction));
3234 } // namespace Catch
3236 ///////////////////////////////////////////////////////////////////////////////
3237 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2(translatorName, signature) \
3238 static std::string translatorName(signature); \
3239 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
3240 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
3242 Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionRegistrar)(&translatorName); \
3244 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
3245 static std::string translatorName(signature)
3247 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION(signature) \
3248 INTERNAL_CATCH_TRANSLATE_EXCEPTION2(INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionTranslator), signature)
3250 // end catch_interfaces_exception.h
3251 // start catch_approx.h
3253 #include <type_traits>
3260 bool equalityComparisonImpl(double other) const;
3261 // Validates the new margin (margin >= 0)
3262 // out-of-line to avoid including stdexcept in the header
3263 void setMargin(double margin);
3264 // Validates the new epsilon (0 < epsilon < 1)
3265 // out-of-line to avoid including stdexcept in the header
3266 void setEpsilon(double epsilon);
3269 explicit Approx(double value);
3271 static Approx custom();
3273 Approx operator-() const;
3275 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3276 Approx operator()(T const& value)
3278 Approx approx(static_cast<double>(value));
3279 approx.m_epsilon = m_epsilon;
3280 approx.m_margin = m_margin;
3281 approx.m_scale = m_scale;
3285 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3286 explicit Approx(T const& value) : Approx(static_cast<double>(value))
3290 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3291 friend bool operator==(const T& lhs, Approx const& rhs)
3293 auto lhs_v = static_cast<double>(lhs);
3294 return rhs.equalityComparisonImpl(lhs_v);
3297 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3298 friend bool operator==(Approx const& lhs, const T& rhs)
3300 return operator==(rhs, lhs);
3303 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3304 friend bool operator!=(T const& lhs, Approx const& rhs)
3306 return !operator==(lhs, rhs);
3309 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3310 friend bool operator!=(Approx const& lhs, T const& rhs)
3312 return !operator==(rhs, lhs);
3315 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3316 friend bool operator<=(T const& lhs, Approx const& rhs)
3318 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
3321 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3322 friend bool operator<=(Approx const& lhs, T const& rhs)
3324 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
3327 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3328 friend bool operator>=(T const& lhs, Approx const& rhs)
3330 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
3333 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3334 friend bool operator>=(Approx const& lhs, T const& rhs)
3336 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
3339 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3340 Approx& epsilon(T const& newEpsilon)
3342 double epsilonAsDouble = static_cast<double>(newEpsilon);
3343 setEpsilon(epsilonAsDouble);
3347 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3348 Approx& margin(T const& newMargin)
3350 double marginAsDouble = static_cast<double>(newMargin);
3351 setMargin(marginAsDouble);
3355 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3356 Approx& scale(T const& newScale)
3358 m_scale = static_cast<double>(newScale);
3362 std::string toString() const;
3370 } // end namespace Detail
3372 namespace literals {
3373 Detail::Approx operator"" _a(long double val);
3374 Detail::Approx operator"" _a(unsigned long long val);
3375 } // end namespace literals
3377 template <> struct StringMaker<Catch::Detail::Approx> {
3378 static std::string convert(Catch::Detail::Approx const& value);
3381 } // end namespace Catch
3383 // end catch_approx.h
3384 // start catch_string_manip.h
3392 bool startsWith(std::string const& s, std::string const& prefix);
3393 bool startsWith(std::string const& s, char prefix);
3394 bool endsWith(std::string const& s, std::string const& suffix);
3395 bool endsWith(std::string const& s, char suffix);
3396 bool contains(std::string const& s, std::string const& infix);
3397 void toLowerInPlace(std::string& s);
3398 std::string toLower(std::string const& s);
3399 //! Returns a new string without whitespace at the start/end
3400 std::string trim(std::string const& str);
3401 //! Returns a substring of the original ref without whitespace. Beware lifetimes!
3402 StringRef trim(StringRef ref);
3404 // !!! Be aware, returns refs into original string - make sure original string outlives them
3405 std::vector<StringRef> splitStringRef(StringRef str, char delimiter);
3406 bool replaceInPlace(std::string& str, std::string const& replaceThis, std::string const& withThis);
3409 pluralise(std::size_t count, std::string const& label);
3411 friend std::ostream& operator<<(std::ostream& os, pluralise const& pluraliser);
3413 std::size_t m_count;
3414 std::string m_label;
3416 } // namespace Catch
3418 // end catch_string_manip.h
3419 #ifndef CATCH_CONFIG_DISABLE_MATCHERS
3420 // start catch_capture_matchers.h
3422 // start catch_matchers.h
3428 namespace Matchers {
3431 template <typename ArgT> struct MatchAllOf;
3432 template <typename ArgT> struct MatchAnyOf;
3433 template <typename ArgT> struct MatchNotOf;
3435 class MatcherUntypedBase {
3437 MatcherUntypedBase() = default;
3438 MatcherUntypedBase(MatcherUntypedBase const&) = default;
3439 MatcherUntypedBase& operator=(MatcherUntypedBase const&) = delete;
3440 std::string toString() const;
3443 virtual ~MatcherUntypedBase();
3444 virtual std::string describe() const = 0;
3445 mutable std::string m_cachedToString;
3449 #pragma clang diagnostic push
3450 #pragma clang diagnostic ignored "-Wnon-virtual-dtor"
3453 template <typename ObjectT> struct MatcherMethod {
3454 virtual bool match(ObjectT const& arg) const = 0;
3457 #if defined(__OBJC__)
3458 // Hack to fix Catch GH issue #1661. Could use id for generic Object support.
3459 // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks
3461 template <> struct MatcherMethod<NSString*> {
3462 virtual bool match(NSString* arg) const = 0;
3467 #pragma clang diagnostic pop
3470 template <typename T> struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {
3472 MatchAllOf<T> operator&&(MatcherBase const& other) const;
3473 MatchAnyOf<T> operator||(MatcherBase const& other) const;
3474 MatchNotOf<T> operator!() const;
3477 template <typename ArgT> struct MatchAllOf : MatcherBase<ArgT> {
3478 bool match(ArgT const& arg) const override
3480 for (auto matcher : m_matchers) {
3481 if (!matcher->match(arg))
3486 std::string describe() const override
3488 std::string description;
3489 description.reserve(4 + m_matchers.size() * 32);
3490 description += "( ";
3492 for (auto matcher : m_matchers) {
3496 description += " and ";
3497 description += matcher->toString();
3499 description += " )";
3503 MatchAllOf<ArgT> operator&&(MatcherBase<ArgT> const& other)
3506 copy.m_matchers.push_back(&other);
3510 std::vector<MatcherBase<ArgT> const*> m_matchers;
3512 template <typename ArgT> struct MatchAnyOf : MatcherBase<ArgT> {
3514 bool match(ArgT const& arg) const override
3516 for (auto matcher : m_matchers) {
3517 if (matcher->match(arg))
3522 std::string describe() const override
3524 std::string description;
3525 description.reserve(4 + m_matchers.size() * 32);
3526 description += "( ";
3528 for (auto matcher : m_matchers) {
3532 description += " or ";
3533 description += matcher->toString();
3535 description += " )";
3539 MatchAnyOf<ArgT> operator||(MatcherBase<ArgT> const& other)
3542 copy.m_matchers.push_back(&other);
3546 std::vector<MatcherBase<ArgT> const*> m_matchers;
3549 template <typename ArgT> struct MatchNotOf : MatcherBase<ArgT> {
3551 MatchNotOf(MatcherBase<ArgT> const& underlyingMatcher) : m_underlyingMatcher(underlyingMatcher) {}
3553 bool match(ArgT const& arg) const override { return !m_underlyingMatcher.match(arg); }
3555 std::string describe() const override { return "not " + m_underlyingMatcher.toString(); }
3556 MatcherBase<ArgT> const& m_underlyingMatcher;
3559 template <typename T> MatchAllOf<T> MatcherBase<T>::operator&&(MatcherBase const& other) const
3561 return MatchAllOf<T>() && *this && other;
3563 template <typename T> MatchAnyOf<T> MatcherBase<T>::operator||(MatcherBase const& other) const
3565 return MatchAnyOf<T>() || *this || other;
3567 template <typename T> MatchNotOf<T> MatcherBase<T>::operator!() const
3569 return MatchNotOf<T>(*this);
3574 } // namespace Matchers
3576 using namespace Matchers;
3577 using Matchers::Impl::MatcherBase;
3579 } // namespace Catch
3581 // end catch_matchers.h
3582 // start catch_matchers_exception.hpp
3585 namespace Matchers {
3586 namespace Exception {
3588 class ExceptionMessageMatcher : public MatcherBase<std::exception> {
3589 std::string m_message;
3592 ExceptionMessageMatcher(std::string const& message) : m_message(message) {}
3594 bool match(std::exception const& ex) const override;
3596 std::string describe() const override;
3599 } // namespace Exception
3601 Exception::ExceptionMessageMatcher Message(std::string const& message);
3603 } // namespace Matchers
3604 } // namespace Catch
3606 // end catch_matchers_exception.hpp
3607 // start catch_matchers_floating.h
3610 namespace Matchers {
3612 namespace Floating {
3614 enum class FloatingPointKind : uint8_t;
3616 struct WithinAbsMatcher : MatcherBase<double> {
3617 WithinAbsMatcher(double target, double margin);
3618 bool match(double const& matchee) const override;
3619 std::string describe() const override;
3626 struct WithinUlpsMatcher : MatcherBase<double> {
3627 WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType);
3628 bool match(double const& matchee) const override;
3629 std::string describe() const override;
3634 FloatingPointKind m_type;
3637 // Given IEEE-754 format for floats and doubles, we can assume
3638 // that float -> double promotion is lossless. Given this, we can
3639 // assume that if we do the standard relative comparison of
3640 // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
3641 // the same result if we do this for floats, as if we do this for
3642 // doubles that were promoted from floats.
3643 struct WithinRelMatcher : MatcherBase<double> {
3644 WithinRelMatcher(double target, double epsilon);
3645 bool match(double const& matchee) const override;
3646 std::string describe() const override;
3653 } // namespace Floating
3655 // The following functions create the actual matcher objects.
3656 // This allows the types to be inferred
3657 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
3658 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
3659 Floating::WithinAbsMatcher WithinAbs(double target, double margin);
3660 Floating::WithinRelMatcher WithinRel(double target, double eps);
3661 // defaults epsilon to 100*numeric_limits<double>::epsilon()
3662 Floating::WithinRelMatcher WithinRel(double target);
3663 Floating::WithinRelMatcher WithinRel(float target, float eps);
3664 // defaults epsilon to 100*numeric_limits<float>::epsilon()
3665 Floating::WithinRelMatcher WithinRel(float target);
3667 } // namespace Matchers
3668 } // namespace Catch
3670 // end catch_matchers_floating.h
3671 // start catch_matchers_generic.hpp
3673 #include <functional>
3677 namespace Matchers {
3681 std::string finalizeDescription(const std::string& desc);
3684 template <typename T> class PredicateMatcher : public MatcherBase<T> {
3685 std::function<bool(T const&)> m_predicate;
3686 std::string m_description;
3689 PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
3690 : m_predicate(std::move(elem)), m_description(Detail::finalizeDescription(descr))
3694 bool match(T const& item) const override { return m_predicate(item); }
3696 std::string describe() const override { return m_description; }
3699 } // namespace Generic
3701 // The following functions create the actual matcher objects.
3702 // The user has to explicitly specify type to the function, because
3703 // inferring std::function<bool(T const&)> is hard (but possible) and
3704 // requires a lot of TMP.
3705 template <typename T>
3706 Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate,
3707 std::string const& description = "")
3709 return Generic::PredicateMatcher<T>(predicate, description);
3712 } // namespace Matchers
3713 } // namespace Catch
3715 // end catch_matchers_generic.hpp
3716 // start catch_matchers_string.h
3721 namespace Matchers {
3723 namespace StdString {
3725 struct CasedString {
3726 CasedString(std::string const& str, CaseSensitive::Choice caseSensitivity);
3727 std::string adjustString(std::string const& str) const;
3728 std::string caseSensitivitySuffix() const;
3730 CaseSensitive::Choice m_caseSensitivity;
3734 struct StringMatcherBase : MatcherBase<std::string> {
3735 StringMatcherBase(std::string const& operation, CasedString const& comparator);
3736 std::string describe() const override;
3738 CasedString m_comparator;
3739 std::string m_operation;
3742 struct EqualsMatcher : StringMatcherBase {
3743 EqualsMatcher(CasedString const& comparator);
3744 bool match(std::string const& source) const override;
3746 struct ContainsMatcher : StringMatcherBase {
3747 ContainsMatcher(CasedString const& comparator);
3748 bool match(std::string const& source) const override;
3750 struct StartsWithMatcher : StringMatcherBase {
3751 StartsWithMatcher(CasedString const& comparator);
3752 bool match(std::string const& source) const override;
3754 struct EndsWithMatcher : StringMatcherBase {
3755 EndsWithMatcher(CasedString const& comparator);
3756 bool match(std::string const& source) const override;
3759 struct RegexMatcher : MatcherBase<std::string> {
3760 RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity);
3761 bool match(std::string const& matchee) const override;
3762 std::string describe() const override;
3765 std::string m_regex;
3766 CaseSensitive::Choice m_caseSensitivity;
3769 } // namespace StdString
3771 // The following functions create the actual matcher objects.
3772 // This allows the types to be inferred
3774 StdString::EqualsMatcher Equals(std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes);
3775 StdString::ContainsMatcher Contains(std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes);
3776 StdString::EndsWithMatcher EndsWith(std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes);
3777 StdString::StartsWithMatcher StartsWith(std::string const& str,
3778 CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes);
3779 StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes);
3781 } // namespace Matchers
3782 } // namespace Catch
3784 // end catch_matchers_string.h
3785 // start catch_matchers_vector.h
3787 #include <algorithm>
3790 namespace Matchers {
3793 template <typename T, typename Alloc> struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> {
3795 ContainsElementMatcher(T const& comparator) : m_comparator(comparator) {}
3797 bool match(std::vector<T, Alloc> const& v) const override
3799 for (auto const& el : v) {
3800 if (el == m_comparator) {
3807 std::string describe() const override { return "Contains: " + ::Catch::Detail::stringify(m_comparator); }
3809 T const& m_comparator;
3812 template <typename T, typename AllocComp, typename AllocMatch>
3813 struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
3815 ContainsMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator(comparator) {}
3817 bool match(std::vector<T, AllocMatch> const& v) const override
3819 // !TBD: see note in EqualsMatcher
3820 if (m_comparator.size() > v.size())
3822 for (auto const& comparator : m_comparator) {
3823 auto present = false;
3824 for (const auto& el : v) {
3825 if (el == comparator) {
3836 std::string describe() const override { return "Contains: " + ::Catch::Detail::stringify(m_comparator); }
3838 std::vector<T, AllocComp> const& m_comparator;
3841 template <typename T, typename AllocComp, typename AllocMatch>
3842 struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
3844 EqualsMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator(comparator) {}
3846 bool match(std::vector<T, AllocMatch> const& v) const override
3848 // !TBD: This currently works if all elements can be compared using !=
3849 // - a more general approach would be via a compare template that defaults
3850 // to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc
3851 // - then just call that directly
3852 if (m_comparator.size() != v.size())
3854 for (std::size_t i = 0; i < v.size(); ++i)
3855 if (m_comparator[i] != v[i])
3859 std::string describe() const override { return "Equals: " + ::Catch::Detail::stringify(m_comparator); }
3860 std::vector<T, AllocComp> const& m_comparator;
3863 template <typename T, typename AllocComp, typename AllocMatch>
3864 struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> {
3866 ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator(comparator) {}
3868 bool match(std::vector<T, AllocMatch> const& v) const override
3870 if (m_comparator.size() != v.size())
3872 for (std::size_t i = 0; i < v.size(); ++i)
3873 if (m_comparator[i] != approx(v[i]))
3877 std::string describe() const override { return "is approx: " + ::Catch::Detail::stringify(m_comparator); }
3878 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3879 ApproxMatcher& epsilon(T const& newEpsilon)
3881 approx.epsilon(newEpsilon);
3884 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3885 ApproxMatcher& margin(T const& newMargin)
3887 approx.margin(newMargin);
3890 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
3891 ApproxMatcher& scale(T const& newScale)
3893 approx.scale(newScale);
3897 std::vector<T, AllocComp> const& m_comparator;
3898 mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
3901 template <typename T, typename AllocComp, typename AllocMatch>
3902 struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {
3903 UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {}
3904 bool match(std::vector<T, AllocMatch> const& vec) const override
3906 if (m_target.size() != vec.size()) {
3909 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
3912 std::string describe() const override { return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); }
3915 std::vector<T, AllocComp> const& m_target;
3918 } // namespace Vector
3920 // The following functions create the actual matcher objects.
3921 // This allows the types to be inferred
3923 template <typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
3924 Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains(std::vector<T, AllocComp> const& comparator)
3926 return Vector::ContainsMatcher<T, AllocComp, AllocMatch>(comparator);
3929 template <typename T, typename Alloc = std::allocator<T>>
3930 Vector::ContainsElementMatcher<T, Alloc> VectorContains(T const& comparator)
3932 return Vector::ContainsElementMatcher<T, Alloc>(comparator);
3935 template <typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
3936 Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals(std::vector<T, AllocComp> const& comparator)
3938 return Vector::EqualsMatcher<T, AllocComp, AllocMatch>(comparator);
3941 template <typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
3942 Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx(std::vector<T, AllocComp> const& comparator)
3944 return Vector::ApproxMatcher<T, AllocComp, AllocMatch>(comparator);
3947 template <typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>
3948 Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target)
3950 return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>(target);
3953 } // namespace Matchers
3954 } // namespace Catch
3956 // end catch_matchers_vector.h
3959 template <typename ArgT, typename MatcherT> class MatchExpr : public ITransientExpression {
3962 StringRef m_matcherString;
3965 MatchExpr(ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString)
3966 : ITransientExpression{true, matcher.match(arg)}, m_arg(arg), m_matcher(matcher), m_matcherString(matcherString)
3970 void streamReconstructedExpression(std::ostream& os) const override
3972 auto matcherAsString = m_matcher.toString();
3973 os << Catch::Detail::stringify(m_arg) << ' ';
3974 if (matcherAsString == Detail::unprintableString)
3975 os << m_matcherString;
3977 os << matcherAsString;
3981 using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
3983 void handleExceptionMatchExpr(AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString);
3985 template <typename ArgT, typename MatcherT>
3986 auto makeMatchExpr(ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString)
3987 -> MatchExpr<ArgT, MatcherT>
3989 return MatchExpr<ArgT, MatcherT>(arg, matcher, matcherString);
3992 } // namespace Catch
3994 ///////////////////////////////////////////////////////////////////////////////
3995 #define INTERNAL_CHECK_THAT(macroName, matcher, resultDisposition, arg) \
3997 Catch::AssertionHandler catchAssertionHandler( \
3998 macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \
3999 CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition); \
4000 INTERNAL_CATCH_TRY \
4002 catchAssertionHandler.handleExpr(Catch::makeMatchExpr(arg, matcher, #matcher##_catch_sr)); \
4004 INTERNAL_CATCH_CATCH(catchAssertionHandler) \
4005 INTERNAL_CATCH_REACT(catchAssertionHandler) \
4008 ///////////////////////////////////////////////////////////////////////////////
4009 #define INTERNAL_CATCH_THROWS_MATCHES(macroName, exceptionType, resultDisposition, matcher, ...) \
4011 Catch::AssertionHandler catchAssertionHandler(macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, \
4012 CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY( \
4013 exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), \
4014 resultDisposition); \
4015 if (catchAssertionHandler.allowThrows()) \
4017 static_cast<void>(__VA_ARGS__); \
4018 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
4019 } catch (exceptionType const& ex) { \
4020 catchAssertionHandler.handleExpr(Catch::makeMatchExpr(ex, matcher, #matcher##_catch_sr)); \
4022 catchAssertionHandler.handleUnexpectedInflightException(); \
4025 catchAssertionHandler.handleThrowingCallSkipped(); \
4026 INTERNAL_CATCH_REACT(catchAssertionHandler) \
4029 // end catch_capture_matchers.h
4031 // start catch_generators.hpp
4033 // start catch_interfaces_generatortracker.h
4039 namespace Generators {
4040 class GeneratorUntypedBase {
4042 GeneratorUntypedBase() = default;
4043 virtual ~GeneratorUntypedBase();
4044 // Attempts to move the generator to the next element
4046 // Returns true iff the move succeeded (and a valid element
4047 // can be retrieved).
4048 virtual bool next() = 0;
4050 using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;
4052 } // namespace Generators
4054 struct IGeneratorTracker {
4055 virtual ~IGeneratorTracker();
4056 virtual auto hasGenerator() const -> bool = 0;
4057 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
4058 virtual void setGenerator(Generators::GeneratorBasePtr&& generator) = 0;
4061 } // namespace Catch
4063 // end catch_interfaces_generatortracker.h
4064 // start catch_enforce.h
4066 #include <exception>
4069 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
4070 template <typename Ex> [[noreturn]] void throw_exception(Ex const& e)
4074 #else // ^^ Exceptions are enabled // Exceptions are disabled vv
4075 [[noreturn]] void throw_exception(std::exception const& e);
4078 [[noreturn]] void throw_logic_error(std::string const& msg);
4079 [[noreturn]] void throw_domain_error(std::string const& msg);
4080 [[noreturn]] void throw_runtime_error(std::string const& msg);
4082 } // namespace Catch
4084 #define CATCH_MAKE_MSG(...) (Catch::ReusableStringStream() << __VA_ARGS__).str()
4086 #define CATCH_INTERNAL_ERROR(...) \
4087 Catch::throw_logic_error(CATCH_MAKE_MSG(CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))
4089 #define CATCH_ERROR(...) Catch::throw_domain_error(CATCH_MAKE_MSG(__VA_ARGS__))
4091 #define CATCH_RUNTIME_ERROR(...) Catch::throw_runtime_error(CATCH_MAKE_MSG(__VA_ARGS__))
4093 #define CATCH_ENFORCE(condition, ...) \
4096 CATCH_ERROR(__VA_ARGS__); \
4099 // end catch_enforce.h
4104 #include <exception>
4109 class GeneratorException : public std::exception {
4110 const char* const m_msg = "";
4113 GeneratorException(const char* msg) : m_msg(msg) {}
4115 const char* what() const noexcept override final;
4118 namespace Generators {
4120 // !TBD move this into its own location?
4122 template <typename T, typename... Args> std::unique_ptr<T> make_unique(Args&&... args)
4124 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
4128 template <typename T> struct IGenerator : GeneratorUntypedBase {
4129 virtual ~IGenerator() = default;
4131 // Returns the current element of the generator
4133 // \Precondition The generator is either freshly constructed,
4134 // or the last call to `next()` returned true
4135 virtual T const& get() const = 0;
4139 template <typename T> class SingleValueGenerator final : public IGenerator<T> {
4143 SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
4145 T const& get() const override { return m_value; }
4146 bool next() override { return false; }
4149 template <typename T> class FixedValuesGenerator final : public IGenerator<T> {
4150 static_assert(!std::is_same<T, bool>::value,
4151 "FixedValuesGenerator does not support bools because of std::vector<bool>"
4152 "specialization, use SingleValue Generator instead.");
4153 std::vector<T> m_values;
4157 FixedValuesGenerator(std::initializer_list<T> values) : m_values(values) {}
4159 T const& get() const override { return m_values[m_idx]; }
4160 bool next() override
4163 return m_idx < m_values.size();
4167 template <typename T> class GeneratorWrapper final {
4168 std::unique_ptr<IGenerator<T>> m_generator;
4171 GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator) : m_generator(std::move(generator)) {}
4172 T const& get() const { return m_generator->get(); }
4173 bool next() { return m_generator->next(); }
4176 template <typename T> GeneratorWrapper<T> value(T&& value)
4178 return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value)));
4180 template <typename T> GeneratorWrapper<T> values(std::initializer_list<T> values)
4182 return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));
4185 template <typename T> class Generators : public IGenerator<T> {
4186 std::vector<GeneratorWrapper<T>> m_generators;
4187 size_t m_current = 0;
4189 void populate(GeneratorWrapper<T>&& generator) { m_generators.emplace_back(std::move(generator)); }
4190 void populate(T&& val) { m_generators.emplace_back(value(std::forward<T>(val))); }
4191 template <typename U> void populate(U&& val) { populate(T(std::forward<U>(val))); }
4192 template <typename U, typename... Gs> void populate(U&& valueOrGenerator, Gs&&... moreGenerators)
4194 populate(std::forward<U>(valueOrGenerator));
4195 populate(std::forward<Gs>(moreGenerators)...);
4199 template <typename... Gs> Generators(Gs&&... moreGenerators)
4201 m_generators.reserve(sizeof...(Gs));
4202 populate(std::forward<Gs>(moreGenerators)...);
4205 T const& get() const override { return m_generators[m_current].get(); }
4207 bool next() override
4209 if (m_current >= m_generators.size()) {
4212 const bool current_status = m_generators[m_current].next();
4213 if (!current_status) {
4216 return m_current < m_generators.size();
4220 template <typename... Ts>
4221 GeneratorWrapper<std::tuple<Ts...>> table(std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples)
4223 return values<std::tuple<Ts...>>(tuples);
4226 // Tag type to signal that a generator sequence should convert arguments to a specific type
4227 template <typename T> struct as {
4230 template <typename T, typename... Gs>
4231 auto makeGenerators(GeneratorWrapper<T>&& generator, Gs&&... moreGenerators) -> Generators<T>
4233 return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
4235 template <typename T> auto makeGenerators(GeneratorWrapper<T>&& generator) -> Generators<T>
4237 return Generators<T>(std::move(generator));
4239 template <typename T, typename... Gs> auto makeGenerators(T&& val, Gs&&... moreGenerators) -> Generators<T>
4241 return makeGenerators(value(std::forward<T>(val)), std::forward<Gs>(moreGenerators)...);
4243 template <typename T, typename U, typename... Gs>
4244 auto makeGenerators(as<T>, U&& val, Gs&&... moreGenerators) -> Generators<T>
4246 return makeGenerators(value(T(std::forward<U>(val))), std::forward<Gs>(moreGenerators)...);
4249 auto acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo) -> IGeneratorTracker&;
4251 template <typename L>
4252 // Note: The type after -> is weird, because VS2015 cannot parse
4253 // the expression used in the typedef inside, when it is in
4254 // return type. Yeah.
4255 auto generate(StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression)
4256 -> decltype(std::declval<decltype(generatorExpression())>().get())
4258 using UnderlyingType = typename decltype(generatorExpression())::type;
4260 IGeneratorTracker& tracker = acquireGeneratorTracker(generatorName, lineInfo);
4261 if (!tracker.hasGenerator()) {
4262 tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
4265 auto const& generator = static_cast<IGenerator<UnderlyingType> const&>(*tracker.getGenerator());
4266 return generator.get();
4269 } // namespace Generators
4270 } // namespace Catch
4272 #define GENERATE(...) \
4273 Catch::Generators::generate(INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
4274 CATCH_INTERNAL_LINEINFO, [] { \
4275 using namespace Catch::Generators; \
4276 return makeGenerators(__VA_ARGS__); \
4277 }) // NOLINT(google-build-using-namespace)
4278 #define GENERATE_COPY(...) \
4279 Catch::Generators::generate(INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
4280 CATCH_INTERNAL_LINEINFO, [=] { \
4281 using namespace Catch::Generators; \
4282 return makeGenerators(__VA_ARGS__); \
4283 }) // NOLINT(google-build-using-namespace)
4284 #define GENERATE_REF(...) \
4285 Catch::Generators::generate(INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \
4286 CATCH_INTERNAL_LINEINFO, [&] { \
4287 using namespace Catch::Generators; \
4288 return makeGenerators(__VA_ARGS__); \
4289 }) // NOLINT(google-build-using-namespace)
4291 // end catch_generators.hpp
4292 // start catch_generators_generic.hpp
4295 namespace Generators {
4297 template <typename T> class TakeGenerator : public IGenerator<T> {
4298 GeneratorWrapper<T> m_generator;
4299 size_t m_returned = 0;
4303 TakeGenerator(size_t target, GeneratorWrapper<T>&& generator) : m_generator(std::move(generator)), m_target(target)
4305 assert(target != 0 && "Empty generators are not allowed");
4307 T const& get() const override { return m_generator.get(); }
4308 bool next() override
4311 if (m_returned >= m_target) {
4315 const auto success = m_generator.next();
4316 // If the underlying generator does not contain enough values
4317 // then we cut short as well
4319 m_returned = m_target;
4325 template <typename T> GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator)
4327 return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
4330 template <typename T, typename Predicate> class FilterGenerator : public IGenerator<T> {
4331 GeneratorWrapper<T> m_generator;
4332 Predicate m_predicate;
4335 template <typename P = Predicate>
4336 FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator)
4337 : m_generator(std::move(generator)), m_predicate(std::forward<P>(pred))
4339 if (!m_predicate(m_generator.get())) {
4340 // It might happen that there are no values that pass the
4341 // filter. In that case we throw an exception.
4342 auto has_initial_value = next();
4343 if (!has_initial_value) {
4344 Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
4349 T const& get() const override { return m_generator.get(); }
4351 bool next() override
4353 bool success = m_generator.next();
4357 while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true)
4363 template <typename T, typename Predicate> GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator)
4365 return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(
4366 pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
4369 template <typename T> class RepeatGenerator : public IGenerator<T> {
4370 static_assert(!std::is_same<T, bool>::value, "RepeatGenerator currently does not support bools"
4371 "because of std::vector<bool> specialization");
4372 GeneratorWrapper<T> m_generator;
4373 mutable std::vector<T> m_returned;
4374 size_t m_target_repeats;
4375 size_t m_current_repeat = 0;
4376 size_t m_repeat_index = 0;
4379 RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator)
4380 : m_generator(std::move(generator)), m_target_repeats(repeats)
4382 assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
4385 T const& get() const override
4387 if (m_current_repeat == 0) {
4388 m_returned.push_back(m_generator.get());
4389 return m_returned.back();
4391 return m_returned[m_repeat_index];
4394 bool next() override
4396 // There are 2 basic cases:
4397 // 1) We are still reading the generator
4398 // 2) We are reading our own cache
4400 // In the first case, we need to poke the underlying generator.
4401 // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
4402 if (m_current_repeat == 0) {
4403 const auto success = m_generator.next();
4407 return m_current_repeat < m_target_repeats;
4410 // In the second case, we need to move indices forward and check that we haven't run up against the end
4412 if (m_repeat_index == m_returned.size()) {
4416 return m_current_repeat < m_target_repeats;
4420 template <typename T> GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator)
4422 return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
4425 template <typename T, typename U, typename Func> class MapGenerator : public IGenerator<T> {
4426 // TBD: provide static assert for mapping function, for friendly error message
4427 GeneratorWrapper<U> m_generator;
4429 // To avoid returning dangling reference, we have to save the values
4433 template <typename F2 = Func>
4434 MapGenerator(F2&& function, GeneratorWrapper<U>&& generator)
4435 : m_generator(std::move(generator))
4436 , m_function(std::forward<F2>(function))
4437 , m_cache(m_function(m_generator.get()))
4441 T const& get() const override { return m_cache; }
4442 bool next() override
4444 const auto success = m_generator.next();
4446 m_cache = m_function(m_generator.get());
4452 template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
4453 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator)
4455 return GeneratorWrapper<T>(
4456 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)));
4459 template <typename T, typename U, typename Func>
4460 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator)
4462 return GeneratorWrapper<T>(
4463 pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator)));
4466 template <typename T> class ChunkGenerator final : public IGenerator<std::vector<T>> {
4467 std::vector<T> m_chunk;
4468 size_t m_chunk_size;
4469 GeneratorWrapper<T> m_generator;
4470 bool m_used_up = false;
4473 ChunkGenerator(size_t size, GeneratorWrapper<T> generator) : m_chunk_size(size), m_generator(std::move(generator))
4475 m_chunk.reserve(m_chunk_size);
4476 if (m_chunk_size != 0) {
4477 m_chunk.push_back(m_generator.get());
4478 for (size_t i = 1; i < m_chunk_size; ++i) {
4479 if (!m_generator.next()) {
4480 Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));
4482 m_chunk.push_back(m_generator.get());
4486 std::vector<T> const& get() const override { return m_chunk; }
4487 bool next() override
4490 for (size_t idx = 0; idx < m_chunk_size; ++idx) {
4491 if (!m_generator.next()) {
4494 m_chunk.push_back(m_generator.get());
4500 template <typename T> GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator)
4502 return GeneratorWrapper<std::vector<T>>(pf::make_unique<ChunkGenerator<T>>(size, std::move(generator)));
4505 } // namespace Generators
4506 } // namespace Catch
4508 // end catch_generators_generic.hpp
4509 // start catch_generators_specific.hpp
4511 // start catch_context.h
4517 struct IResultCapture;
4520 struct IMutableContext;
4522 using IConfigPtr = std::shared_ptr<IConfig const>;
4525 virtual ~IContext();
4527 virtual IResultCapture* getResultCapture() = 0;
4528 virtual IRunner* getRunner() = 0;
4529 virtual IConfigPtr const& getConfig() const = 0;
4532 struct IMutableContext : IContext {
4533 virtual ~IMutableContext();
4534 virtual void setResultCapture(IResultCapture* resultCapture) = 0;
4535 virtual void setRunner(IRunner* runner) = 0;
4536 virtual void setConfig(IConfigPtr const& config) = 0;
4539 static IMutableContext* currentContext;
4540 friend IMutableContext& getCurrentMutableContext();
4541 friend void cleanUpContext();
4542 static void createContext();
4545 inline IMutableContext& getCurrentMutableContext()
4547 if (!IMutableContext::currentContext)
4548 IMutableContext::createContext();
4549 // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
4550 return *IMutableContext::currentContext;
4553 inline IContext& getCurrentContext()
4555 return getCurrentMutableContext();
4558 void cleanUpContext();
4562 } // namespace Catch
4564 // end catch_context.h
4565 // start catch_interfaces_config.h
4567 // start catch_option.hpp
4572 template <typename T> class Option {
4574 Option() : nullableValue(nullptr) {}
4575 Option(T const& _value) : nullableValue(new (storage) T(_value)) {}
4576 Option(Option const& _other) : nullableValue(_other ? new (storage) T(*_other) : nullptr) {}
4578 ~Option() { reset(); }
4580 Option& operator=(Option const& _other)
4582 if (&_other != this) {
4585 nullableValue = new (storage) T(*_other);
4589 Option& operator=(T const& _value)
4592 nullableValue = new (storage) T(_value);
4599 nullableValue->~T();
4600 nullableValue = nullptr;
4603 T& operator*() { return *nullableValue; }
4604 T const& operator*() const { return *nullableValue; }
4605 T* operator->() { return nullableValue; }
4606 const T* operator->() const { return nullableValue; }
4608 T valueOr(T const& defaultValue) const { return nullableValue ? *nullableValue : defaultValue; }
4610 bool some() const { return nullableValue != nullptr; }
4611 bool none() const { return nullableValue == nullptr; }
4613 bool operator!() const { return nullableValue == nullptr; }
4614 explicit operator bool() const { return some(); }
4618 alignas(alignof(T)) char storage[sizeof(T)];
4621 } // end namespace Catch
4623 // end catch_option.hpp
4632 enum class Verbosity { Quiet = 0, Normal, High };
4635 enum What { Nothing = 0x00, NoAssertions = 0x01, NoTests = 0x02 };
4638 struct ShowDurations {
4639 enum OrNot { DefaultForReporter, Always, Never };
4642 enum InWhatOrder { InDeclarationOrder, InLexicographicalOrder, InRandomOrder };
4645 enum YesOrNo { Auto, Yes, No };
4647 struct WaitForKeypress {
4648 enum When { Never, BeforeStart = 1, BeforeExit = 2, BeforeStartAndExit = BeforeStart | BeforeExit };
4653 struct IConfig : NonCopyable {
4657 virtual bool allowThrows() const = 0;
4658 virtual std::ostream& stream() const = 0;
4659 virtual std::string name() const = 0;
4660 virtual bool includeSuccessfulResults() const = 0;
4661 virtual bool shouldDebugBreak() const = 0;
4662 virtual bool warnAboutMissingAssertions() const = 0;
4663 virtual bool warnAboutNoTests() const = 0;
4664 virtual int abortAfter() const = 0;
4665 virtual bool showInvisibles() const = 0;
4666 virtual ShowDurations::OrNot showDurations() const = 0;
4667 virtual double minDuration() const = 0;
4668 virtual TestSpec const& testSpec() const = 0;
4669 virtual bool hasTestFilters() const = 0;
4670 virtual std::vector<std::string> const& getTestsOrTags() const = 0;
4671 virtual RunTests::InWhatOrder runOrder() const = 0;
4672 virtual unsigned int rngSeed() const = 0;
4673 virtual UseColour::YesOrNo useColour() const = 0;
4674 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
4675 virtual Verbosity verbosity() const = 0;
4677 virtual bool benchmarkNoAnalysis() const = 0;
4678 virtual int benchmarkSamples() const = 0;
4679 virtual double benchmarkConfidenceInterval() const = 0;
4680 virtual unsigned int benchmarkResamples() const = 0;
4681 virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;
4684 using IConfigPtr = std::shared_ptr<IConfig const>;
4685 } // namespace Catch
4687 // end catch_interfaces_config.h
4688 // start catch_random_number_generator.h
4694 // This is a simple implementation of C++11 Uniform Random Number
4695 // Generator. It does not provide all operators, because Catch2
4696 // does not use it, but it should behave as expected inside stdlib's
4698 // The implementation is based on the PCG family (http://pcg-random.org)
4700 using state_type = std::uint64_t;
4703 using result_type = std::uint32_t;
4704 static constexpr result_type(min)() { return 0; }
4705 static constexpr result_type(max)() { return static_cast<result_type>(-1); }
4707 // Provide some default initial state for the default constructor
4708 SimplePcg32() : SimplePcg32(0xed743cc4U) {}
4710 explicit SimplePcg32(result_type seed_);
4712 void seed(result_type seed_);
4713 void discard(uint64_t skip);
4715 result_type operator()();
4718 friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
4719 friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
4721 // In theory we also need operator<< and operator>>
4722 // In practice we do not use them, so we will skip them for now
4724 std::uint64_t m_state;
4725 // This part of the state determines which "stream" of the numbers
4726 // is chosen -- we take it as a constant for Catch2, so we only
4727 // need to deal with seeding the main state.
4728 // Picked by reading 8 bytes from `/dev/random` :-)
4729 static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
4732 } // end namespace Catch
4734 // end catch_random_number_generator.h
4738 namespace Generators {
4740 template <typename Float> class RandomFloatingGenerator final : public IGenerator<Float> {
4741 Catch::SimplePcg32& m_rng;
4742 std::uniform_real_distribution<Float> m_dist;
4743 Float m_current_number;
4746 RandomFloatingGenerator(Float a, Float b) : m_rng(rng()), m_dist(a, b) { static_cast<void>(next()); }
4748 Float const& get() const override { return m_current_number; }
4749 bool next() override
4751 m_current_number = m_dist(m_rng);
4756 template <typename Integer> class RandomIntegerGenerator final : public IGenerator<Integer> {
4757 Catch::SimplePcg32& m_rng;
4758 std::uniform_int_distribution<Integer> m_dist;
4759 Integer m_current_number;
4762 RandomIntegerGenerator(Integer a, Integer b) : m_rng(rng()), m_dist(a, b) { static_cast<void>(next()); }
4764 Integer const& get() const override { return m_current_number; }
4765 bool next() override
4767 m_current_number = m_dist(m_rng);
4772 // TODO: Ideally this would be also constrained against the various char types,
4773 // but I don't expect users to run into that in practice.
4774 template <typename T>
4775 typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, GeneratorWrapper<T>>::type
4778 return GeneratorWrapper<T>(pf::make_unique<RandomIntegerGenerator<T>>(a, b));
4781 template <typename T>
4782 typename std::enable_if<std::is_floating_point<T>::value, GeneratorWrapper<T>>::type random(T a, T b)
4784 return GeneratorWrapper<T>(pf::make_unique<RandomFloatingGenerator<T>>(a, b));
4787 template <typename T> class RangeGenerator final : public IGenerator<T> {
4794 RangeGenerator(T const& start, T const& end, T const& step)
4795 : m_current(start), m_end(end), m_step(step), m_positive(m_step > T(0))
4797 assert(m_current != m_end && "Range start and end cannot be equal");
4798 assert(m_step != T(0) && "Step size cannot be zero");
4799 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
4802 RangeGenerator(T const& start, T const& end) : RangeGenerator(start, end, (start < end) ? T(1) : T(-1)) {}
4804 T const& get() const override { return m_current; }
4806 bool next() override
4808 m_current += m_step;
4809 return (m_positive) ? (m_current < m_end) : (m_current > m_end);
4813 template <typename T> GeneratorWrapper<T> range(T const& start, T const& end, T const& step)
4815 static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");
4816 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
4819 template <typename T> GeneratorWrapper<T> range(T const& start, T const& end)
4821 static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
4822 return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end));
4825 template <typename T> class IteratorGenerator final : public IGenerator<T> {
4826 static_assert(!std::is_same<T, bool>::value, "IteratorGenerator currently does not support bools"
4827 "because of std::vector<bool> specialization");
4829 std::vector<T> m_elems;
4830 size_t m_current = 0;
4833 template <typename InputIterator, typename InputSentinel>
4834 IteratorGenerator(InputIterator first, InputSentinel last) : m_elems(first, last)
4836 if (m_elems.empty()) {
4837 Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values"));
4841 T const& get() const override { return m_elems[m_current]; }
4843 bool next() override
4846 return m_current != m_elems.size();
4850 template <typename InputIterator, typename InputSentinel,
4851 typename ResultType = typename std::iterator_traits<InputIterator>::value_type>
4852 GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to)
4854 return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to));
4857 template <typename Container, typename ResultType = typename Container::value_type>
4858 GeneratorWrapper<ResultType> from_range(Container const& cnt)
4860 return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(cnt.begin(), cnt.end()));
4863 } // namespace Generators
4864 } // namespace Catch
4866 // end catch_generators_specific.hpp
4868 // These files are included here so the single_include script doesn't put them
4869 // in the conditionally compiled sections
4870 // start catch_test_case_info.h
4877 #pragma clang diagnostic push
4878 #pragma clang diagnostic ignored "-Wpadded"
4883 struct ITestInvoker;
4885 struct TestCaseInfo {
4886 enum SpecialProperties {
4889 ShouldFail = 1 << 2,
4892 NonPortable = 1 << 5,
4896 TestCaseInfo(std::string const& _name, std::string const& _className, std::string const& _description,
4897 std::vector<std::string> const& _tags, SourceLineInfo const& _lineInfo);
4899 friend void setTags(TestCaseInfo& testCaseInfo, std::vector<std::string> tags);
4901 bool isHidden() const;
4902 bool throws() const;
4903 bool okToFail() const;
4904 bool expectedToFail() const;
4906 std::string tagsAsString() const;
4909 std::string className;
4910 std::string description;
4911 std::vector<std::string> tags;
4912 std::vector<std::string> lcaseTags;
4913 SourceLineInfo lineInfo;
4914 SpecialProperties properties;
4917 class TestCase : public TestCaseInfo {
4919 TestCase(ITestInvoker* testCase, TestCaseInfo&& info);
4921 TestCase withName(std::string const& _newName) const;
4923 void invoke() const;
4925 TestCaseInfo const& getTestCaseInfo() const;
4927 bool operator==(TestCase const& other) const;
4928 bool operator<(TestCase const& other) const;
4931 std::shared_ptr<ITestInvoker> test;
4934 TestCase makeTestCase(ITestInvoker* testCase, std::string const& className, NameAndTags const& nameAndTags,
4935 SourceLineInfo const& lineInfo);
4936 } // namespace Catch
4939 #pragma clang diagnostic pop
4942 // end catch_test_case_info.h
4943 // start catch_interfaces_runner.h
4949 virtual bool aborting() const = 0;
4951 } // namespace Catch
4953 // end catch_interfaces_runner.h
4956 // start catch_objc.hpp
4958 #import <objc/runtime.h>
4962 // NB. Any general catch headers included here must be included
4963 // in catch.hpp first to make sure they are included by the single
4964 // header for non obj-usage
4966 ///////////////////////////////////////////////////////////////////////////////
4967 // This protocol is really only here for (self) documenting purposes, since
4968 // all its methods are optional.
4980 class OcMethod : public ITestInvoker {
4983 OcMethod(Class cls, SEL sel) : m_cls(cls), m_sel(sel) {}
4985 virtual void invoke() const
4987 id obj = [[m_cls alloc] init];
4989 performOptionalSelector(obj, @selector(setUp));
4990 performOptionalSelector(obj, m_sel);
4991 performOptionalSelector(obj, @selector(tearDown));
4993 arcSafeRelease(obj);
4997 virtual ~OcMethod() {}
5005 inline std::string getAnnotation(Class cls, std::string const& annotationName, std::string const& testCaseName)
5007 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
5008 SEL sel = NSSelectorFromString(selStr);
5009 arcSafeRelease(selStr);
5010 id value = performOptionalSelector(cls, sel);
5012 return [(NSString*)value UTF8String];
5015 } // namespace Detail
5017 inline std::size_t registerTestMethods()
5019 std::size_t noTestMethods = 0;
5020 int noClasses = objc_getClassList(nullptr, 0);
5022 Class* classes = (CATCH_UNSAFE_UNRETAINED Class*)malloc(sizeof(Class) * noClasses);
5023 objc_getClassList(classes, noClasses);
5025 for (int c = 0; c < noClasses; c++) {
5026 Class cls = classes[c];
5029 Method* methods = class_copyMethodList(cls, &count);
5030 for (u_int m = 0; m < count; m++) {
5031 SEL selector = method_getName(methods[m]);
5032 std::string methodName = sel_getName(selector);
5033 if (startsWith(methodName, "Catch_TestCase_")) {
5034 std::string testCaseName = methodName.substr(15);
5035 std::string name = Detail::getAnnotation(cls, "Name", testCaseName);
5036 std::string desc = Detail::getAnnotation(cls, "Description", testCaseName);
5037 const char* className = class_getName(cls);
5039 getMutableRegistryHub().registerTest(makeTestCase(
5040 new OcMethod(cls, selector), className, NameAndTags(name.c_str(), desc.c_str()), SourceLineInfo("", 0)));
5047 return noTestMethods;
5050 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
5052 namespace Matchers {
5054 namespace NSStringMatchers {
5056 struct StringHolder : MatcherBase<NSString*> {
5057 StringHolder(NSString* substr) : m_substr([substr copy]) {}
5058 StringHolder(StringHolder const& other) : m_substr([other.m_substr copy]) {}
5059 StringHolder() { arcSafeRelease(m_substr); }
5061 bool match(NSString* str) const override { return false; }
5063 NSString* CATCH_ARC_STRONG m_substr;
5066 struct Equals : StringHolder {
5067 Equals(NSString* substr) : StringHolder(substr) {}
5069 bool match(NSString* str) const override { return (str != nil || m_substr == nil) && [str isEqualToString:m_substr]; }
5071 std::string describe() const override { return "equals string: " + Catch::Detail::stringify(m_substr); }
5074 struct Contains : StringHolder {
5075 Contains(NSString* substr) : StringHolder(substr) {}
5077 bool match(NSString* str) const override
5079 return (str != nil || m_substr == nil) && [str rangeOfString:m_substr].location != NSNotFound;
5082 std::string describe() const override { return "contains string: " + Catch::Detail::stringify(m_substr); }
5085 struct StartsWith : StringHolder {
5086 StartsWith(NSString* substr) : StringHolder(substr) {}
5088 bool match(NSString* str) const override
5090 return (str != nil || m_substr == nil) && [str rangeOfString:m_substr].location == 0;
5093 std::string describe() const override { return "starts with: " + Catch::Detail::stringify(m_substr); }
5095 struct EndsWith : StringHolder {
5096 EndsWith(NSString* substr) : StringHolder(substr) {}
5098 bool match(NSString* str) const override
5100 return (str != nil || m_substr == nil) && [str rangeOfString:m_substr].location == [str length] - [m_substr length];
5103 std::string describe() const override { return "ends with: " + Catch::Detail::stringify(m_substr); }
5106 } // namespace NSStringMatchers
5109 inline Impl::NSStringMatchers::Equals Equals(NSString* substr)
5111 return Impl::NSStringMatchers::Equals(substr);
5114 inline Impl::NSStringMatchers::Contains Contains(NSString* substr)
5116 return Impl::NSStringMatchers::Contains(substr);
5119 inline Impl::NSStringMatchers::StartsWith StartsWith(NSString* substr)
5121 return Impl::NSStringMatchers::StartsWith(substr);
5124 inline Impl::NSStringMatchers::EndsWith EndsWith(NSString* substr)
5126 return Impl::NSStringMatchers::EndsWith(substr);
5129 } // namespace Matchers
5131 using namespace Matchers;
5133 #endif // CATCH_CONFIG_DISABLE_MATCHERS
5135 } // namespace Catch
5137 ///////////////////////////////////////////////////////////////////////////////
5138 #define OC_MAKE_UNIQUE_NAME(root, uniqueSuffix) root##uniqueSuffix
5139 #define OC_TEST_CASE2(name, desc, uniqueSuffix) \
5140 +(NSString*)OC_MAKE_UNIQUE_NAME(Catch_Name_test_, uniqueSuffix) \
5144 +(NSString*)OC_MAKE_UNIQUE_NAME(Catch_Description_test_, uniqueSuffix) \
5148 -(void)OC_MAKE_UNIQUE_NAME(Catch_TestCase_test_, uniqueSuffix)
5150 #define OC_TEST_CASE(name, desc) OC_TEST_CASE2(name, desc, __LINE__)
5152 // end catch_objc.hpp
5155 // Benchmarking needs the externally-facing parts of reporters to work
5156 #if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5157 // start catch_external_interfaces.h
5159 // start catch_reporter_bases.hpp
5161 // start catch_interfaces_reporter.h
5163 // start catch_config.hpp
5165 // start catch_test_spec_parser.h
5168 #pragma clang diagnostic push
5169 #pragma clang diagnostic ignored "-Wpadded"
5172 // start catch_test_spec.h
5175 #pragma clang diagnostic push
5176 #pragma clang diagnostic ignored "-Wpadded"
5179 // start catch_wildcard_pattern.h
5182 class WildcardPattern {
5183 enum WildcardPosition {
5185 WildcardAtStart = 1,
5187 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
5191 WildcardPattern(std::string const& pattern, CaseSensitive::Choice caseSensitivity);
5192 virtual ~WildcardPattern() = default;
5193 virtual bool matches(std::string const& str) const;
5196 std::string normaliseString(std::string const& str) const;
5197 CaseSensitive::Choice m_caseSensitivity;
5198 WildcardPosition m_wildcard = NoWildcard;
5199 std::string m_pattern;
5201 } // namespace Catch
5203 // end catch_wildcard_pattern.h
5215 explicit Pattern(std::string const& name);
5217 virtual bool matches(TestCaseInfo const& testCase) const = 0;
5218 std::string const& name() const;
5221 std::string const m_name;
5223 using PatternPtr = std::shared_ptr<Pattern>;
5225 class NamePattern : public Pattern {
5227 explicit NamePattern(std::string const& name, std::string const& filterString);
5228 bool matches(TestCaseInfo const& testCase) const override;
5231 WildcardPattern m_wildcardPattern;
5234 class TagPattern : public Pattern {
5236 explicit TagPattern(std::string const& tag, std::string const& filterString);
5237 bool matches(TestCaseInfo const& testCase) const override;
5243 class ExcludedPattern : public Pattern {
5245 explicit ExcludedPattern(PatternPtr const& underlyingPattern);
5246 bool matches(TestCaseInfo const& testCase) const override;
5249 PatternPtr m_underlyingPattern;
5253 std::vector<PatternPtr> m_patterns;
5255 bool matches(TestCaseInfo const& testCase) const;
5256 std::string name() const;
5260 struct FilterMatch {
5262 std::vector<TestCase const*> tests;
5264 using Matches = std::vector<FilterMatch>;
5265 using vectorStrings = std::vector<std::string>;
5267 bool hasFilters() const;
5268 bool matches(TestCaseInfo const& testCase) const;
5269 Matches matchesByFilter(std::vector<TestCase> const& testCases, IConfig const& config) const;
5270 const vectorStrings& getInvalidArgs() const;
5273 std::vector<Filter> m_filters;
5274 std::vector<std::string> m_invalidArgs;
5275 friend class TestSpecParser;
5277 } // namespace Catch
5280 #pragma clang diagnostic pop
5283 // end catch_test_spec.h
5284 // start catch_interfaces_tag_alias_registry.h
5292 struct ITagAliasRegistry {
5293 virtual ~ITagAliasRegistry();
5294 // Nullptr if not present
5295 virtual TagAlias const* find(std::string const& alias) const = 0;
5296 virtual std::string expandAliases(std::string const& unexpandedTestSpec) const = 0;
5298 static ITagAliasRegistry const& get();
5301 } // end namespace Catch
5303 // end catch_interfaces_tag_alias_registry.h
5306 class TestSpecParser {
5307 enum Mode { None, Name, QuotedName, Tag, EscapedName };
5309 Mode lastMode = None;
5310 bool m_exclusion = false;
5311 std::size_t m_pos = 0;
5312 std::size_t m_realPatternPos = 0;
5314 std::string m_substring;
5315 std::string m_patternName;
5316 std::vector<std::size_t> m_escapeChars;
5317 TestSpec::Filter m_currentFilter;
5318 TestSpec m_testSpec;
5319 ITagAliasRegistry const* m_tagAliases = nullptr;
5322 TestSpecParser(ITagAliasRegistry const& tagAliases);
5324 TestSpecParser& parse(std::string const& arg);
5325 TestSpec testSpec();
5328 bool visitChar(char c);
5329 void startNewMode(Mode mode);
5330 bool processNoneChar(char c);
5331 void processNameChar(char c);
5332 bool processOtherChar(char c);
5335 bool isControlChar(char c) const;
5336 void saveLastMode();
5337 void revertBackToLastMode();
5341 // Handles common preprocessing of the pattern for name/tag patterns
5342 std::string preprocessPattern();
5343 // Adds the current pattern as a test name
5344 void addNamePattern();
5345 // Adds the current pattern as a tag
5346 void addTagPattern();
5348 inline void addCharToPattern(char c)
5355 TestSpec parseTestSpec(std::string const& arg);
5357 } // namespace Catch
5360 #pragma clang diagnostic pop
5363 // end catch_test_spec_parser.h
5364 // Libstdc++ doesn't like incomplete classes for unique_ptr
5370 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
5371 #define CATCH_CONFIG_CONSOLE_WIDTH 80
5379 bool listTests = false;
5380 bool listTags = false;
5381 bool listReporters = false;
5382 bool listTestNamesOnly = false;
5384 bool showSuccessfulTests = false;
5385 bool shouldDebugBreak = false;
5386 bool noThrow = false;
5387 bool showHelp = false;
5388 bool showInvisibles = false;
5389 bool filenamesAsTags = false;
5390 bool libIdentify = false;
5392 int abortAfter = -1;
5393 unsigned int rngSeed = 0;
5395 bool benchmarkNoAnalysis = false;
5396 unsigned int benchmarkSamples = 100;
5397 double benchmarkConfidenceInterval = 0.95;
5398 unsigned int benchmarkResamples = 100000;
5399 std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
5401 Verbosity verbosity = Verbosity::Normal;
5402 WarnAbout::What warnings = WarnAbout::Nothing;
5403 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
5404 double minDuration = -1;
5405 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
5406 UseColour::YesOrNo useColour = UseColour::Auto;
5407 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
5409 std::string outputFilename;
5411 std::string processName;
5412 #ifndef CATCH_CONFIG_DEFAULT_REPORTER
5413 #define CATCH_CONFIG_DEFAULT_REPORTER "console"
5415 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
5416 #undef CATCH_CONFIG_DEFAULT_REPORTER
5418 std::vector<std::string> testsOrTags;
5419 std::vector<std::string> sectionsToRun;
5422 class Config : public IConfig {
5425 Config(ConfigData const& data);
5426 virtual ~Config() = default;
5428 std::string const& getFilename() const;
5430 bool listTests() const;
5431 bool listTestNamesOnly() const;
5432 bool listTags() const;
5433 bool listReporters() const;
5435 std::string getProcessName() const;
5436 std::string const& getReporterName() const;
5438 std::vector<std::string> const& getTestsOrTags() const override;
5439 std::vector<std::string> const& getSectionsToRun() const override;
5441 TestSpec const& testSpec() const override;
5442 bool hasTestFilters() const override;
5444 bool showHelp() const;
5446 // IConfig interface
5447 bool allowThrows() const override;
5448 std::ostream& stream() const override;
5449 std::string name() const override;
5450 bool includeSuccessfulResults() const override;
5451 bool warnAboutMissingAssertions() const override;
5452 bool warnAboutNoTests() const override;
5453 ShowDurations::OrNot showDurations() const override;
5454 double minDuration() const override;
5455 RunTests::InWhatOrder runOrder() const override;
5456 unsigned int rngSeed() const override;
5457 UseColour::YesOrNo useColour() const override;
5458 bool shouldDebugBreak() const override;
5459 int abortAfter() const override;
5460 bool showInvisibles() const override;
5461 Verbosity verbosity() const override;
5462 bool benchmarkNoAnalysis() const override;
5463 int benchmarkSamples() const override;
5464 double benchmarkConfidenceInterval() const override;
5465 unsigned int benchmarkResamples() const override;
5466 std::chrono::milliseconds benchmarkWarmupTime() const override;
5469 IStream const* openStream();
5472 std::unique_ptr<IStream const> m_stream;
5473 TestSpec m_testSpec;
5474 bool m_hasTestFilters = false;
5477 } // end namespace Catch
5479 // end catch_config.hpp
5480 // start catch_assertionresult.h
5486 struct AssertionResultData {
5487 AssertionResultData() = delete;
5489 AssertionResultData(ResultWas::OfType _resultType, LazyExpression const& _lazyExpression);
5491 std::string message;
5492 mutable std::string reconstructedExpression;
5493 LazyExpression lazyExpression;
5494 ResultWas::OfType resultType;
5496 std::string reconstructExpression() const;
5499 class AssertionResult {
5501 AssertionResult() = delete;
5502 AssertionResult(AssertionInfo const& info, AssertionResultData const& data);
5505 bool succeeded() const;
5506 ResultWas::OfType getResultType() const;
5507 bool hasExpression() const;
5508 bool hasMessage() const;
5509 std::string getExpression() const;
5510 std::string getExpressionInMacro() const;
5511 bool hasExpandedExpression() const;
5512 std::string getExpandedExpression() const;
5513 std::string getMessage() const;
5514 SourceLineInfo getSourceInfo() const;
5515 StringRef getTestMacroName() const;
5518 AssertionInfo m_info;
5519 AssertionResultData m_resultData;
5522 } // end namespace Catch
5524 // end catch_assertionresult.h
5525 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5526 // start catch_estimate.hpp
5528 // Statistics estimates
5531 namespace Benchmark {
5532 template <typename Duration> struct Estimate {
5534 Duration lower_bound;
5535 Duration upper_bound;
5536 double confidence_interval;
5538 template <typename Duration2> operator Estimate<Duration2>() const
5540 return {point, lower_bound, upper_bound, confidence_interval};
5543 } // namespace Benchmark
5544 } // namespace Catch
5546 // end catch_estimate.hpp
5547 // start catch_outlier_classification.hpp
5549 // Outlier information
5552 namespace Benchmark {
5553 struct OutlierClassification {
5554 int samples_seen = 0;
5555 int low_severe = 0; // more than 3 times IQR below Q1
5556 int low_mild = 0; // 1.5 to 3 times IQR below Q1
5557 int high_mild = 0; // 1.5 to 3 times IQR above Q3
5558 int high_severe = 0; // more than 3 times IQR above Q3
5560 int total() const { return low_severe + low_mild + high_mild + high_severe; }
5562 } // namespace Benchmark
5563 } // namespace Catch
5565 // end catch_outlier_classification.hpp
5566 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
5568 #include <algorithm>
5577 struct ReporterConfig {
5578 explicit ReporterConfig(IConfigPtr const& _fullConfig);
5580 ReporterConfig(IConfigPtr const& _fullConfig, std::ostream& _stream);
5582 std::ostream& stream() const;
5583 IConfigPtr fullConfig() const;
5586 std::ostream* m_stream;
5587 IConfigPtr m_fullConfig;
5590 struct ReporterPreferences {
5591 bool shouldRedirectStdOut = false;
5592 bool shouldReportAllAssertions = false;
5595 template <typename T> struct LazyStat : Option<T> {
5596 LazyStat& operator=(T const& _value)
5598 Option<T>::operator=(_value);
5610 struct TestRunInfo {
5611 TestRunInfo(std::string const& _name);
5615 GroupInfo(std::string const& _name, std::size_t _groupIndex, std::size_t _groupsCount);
5618 std::size_t groupIndex;
5619 std::size_t groupsCounts;
5622 struct AssertionStats {
5623 AssertionStats(AssertionResult const& _assertionResult, std::vector<MessageInfo> const& _infoMessages,
5624 Totals const& _totals);
5626 AssertionStats(AssertionStats const&) = default;
5627 AssertionStats(AssertionStats&&) = default;
5628 AssertionStats& operator=(AssertionStats const&) = delete;
5629 AssertionStats& operator=(AssertionStats&&) = delete;
5630 virtual ~AssertionStats();
5632 AssertionResult assertionResult;
5633 std::vector<MessageInfo> infoMessages;
5637 struct SectionStats {
5638 SectionStats(SectionInfo const& _sectionInfo, Counts const& _assertions, double _durationInSeconds,
5639 bool _missingAssertions);
5640 SectionStats(SectionStats const&) = default;
5641 SectionStats(SectionStats&&) = default;
5642 SectionStats& operator=(SectionStats const&) = default;
5643 SectionStats& operator=(SectionStats&&) = default;
5644 virtual ~SectionStats();
5646 SectionInfo sectionInfo;
5648 double durationInSeconds;
5649 bool missingAssertions;
5652 struct TestCaseStats {
5653 TestCaseStats(TestCaseInfo const& _testInfo, Totals const& _totals, std::string const& _stdOut,
5654 std::string const& _stdErr, bool _aborting);
5656 TestCaseStats(TestCaseStats const&) = default;
5657 TestCaseStats(TestCaseStats&&) = default;
5658 TestCaseStats& operator=(TestCaseStats const&) = default;
5659 TestCaseStats& operator=(TestCaseStats&&) = default;
5660 virtual ~TestCaseStats();
5662 TestCaseInfo testInfo;
5669 struct TestGroupStats {
5670 TestGroupStats(GroupInfo const& _groupInfo, Totals const& _totals, bool _aborting);
5671 TestGroupStats(GroupInfo const& _groupInfo);
5673 TestGroupStats(TestGroupStats const&) = default;
5674 TestGroupStats(TestGroupStats&&) = default;
5675 TestGroupStats& operator=(TestGroupStats const&) = default;
5676 TestGroupStats& operator=(TestGroupStats&&) = default;
5677 virtual ~TestGroupStats();
5679 GroupInfo groupInfo;
5684 struct TestRunStats {
5685 TestRunStats(TestRunInfo const& _runInfo, Totals const& _totals, bool _aborting);
5687 TestRunStats(TestRunStats const&) = default;
5688 TestRunStats(TestRunStats&&) = default;
5689 TestRunStats& operator=(TestRunStats const&) = default;
5690 TestRunStats& operator=(TestRunStats&&) = default;
5691 virtual ~TestRunStats();
5693 TestRunInfo runInfo;
5698 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5699 struct BenchmarkInfo {
5701 double estimatedDuration;
5704 unsigned int resamples;
5705 double clockResolution;
5709 template <class Duration> struct BenchmarkStats {
5712 std::vector<Duration> samples;
5713 Benchmark::Estimate<Duration> mean;
5714 Benchmark::Estimate<Duration> standardDeviation;
5715 Benchmark::OutlierClassification outliers;
5716 double outlierVariance;
5718 template <typename Duration2> operator BenchmarkStats<Duration2>() const
5720 std::vector<Duration2> samples2;
5721 samples2.reserve(samples.size());
5722 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2),
5723 [](Duration d) { return Duration2(d); });
5725 info, std::move(samples2), mean, standardDeviation, outliers, outlierVariance,
5729 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
5731 struct IStreamingReporter {
5732 virtual ~IStreamingReporter() = default;
5734 // Implementing class must also provide the following static methods:
5735 // static std::string getDescription();
5736 // static std::set<Verbosity> getSupportedVerbosities()
5738 virtual ReporterPreferences getPreferences() const = 0;
5740 virtual void noMatchingTestCases(std::string const& spec) = 0;
5742 virtual void reportInvalidArguments(std::string const&) {}
5744 virtual void testRunStarting(TestRunInfo const& testRunInfo) = 0;
5745 virtual void testGroupStarting(GroupInfo const& groupInfo) = 0;
5747 virtual void testCaseStarting(TestCaseInfo const& testInfo) = 0;
5748 virtual void sectionStarting(SectionInfo const& sectionInfo) = 0;
5750 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5751 virtual void benchmarkPreparing(std::string const&) {}
5752 virtual void benchmarkStarting(BenchmarkInfo const&) {}
5753 virtual void benchmarkEnded(BenchmarkStats<> const&) {}
5754 virtual void benchmarkFailed(std::string const&) {}
5755 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
5757 virtual void assertionStarting(AssertionInfo const& assertionInfo) = 0;
5759 // The return value indicates if the messages buffer should be cleared:
5760 virtual bool assertionEnded(AssertionStats const& assertionStats) = 0;
5762 virtual void sectionEnded(SectionStats const& sectionStats) = 0;
5763 virtual void testCaseEnded(TestCaseStats const& testCaseStats) = 0;
5764 virtual void testGroupEnded(TestGroupStats const& testGroupStats) = 0;
5765 virtual void testRunEnded(TestRunStats const& testRunStats) = 0;
5767 virtual void skipTest(TestCaseInfo const& testInfo) = 0;
5769 // Default empty implementation provided
5770 virtual void fatalErrorEncountered(StringRef name);
5772 virtual bool isMulti() const;
5774 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
5776 struct IReporterFactory {
5777 virtual ~IReporterFactory();
5778 virtual IStreamingReporterPtr create(ReporterConfig const& config) const = 0;
5779 virtual std::string getDescription() const = 0;
5781 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
5783 struct IReporterRegistry {
5784 using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
5785 using Listeners = std::vector<IReporterFactoryPtr>;
5787 virtual ~IReporterRegistry();
5788 virtual IStreamingReporterPtr create(std::string const& name, IConfigPtr const& config) const = 0;
5789 virtual FactoryMap const& getFactories() const = 0;
5790 virtual Listeners const& getListeners() const = 0;
5793 } // end namespace Catch
5795 // end catch_interfaces_reporter.h
5796 #include <algorithm>
5805 void prepareExpandedExpression(AssertionResult& result);
5807 // Returns double formatted as %.3f (format expected on output)
5808 std::string getFormattedDuration(double duration);
5810 //! Should the reporter show
5811 bool shouldShowDuration(IConfig const& config, double duration);
5813 std::string serializeFilters(std::vector<std::string> const& container);
5815 template <typename DerivedT> struct StreamingReporterBase : IStreamingReporter {
5817 StreamingReporterBase(ReporterConfig const& _config) : m_config(_config.fullConfig()), stream(_config.stream())
5819 m_reporterPrefs.shouldRedirectStdOut = false;
5820 if (!DerivedT::getSupportedVerbosities().count(m_config->verbosity()))
5821 CATCH_ERROR("Verbosity level not supported by this reporter");
5824 ReporterPreferences getPreferences() const override { return m_reporterPrefs; }
5826 static std::set<Verbosity> getSupportedVerbosities() { return {Verbosity::Normal}; }
5828 ~StreamingReporterBase() override = default;
5830 void noMatchingTestCases(std::string const&) override {}
5832 void reportInvalidArguments(std::string const&) override {}
5834 void testRunStarting(TestRunInfo const& _testRunInfo) override { currentTestRunInfo = _testRunInfo; }
5836 void testGroupStarting(GroupInfo const& _groupInfo) override { currentGroupInfo = _groupInfo; }
5838 void testCaseStarting(TestCaseInfo const& _testInfo) override { currentTestCaseInfo = _testInfo; }
5839 void sectionStarting(SectionInfo const& _sectionInfo) override { m_sectionStack.push_back(_sectionInfo); }
5841 void sectionEnded(SectionStats const& /* _sectionStats */) override { m_sectionStack.pop_back(); }
5842 void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { currentTestCaseInfo.reset(); }
5843 void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { currentGroupInfo.reset(); }
5844 void testRunEnded(TestRunStats const& /* _testRunStats */) override
5846 currentTestCaseInfo.reset();
5847 currentGroupInfo.reset();
5848 currentTestRunInfo.reset();
5851 void skipTest(TestCaseInfo const&) override
5853 // Don't do anything with this by default.
5854 // It can optionally be overridden in the derived class.
5857 IConfigPtr m_config;
5858 std::ostream& stream;
5860 LazyStat<TestRunInfo> currentTestRunInfo;
5861 LazyStat<GroupInfo> currentGroupInfo;
5862 LazyStat<TestCaseInfo> currentTestCaseInfo;
5864 std::vector<SectionInfo> m_sectionStack;
5865 ReporterPreferences m_reporterPrefs;
5868 template <typename DerivedT> struct CumulativeReporterBase : IStreamingReporter {
5869 template <typename T, typename ChildNodeT> struct Node {
5870 explicit Node(T const& _value) : value(_value) {}
5873 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
5875 ChildNodes children;
5877 struct SectionNode {
5878 explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
5879 virtual ~SectionNode() = default;
5881 bool operator==(SectionNode const& other) const
5883 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
5885 bool operator==(std::shared_ptr<SectionNode> const& other) const { return operator==(*other); }
5888 using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
5889 using Assertions = std::vector<AssertionStats>;
5890 ChildSections childSections;
5891 Assertions assertions;
5896 struct BySectionInfo {
5897 BySectionInfo(SectionInfo const& other) : m_other(other) {}
5898 BySectionInfo(BySectionInfo const& other) : m_other(other.m_other) {}
5899 bool operator()(std::shared_ptr<SectionNode> const& node) const
5901 return ((node->stats.sectionInfo.name == m_other.name) && (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
5903 void operator=(BySectionInfo const&) = delete;
5906 SectionInfo const& m_other;
5909 using TestCaseNode = Node<TestCaseStats, SectionNode>;
5910 using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
5911 using TestRunNode = Node<TestRunStats, TestGroupNode>;
5913 CumulativeReporterBase(ReporterConfig const& _config) : m_config(_config.fullConfig()), stream(_config.stream())
5915 m_reporterPrefs.shouldRedirectStdOut = false;
5916 if (!DerivedT::getSupportedVerbosities().count(m_config->verbosity()))
5917 CATCH_ERROR("Verbosity level not supported by this reporter");
5919 ~CumulativeReporterBase() override = default;
5921 ReporterPreferences getPreferences() const override { return m_reporterPrefs; }
5923 static std::set<Verbosity> getSupportedVerbosities() { return {Verbosity::Normal}; }
5925 void testRunStarting(TestRunInfo const&) override {}
5926 void testGroupStarting(GroupInfo const&) override {}
5928 void testCaseStarting(TestCaseInfo const&) override {}
5930 void sectionStarting(SectionInfo const& sectionInfo) override
5932 SectionStats incompleteStats(sectionInfo, Counts(), 0, false);
5933 std::shared_ptr<SectionNode> node;
5934 if (m_sectionStack.empty()) {
5936 m_rootSection = std::make_shared<SectionNode>(incompleteStats);
5937 node = m_rootSection;
5939 SectionNode& parentNode = *m_sectionStack.back();
5941 std::find_if(parentNode.childSections.begin(), parentNode.childSections.end(), BySectionInfo(sectionInfo));
5942 if (it == parentNode.childSections.end()) {
5943 node = std::make_shared<SectionNode>(incompleteStats);
5944 parentNode.childSections.push_back(node);
5948 m_sectionStack.push_back(node);
5949 m_deepestSection = std::move(node);
5952 void assertionStarting(AssertionInfo const&) override {}
5954 bool assertionEnded(AssertionStats const& assertionStats) override
5956 assert(!m_sectionStack.empty());
5957 // AssertionResult holds a pointer to a temporary DecomposedExpression,
5958 // which getExpandedExpression() calls to build the expression string.
5959 // Our section stack copy of the assertionResult will likely outlive the
5960 // temporary, so it must be expanded or discarded now to avoid calling
5961 // a destroyed object later.
5962 prepareExpandedExpression(const_cast<AssertionResult&>(assertionStats.assertionResult));
5963 SectionNode& sectionNode = *m_sectionStack.back();
5964 sectionNode.assertions.push_back(assertionStats);
5967 void sectionEnded(SectionStats const& sectionStats) override
5969 assert(!m_sectionStack.empty());
5970 SectionNode& node = *m_sectionStack.back();
5971 node.stats = sectionStats;
5972 m_sectionStack.pop_back();
5974 void testCaseEnded(TestCaseStats const& testCaseStats) override
5976 auto node = std::make_shared<TestCaseNode>(testCaseStats);
5977 assert(m_sectionStack.size() == 0);
5978 node->children.push_back(m_rootSection);
5979 m_testCases.push_back(node);
5980 m_rootSection.reset();
5982 assert(m_deepestSection);
5983 m_deepestSection->stdOut = testCaseStats.stdOut;
5984 m_deepestSection->stdErr = testCaseStats.stdErr;
5986 void testGroupEnded(TestGroupStats const& testGroupStats) override
5988 auto node = std::make_shared<TestGroupNode>(testGroupStats);
5989 node->children.swap(m_testCases);
5990 m_testGroups.push_back(node);
5992 void testRunEnded(TestRunStats const& testRunStats) override
5994 auto node = std::make_shared<TestRunNode>(testRunStats);
5995 node->children.swap(m_testGroups);
5996 m_testRuns.push_back(node);
5997 testRunEndedCumulative();
5999 virtual void testRunEndedCumulative() = 0;
6001 void skipTest(TestCaseInfo const&) override {}
6003 IConfigPtr m_config;
6004 std::ostream& stream;
6005 std::vector<AssertionStats> m_assertions;
6006 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
6007 std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
6008 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
6010 std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
6012 std::shared_ptr<SectionNode> m_rootSection;
6013 std::shared_ptr<SectionNode> m_deepestSection;
6014 std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
6015 ReporterPreferences m_reporterPrefs;
6018 template <char C> char const* getLineOfChars()
6020 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
6022 std::memset(line, C, CATCH_CONFIG_CONSOLE_WIDTH - 1);
6023 line[CATCH_CONFIG_CONSOLE_WIDTH - 1] = 0;
6028 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
6029 TestEventListenerBase(ReporterConfig const& _config);
6031 static std::set<Verbosity> getSupportedVerbosities();
6033 void assertionStarting(AssertionInfo const&) override;
6034 bool assertionEnded(AssertionStats const&) override;
6037 } // end namespace Catch
6039 // end catch_reporter_bases.hpp
6040 // start catch_console_colour.h
6058 BrightRed = Bright | Red,
6059 BrightGreen = Bright | Green,
6060 LightGrey = Bright | Grey,
6061 BrightWhite = Bright | White,
6062 BrightYellow = Bright | Yellow,
6065 FileName = LightGrey,
6066 Warning = BrightYellow,
6067 ResultError = BrightRed,
6068 ResultSuccess = BrightGreen,
6069 ResultExpectedFailure = Warning,
6074 OriginalExpression = Cyan,
6075 ReconstructedExpression = BrightYellow,
6077 SecondaryText = LightGrey,
6081 // Use constructed object for RAII guard
6082 Colour(Code _colourCode);
6083 Colour(Colour&& other) noexcept;
6084 Colour& operator=(Colour&& other) noexcept;
6087 // Use static method for one-shot changes
6088 static void use(Code _colourCode);
6091 bool m_moved = false;
6094 std::ostream& operator<<(std::ostream& os, Colour const&);
6096 } // end namespace Catch
6098 // end catch_console_colour.h
6099 // start catch_reporter_registrars.hpp
6103 template <typename T> class ReporterRegistrar {
6105 class ReporterFactory : public IReporterFactory {
6107 IStreamingReporterPtr create(ReporterConfig const& config) const override
6109 return std::unique_ptr<T>(new T(config));
6112 std::string getDescription() const override { return T::getDescription(); }
6116 explicit ReporterRegistrar(std::string const& name)
6118 getMutableRegistryHub().registerReporter(name, std::make_shared<ReporterFactory>());
6122 template <typename T> class ListenerRegistrar {
6124 class ListenerFactory : public IReporterFactory {
6126 IStreamingReporterPtr create(ReporterConfig const& config) const override
6128 return std::unique_ptr<T>(new T(config));
6130 std::string getDescription() const override { return std::string(); }
6134 ListenerRegistrar() { getMutableRegistryHub().registerListener(std::make_shared<ListenerFactory>()); }
6136 } // namespace Catch
6138 #if !defined(CATCH_CONFIG_DISABLE)
6140 #define CATCH_REGISTER_REPORTER(name, reporterType) \
6141 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6142 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6144 Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType(name); \
6146 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
6148 #define CATCH_REGISTER_LISTENER(listenerType) \
6149 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
6150 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
6152 Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; \
6154 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
6155 #else // CATCH_CONFIG_DISABLE
6157 #define CATCH_REGISTER_REPORTER(name, reporterType)
6158 #define CATCH_REGISTER_LISTENER(listenerType)
6160 #endif // CATCH_CONFIG_DISABLE
6162 // end catch_reporter_registrars.hpp
6163 // Allow users to base their work off existing reporters
6164 // start catch_reporter_compact.h
6168 struct CompactReporter : StreamingReporterBase<CompactReporter> {
6170 using StreamingReporterBase::StreamingReporterBase;
6172 ~CompactReporter() override;
6174 static std::string getDescription();
6176 void noMatchingTestCases(std::string const& spec) override;
6178 void assertionStarting(AssertionInfo const&) override;
6180 bool assertionEnded(AssertionStats const& _assertionStats) override;
6182 void sectionEnded(SectionStats const& _sectionStats) override;
6184 void testRunEnded(TestRunStats const& _testRunStats) override;
6187 } // end namespace Catch
6189 // end catch_reporter_compact.h
6190 // start catch_reporter_console.h
6192 #if defined(_MSC_VER)
6193 #pragma warning(push)
6194 #pragma warning(disable : 4061) // Not all labels are EXPLICITLY handled in switch
6195 // Note that 4062 (not all labels are handled
6196 // and default is missing) is enabled
6201 struct SummaryColumn;
6204 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
6205 std::unique_ptr<TablePrinter> m_tablePrinter;
6207 ConsoleReporter(ReporterConfig const& config);
6208 ~ConsoleReporter() override;
6209 static std::string getDescription();
6211 void noMatchingTestCases(std::string const& spec) override;
6213 void reportInvalidArguments(std::string const& arg) override;
6215 void assertionStarting(AssertionInfo const&) override;
6217 bool assertionEnded(AssertionStats const& _assertionStats) override;
6219 void sectionStarting(SectionInfo const& _sectionInfo) override;
6220 void sectionEnded(SectionStats const& _sectionStats) override;
6222 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
6223 void benchmarkPreparing(std::string const& name) override;
6224 void benchmarkStarting(BenchmarkInfo const& info) override;
6225 void benchmarkEnded(BenchmarkStats<> const& stats) override;
6226 void benchmarkFailed(std::string const& error) override;
6227 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
6229 void testCaseEnded(TestCaseStats const& _testCaseStats) override;
6230 void testGroupEnded(TestGroupStats const& _testGroupStats) override;
6231 void testRunEnded(TestRunStats const& _testRunStats) override;
6232 void testRunStarting(TestRunInfo const& _testRunInfo) override;
6237 void lazyPrintWithoutClosingBenchmarkTable();
6238 void lazyPrintRunInfo();
6239 void lazyPrintGroupInfo();
6240 void printTestCaseAndSectionHeader();
6242 void printClosedHeader(std::string const& _name);
6243 void printOpenHeader(std::string const& _name);
6245 // if string has a : in first line will set indent to follow it on
6247 void printHeaderString(std::string const& _string, std::size_t indent = 0);
6249 void printTotals(Totals const& totals);
6250 void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row);
6252 void printTotalsDivider(Totals const& totals);
6253 void printSummaryDivider();
6254 void printTestFilters();
6257 bool m_headerPrinted = false;
6260 } // end namespace Catch
6262 #if defined(_MSC_VER)
6263 #pragma warning(pop)
6266 // end catch_reporter_console.h
6267 // start catch_reporter_junit.h
6269 // start catch_xmlwriter.h
6274 enum class XmlFormatting {
6280 XmlFormatting operator|(XmlFormatting lhs, XmlFormatting rhs);
6281 XmlFormatting operator&(XmlFormatting lhs, XmlFormatting rhs);
6285 enum ForWhat { ForTextNodes, ForAttributes };
6287 XmlEncode(std::string const& str, ForWhat forWhat = ForTextNodes);
6289 void encodeTo(std::ostream& os) const;
6291 friend std::ostream& operator<<(std::ostream& os, XmlEncode const& xmlEncode);
6300 class ScopedElement {
6302 ScopedElement(XmlWriter* writer, XmlFormatting fmt);
6304 ScopedElement(ScopedElement&& other) noexcept;
6305 ScopedElement& operator=(ScopedElement&& other) noexcept;
6309 ScopedElement& writeText(std::string const& text,
6310 XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6312 template <typename T> ScopedElement& writeAttribute(std::string const& name, T const& attribute)
6314 m_writer->writeAttribute(name, attribute);
6319 mutable XmlWriter* m_writer = nullptr;
6320 XmlFormatting m_fmt;
6323 XmlWriter(std::ostream& os = Catch::cout());
6326 XmlWriter(XmlWriter const&) = delete;
6327 XmlWriter& operator=(XmlWriter const&) = delete;
6329 XmlWriter& startElement(std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6331 ScopedElement scopedElement(std::string const& name,
6332 XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6334 XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6336 XmlWriter& writeAttribute(std::string const& name, std::string const& attribute);
6338 XmlWriter& writeAttribute(std::string const& name, bool attribute);
6340 template <typename T> XmlWriter& writeAttribute(std::string const& name, T const& attribute)
6342 ReusableStringStream rss;
6344 return writeAttribute(name, rss.str());
6347 XmlWriter& writeText(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6349 XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6351 void writeStylesheetRef(std::string const& url);
6353 XmlWriter& writeBlankLine();
6355 void ensureTagClosed();
6358 void applyFormatting(XmlFormatting fmt);
6360 void writeDeclaration();
6362 void newlineIfNecessary();
6364 bool m_tagIsOpen = false;
6365 bool m_needsNewline = false;
6366 std::vector<std::string> m_tags;
6367 std::string m_indent;
6371 } // namespace Catch
6373 // end catch_xmlwriter.h
6376 class JunitReporter : public CumulativeReporterBase<JunitReporter> {
6378 JunitReporter(ReporterConfig const& _config);
6380 ~JunitReporter() override;
6382 static std::string getDescription();
6384 void noMatchingTestCases(std::string const& /*spec*/) override;
6386 void testRunStarting(TestRunInfo const& runInfo) override;
6388 void testGroupStarting(GroupInfo const& groupInfo) override;
6390 void testCaseStarting(TestCaseInfo const& testCaseInfo) override;
6391 bool assertionEnded(AssertionStats const& assertionStats) override;
6393 void testCaseEnded(TestCaseStats const& testCaseStats) override;
6395 void testGroupEnded(TestGroupStats const& testGroupStats) override;
6397 void testRunEndedCumulative() override;
6399 void writeGroup(TestGroupNode const& groupNode, double suiteTime);
6401 void writeTestCase(TestCaseNode const& testCaseNode);
6403 void writeSection(std::string const& className, std::string const& rootName, SectionNode const& sectionNode);
6405 void writeAssertions(SectionNode const& sectionNode);
6406 void writeAssertion(AssertionStats const& stats);
6410 std::string stdOutForSuite;
6411 std::string stdErrForSuite;
6412 unsigned int unexpectedExceptions = 0;
6413 bool m_okToFail = false;
6416 } // end namespace Catch
6418 // end catch_reporter_junit.h
6419 // start catch_reporter_xml.h
6422 class XmlReporter : public StreamingReporterBase<XmlReporter> {
6424 XmlReporter(ReporterConfig const& _config);
6426 ~XmlReporter() override;
6428 static std::string getDescription();
6430 virtual std::string getStylesheetRef() const;
6432 void writeSourceInfo(SourceLineInfo const& sourceInfo);
6434 public: // StreamingReporterBase
6435 void noMatchingTestCases(std::string const& s) override;
6437 void testRunStarting(TestRunInfo const& testInfo) override;
6439 void testGroupStarting(GroupInfo const& groupInfo) override;
6441 void testCaseStarting(TestCaseInfo const& testInfo) override;
6443 void sectionStarting(SectionInfo const& sectionInfo) override;
6445 void assertionStarting(AssertionInfo const&) override;
6447 bool assertionEnded(AssertionStats const& assertionStats) override;
6449 void sectionEnded(SectionStats const& sectionStats) override;
6451 void testCaseEnded(TestCaseStats const& testCaseStats) override;
6453 void testGroupEnded(TestGroupStats const& testGroupStats) override;
6455 void testRunEnded(TestRunStats const& testRunStats) override;
6457 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
6458 void benchmarkPreparing(std::string const& name) override;
6459 void benchmarkStarting(BenchmarkInfo const&) override;
6460 void benchmarkEnded(BenchmarkStats<> const&) override;
6461 void benchmarkFailed(std::string const&) override;
6462 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
6465 Timer m_testCaseTimer;
6467 int m_sectionDepth = 0;
6470 } // end namespace Catch
6472 // end catch_reporter_xml.h
6474 // end catch_external_interfaces.h
6477 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
6478 // start catch_benchmarking_all.hpp
6480 // A proxy header that includes all of the benchmarking headers to allow
6481 // concise include of the benchmarking features. You should prefer the
6482 // individual includes in standard use.
6484 // start catch_benchmark.hpp
6488 // start catch_chronometer.hpp
6490 // User-facing chronometer
6492 // start catch_clock.hpp
6500 namespace Benchmark {
6501 template <typename Clock> using ClockDuration = typename Clock::duration;
6502 template <typename Clock> using FloatDuration = std::chrono::duration<double, typename Clock::period>;
6504 template <typename Clock> using TimePoint = typename Clock::time_point;
6506 using default_clock = std::chrono::steady_clock;
6508 template <typename Clock> struct now {
6509 TimePoint<Clock> operator()() const { return Clock::now(); }
6512 using fp_seconds = std::chrono::duration<double, std::ratio<1>>;
6513 } // namespace Benchmark
6514 } // namespace Catch
6516 // end catch_clock.hpp
6517 // start catch_optimizer.hpp
6519 // Hinting the optimizer
6521 #if defined(_MSC_VER)
6522 #include <atomic> // atomic_thread_fence
6526 namespace Benchmark {
6527 #if defined(__GNUC__) || defined(__clang__)
6528 template <typename T> inline void keep_memory(T* p)
6530 asm volatile("" : : "g"(p) : "memory");
6532 inline void keep_memory()
6534 asm volatile("" : : : "memory");
6538 inline void optimizer_barrier()
6542 } // namespace Detail
6543 #elif defined(_MSC_VER)
6545 #pragma optimize("", off)
6546 template <typename T> inline void keep_memory(T* p)
6548 // thanks @milleniumbug
6549 *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);
6551 // TODO equivalent keep_memory()
6552 #pragma optimize("", on)
6555 inline void optimizer_barrier()
6557 std::atomic_thread_fence(std::memory_order_seq_cst);
6559 } // namespace Detail
6563 template <typename T> inline void deoptimize_value(T&& x)
6568 template <typename Fn, typename... Args>
6569 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) ->
6570 typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type
6572 deoptimize_value(std::forward<Fn>(fn)(std::forward<Args...>(args...)));
6575 template <typename Fn, typename... Args>
6576 inline auto invoke_deoptimized(Fn&& fn, Args&&... args) ->
6577 typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type
6579 std::forward<Fn>(fn)(std::forward<Args...>(args...));
6581 } // namespace Benchmark
6582 } // namespace Catch
6584 // end catch_optimizer.hpp
6585 // start catch_complete_invoke.hpp
6587 // Invoke with a special case for void
6589 #include <type_traits>
6593 namespace Benchmark {
6595 template <typename T> struct CompleteType {
6598 template <> struct CompleteType<void> {
6602 template <typename T> using CompleteType_t = typename CompleteType<T>::type;
6604 template <typename Result> struct CompleteInvoker {
6605 template <typename Fun, typename... Args> static Result invoke(Fun&& fun, Args&&... args)
6607 return std::forward<Fun>(fun)(std::forward<Args>(args)...);
6610 template <> struct CompleteInvoker<void> {
6611 template <typename Fun, typename... Args> static CompleteType_t<void> invoke(Fun&& fun, Args&&... args)
6613 std::forward<Fun>(fun)(std::forward<Args>(args)...);
6618 // invoke and not return void :(
6619 template <typename Fun, typename... Args>
6620 CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args)
6622 return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...);
6625 const std::string benchmarkErrorMsg = "a benchmark failed to run successfully";
6626 } // namespace Detail
6628 template <typename Fun> Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun)
6632 return Detail::complete_invoke(std::forward<Fun>(fun));
6636 getResultCapture().benchmarkFailed(translateActiveException());
6637 CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg);
6640 } // namespace Benchmark
6641 } // namespace Catch
6643 // end catch_complete_invoke.hpp
6645 namespace Benchmark {
6647 struct ChronometerConcept {
6648 virtual void start() = 0;
6649 virtual void finish() = 0;
6650 virtual ~ChronometerConcept() = default;
6652 template <typename Clock> struct ChronometerModel final : public ChronometerConcept {
6653 void start() override { started = Clock::now(); }
6654 void finish() override { finished = Clock::now(); }
6656 ClockDuration<Clock> elapsed() const { return finished - started; }
6658 TimePoint<Clock> started;
6659 TimePoint<Clock> finished;
6661 } // namespace Detail
6663 struct Chronometer {
6665 template <typename Fun> void measure(Fun&& fun) { measure(std::forward<Fun>(fun), is_callable<Fun(int)>()); }
6667 int runs() const { return k; }
6669 Chronometer(Detail::ChronometerConcept& meter, int k) : impl(&meter), k(k) {}
6672 template <typename Fun> void measure(Fun&& fun, std::false_type)
6674 measure([&fun](int) { return fun(); }, std::true_type());
6677 template <typename Fun> void measure(Fun&& fun, std::true_type)
6679 Detail::optimizer_barrier();
6681 for (int i = 0; i < k; ++i)
6682 invoke_deoptimized(fun, i);
6684 Detail::optimizer_barrier();
6687 Detail::ChronometerConcept* impl;
6690 } // namespace Benchmark
6691 } // namespace Catch
6693 // end catch_chronometer.hpp
6694 // start catch_environment.hpp
6696 // Environment information
6699 namespace Benchmark {
6700 template <typename Duration> struct EnvironmentEstimate {
6702 OutlierClassification outliers;
6704 template <typename Duration2> operator EnvironmentEstimate<Duration2>() const { return {mean, outliers}; }
6706 template <typename Clock> struct Environment {
6707 using clock_type = Clock;
6708 EnvironmentEstimate<FloatDuration<Clock>> clock_resolution;
6709 EnvironmentEstimate<FloatDuration<Clock>> clock_cost;
6711 } // namespace Benchmark
6712 } // namespace Catch
6714 // end catch_environment.hpp
6715 // start catch_execution_plan.hpp
6719 // start catch_benchmark_function.hpp
6721 // Dumb std::function implementation for consistent call overhead
6725 #include <type_traits>
6729 namespace Benchmark {
6731 template <typename T> using Decay = typename std::decay<T>::type;
6732 template <typename T, typename U> struct is_related : std::is_same<Decay<T>, Decay<U>> {
6735 /// We need to reinvent std::function because every piece of code that might add overhead
6736 /// in a measurement context needs to have consistent performance characteristics so that we
6737 /// can account for it in the measurement.
6738 /// Implementations of std::function with optimizations that aren't always applicable, like
6739 /// small buffer optimizations, are not uncommon.
6740 /// This is effectively an implementation of std::function without any such optimizations;
6741 /// it may be slow, but it is consistently slow.
6742 struct BenchmarkFunction {
6745 virtual void call(Chronometer meter) const = 0;
6746 virtual callable* clone() const = 0;
6747 virtual ~callable() = default;
6749 template <typename Fun> struct model : public callable {
6750 model(Fun&& fun) : fun(std::move(fun)) {}
6751 model(Fun const& fun) : fun(fun) {}
6753 model<Fun>* clone() const override { return new model<Fun>(*this); }
6755 void call(Chronometer meter) const override { call(meter, is_callable<Fun(Chronometer)>()); }
6756 void call(Chronometer meter, std::true_type) const { fun(meter); }
6757 void call(Chronometer meter, std::false_type) const { meter.measure(fun); }
6763 void operator()() const {}
6766 template <typename T> BenchmarkFunction(model<T>* c) : f(c) {}
6769 BenchmarkFunction() : f(new model<do_nothing>{{}}) {}
6771 template <typename Fun, typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0>
6772 BenchmarkFunction(Fun&& fun) : f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun)))
6776 BenchmarkFunction(BenchmarkFunction&& that) : f(std::move(that.f)) {}
6778 BenchmarkFunction(BenchmarkFunction const& that) : f(that.f->clone()) {}
6780 BenchmarkFunction& operator=(BenchmarkFunction&& that)
6782 f = std::move(that.f);
6786 BenchmarkFunction& operator=(BenchmarkFunction const& that)
6788 f.reset(that.f->clone());
6792 void operator()(Chronometer meter) const { f->call(meter); }
6795 std::unique_ptr<callable> f;
6797 } // namespace Detail
6798 } // namespace Benchmark
6799 } // namespace Catch
6801 // end catch_benchmark_function.hpp
6802 // start catch_repeat.hpp
6806 #include <type_traits>
6810 namespace Benchmark {
6812 template <typename Fun> struct repeater {
6813 void operator()(int k) const
6815 for (int i = 0; i < k; ++i) {
6821 template <typename Fun> repeater<typename std::decay<Fun>::type> repeat(Fun&& fun)
6823 return {std::forward<Fun>(fun)};
6825 } // namespace Detail
6826 } // namespace Benchmark
6827 } // namespace Catch
6829 // end catch_repeat.hpp
6830 // start catch_run_for_at_least.hpp
6832 // Run a function for a minimum amount of time
6834 // start catch_measure.hpp
6838 // start catch_timing.hpp
6843 #include <type_traits>
6846 namespace Benchmark {
6847 template <typename Duration, typename Result> struct Timing {
6852 template <typename Clock, typename Func, typename... Args>
6853 using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;
6854 } // namespace Benchmark
6855 } // namespace Catch
6857 // end catch_timing.hpp
6861 namespace Benchmark {
6863 template <typename Clock, typename Fun, typename... Args>
6864 TimingOf<Clock, Fun, Args...> measure(Fun&& fun, Args&&... args)
6866 auto start = Clock::now();
6867 auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...);
6868 auto end = Clock::now();
6869 auto delta = end - start;
6870 return {delta, std::forward<decltype(r)>(r), 1};
6872 } // namespace Detail
6873 } // namespace Benchmark
6874 } // namespace Catch
6876 // end catch_measure.hpp
6877 #include <type_traits>
6881 namespace Benchmark {
6883 template <typename Clock, typename Fun> TimingOf<Clock, Fun, int> measure_one(Fun&& fun, int iters, std::false_type)
6885 return Detail::measure<Clock>(fun, iters);
6887 template <typename Clock, typename Fun>
6888 TimingOf<Clock, Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type)
6890 Detail::ChronometerModel<Clock> meter;
6891 auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
6893 return {meter.elapsed(), std::move(result), iters};
6896 template <typename Clock, typename Fun>
6897 using run_for_at_least_argument_t =
6898 typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type;
6900 struct optimized_away_error : std::exception {
6901 const char* what() const noexcept override { return "could not measure benchmark, maybe it was optimized away"; }
6904 template <typename Clock, typename Fun>
6905 TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>> run_for_at_least(ClockDuration<Clock> how_long, int seed,
6909 while (iters < (1 << 30)) {
6910 auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
6912 if (Timing.elapsed >= how_long) {
6913 return {Timing.elapsed, std::move(Timing.result), iters};
6917 throw optimized_away_error{};
6919 } // namespace Detail
6920 } // namespace Benchmark
6921 } // namespace Catch
6923 // end catch_run_for_at_least.hpp
6924 #include <algorithm>
6927 namespace Benchmark {
6928 template <typename Duration> struct ExecutionPlan {
6929 int iterations_per_sample;
6930 Duration estimated_duration;
6931 Detail::BenchmarkFunction benchmark;
6932 Duration warmup_time;
6933 int warmup_iterations;
6935 template <typename Duration2> operator ExecutionPlan<Duration2>() const
6937 return {iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations};
6940 template <typename Clock>
6941 std::vector<FloatDuration<Clock>> run(const IConfig& cfg, Environment<FloatDuration<Clock>> env) const
6944 Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations,
6945 Detail::repeat(now<Clock>{}));
6947 std::vector<FloatDuration<Clock>> times;
6948 times.reserve(cfg.benchmarkSamples());
6949 std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] {
6950 Detail::ChronometerModel<Clock> model;
6951 this->benchmark(Chronometer(model, iterations_per_sample));
6952 auto sample_time = model.elapsed() - env.clock_cost.mean;
6953 if (sample_time < FloatDuration<Clock>::zero())
6954 sample_time = FloatDuration<Clock>::zero();
6955 return sample_time / iterations_per_sample;
6960 } // namespace Benchmark
6961 } // namespace Catch
6963 // end catch_execution_plan.hpp
6964 // start catch_estimate_clock.hpp
6966 // Environment measurement
6968 // start catch_stats.hpp
6970 // Statistical analysis tools
6972 #include <algorithm>
6975 #include <functional>
6984 namespace Benchmark {
6986 using sample = std::vector<double>;
6988 double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last);
6990 template <typename Iterator> OutlierClassification classify_outliers(Iterator first, Iterator last)
6992 std::vector<double> copy(first, last);
6994 auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end());
6995 auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end());
6997 auto los = q1 - (iqr * 3.);
6998 auto lom = q1 - (iqr * 1.5);
6999 auto him = q3 + (iqr * 1.5);
7000 auto his = q3 + (iqr * 3.);
7002 OutlierClassification o;
7003 for (; first != last; ++first) {
7018 template <typename Iterator> double mean(Iterator first, Iterator last)
7020 auto count = last - first;
7021 double sum = std::accumulate(first, last, 0.);
7025 template <typename URng, typename Iterator, typename Estimator>
7026 sample resample(URng& rng, int resamples, Iterator first, Iterator last, Estimator& estimator)
7028 auto n = last - first;
7029 std::uniform_int_distribution<decltype(n)> dist(0, n - 1);
7032 out.reserve(resamples);
7033 std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] {
7034 std::vector<double> resampled;
7035 resampled.reserve(n);
7036 std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[dist(rng)]; });
7037 return estimator(resampled.begin(), resampled.end());
7039 std::sort(out.begin(), out.end());
7043 template <typename Estimator, typename Iterator> sample jackknife(Estimator&& estimator, Iterator first, Iterator last)
7045 auto n = last - first;
7046 auto second = std::next(first);
7050 for (auto it = first; it != last; ++it) {
7051 std::iter_swap(it, first);
7052 results.push_back(estimator(second, last));
7058 inline double normal_cdf(double x)
7060 return std::erfc(-x / std::sqrt(2.0)) / 2.0;
7063 double erfc_inv(double x);
7065 double normal_quantile(double p);
7067 template <typename Iterator, typename Estimator>
7068 Estimate<double> bootstrap(double confidence_level, Iterator first, Iterator last, sample const& resample,
7069 Estimator&& estimator)
7071 auto n_samples = last - first;
7073 double point = estimator(first, last);
7074 // Degenerate case with a single sample
7076 return {point, point, point, confidence_level};
7078 sample jack = jackknife(estimator, first, last);
7079 double jack_mean = mean(jack.begin(), jack.end());
7080 double sum_squares, sum_cubes;
7081 std::tie(sum_squares, sum_cubes) =
7082 std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.),
7083 [jack_mean](std::pair<double, double> sqcb, double x) -> std::pair<double, double> {
7084 auto d = jack_mean - x;
7087 return {sqcb.first + d2, sqcb.second + d3};
7090 double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));
7091 int n = static_cast<int>(resample.size());
7092 double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / (double)n;
7093 // degenerate case with uniform samples
7095 return {point, point, point, confidence_level};
7097 double bias = normal_quantile(prob_n);
7098 double z1 = normal_quantile((1. - confidence_level) / 2.);
7100 auto cumn = [n](double x) -> int { return std::lround(normal_cdf(x) * n); };
7101 auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); };
7102 double b1 = bias + z1;
7103 double b2 = bias - z1;
7106 auto lo = (std::max)(cumn(a1), 0);
7107 auto hi = (std::min)(cumn(a2), n - 1);
7109 return {point, resample[lo], resample[hi], confidence_level};
7112 double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n);
7114 struct bootstrap_analysis {
7115 Estimate<double> mean;
7116 Estimate<double> standard_deviation;
7117 double outlier_variance;
7120 bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first,
7121 std::vector<double>::iterator last);
7122 } // namespace Detail
7123 } // namespace Benchmark
7124 } // namespace Catch
7126 // end catch_stats.hpp
7127 #include <algorithm>
7134 namespace Benchmark {
7136 template <typename Clock> std::vector<double> resolution(int k)
7138 std::vector<TimePoint<Clock>> times;
7139 times.reserve(k + 1);
7140 std::generate_n(std::back_inserter(times), k + 1, now<Clock>{});
7142 std::vector<double> deltas;
7144 std::transform(std::next(times.begin()), times.end(), times.begin(), std::back_inserter(deltas),
7145 [](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); });
7150 const auto warmup_iterations = 10000;
7151 const auto warmup_time = std::chrono::milliseconds(100);
7152 const auto minimum_ticks = 1000;
7153 const auto warmup_seed = 10000;
7154 const auto clock_resolution_estimation_time = std::chrono::milliseconds(500);
7155 const auto clock_cost_estimation_time_limit = std::chrono::seconds(1);
7156 const auto clock_cost_estimation_tick_limit = 100000;
7157 const auto clock_cost_estimation_time = std::chrono::milliseconds(10);
7158 const auto clock_cost_estimation_iterations = 10000;
7160 template <typename Clock> int warmup()
7162 return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed,
7166 template <typename Clock> EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations)
7168 auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time),
7169 iterations, &resolution<Clock>)
7172 FloatDuration<Clock>(mean(r.begin(), r.end())),
7173 classify_outliers(r.begin(), r.end()),
7176 template <typename Clock> EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution)
7179 (std::min)(resolution * clock_cost_estimation_tick_limit, FloatDuration<Clock>(clock_cost_estimation_time_limit));
7180 auto time_clock = [](int k) {
7181 return Detail::measure<Clock>([k] {
7182 for (int i = 0; i < k; ++i) {
7183 volatile auto ignored = Clock::now();
7190 int iters = clock_cost_estimation_iterations;
7191 auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time),
7193 std::vector<double> times;
7194 int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
7195 times.reserve(nsamples);
7196 std::generate_n(std::back_inserter(times), nsamples,
7197 [time_clock, &r] { return static_cast<double>((time_clock(r.iterations) / r.iterations).count()); });
7199 FloatDuration<Clock>(mean(times.begin(), times.end())),
7200 classify_outliers(times.begin(), times.end()),
7204 template <typename Clock> Environment<FloatDuration<Clock>> measure_environment()
7206 static Environment<FloatDuration<Clock>>* env = nullptr;
7211 auto iters = Detail::warmup<Clock>();
7212 auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
7213 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
7215 env = new Environment<FloatDuration<Clock>>{resolution, cost};
7218 } // namespace Detail
7219 } // namespace Benchmark
7220 } // namespace Catch
7222 // end catch_estimate_clock.hpp
7223 // start catch_analyse.hpp
7225 // Run and analyse one benchmark
7227 // start catch_sample_analysis.hpp
7229 // Benchmark results
7231 #include <algorithm>
7237 namespace Benchmark {
7238 template <typename Duration> struct SampleAnalysis {
7239 std::vector<Duration> samples;
7240 Estimate<Duration> mean;
7241 Estimate<Duration> standard_deviation;
7242 OutlierClassification outliers;
7243 double outlier_variance;
7245 template <typename Duration2> operator SampleAnalysis<Duration2>() const
7247 std::vector<Duration2> samples2;
7248 samples2.reserve(samples.size());
7249 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2),
7250 [](Duration d) { return Duration2(d); });
7252 std::move(samples2), mean, standard_deviation, outliers, outlier_variance,
7256 } // namespace Benchmark
7257 } // namespace Catch
7259 // end catch_sample_analysis.hpp
7260 #include <algorithm>
7265 namespace Benchmark {
7267 template <typename Duration, typename Iterator>
7268 SampleAnalysis<Duration> analyse(const IConfig& cfg, Environment<Duration>, Iterator first, Iterator last)
7270 if (!cfg.benchmarkNoAnalysis()) {
7271 std::vector<double> samples;
7272 samples.reserve(last - first);
7273 std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); });
7275 auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(),
7276 cfg.benchmarkResamples(), samples.begin(), samples.end());
7277 auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end());
7279 auto wrap_estimate = [](Estimate<double> e) {
7280 return Estimate<Duration>{
7282 Duration(e.lower_bound),
7283 Duration(e.upper_bound),
7284 e.confidence_interval,
7287 std::vector<Duration> samples2;
7288 samples2.reserve(samples.size());
7289 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); });
7291 std::move(samples2), wrap_estimate(analysis.mean), wrap_estimate(analysis.standard_deviation), outliers,
7292 analysis.outlier_variance,
7295 std::vector<Duration> samples;
7296 samples.reserve(last - first);
7298 Duration mean = Duration(0);
7300 for (auto it = first; it < last; ++it, ++i) {
7301 samples.push_back(Duration(*it));
7302 mean += Duration(*it);
7306 return {std::move(samples), Estimate<Duration>{mean, mean, mean, 0.0},
7307 Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0}, OutlierClassification{}, 0.0};
7310 } // namespace Detail
7311 } // namespace Benchmark
7312 } // namespace Catch
7314 // end catch_analyse.hpp
7315 #include <algorithm>
7317 #include <functional>
7322 namespace Benchmark {
7324 Benchmark(std::string&& name) : name(std::move(name)) {}
7326 template <class FUN> Benchmark(std::string&& name, FUN&& func) : fun(std::move(func)), name(std::move(name)) {}
7328 template <typename Clock>
7329 ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig& cfg, Environment<FloatDuration<Clock>> env) const
7331 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
7332 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
7333 auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun);
7334 int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
7335 return {new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun,
7336 std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations};
7339 template <typename Clock = default_clock> void run()
7341 IConfigPtr cfg = getCurrentContext().getConfig();
7343 auto env = Detail::measure_environment<Clock>();
7345 getResultCapture().benchmarkPreparing(name);
7348 auto plan = user_code([&] { return prepare<Clock>(*cfg, env); });
7350 BenchmarkInfo info{name,
7351 plan.estimated_duration.count(),
7352 plan.iterations_per_sample,
7353 cfg->benchmarkSamples(),
7354 cfg->benchmarkResamples(),
7355 env.clock_resolution.mean.count(),
7356 env.clock_cost.mean.count()};
7358 getResultCapture().benchmarkStarting(info);
7360 auto samples = user_code([&] { return plan.template run<Clock>(*cfg, env); });
7362 auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
7363 BenchmarkStats<FloatDuration<Clock>> stats{info,
7366 analysis.standard_deviation,
7368 analysis.outlier_variance};
7369 getResultCapture().benchmarkEnded(stats);
7373 if (translateActiveException() !=
7374 Detail::benchmarkErrorMsg) // benchmark errors have been reported, otherwise rethrow.
7375 std::rethrow_exception(std::current_exception());
7379 // sets lambda to be used in fun *and* executes benchmark!
7380 template <typename Fun, typename std::enable_if<!Detail::is_related<Fun, Benchmark>::value, int>::type = 0>
7381 Benchmark& operator=(Fun func)
7383 fun = Detail::BenchmarkFunction(func);
7388 explicit operator bool() { return true; }
7391 Detail::BenchmarkFunction fun;
7394 } // namespace Benchmark
7395 } // namespace Catch
7397 #define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1
7398 #define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2
7400 #define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex) \
7401 if (Catch::Benchmark::Benchmark BenchmarkName{name}) \
7402 BenchmarkName = [&](int benchmarkIndex)
7404 #define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name) \
7405 if (Catch::Benchmark::Benchmark BenchmarkName{name}) \
7408 // end catch_benchmark.hpp
7409 // start catch_constructor.hpp
7411 // Constructor and destructor helpers
7413 #include <type_traits>
7416 namespace Benchmark {
7418 template <typename T, bool Destruct> struct ObjectStorage {
7419 using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
7421 ObjectStorage() : data() {}
7423 ObjectStorage(const ObjectStorage& other) { new (&data) T(other.stored_object()); }
7425 ObjectStorage(ObjectStorage&& other) { new (&data) T(std::move(other.stored_object())); }
7427 ~ObjectStorage() { destruct_on_exit<T>(); }
7429 template <typename... Args> void construct(Args&&... args) { new (&data) T(std::forward<Args>(args)...); }
7431 template <bool AllowManualDestruction = !Destruct> typename std::enable_if<AllowManualDestruction>::type destruct()
7433 stored_object().~T();
7437 // If this is a constructor benchmark, destruct the underlying object
7438 template <typename U> void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
7440 template <typename U> void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) {}
7442 T& stored_object() { return *static_cast<T*>(static_cast<void*>(&data)); }
7444 T const& stored_object() const { return *static_cast<T*>(static_cast<void*>(&data)); }
7448 } // namespace Detail
7450 template <typename T> using storage_for = Detail::ObjectStorage<T, true>;
7452 template <typename T> using destructable_object = Detail::ObjectStorage<T, false>;
7453 } // namespace Benchmark
7454 } // namespace Catch
7456 // end catch_constructor.hpp
7457 // end catch_benchmarking_all.hpp
7460 #endif // ! CATCH_CONFIG_IMPL_ONLY
7463 // start catch_impl.hpp
7466 #pragma clang diagnostic push
7467 #pragma clang diagnostic ignored "-Wweak-vtables"
7470 // Keep these here for external reporters
7471 // start catch_test_case_tracker.h
7478 namespace TestCaseTracking {
7480 struct NameAndLocation {
7482 SourceLineInfo location;
7484 NameAndLocation(std::string const& _name, SourceLineInfo const& _location);
7485 friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs)
7487 return lhs.name == rhs.name && lhs.location == rhs.location;
7493 using ITrackerPtr = std::shared_ptr<ITracker>;
7496 NameAndLocation m_nameAndLocation;
7499 ITracker(NameAndLocation const& nameAndLoc) : m_nameAndLocation(nameAndLoc) {}
7502 NameAndLocation const& nameAndLocation() const { return m_nameAndLocation; }
7504 virtual ~ITracker();
7507 virtual bool isComplete() const = 0; // Successfully completed or failed
7508 virtual bool isSuccessfullyCompleted() const = 0;
7509 virtual bool isOpen() const = 0; // Started but not complete
7510 virtual bool hasChildren() const = 0;
7511 virtual bool hasStarted() const = 0;
7513 virtual ITracker& parent() = 0;
7516 virtual void close() = 0; // Successfully complete
7517 virtual void fail() = 0;
7518 virtual void markAsNeedingAnotherRun() = 0;
7520 virtual void addChild(ITrackerPtr const& child) = 0;
7521 virtual ITrackerPtr findChild(NameAndLocation const& nameAndLocation) = 0;
7522 virtual void openChild() = 0;
7525 virtual bool isSectionTracker() const = 0;
7526 virtual bool isGeneratorTracker() const = 0;
7529 class TrackerContext {
7531 enum RunState { NotStarted, Executing, CompletedCycle };
7533 ITrackerPtr m_rootTracker;
7534 ITracker* m_currentTracker = nullptr;
7535 RunState m_runState = NotStarted;
7538 ITracker& startRun();
7542 void completeCycle();
7544 bool completedCycle() const;
7545 ITracker& currentTracker();
7546 void setCurrentTracker(ITracker* tracker);
7549 class TrackerBase : public ITracker {
7551 enum CycleState { NotStarted, Executing, ExecutingChildren, NeedsAnotherRun, CompletedSuccessfully, Failed };
7553 using Children = std::vector<ITrackerPtr>;
7554 TrackerContext& m_ctx;
7556 Children m_children;
7557 CycleState m_runState = NotStarted;
7560 TrackerBase(NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent);
7562 bool isComplete() const override;
7563 bool isSuccessfullyCompleted() const override;
7564 bool isOpen() const override;
7565 bool hasChildren() const override;
7566 bool hasStarted() const override { return m_runState != NotStarted; }
7568 void addChild(ITrackerPtr const& child) override;
7570 ITrackerPtr findChild(NameAndLocation const& nameAndLocation) override;
7571 ITracker& parent() override;
7573 void openChild() override;
7575 bool isSectionTracker() const override;
7576 bool isGeneratorTracker() const override;
7580 void close() override;
7581 void fail() override;
7582 void markAsNeedingAnotherRun() override;
7585 void moveToParent();
7589 class SectionTracker : public TrackerBase {
7590 std::vector<std::string> m_filters;
7591 std::string m_trimmed_name;
7594 SectionTracker(NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent);
7596 bool isSectionTracker() const override;
7598 bool isComplete() const override;
7600 static SectionTracker& acquire(TrackerContext& ctx, NameAndLocation const& nameAndLocation);
7604 void addInitialFilters(std::vector<std::string> const& filters);
7605 void addNextFilters(std::vector<std::string> const& filters);
7606 //! Returns filters active in this tracker
7607 std::vector<std::string> const& getFilters() const;
7608 //! Returns whitespace-trimmed name of the tracked section
7609 std::string const& trimmedName() const;
7612 } // namespace TestCaseTracking
7614 using TestCaseTracking::ITracker;
7615 using TestCaseTracking::SectionTracker;
7616 using TestCaseTracking::TrackerContext;
7618 } // namespace Catch
7620 // end catch_test_case_tracker.h
7622 // start catch_leak_detector.h
7626 struct LeakDetector {
7631 } // namespace Catch
7632 // end catch_leak_detector.h
7633 // Cpp files will be included in the single-header file here
7634 // start catch_stats.cpp
7636 // Statistical analysis tools
7638 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
7643 #if defined(CATCH_CONFIG_USE_ASYNC)
7648 double erf_inv(double x)
7650 // Code accompanying the article "Approximating the erfinv function" in GPU Computing Gems, Volume 2
7653 w = -log((1.0 - x) * (1.0 + x));
7657 p = -3.6444120640178196996e-21;
7658 p = -1.685059138182016589e-19 + p * w;
7659 p = 1.2858480715256400167e-18 + p * w;
7660 p = 1.115787767802518096e-17 + p * w;
7661 p = -1.333171662854620906e-16 + p * w;
7662 p = 2.0972767875968561637e-17 + p * w;
7663 p = 6.6376381343583238325e-15 + p * w;
7664 p = -4.0545662729752068639e-14 + p * w;
7665 p = -8.1519341976054721522e-14 + p * w;
7666 p = 2.6335093153082322977e-12 + p * w;
7667 p = -1.2975133253453532498e-11 + p * w;
7668 p = -5.4154120542946279317e-11 + p * w;
7669 p = 1.051212273321532285e-09 + p * w;
7670 p = -4.1126339803469836976e-09 + p * w;
7671 p = -2.9070369957882005086e-08 + p * w;
7672 p = 4.2347877827932403518e-07 + p * w;
7673 p = -1.3654692000834678645e-06 + p * w;
7674 p = -1.3882523362786468719e-05 + p * w;
7675 p = 0.0001867342080340571352 + p * w;
7676 p = -0.00074070253416626697512 + p * w;
7677 p = -0.0060336708714301490533 + p * w;
7678 p = 0.24015818242558961693 + p * w;
7679 p = 1.6536545626831027356 + p * w;
7680 } else if (w < 16.000000) {
7681 w = sqrt(w) - 3.250000;
7682 p = 2.2137376921775787049e-09;
7683 p = 9.0756561938885390979e-08 + p * w;
7684 p = -2.7517406297064545428e-07 + p * w;
7685 p = 1.8239629214389227755e-08 + p * w;
7686 p = 1.5027403968909827627e-06 + p * w;
7687 p = -4.013867526981545969e-06 + p * w;
7688 p = 2.9234449089955446044e-06 + p * w;
7689 p = 1.2475304481671778723e-05 + p * w;
7690 p = -4.7318229009055733981e-05 + p * w;
7691 p = 6.8284851459573175448e-05 + p * w;
7692 p = 2.4031110387097893999e-05 + p * w;
7693 p = -0.0003550375203628474796 + p * w;
7694 p = 0.00095328937973738049703 + p * w;
7695 p = -0.0016882755560235047313 + p * w;
7696 p = 0.0024914420961078508066 + p * w;
7697 p = -0.0037512085075692412107 + p * w;
7698 p = 0.005370914553590063617 + p * w;
7699 p = 1.0052589676941592334 + p * w;
7700 p = 3.0838856104922207635 + p * w;
7702 w = sqrt(w) - 5.000000;
7703 p = -2.7109920616438573243e-11;
7704 p = -2.5556418169965252055e-10 + p * w;
7705 p = 1.5076572693500548083e-09 + p * w;
7706 p = -3.7894654401267369937e-09 + p * w;
7707 p = 7.6157012080783393804e-09 + p * w;
7708 p = -1.4960026627149240478e-08 + p * w;
7709 p = 2.9147953450901080826e-08 + p * w;
7710 p = -6.7711997758452339498e-08 + p * w;
7711 p = 2.2900482228026654717e-07 + p * w;
7712 p = -9.9298272942317002539e-07 + p * w;
7713 p = 4.5260625972231537039e-06 + p * w;
7714 p = -1.9681778105531670567e-05 + p * w;
7715 p = 7.5995277030017761139e-05 + p * w;
7716 p = -0.00021503011930044477347 + p * w;
7717 p = -0.00013871931833623122026 + p * w;
7718 p = 1.0103004648645343977 + p * w;
7719 p = 4.8499064014085844221 + p * w;
7724 double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last)
7726 auto m = Catch::Benchmark::Detail::mean(first, last);
7727 double variance = std::accumulate(first, last, 0.,
7728 [m](double a, double b) {
7729 double diff = b - m;
7730 return a + diff * diff;
7733 return std::sqrt(variance);
7739 namespace Benchmark {
7742 double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last)
7744 auto count = last - first;
7745 double idx = (count - 1) * k / static_cast<double>(q);
7746 int j = static_cast<int>(idx);
7748 std::nth_element(first, first + j, last);
7753 auto xj1 = *std::min_element(first + (j + 1), last);
7754 return xj + g * (xj1 - xj);
7757 double erfc_inv(double x)
7759 return erf_inv(1.0 - x);
7762 double normal_quantile(double p)
7764 static const double ROOT_TWO = std::sqrt(2.0);
7766 double result = 0.0;
7767 assert(p >= 0 && p <= 1);
7768 if (p < 0 || p > 1) {
7772 result = -erfc_inv(2.0 * p);
7773 // result *= normal distribution standard deviation (1.0) * sqrt(2)
7774 result *= /*sd * */ ROOT_TWO;
7775 // result += normal disttribution mean (0)
7779 double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n)
7781 double sb = stddev.point;
7782 double mn = mean.point / n;
7783 double mg_min = mn / 2.;
7784 double sg = (std::min)(mg_min / 4., sb / std::sqrt(n));
7785 double sg2 = sg * sg;
7786 double sb2 = sb * sb;
7788 auto c_max = [n, mn, sb2, sg2](double x) -> double {
7792 double k0 = -n * nd;
7793 double k1 = sb2 - n * sg2 + nd;
7794 double det = k1 * k1 - 4 * sg2 * k0;
7795 return (int)(-2. * k0 / (k1 + std::sqrt(det)));
7798 auto var_out = [n, sb2, sg2](double c) {
7800 return (nc / n) * (sb2 - nc * sg2);
7803 return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2;
7806 bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first,
7807 std::vector<double>::iterator last)
7809 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
7810 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
7811 static std::random_device entropy;
7812 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
7814 auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++
7816 auto mean = &Detail::mean<std::vector<double>::iterator>;
7817 auto stddev = &standard_deviation;
7819 #if defined(CATCH_CONFIG_USE_ASYNC)
7820 auto Estimate = [=](double (*f)(std::vector<double>::iterator, std::vector<double>::iterator)) {
7821 auto seed = entropy();
7822 return std::async(std::launch::async, [=] {
7823 std::mt19937 rng(seed);
7824 auto resampled = resample(rng, n_resamples, first, last, f);
7825 return bootstrap(confidence_level, first, last, resampled, f);
7829 auto mean_future = Estimate(mean);
7830 auto stddev_future = Estimate(stddev);
7832 auto mean_estimate = mean_future.get();
7833 auto stddev_estimate = stddev_future.get();
7835 auto Estimate = [=](double (*f)(std::vector<double>::iterator, std::vector<double>::iterator)) {
7836 auto seed = entropy();
7837 std::mt19937 rng(seed);
7838 auto resampled = resample(rng, n_resamples, first, last, f);
7839 return bootstrap(confidence_level, first, last, resampled, f);
7842 auto mean_estimate = Estimate(mean);
7843 auto stddev_estimate = Estimate(stddev);
7844 #endif // CATCH_USE_ASYNC
7846 double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n);
7848 return {mean_estimate, stddev_estimate, outlier_variance};
7850 } // namespace Detail
7851 } // namespace Benchmark
7852 } // namespace Catch
7854 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
7855 // end catch_stats.cpp
7856 // start catch_approx.cpp
7863 // Performs equivalent check of std::fabs(lhs - rhs) <= margin
7864 // But without the subtraction to allow for INFINITY in comparison
7865 bool marginComparison(double lhs, double rhs, double margin)
7867 return (lhs + margin >= rhs) && (rhs + margin >= lhs);
7875 Approx::Approx(double value)
7876 : m_epsilon(std::numeric_limits<float>::epsilon() * 100), m_margin(0.0), m_scale(0.0), m_value(value)
7880 Approx Approx::custom()
7885 Approx Approx::operator-() const
7888 temp.m_value = -temp.m_value;
7892 std::string Approx::toString() const
7894 ReusableStringStream rss;
7895 rss << "Approx( " << ::Catch::Detail::stringify(m_value) << " )";
7899 bool Approx::equalityComparisonImpl(const double other) const
7901 // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
7902 // Thanks to Richard Harris for his help refining the scaled margin value
7903 return marginComparison(m_value, other, m_margin) ||
7904 marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value) ? 0 : m_value)));
7907 void Approx::setMargin(double newMargin)
7909 CATCH_ENFORCE(newMargin >= 0,
7910 "Invalid Approx::margin: " << newMargin << '.' << " Approx::Margin has to be non-negative.");
7911 m_margin = newMargin;
7914 void Approx::setEpsilon(double newEpsilon)
7916 CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
7917 "Invalid Approx::epsilon: " << newEpsilon << '.' << " Approx::epsilon has to be in [0, 1]");
7918 m_epsilon = newEpsilon;
7921 } // end namespace Detail
7923 namespace literals {
7924 Detail::Approx operator"" _a(long double val)
7926 return Detail::Approx(val);
7928 Detail::Approx operator"" _a(unsigned long long val)
7930 return Detail::Approx(val);
7932 } // end namespace literals
7934 std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value)
7936 return value.toString();
7939 } // end namespace Catch
7940 // end catch_approx.cpp
7941 // start catch_assertionhandler.cpp
7943 // start catch_debugger.h
7946 bool isDebuggerActive();
7949 #ifdef CATCH_PLATFORM_MAC
7951 #if defined(__i386__) || defined(__x86_64__)
7952 #define CATCH_TRAP() __asm__("int $3\n" : :) /* NOLINT */
7953 #elif defined(__aarch64__)
7954 #define CATCH_TRAP() __asm__(".inst 0xd4200000")
7957 #elif defined(CATCH_PLATFORM_IPHONE)
7959 // use inline assembler
7960 #if defined(__i386__) || defined(__x86_64__)
7961 #define CATCH_TRAP() __asm__("int $3")
7962 #elif defined(__aarch64__)
7963 #define CATCH_TRAP() __asm__(".inst 0xd4200000")
7964 #elif defined(__arm__) && !defined(__thumb__)
7965 #define CATCH_TRAP() __asm__(".inst 0xe7f001f0")
7966 #elif defined(__arm__) && defined(__thumb__)
7967 #define CATCH_TRAP() __asm__(".inst 0xde01")
7970 #elif defined(CATCH_PLATFORM_LINUX)
7971 // If we can use inline assembler, do it because this allows us to break
7972 // directly at the location of the failing check instead of breaking inside
7973 // raise() called from it, i.e. one stack frame below.
7974 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
7975 #define CATCH_TRAP() asm volatile("int $3") /* NOLINT */
7976 #else // Fall back to the generic way.
7979 #define CATCH_TRAP() raise(SIGTRAP)
7981 #elif defined(_MSC_VER)
7982 #define CATCH_TRAP() __debugbreak()
7983 #elif defined(__MINGW32__)
7984 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
7985 #define CATCH_TRAP() DebugBreak()
7988 #ifndef CATCH_BREAK_INTO_DEBUGGER
7990 #define CATCH_BREAK_INTO_DEBUGGER() \
7992 if (Catch::isDebuggerActive()) { \
7997 #define CATCH_BREAK_INTO_DEBUGGER() [] {}()
8001 // end catch_debugger.h
8002 // start catch_run_context.h
8004 // start catch_fatal_condition.h
8010 // Wrapper for platform-specific fatal error (signals/SEH) handlers
8012 // Tries to be cooperative with other handlers, and not step over
8013 // other handlers. This means that unknown structured exceptions
8014 // are passed on, previous signal handlers are called, and so on.
8016 // Can only be instantiated once, and assumes that once a signal
8017 // is caught, the binary will end up terminating. Thus, there
8018 class FatalConditionHandler {
8019 bool m_started = false;
8021 // Install/disengage implementation for specific platform.
8022 // Should be if-defed to work on current platform, can assume
8023 // engage-disengage 1:1 pairing.
8024 void engage_platform();
8025 void disengage_platform();
8028 // Should also have platform-specific implementations as needed
8029 FatalConditionHandler();
8030 ~FatalConditionHandler();
8034 assert(!m_started && "Handler cannot be installed twice.");
8041 assert(m_started && "Handler cannot be uninstalled without being installed first");
8043 disengage_platform();
8047 //! Simple RAII guard for (dis)engaging the FatalConditionHandler
8048 class FatalConditionHandlerGuard {
8049 FatalConditionHandler* m_handler;
8052 FatalConditionHandlerGuard(FatalConditionHandler* handler) : m_handler(handler) { m_handler->engage(); }
8053 ~FatalConditionHandlerGuard() { m_handler->disengage(); }
8056 } // end namespace Catch
8058 // end catch_fatal_condition.h
8063 struct IMutableContext;
8065 ///////////////////////////////////////////////////////////////////////////
8067 class RunContext : public IResultCapture, public IRunner {
8070 RunContext(RunContext const&) = delete;
8071 RunContext& operator=(RunContext const&) = delete;
8073 explicit RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter);
8075 ~RunContext() override;
8077 void testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount);
8078 void testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex,
8079 std::size_t groupsCount);
8081 Totals runTest(TestCase const& testCase);
8083 IConfigPtr config() const;
8084 IStreamingReporter& reporter() const;
8086 public: // IResultCapture
8087 // Assertion handlers
8088 void handleExpr(AssertionInfo const& info, ITransientExpression const& expr, AssertionReaction& reaction) override;
8089 void handleMessage(AssertionInfo const& info, ResultWas::OfType resultType, StringRef const& message,
8090 AssertionReaction& reaction) override;
8091 void handleUnexpectedExceptionNotThrown(AssertionInfo const& info, AssertionReaction& reaction) override;
8092 void handleUnexpectedInflightException(AssertionInfo const& info, std::string const& message,
8093 AssertionReaction& reaction) override;
8094 void handleIncomplete(AssertionInfo const& info) override;
8095 void handleNonExpr(AssertionInfo const& info, ResultWas::OfType resultType, AssertionReaction& reaction) override;
8097 bool sectionStarted(SectionInfo const& sectionInfo, Counts& assertions) override;
8099 void sectionEnded(SectionEndInfo const& endInfo) override;
8100 void sectionEndedEarly(SectionEndInfo const& endInfo) override;
8102 auto acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo) -> IGeneratorTracker& override;
8104 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
8105 void benchmarkPreparing(std::string const& name) override;
8106 void benchmarkStarting(BenchmarkInfo const& info) override;
8107 void benchmarkEnded(BenchmarkStats<> const& stats) override;
8108 void benchmarkFailed(std::string const& error) override;
8109 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
8111 void pushScopedMessage(MessageInfo const& message) override;
8112 void popScopedMessage(MessageInfo const& message) override;
8114 void emplaceUnscopedMessage(MessageBuilder const& builder) override;
8116 std::string getCurrentTestName() const override;
8118 const AssertionResult* getLastResult() const override;
8120 void exceptionEarlyReported() override;
8122 void handleFatalErrorCondition(StringRef message) override;
8124 bool lastAssertionPassed() override;
8126 void assertionPassed() override;
8129 // !TBD We need to do this another way!
8130 bool aborting() const final;
8133 void runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr);
8134 void invokeActiveTestCase();
8136 void resetAssertionInfo();
8137 bool testForMissingAssertions(Counts& assertions);
8139 void assertionEnded(AssertionResult const& result);
8140 void reportExpr(AssertionInfo const& info, ResultWas::OfType resultType, ITransientExpression const* expr,
8143 void populateReaction(AssertionReaction& reaction);
8146 void handleUnfinishedSections();
8148 TestRunInfo m_runInfo;
8149 IMutableContext& m_context;
8150 TestCase const* m_activeTestCase = nullptr;
8151 ITracker* m_testCaseTracker = nullptr;
8152 Option<AssertionResult> m_lastResult;
8154 IConfigPtr m_config;
8156 IStreamingReporterPtr m_reporter;
8157 std::vector<MessageInfo> m_messages;
8158 std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
8159 AssertionInfo m_lastAssertionInfo;
8160 std::vector<SectionEndInfo> m_unfinishedSections;
8161 std::vector<ITracker*> m_activeSections;
8162 TrackerContext m_trackerContext;
8163 FatalConditionHandler m_fatalConditionhandler;
8164 bool m_lastAssertionPassed = false;
8165 bool m_shouldReportUnexpected = true;
8166 bool m_includeSuccessfulResults;
8169 void seedRng(IConfig const& config);
8170 unsigned int rngSeed();
8171 } // end namespace Catch
8173 // end catch_run_context.h
8177 auto operator<<(std::ostream& os, ITransientExpression const& expr) -> std::ostream&
8179 expr.streamReconstructedExpression(os);
8184 LazyExpression::LazyExpression(bool isNegated) : m_isNegated(isNegated) {}
8186 LazyExpression::LazyExpression(LazyExpression const& other) : m_isNegated(other.m_isNegated) {}
8188 LazyExpression::operator bool() const
8190 return m_transientExpression != nullptr;
8193 auto operator<<(std::ostream& os, LazyExpression const& lazyExpr) -> std::ostream&
8195 if (lazyExpr.m_isNegated)
8199 if (lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression())
8200 os << "(" << *lazyExpr.m_transientExpression << ")";
8202 os << *lazyExpr.m_transientExpression;
8204 os << "{** error - unchecked empty expression requested **}";
8209 AssertionHandler::AssertionHandler(StringRef const& macroName, SourceLineInfo const& lineInfo,
8210 StringRef capturedExpression, ResultDisposition::Flags resultDisposition)
8211 : m_assertionInfo{macroName, lineInfo, capturedExpression, resultDisposition}, m_resultCapture(getResultCapture())
8215 void AssertionHandler::handleExpr(ITransientExpression const& expr)
8217 m_resultCapture.handleExpr(m_assertionInfo, expr, m_reaction);
8219 void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message)
8221 m_resultCapture.handleMessage(m_assertionInfo, resultType, message, m_reaction);
8224 auto AssertionHandler::allowThrows() const -> bool
8226 return getCurrentContext().getConfig()->allowThrows();
8229 void AssertionHandler::complete()
8232 if (m_reaction.shouldDebugBreak) {
8234 // If you find your debugger stopping you here then go one level up on the
8235 // call-stack for the code that caused it (typically a failed assertion)
8237 // (To go back to the test and change execution, jump over the throw, next)
8238 CATCH_BREAK_INTO_DEBUGGER();
8240 if (m_reaction.shouldThrow) {
8241 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
8242 throw Catch::TestFailureException();
8244 CATCH_ERROR("Test failure requires aborting test!");
8248 void AssertionHandler::setCompleted()
8253 void AssertionHandler::handleUnexpectedInflightException()
8255 m_resultCapture.handleUnexpectedInflightException(m_assertionInfo, Catch::translateActiveException(), m_reaction);
8258 void AssertionHandler::handleExceptionThrownAsExpected()
8260 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
8262 void AssertionHandler::handleExceptionNotThrownAsExpected()
8264 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
8267 void AssertionHandler::handleUnexpectedExceptionNotThrown()
8269 m_resultCapture.handleUnexpectedExceptionNotThrown(m_assertionInfo, m_reaction);
8272 void AssertionHandler::handleThrowingCallSkipped()
8274 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
8277 // This is the overload that takes a string and infers the Equals matcher from it
8278 // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
8279 void handleExceptionMatchExpr(AssertionHandler& handler, std::string const& str, StringRef const& matcherString)
8281 handleExceptionMatchExpr(handler, Matchers::Equals(str), matcherString);
8284 } // namespace Catch
8285 // end catch_assertionhandler.cpp
8286 // start catch_assertionresult.cpp
8289 AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const& _lazyExpression)
8290 : lazyExpression(_lazyExpression), resultType(_resultType)
8294 std::string AssertionResultData::reconstructExpression() const
8297 if (reconstructedExpression.empty()) {
8298 if (lazyExpression) {
8299 ReusableStringStream rss;
8300 rss << lazyExpression;
8301 reconstructedExpression = rss.str();
8304 return reconstructedExpression;
8307 AssertionResult::AssertionResult(AssertionInfo const& info, AssertionResultData const& data)
8308 : m_info(info), m_resultData(data)
8312 // Result was a success
8313 bool AssertionResult::succeeded() const
8315 return Catch::isOk(m_resultData.resultType);
8318 // Result was a success, or failure is suppressed
8319 bool AssertionResult::isOk() const
8321 return Catch::isOk(m_resultData.resultType) || shouldSuppressFailure(m_info.resultDisposition);
8324 ResultWas::OfType AssertionResult::getResultType() const
8326 return m_resultData.resultType;
8329 bool AssertionResult::hasExpression() const
8331 return !m_info.capturedExpression.empty();
8334 bool AssertionResult::hasMessage() const
8336 return !m_resultData.message.empty();
8339 std::string AssertionResult::getExpression() const
8341 // Possibly overallocating by 3 characters should be basically free
8343 expr.reserve(m_info.capturedExpression.size() + 3);
8344 if (isFalseTest(m_info.resultDisposition)) {
8347 expr += m_info.capturedExpression;
8348 if (isFalseTest(m_info.resultDisposition)) {
8354 std::string AssertionResult::getExpressionInMacro() const
8357 if (m_info.macroName.empty())
8358 expr = static_cast<std::string>(m_info.capturedExpression);
8360 expr.reserve(m_info.macroName.size() + m_info.capturedExpression.size() + 4);
8361 expr += m_info.macroName;
8363 expr += m_info.capturedExpression;
8369 bool AssertionResult::hasExpandedExpression() const
8371 return hasExpression() && getExpandedExpression() != getExpression();
8374 std::string AssertionResult::getExpandedExpression() const
8376 std::string expr = m_resultData.reconstructExpression();
8377 return expr.empty() ? getExpression() : expr;
8380 std::string AssertionResult::getMessage() const
8382 return m_resultData.message;
8384 SourceLineInfo AssertionResult::getSourceInfo() const
8386 return m_info.lineInfo;
8389 StringRef AssertionResult::getTestMacroName() const
8391 return m_info.macroName;
8394 } // end namespace Catch
8395 // end catch_assertionresult.cpp
8396 // start catch_capture_matchers.cpp
8400 using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
8402 // This is the general overload that takes a any string matcher
8403 // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
8404 // the Equals matcher (so the header does not mention matchers)
8405 void handleExceptionMatchExpr(AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString)
8407 std::string exceptionMessage = Catch::translateActiveException();
8408 MatchExpr<std::string, StringMatcher const&> expr(exceptionMessage, matcher, matcherString);
8409 handler.handleExpr(expr);
8412 } // namespace Catch
8413 // end catch_capture_matchers.cpp
8414 // start catch_commandline.cpp
8416 // start catch_commandline.h
8418 // start catch_clara.h
8420 // Use Catch's value for console width (store Clara's off to the side, if present)
8421 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
8422 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8423 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8425 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH - 1
8428 #pragma clang diagnostic push
8429 #pragma clang diagnostic ignored "-Wweak-vtables"
8430 #pragma clang diagnostic ignored "-Wexit-time-destructors"
8431 #pragma clang diagnostic ignored "-Wshadow"
8435 // Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
8437 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8438 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8440 // See https://github.com/philsquared/Clara for more details
8444 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
8445 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
8448 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8449 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
8452 #ifndef CLARA_CONFIG_OPTIONAL_TYPE
8453 #ifdef __has_include
8454 #if __has_include(<optional>) && __cplusplus >= 201703L
8456 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional
8461 // ----------- #included from clara_textflow.hpp -----------
8465 // A single-header library for wrapping and laying out basic text, by Phil Nash
8467 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8468 // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8470 // This project is hosted at https://github.com/philsquared/textflowcpp
8477 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8478 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
8483 namespace TextFlow {
8485 inline auto isWhitespace(char c) -> bool
8487 static std::string chars = " \t\n\r";
8488 return chars.find(c) != std::string::npos;
8490 inline auto isBreakableBefore(char c) -> bool
8492 static std::string chars = "[({<|";
8493 return chars.find(c) != std::string::npos;
8495 inline auto isBreakableAfter(char c) -> bool
8497 static std::string chars = "])}>.,:;*+-=&/\\";
8498 return chars.find(c) != std::string::npos;
8504 std::vector<std::string> m_strings;
8505 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
8506 size_t m_indent = 0;
8507 size_t m_initialIndent = std::string::npos;
8513 Column const& m_column;
8514 size_t m_stringIndex = 0;
8519 bool m_suffix = false;
8521 iterator(Column const& column, size_t stringIndex) : m_column(column), m_stringIndex(stringIndex) {}
8523 auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
8525 auto isBoundary(size_t at) const -> bool
8528 assert(at <= line().size());
8530 return at == line().size() || (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
8531 isBreakableBefore(line()[at]) || isBreakableAfter(line()[at - 1]);
8536 assert(m_stringIndex < m_column.m_strings.size());
8539 auto width = m_column.m_width - indent();
8541 if (line()[m_pos] == '\n') {
8544 while (m_end < line().size() && line()[m_end] != '\n')
8547 if (m_end < m_pos + width) {
8548 m_len = m_end - m_pos;
8551 while (len > 0 && !isBoundary(m_pos + len))
8553 while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
8565 auto indent() const -> size_t
8567 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
8568 return initial == std::string::npos ? m_column.m_indent : initial;
8571 auto addIndentAndSuffix(std::string const& plain) const -> std::string
8573 return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);
8577 using difference_type = std::ptrdiff_t;
8578 using value_type = std::string;
8579 using pointer = value_type*;
8580 using reference = value_type&;
8581 using iterator_category = std::forward_iterator_tag;
8583 explicit iterator(Column const& column) : m_column(column)
8585 assert(m_column.m_width > m_column.m_indent);
8586 assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
8589 m_stringIndex++; // Empty string
8592 auto operator*() const -> std::string
8594 assert(m_stringIndex < m_column.m_strings.size());
8595 assert(m_pos <= m_end);
8596 return addIndentAndSuffix(line().substr(m_pos, m_len));
8599 auto operator++() -> iterator&
8602 if (m_pos < line().size() && line()[m_pos] == '\n')
8605 while (m_pos < line().size() && isWhitespace(line()[m_pos]))
8608 if (m_pos == line().size()) {
8612 if (m_stringIndex < m_column.m_strings.size())
8616 auto operator++(int) -> iterator
8618 iterator prev(*this);
8623 auto operator==(iterator const& other) const -> bool
8625 return m_pos == other.m_pos && m_stringIndex == other.m_stringIndex && &m_column == &other.m_column;
8627 auto operator!=(iterator const& other) const -> bool { return !operator==(other); }
8629 using const_iterator = iterator;
8631 explicit Column(std::string const& text) { m_strings.push_back(text); }
8633 auto width(size_t newWidth) -> Column&
8635 assert(newWidth > 0);
8639 auto indent(size_t newIndent) -> Column&
8641 m_indent = newIndent;
8644 auto initialIndent(size_t newIndent) -> Column&
8646 m_initialIndent = newIndent;
8650 auto width() const -> size_t { return m_width; }
8651 auto begin() const -> iterator { return iterator(*this); }
8652 auto end() const -> iterator { return {*this, m_strings.size()}; }
8654 inline friend std::ostream& operator<<(std::ostream& os, Column const& col)
8657 for (auto line : col) {
8667 auto operator+(Column const& other) -> Columns;
8669 auto toString() const -> std::string
8671 std::ostringstream oss;
8677 class Spacer : public Column {
8680 explicit Spacer(size_t spaceWidth) : Column("") { width(spaceWidth); }
8684 std::vector<Column> m_columns;
8691 std::vector<Column> const& m_columns;
8692 std::vector<Column::iterator> m_iterators;
8693 size_t m_activeIterators;
8695 iterator(Columns const& columns, EndTag) : m_columns(columns.m_columns), m_activeIterators(0)
8697 m_iterators.reserve(m_columns.size());
8699 for (auto const& col : m_columns)
8700 m_iterators.push_back(col.end());
8704 using difference_type = std::ptrdiff_t;
8705 using value_type = std::string;
8706 using pointer = value_type*;
8707 using reference = value_type&;
8708 using iterator_category = std::forward_iterator_tag;
8710 explicit iterator(Columns const& columns) : m_columns(columns.m_columns), m_activeIterators(m_columns.size())
8712 m_iterators.reserve(m_columns.size());
8714 for (auto const& col : m_columns)
8715 m_iterators.push_back(col.begin());
8718 auto operator==(iterator const& other) const -> bool { return m_iterators == other.m_iterators; }
8719 auto operator!=(iterator const& other) const -> bool { return m_iterators != other.m_iterators; }
8720 auto operator*() const -> std::string
8722 std::string row, padding;
8724 for (size_t i = 0; i < m_columns.size(); ++i) {
8725 auto width = m_columns[i].width();
8726 if (m_iterators[i] != m_columns[i].end()) {
8727 std::string col = *m_iterators[i];
8728 row += padding + col;
8729 if (col.size() < width)
8730 padding = std::string(width - col.size(), ' ');
8734 padding += std::string(width, ' ');
8739 auto operator++() -> iterator&
8741 for (size_t i = 0; i < m_columns.size(); ++i) {
8742 if (m_iterators[i] != m_columns[i].end())
8747 auto operator++(int) -> iterator
8749 iterator prev(*this);
8754 using const_iterator = iterator;
8756 auto begin() const -> iterator { return iterator(*this); }
8757 auto end() const -> iterator { return {*this, iterator::EndTag()}; }
8759 auto operator+=(Column const& col) -> Columns&
8761 m_columns.push_back(col);
8764 auto operator+(Column const& col) -> Columns
8766 Columns combined = *this;
8771 inline friend std::ostream& operator<<(std::ostream& os, Columns const& cols)
8775 for (auto line : cols) {
8785 auto toString() const -> std::string
8787 std::ostringstream oss;
8793 inline auto Column::operator+(Column const& other) -> Columns
8800 } // namespace TextFlow
8802 } // namespace clara
8803 } // namespace Catch
8805 // ----------- end of #include from clara_textflow.hpp -----------
8806 // ........... back in clara.hpp
8808 #include <algorithm>
8814 #if !defined(CATCH_PLATFORM_WINDOWS) && (defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER))
8815 #define CATCH_PLATFORM_WINDOWS
8822 // Traits for extracting arg and return type of lambdas (for single argument lambdas)
8823 template <typename L> struct UnaryLambdaTraits : UnaryLambdaTraits<decltype(&L::operator())> {
8826 template <typename ClassT, typename ReturnT, typename... Args>
8827 struct UnaryLambdaTraits<ReturnT (ClassT::*)(Args...) const> {
8828 static const bool isValid = false;
8831 template <typename ClassT, typename ReturnT, typename ArgT> struct UnaryLambdaTraits<ReturnT (ClassT::*)(ArgT) const> {
8832 static const bool isValid = true;
8833 using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
8834 using ReturnType = ReturnT;
8839 // Transport for raw args (copied from main args, or supplied via init list for testing)
8842 std::string m_exeName;
8843 std::vector<std::string> m_args;
8846 Args(int argc, char const* const* argv) : m_exeName(argv[0]), m_args(argv + 1, argv + argc) {}
8848 Args(std::initializer_list<std::string> args) : m_exeName(*args.begin()), m_args(args.begin() + 1, args.end()) {}
8850 auto exeName() const -> std::string { return m_exeName; }
8853 // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string
8854 // may encode an option + its argument if the : or = form is used
8855 enum class TokenType { Option, Argument };
8861 inline auto isOptPrefix(char c) -> bool
8864 #ifdef CATCH_PLATFORM_WINDOWS
8870 // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled
8872 using Iterator = std::vector<std::string>::const_iterator;
8875 std::vector<Token> m_tokenBuffer;
8879 m_tokenBuffer.resize(0);
8881 // Skip any empty strings
8882 while (it != itEnd && it->empty())
8886 auto const& next = *it;
8887 if (isOptPrefix(next[0])) {
8888 auto delimiterPos = next.find_first_of(" :=");
8889 if (delimiterPos != std::string::npos) {
8890 m_tokenBuffer.push_back({TokenType::Option, next.substr(0, delimiterPos)});
8891 m_tokenBuffer.push_back({TokenType::Argument, next.substr(delimiterPos + 1)});
8893 if (next[1] != '-' && next.size() > 2) {
8894 std::string opt = "- ";
8895 for (size_t i = 1; i < next.size(); ++i) {
8897 m_tokenBuffer.push_back({TokenType::Option, opt});
8900 m_tokenBuffer.push_back({TokenType::Option, next});
8904 m_tokenBuffer.push_back({TokenType::Argument, next});
8910 explicit TokenStream(Args const& args) : TokenStream(args.m_args.begin(), args.m_args.end()) {}
8912 TokenStream(Iterator it, Iterator itEnd) : it(it), itEnd(itEnd) { loadBuffer(); }
8914 explicit operator bool() const { return !m_tokenBuffer.empty() || it != itEnd; }
8916 auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
8918 auto operator*() const -> Token
8920 assert(!m_tokenBuffer.empty());
8921 return m_tokenBuffer.front();
8924 auto operator->() const -> Token const*
8926 assert(!m_tokenBuffer.empty());
8927 return &m_tokenBuffer.front();
8930 auto operator++() -> TokenStream&
8932 if (m_tokenBuffer.size() >= 2) {
8933 m_tokenBuffer.erase(m_tokenBuffer.begin());
8945 enum Type { Ok, LogicError, RuntimeError };
8948 ResultBase(Type type) : m_type(type) {}
8949 virtual ~ResultBase() = default;
8951 virtual void enforceOk() const = 0;
8956 template <typename T> class ResultValueBase : public ResultBase {
8958 auto value() const -> T const&
8965 ResultValueBase(Type type) : ResultBase(type) {}
8967 ResultValueBase(ResultValueBase const& other) : ResultBase(other)
8969 if (m_type == ResultBase::Ok)
8970 new (&m_value) T(other.m_value);
8973 ResultValueBase(Type, T const& value) : ResultBase(Ok) { new (&m_value) T(value); }
8975 auto operator=(ResultValueBase const& other) -> ResultValueBase&
8977 if (m_type == ResultBase::Ok)
8979 ResultBase::operator=(other);
8980 if (m_type == ResultBase::Ok)
8981 new (&m_value) T(other.m_value);
8985 ~ResultValueBase() override
8996 template <> class ResultValueBase<void> : public ResultBase {
8998 using ResultBase::ResultBase;
9001 template <typename T = void> class BasicResult : public ResultValueBase<T> {
9003 template <typename U>
9004 explicit BasicResult(BasicResult<U> const& other)
9005 : ResultValueBase<T>(other.type()), m_errorMessage(other.errorMessage())
9007 assert(type() != ResultBase::Ok);
9010 template <typename U> static auto ok(U const& value) -> BasicResult { return {ResultBase::Ok, value}; }
9011 static auto ok() -> BasicResult { return {ResultBase::Ok}; }
9012 static auto logicError(std::string const& message) -> BasicResult { return {ResultBase::LogicError, message}; }
9013 static auto runtimeError(std::string const& message) -> BasicResult { return {ResultBase::RuntimeError, message}; }
9015 explicit operator bool() const { return m_type == ResultBase::Ok; }
9016 auto type() const -> ResultBase::Type { return m_type; }
9017 auto errorMessage() const -> std::string { return m_errorMessage; }
9020 void enforceOk() const override
9023 // Errors shouldn't reach this point, but if they do
9024 // the actual error message will be in m_errorMessage
9025 assert(m_type != ResultBase::LogicError);
9026 assert(m_type != ResultBase::RuntimeError);
9027 if (m_type != ResultBase::Ok)
9031 std::string m_errorMessage; // Only populated if resultType is an error
9033 BasicResult(ResultBase::Type type, std::string const& message) : ResultValueBase<T>(type), m_errorMessage(message)
9035 assert(m_type != ResultBase::Ok);
9038 using ResultValueBase<T>::ResultValueBase;
9039 using ResultBase::m_type;
9042 enum class ParseResultType { Matched, NoMatch, ShortCircuitAll, ShortCircuitSame };
9046 ParseState(ParseResultType type, TokenStream const& remainingTokens)
9047 : m_type(type), m_remainingTokens(remainingTokens)
9051 auto type() const -> ParseResultType { return m_type; }
9052 auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
9055 ParseResultType m_type;
9056 TokenStream m_remainingTokens;
9059 using Result = BasicResult<void>;
9060 using ParserResult = BasicResult<ParseResultType>;
9061 using InternalParseResult = BasicResult<ParseState>;
9063 struct HelpColumns {
9068 template <typename T> inline auto convertInto(std::string const& source, T& target) -> ParserResult
9070 std::stringstream ss;
9074 return ParserResult::runtimeError("Unable to convert '" + source + "' to destination type");
9076 return ParserResult::ok(ParseResultType::Matched);
9078 inline auto convertInto(std::string const& source, std::string& target) -> ParserResult
9081 return ParserResult::ok(ParseResultType::Matched);
9083 inline auto convertInto(std::string const& source, bool& target) -> ParserResult
9085 std::string srcLC = source;
9086 std::transform(srcLC.begin(), srcLC.end(), srcLC.begin(),
9087 [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
9088 if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
9090 else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
9093 return ParserResult::runtimeError("Expected a boolean value but did not recognise: '" + source + "'");
9094 return ParserResult::ok(ParseResultType::Matched);
9096 #ifdef CLARA_CONFIG_OPTIONAL_TYPE
9097 template <typename T>
9098 inline auto convertInto(std::string const& source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target) -> ParserResult
9101 auto result = convertInto(source, temp);
9103 target = std::move(temp);
9106 #endif // CLARA_CONFIG_OPTIONAL_TYPE
9108 struct NonCopyable {
9109 NonCopyable() = default;
9110 NonCopyable(NonCopyable const&) = delete;
9111 NonCopyable(NonCopyable&&) = delete;
9112 NonCopyable& operator=(NonCopyable const&) = delete;
9113 NonCopyable& operator=(NonCopyable&&) = delete;
9116 struct BoundRef : NonCopyable {
9117 virtual ~BoundRef() = default;
9118 virtual auto isContainer() const -> bool { return false; }
9119 virtual auto isFlag() const -> bool { return false; }
9121 struct BoundValueRefBase : BoundRef {
9122 virtual auto setValue(std::string const& arg) -> ParserResult = 0;
9124 struct BoundFlagRefBase : BoundRef {
9125 virtual auto setFlag(bool flag) -> ParserResult = 0;
9126 virtual auto isFlag() const -> bool { return true; }
9129 template <typename T> struct BoundValueRef : BoundValueRefBase {
9132 explicit BoundValueRef(T& ref) : m_ref(ref) {}
9134 auto setValue(std::string const& arg) -> ParserResult override { return convertInto(arg, m_ref); }
9137 template <typename T> struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
9138 std::vector<T>& m_ref;
9140 explicit BoundValueRef(std::vector<T>& ref) : m_ref(ref) {}
9142 auto isContainer() const -> bool override { return true; }
9144 auto setValue(std::string const& arg) -> ParserResult override
9147 auto result = convertInto(arg, temp);
9149 m_ref.push_back(temp);
9154 struct BoundFlagRef : BoundFlagRefBase {
9157 explicit BoundFlagRef(bool& ref) : m_ref(ref) {}
9159 auto setFlag(bool flag) -> ParserResult override
9162 return ParserResult::ok(ParseResultType::Matched);
9166 template <typename ReturnType> struct LambdaInvoker {
9167 static_assert(std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult");
9169 template <typename L, typename ArgType> static auto invoke(L const& lambda, ArgType const& arg) -> ParserResult
9175 template <> struct LambdaInvoker<void> {
9176 template <typename L, typename ArgType> static auto invoke(L const& lambda, ArgType const& arg) -> ParserResult
9179 return ParserResult::ok(ParseResultType::Matched);
9183 template <typename ArgType, typename L>
9184 inline auto invokeLambda(L const& lambda, std::string const& arg) -> ParserResult
9187 auto result = convertInto(arg, temp);
9188 return !result ? result : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(lambda, temp);
9191 template <typename L> struct BoundLambda : BoundValueRefBase {
9194 static_assert(UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument");
9195 explicit BoundLambda(L const& lambda) : m_lambda(lambda) {}
9197 auto setValue(std::string const& arg) -> ParserResult override
9199 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>(m_lambda, arg);
9203 template <typename L> struct BoundFlagLambda : BoundFlagRefBase {
9206 static_assert(UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument");
9207 static_assert(std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean");
9209 explicit BoundFlagLambda(L const& lambda) : m_lambda(lambda) {}
9211 auto setFlag(bool flag) -> ParserResult override
9213 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke(m_lambda, flag);
9217 enum class Optionality { Optional, Required };
9223 virtual ~ParserBase() = default;
9224 virtual auto validate() const -> Result { return Result::ok(); }
9225 virtual auto parse(std::string const& exeName, TokenStream const& tokens) const -> InternalParseResult = 0;
9226 virtual auto cardinality() const -> size_t { return 1; }
9228 auto parse(Args const& args) const -> InternalParseResult { return parse(args.exeName(), TokenStream(args)); }
9231 template <typename DerivedT> class ComposableParserImpl : public ParserBase {
9233 template <typename T> auto operator|(T const& other) const -> Parser;
9235 template <typename T> auto operator+(T const& other) const -> Parser;
9238 // Common code and state for Args and Opts
9239 template <typename DerivedT> class ParserRefImpl : public ComposableParserImpl<DerivedT> {
9241 Optionality m_optionality = Optionality::Optional;
9242 std::shared_ptr<BoundRef> m_ref;
9244 std::string m_description;
9246 explicit ParserRefImpl(std::shared_ptr<BoundRef> const& ref) : m_ref(ref) {}
9249 template <typename T>
9250 ParserRefImpl(T& ref, std::string const& hint) : m_ref(std::make_shared<BoundValueRef<T>>(ref)), m_hint(hint)
9254 template <typename LambdaT>
9255 ParserRefImpl(LambdaT const& ref, std::string const& hint)
9256 : m_ref(std::make_shared<BoundLambda<LambdaT>>(ref)), m_hint(hint)
9260 auto operator()(std::string const& description) -> DerivedT&
9262 m_description = description;
9263 return static_cast<DerivedT&>(*this);
9266 auto optional() -> DerivedT&
9268 m_optionality = Optionality::Optional;
9269 return static_cast<DerivedT&>(*this);
9272 auto required() -> DerivedT&
9274 m_optionality = Optionality::Required;
9275 return static_cast<DerivedT&>(*this);
9278 auto isOptional() const -> bool { return m_optionality == Optionality::Optional; }
9280 auto cardinality() const -> size_t override
9282 if (m_ref->isContainer())
9288 auto hint() const -> std::string { return m_hint; }
9291 class ExeName : public ComposableParserImpl<ExeName> {
9292 std::shared_ptr<std::string> m_name;
9293 std::shared_ptr<BoundValueRefBase> m_ref;
9295 template <typename LambdaT> static auto makeRef(LambdaT const& lambda) -> std::shared_ptr<BoundValueRefBase>
9297 return std::make_shared<BoundLambda<LambdaT>>(lambda);
9301 ExeName() : m_name(std::make_shared<std::string>("<executable>")) {}
9303 explicit ExeName(std::string& ref) : ExeName() { m_ref = std::make_shared<BoundValueRef<std::string>>(ref); }
9305 template <typename LambdaT> explicit ExeName(LambdaT const& lambda) : ExeName()
9307 m_ref = std::make_shared<BoundLambda<LambdaT>>(lambda);
9310 // The exe name is not parsed out of the normal tokens, but is handled specially
9311 auto parse(std::string const&, TokenStream const& tokens) const -> InternalParseResult override
9313 return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens));
9316 auto name() const -> std::string { return *m_name; }
9317 auto set(std::string const& newName) -> ParserResult
9320 auto lastSlash = newName.find_last_of("\\/");
9321 auto filename = (lastSlash == std::string::npos) ? newName : newName.substr(lastSlash + 1);
9325 return m_ref->setValue(filename);
9327 return ParserResult::ok(ParseResultType::Matched);
9331 class Arg : public ParserRefImpl<Arg> {
9333 using ParserRefImpl::ParserRefImpl;
9335 auto parse(std::string const&, TokenStream const& tokens) const -> InternalParseResult override
9337 auto validationResult = validate();
9338 if (!validationResult)
9339 return InternalParseResult(validationResult);
9341 auto remainingTokens = tokens;
9342 auto const& token = *remainingTokens;
9343 if (token.type != TokenType::Argument)
9344 return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens));
9346 assert(!m_ref->isFlag());
9347 auto valueRef = static_cast<detail::BoundValueRefBase*>(m_ref.get());
9349 auto result = valueRef->setValue(remainingTokens->token);
9351 return InternalParseResult(result);
9353 return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens));
9357 inline auto normaliseOpt(std::string const& optName) -> std::string
9359 #ifdef CATCH_PLATFORM_WINDOWS
9360 if (optName[0] == '/')
9361 return "-" + optName.substr(1);
9367 class Opt : public ParserRefImpl<Opt> {
9369 std::vector<std::string> m_optNames;
9372 template <typename LambdaT>
9373 explicit Opt(LambdaT const& ref) : ParserRefImpl(std::make_shared<BoundFlagLambda<LambdaT>>(ref))
9377 explicit Opt(bool& ref) : ParserRefImpl(std::make_shared<BoundFlagRef>(ref)) {}
9379 template <typename LambdaT> Opt(LambdaT const& ref, std::string const& hint) : ParserRefImpl(ref, hint) {}
9381 template <typename T> Opt(T& ref, std::string const& hint) : ParserRefImpl(ref, hint) {}
9383 auto operator[](std::string const& optName) -> Opt&
9385 m_optNames.push_back(optName);
9389 auto getHelpColumns() const -> std::vector<HelpColumns>
9391 std::ostringstream oss;
9393 for (auto const& opt : m_optNames) {
9400 if (!m_hint.empty())
9401 oss << " <" << m_hint << ">";
9402 return {{oss.str(), m_description}};
9405 auto isMatch(std::string const& optToken) const -> bool
9407 auto normalisedToken = normaliseOpt(optToken);
9408 for (auto const& name : m_optNames) {
9409 if (normaliseOpt(name) == normalisedToken)
9415 using ParserBase::parse;
9417 auto parse(std::string const&, TokenStream const& tokens) const -> InternalParseResult override
9419 auto validationResult = validate();
9420 if (!validationResult)
9421 return InternalParseResult(validationResult);
9423 auto remainingTokens = tokens;
9424 if (remainingTokens && remainingTokens->type == TokenType::Option) {
9425 auto const& token = *remainingTokens;
9426 if (isMatch(token.token)) {
9427 if (m_ref->isFlag()) {
9428 auto flagRef = static_cast<detail::BoundFlagRefBase*>(m_ref.get());
9429 auto result = flagRef->setFlag(true);
9431 return InternalParseResult(result);
9432 if (result.value() == ParseResultType::ShortCircuitAll)
9433 return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
9435 auto valueRef = static_cast<detail::BoundValueRefBase*>(m_ref.get());
9437 if (!remainingTokens)
9438 return InternalParseResult::runtimeError("Expected argument following " + token.token);
9439 auto const& argToken = *remainingTokens;
9440 if (argToken.type != TokenType::Argument)
9441 return InternalParseResult::runtimeError("Expected argument following " + token.token);
9442 auto result = valueRef->setValue(argToken.token);
9444 return InternalParseResult(result);
9445 if (result.value() == ParseResultType::ShortCircuitAll)
9446 return InternalParseResult::ok(ParseState(result.value(), remainingTokens));
9448 return InternalParseResult::ok(ParseState(ParseResultType::Matched, ++remainingTokens));
9451 return InternalParseResult::ok(ParseState(ParseResultType::NoMatch, remainingTokens));
9454 auto validate() const -> Result override
9456 if (m_optNames.empty())
9457 return Result::logicError("No options supplied to Opt");
9458 for (auto const& name : m_optNames) {
9460 return Result::logicError("Option name cannot be empty");
9461 #ifdef CATCH_PLATFORM_WINDOWS
9462 if (name[0] != '-' && name[0] != '/')
9463 return Result::logicError("Option name must begin with '-' or '/'");
9466 return Result::logicError("Option name must begin with '-'");
9469 return ParserRefImpl::validate();
9474 Help(bool& showHelpFlag)
9475 : Opt([&](bool flag) {
9476 showHelpFlag = flag;
9477 return ParserResult::ok(ParseResultType::ShortCircuitAll);
9480 static_cast<Opt&> (*this)("display usage information")["-?"]["-h"]["--help"].optional();
9484 struct Parser : ParserBase {
9486 mutable ExeName m_exeName;
9487 std::vector<Opt> m_options;
9488 std::vector<Arg> m_args;
9490 auto operator|=(ExeName const& exeName) -> Parser&
9492 m_exeName = exeName;
9496 auto operator|=(Arg const& arg) -> Parser&
9498 m_args.push_back(arg);
9502 auto operator|=(Opt const& opt) -> Parser&
9504 m_options.push_back(opt);
9508 auto operator|=(Parser const& other) -> Parser&
9510 m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
9511 m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
9515 template <typename T> auto operator|(T const& other) const -> Parser { return Parser(*this) |= other; }
9517 // Forward deprecated interface with '+' instead of '|'
9518 template <typename T> auto operator+=(T const& other) -> Parser& { return operator|=(other); }
9519 template <typename T> auto operator+(T const& other) const -> Parser { return operator|(other); }
9521 auto getHelpColumns() const -> std::vector<HelpColumns>
9523 std::vector<HelpColumns> cols;
9524 for (auto const& o : m_options) {
9525 auto childCols = o.getHelpColumns();
9526 cols.insert(cols.end(), childCols.begin(), childCols.end());
9531 void writeToStream(std::ostream& os) const
9533 if (!m_exeName.name().empty()) {
9535 << " " << m_exeName.name() << " ";
9536 bool required = true, first = true;
9537 for (auto const& arg : m_args) {
9542 if (arg.isOptional() && required) {
9546 os << "<" << arg.hint() << ">";
9547 if (arg.cardinality() == 0)
9552 if (!m_options.empty())
9554 os << "\n\nwhere options are:" << std::endl;
9557 auto rows = getHelpColumns();
9558 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
9559 size_t optWidth = 0;
9560 for (auto const& cols : rows)
9561 optWidth = (std::max)(optWidth, cols.left.size() + 2);
9563 optWidth = (std::min)(optWidth, consoleWidth / 2);
9565 for (auto const& cols : rows) {
9566 auto row = TextFlow::Column(cols.left).width(optWidth).indent(2) + TextFlow::Spacer(4) +
9567 TextFlow::Column(cols.right).width(consoleWidth - 7 - optWidth);
9568 os << row << std::endl;
9572 friend auto operator<<(std::ostream& os, Parser const& parser) -> std::ostream&
9574 parser.writeToStream(os);
9578 auto validate() const -> Result override
9580 for (auto const& opt : m_options) {
9581 auto result = opt.validate();
9585 for (auto const& arg : m_args) {
9586 auto result = arg.validate();
9590 return Result::ok();
9593 using ParserBase::parse;
9595 auto parse(std::string const& exeName, TokenStream const& tokens) const -> InternalParseResult override
9599 ParserBase const* parser = nullptr;
9602 const size_t totalParsers = m_options.size() + m_args.size();
9603 assert(totalParsers < 512);
9604 // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do
9605 ParserInfo parseInfos[512];
9609 for (auto const& opt : m_options)
9610 parseInfos[i++].parser = &opt;
9611 for (auto const& arg : m_args)
9612 parseInfos[i++].parser = &arg;
9615 m_exeName.set(exeName);
9617 auto result = InternalParseResult::ok(ParseState(ParseResultType::NoMatch, tokens));
9618 while (result.value().remainingTokens()) {
9619 bool tokenParsed = false;
9621 for (size_t i = 0; i < totalParsers; ++i) {
9622 auto& parseInfo = parseInfos[i];
9623 if (parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality()) {
9624 result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
9627 if (result.value().type() != ParseResultType::NoMatch) {
9635 if (result.value().type() == ParseResultType::ShortCircuitAll)
9638 return InternalParseResult::runtimeError("Unrecognised token: " + result.value().remainingTokens()->token);
9640 // !TBD Check missing required options
9645 template <typename DerivedT>
9646 template <typename T>
9647 auto ComposableParserImpl<DerivedT>::operator|(T const& other) const -> Parser
9649 return Parser() | static_cast<DerivedT const&>(*this) | other;
9651 } // namespace detail
9653 // A Combined parser
9654 using detail::Parser;
9656 // A parser for options
9659 // A parser for arguments
9662 // Wrapper for argc, argv from main()
9665 // Specifies the name of the executable
9666 using detail::ExeName;
9668 // Convenience wrapper for option parser that specifies the help option
9671 // enum of result types from a parse
9672 using detail::ParseResultType;
9674 // Result type for parser operation
9675 using detail::ParserResult;
9677 } // namespace clara
9678 } // namespace Catch
9682 #pragma clang diagnostic pop
9685 // Restore Clara's value for console width, if present
9686 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
9687 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
9688 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
9691 // end catch_clara.h
9694 clara::Parser makeCommandLineParser(ConfigData& config);
9696 } // end namespace Catch
9698 // end catch_commandline.h
9704 clara::Parser makeCommandLineParser(ConfigData& config)
9707 using namespace clara;
9709 auto const setWarning = [&](std::string const& warning) {
9710 auto warningSet = [&]() {
9711 if (warning == "NoAssertions")
9712 return WarnAbout::NoAssertions;
9714 if (warning == "NoTests")
9715 return WarnAbout::NoTests;
9717 return WarnAbout::Nothing;
9720 if (warningSet == WarnAbout::Nothing)
9721 return ParserResult::runtimeError("Unrecognised warning: '" + warning + "'");
9722 config.warnings = static_cast<WarnAbout::What>(config.warnings | warningSet);
9723 return ParserResult::ok(ParseResultType::Matched);
9725 auto const loadTestNamesFromFile = [&](std::string const& filename) {
9726 std::ifstream f(filename.c_str());
9728 return ParserResult::runtimeError("Unable to load input file: '" + filename + "'");
9731 while (std::getline(f, line)) {
9733 if (!line.empty() && !startsWith(line, '#')) {
9734 if (!startsWith(line, '"'))
9735 line = '"' + line + '"';
9736 config.testsOrTags.push_back(line);
9737 config.testsOrTags.emplace_back(",");
9740 // Remove comma in the end
9741 if (!config.testsOrTags.empty())
9742 config.testsOrTags.erase(config.testsOrTags.end() - 1);
9744 return ParserResult::ok(ParseResultType::Matched);
9746 auto const setTestOrder = [&](std::string const& order) {
9747 if (startsWith("declared", order))
9748 config.runOrder = RunTests::InDeclarationOrder;
9749 else if (startsWith("lexical", order))
9750 config.runOrder = RunTests::InLexicographicalOrder;
9751 else if (startsWith("random", order))
9752 config.runOrder = RunTests::InRandomOrder;
9754 return clara::ParserResult::runtimeError("Unrecognised ordering: '" + order + "'");
9755 return ParserResult::ok(ParseResultType::Matched);
9757 auto const setRngSeed = [&](std::string const& seed) {
9759 return clara::detail::convertInto(seed, config.rngSeed);
9760 config.rngSeed = static_cast<unsigned int>(std::time(nullptr));
9761 return ParserResult::ok(ParseResultType::Matched);
9763 auto const setColourUsage = [&](std::string const& useColour) {
9764 auto mode = toLower(useColour);
9767 config.useColour = UseColour::Yes;
9768 else if (mode == "no")
9769 config.useColour = UseColour::No;
9770 else if (mode == "auto")
9771 config.useColour = UseColour::Auto;
9773 return ParserResult::runtimeError("colour mode must be one of: auto, yes or no. '" + useColour +
9774 "' not recognised");
9775 return ParserResult::ok(ParseResultType::Matched);
9777 auto const setWaitForKeypress = [&](std::string const& keypress) {
9778 auto keypressLc = toLower(keypress);
9779 if (keypressLc == "never")
9780 config.waitForKeypress = WaitForKeypress::Never;
9781 else if (keypressLc == "start")
9782 config.waitForKeypress = WaitForKeypress::BeforeStart;
9783 else if (keypressLc == "exit")
9784 config.waitForKeypress = WaitForKeypress::BeforeExit;
9785 else if (keypressLc == "both")
9786 config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
9788 return ParserResult::runtimeError("keypress argument must be one of: never, start, exit or both. '" + keypress +
9789 "' not recognised");
9790 return ParserResult::ok(ParseResultType::Matched);
9792 auto const setVerbosity = [&](std::string const& verbosity) {
9793 auto lcVerbosity = toLower(verbosity);
9794 if (lcVerbosity == "quiet")
9795 config.verbosity = Verbosity::Quiet;
9796 else if (lcVerbosity == "normal")
9797 config.verbosity = Verbosity::Normal;
9798 else if (lcVerbosity == "high")
9799 config.verbosity = Verbosity::High;
9801 return ParserResult::runtimeError("Unrecognised verbosity, '" + verbosity + "'");
9802 return ParserResult::ok(ParseResultType::Matched);
9804 auto const setReporter = [&](std::string const& reporter) {
9805 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
9807 auto lcReporter = toLower(reporter);
9808 auto result = factories.find(lcReporter);
9810 if (factories.end() != result)
9811 config.reporterName = lcReporter;
9813 return ParserResult::runtimeError("Unrecognized reporter, '" + reporter +
9814 "'. Check available with --list-reporters");
9815 return ParserResult::ok(ParseResultType::Matched);
9819 ExeName(config.processName) | Help(config.showHelp) |
9820 Opt(config.listTests)["-l"]["--list-tests"]("list all/matching test cases") |
9821 Opt(config.listTags)["-t"]["--list-tags"]("list all/matching tags") |
9822 Opt(config.showSuccessfulTests)["-s"]["--success"]("include successful tests in output") |
9823 Opt(config.shouldDebugBreak)["-b"]["--break"]("break into debugger on failure") |
9824 Opt(config.noThrow)["-e"]["--nothrow"]("skip exception tests") |
9825 Opt(config.showInvisibles)["-i"]["--invisibles"]("show invisibles (tabs, newlines)") |
9826 Opt(config.outputFilename, "filename")["-o"]["--out"]("output filename") |
9827 Opt(setReporter, "name")["-r"]["--reporter"]("reporter to use (defaults to console)") |
9828 Opt(config.name, "name")["-n"]["--name"]("suite name") |
9829 Opt([&](bool) { config.abortAfter = 1; })["-a"]["--abort"]("abort at first failure") |
9830 Opt([&](int x) { config.abortAfter = x; }, "no. failures")["-x"]["--abortx"]("abort after x failures") |
9831 Opt(setWarning, "warning name")["-w"]["--warn"]("enable warnings") |
9832 Opt([&](bool flag) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; },
9833 "yes|no")["-d"]["--durations"]("show test durations") |
9834 Opt(config.minDuration, "seconds")["-D"]["--min-duration"](
9835 "show test durations for tests taking at least the given number of seconds") |
9836 Opt(loadTestNamesFromFile, "filename")["-f"]["--input-file"]("load test names to run from a file") |
9837 Opt(config.filenamesAsTags)["-#"]["--filenames-as-tags"]("adds a tag for the filename") |
9838 Opt(config.sectionsToRun, "section name")["-c"]["--section"]("specify section to run") |
9839 Opt(setVerbosity, "quiet|normal|high")["-v"]["--verbosity"]("set output verbosity") |
9840 Opt(config.listTestNamesOnly)["--list-test-names-only"]("list all/matching test cases names only") |
9841 Opt(config.listReporters)["--list-reporters"]("list all reporters") |
9842 Opt(setTestOrder, "decl|lex|rand")["--order"]("test case order (defaults to decl)") |
9843 Opt(setRngSeed, "'time'|number")["--rng-seed"]("set a specific seed for random numbers") |
9844 Opt(setColourUsage, "yes|no")["--use-colour"]("should output be colourised") |
9845 Opt(config.libIdentify)["--libidentify"]("report name and version according to libidentify standard") |
9846 Opt(setWaitForKeypress, "never|start|exit|both")["--wait-for-keypress"]("waits for a keypress before exiting") |
9847 Opt(config.benchmarkSamples, "samples")["--benchmark-samples"]("number of samples to collect (default: 100)") |
9848 Opt(config.benchmarkResamples,
9849 "resamples")["--benchmark-resamples"]("number of resamples for the bootstrap (default: 100000)") |
9850 Opt(config.benchmarkConfidenceInterval, "confidence interval")["--benchmark-confidence-interval"](
9851 "confidence interval for the bootstrap (between 0 and 1, default: 0.95)") |
9852 Opt(config.benchmarkNoAnalysis)["--benchmark-no-analysis"](
9853 "perform only measurements; do not perform any analysis") |
9854 Opt(config.benchmarkWarmupTime, "benchmarkWarmupTime")["--benchmark-warmup-time"](
9855 "amount of time in milliseconds spent on warming up each test (default: 100)") |
9856 Arg(config.testsOrTags, "test name|pattern|tags")("which test or tests to use");
9861 } // end namespace Catch
9862 // end catch_commandline.cpp
9863 // start catch_common.cpp
9870 bool SourceLineInfo::operator==(SourceLineInfo const& other) const noexcept
9872 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
9874 bool SourceLineInfo::operator<(SourceLineInfo const& other) const noexcept
9876 // We can assume that the same file will usually have the same pointer.
9877 // Thus, if the pointers are the same, there is no point in calling the strcmp
9878 return line < other.line || (line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));
9881 std::ostream& operator<<(std::ostream& os, SourceLineInfo const& info)
9884 os << info.file << '(' << info.line << ')';
9886 os << info.file << ':' << info.line;
9891 std::string StreamEndStop::operator+() const
9893 return std::string();
9896 NonCopyable::NonCopyable() = default;
9897 NonCopyable::~NonCopyable() = default;
9899 } // namespace Catch
9900 // end catch_common.cpp
9901 // start catch_config.cpp
9905 Config::Config(ConfigData const& data) : m_data(data), m_stream(openStream())
9907 // We need to trim filter specs to avoid trouble with superfluous
9908 // whitespace (esp. important for bdd macros, as those are manually
9909 // aligned with whitespace).
9911 for (auto& elem : m_data.testsOrTags) {
9914 for (auto& elem : m_data.sectionsToRun) {
9918 TestSpecParser parser(ITagAliasRegistry::get());
9919 if (!m_data.testsOrTags.empty()) {
9920 m_hasTestFilters = true;
9921 for (auto const& testOrTags : m_data.testsOrTags) {
9922 parser.parse(testOrTags);
9925 m_testSpec = parser.testSpec();
9928 std::string const& Config::getFilename() const
9930 return m_data.outputFilename;
9933 bool Config::listTests() const
9935 return m_data.listTests;
9937 bool Config::listTestNamesOnly() const
9939 return m_data.listTestNamesOnly;
9941 bool Config::listTags() const
9943 return m_data.listTags;
9945 bool Config::listReporters() const
9947 return m_data.listReporters;
9950 std::string Config::getProcessName() const
9952 return m_data.processName;
9954 std::string const& Config::getReporterName() const
9956 return m_data.reporterName;
9959 std::vector<std::string> const& Config::getTestsOrTags() const
9961 return m_data.testsOrTags;
9963 std::vector<std::string> const& Config::getSectionsToRun() const
9965 return m_data.sectionsToRun;
9968 TestSpec const& Config::testSpec() const
9972 bool Config::hasTestFilters() const
9974 return m_hasTestFilters;
9977 bool Config::showHelp() const
9979 return m_data.showHelp;
9982 // IConfig interface
9983 bool Config::allowThrows() const
9985 return !m_data.noThrow;
9987 std::ostream& Config::stream() const
9989 return m_stream->stream();
9991 std::string Config::name() const
9993 return m_data.name.empty() ? m_data.processName : m_data.name;
9995 bool Config::includeSuccessfulResults() const
9997 return m_data.showSuccessfulTests;
9999 bool Config::warnAboutMissingAssertions() const
10001 return !!(m_data.warnings & WarnAbout::NoAssertions);
10003 bool Config::warnAboutNoTests() const
10005 return !!(m_data.warnings & WarnAbout::NoTests);
10007 ShowDurations::OrNot Config::showDurations() const
10009 return m_data.showDurations;
10011 double Config::minDuration() const
10013 return m_data.minDuration;
10015 RunTests::InWhatOrder Config::runOrder() const
10017 return m_data.runOrder;
10019 unsigned int Config::rngSeed() const
10021 return m_data.rngSeed;
10023 UseColour::YesOrNo Config::useColour() const
10025 return m_data.useColour;
10027 bool Config::shouldDebugBreak() const
10029 return m_data.shouldDebugBreak;
10031 int Config::abortAfter() const
10033 return m_data.abortAfter;
10035 bool Config::showInvisibles() const
10037 return m_data.showInvisibles;
10039 Verbosity Config::verbosity() const
10041 return m_data.verbosity;
10044 bool Config::benchmarkNoAnalysis() const
10046 return m_data.benchmarkNoAnalysis;
10048 int Config::benchmarkSamples() const
10050 return m_data.benchmarkSamples;
10052 double Config::benchmarkConfidenceInterval() const
10054 return m_data.benchmarkConfidenceInterval;
10056 unsigned int Config::benchmarkResamples() const
10058 return m_data.benchmarkResamples;
10060 std::chrono::milliseconds Config::benchmarkWarmupTime() const
10062 return std::chrono::milliseconds(m_data.benchmarkWarmupTime);
10065 IStream const* Config::openStream()
10067 return Catch::makeStream(m_data.outputFilename);
10070 } // end namespace Catch
10071 // end catch_config.cpp
10072 // start catch_console_colour.cpp
10074 #if defined(__clang__)
10075 #pragma clang diagnostic push
10076 #pragma clang diagnostic ignored "-Wexit-time-destructors"
10079 // start catch_errno_guard.h
10092 } // namespace Catch
10094 // end catch_errno_guard.h
10095 // start catch_windows_h_proxy.h
10097 #if defined(CATCH_PLATFORM_WINDOWS)
10099 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
10100 #define CATCH_DEFINED_NOMINMAX
10103 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
10104 #define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
10105 #define WIN32_LEAN_AND_MEAN
10109 #include <AfxWin.h>
10111 #include <windows.h>
10114 #ifdef CATCH_DEFINED_NOMINMAX
10117 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
10118 #undef WIN32_LEAN_AND_MEAN
10121 #endif // defined(CATCH_PLATFORM_WINDOWS)
10123 // end catch_windows_h_proxy.h
10129 struct IColourImpl {
10130 virtual ~IColourImpl() = default;
10131 virtual void use(Colour::Code _colourCode) = 0;
10134 struct NoColourImpl : IColourImpl {
10135 void use(Colour::Code) override {}
10137 static IColourImpl* instance()
10139 static NoColourImpl s_instance;
10140 return &s_instance;
10145 } // namespace Catch
10147 #if !defined(CATCH_CONFIG_COLOUR_NONE) && !defined(CATCH_CONFIG_COLOUR_WINDOWS) && !defined(CATCH_CONFIG_COLOUR_ANSI)
10148 #ifdef CATCH_PLATFORM_WINDOWS
10149 #define CATCH_CONFIG_COLOUR_WINDOWS
10151 #define CATCH_CONFIG_COLOUR_ANSI
10155 #if defined(CATCH_CONFIG_COLOUR_WINDOWS) /////////////////////////////////////////
10160 class Win32ColourImpl : public IColourImpl {
10162 Win32ColourImpl() : stdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE))
10164 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
10165 GetConsoleScreenBufferInfo(stdoutHandle, &csbiInfo);
10166 originalForegroundAttributes =
10167 csbiInfo.wAttributes & ~(BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY);
10168 originalBackgroundAttributes =
10169 csbiInfo.wAttributes & ~(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
10172 void use(Colour::Code _colourCode) override
10174 switch (_colourCode) {
10176 return setTextAttribute(originalForegroundAttributes);
10177 case Colour::White:
10178 return setTextAttribute(FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE);
10180 return setTextAttribute(FOREGROUND_RED);
10181 case Colour::Green:
10182 return setTextAttribute(FOREGROUND_GREEN);
10184 return setTextAttribute(FOREGROUND_BLUE);
10186 return setTextAttribute(FOREGROUND_BLUE | FOREGROUND_GREEN);
10187 case Colour::Yellow:
10188 return setTextAttribute(FOREGROUND_RED | FOREGROUND_GREEN);
10190 return setTextAttribute(0);
10192 case Colour::LightGrey:
10193 return setTextAttribute(FOREGROUND_INTENSITY);
10194 case Colour::BrightRed:
10195 return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_RED);
10196 case Colour::BrightGreen:
10197 return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_GREEN);
10198 case Colour::BrightWhite:
10199 return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE);
10200 case Colour::BrightYellow:
10201 return setTextAttribute(FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN);
10203 case Colour::Bright:
10204 CATCH_INTERNAL_ERROR("not a colour");
10207 CATCH_ERROR("Unknown colour requested");
10212 void setTextAttribute(WORD _textAttribute)
10214 SetConsoleTextAttribute(stdoutHandle, _textAttribute | originalBackgroundAttributes);
10216 HANDLE stdoutHandle;
10217 WORD originalForegroundAttributes;
10218 WORD originalBackgroundAttributes;
10221 IColourImpl* platformColourInstance()
10223 static Win32ColourImpl s_instance;
10225 IConfigPtr config = getCurrentContext().getConfig();
10226 UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto;
10227 if (colourMode == UseColour::Auto)
10228 colourMode = UseColour::Yes;
10229 return colourMode == UseColour::Yes ? &s_instance : NoColourImpl::instance();
10233 } // end namespace Catch
10235 #elif defined(CATCH_CONFIG_COLOUR_ANSI) //////////////////////////////////////
10237 #include <unistd.h>
10242 // use POSIX/ ANSI console terminal codes
10243 // Thanks to Adam Strzelecki for original contribution
10244 // (http://github.com/nanoant)
10245 // https://github.com/philsquared/Catch/pull/131
10246 class PosixColourImpl : public IColourImpl {
10248 void use(Colour::Code _colourCode) override
10250 switch (_colourCode) {
10252 case Colour::White:
10253 return setColour("[0m");
10255 return setColour("[0;31m");
10256 case Colour::Green:
10257 return setColour("[0;32m");
10259 return setColour("[0;34m");
10261 return setColour("[0;36m");
10262 case Colour::Yellow:
10263 return setColour("[0;33m");
10265 return setColour("[1;30m");
10267 case Colour::LightGrey:
10268 return setColour("[0;37m");
10269 case Colour::BrightRed:
10270 return setColour("[1;31m");
10271 case Colour::BrightGreen:
10272 return setColour("[1;32m");
10273 case Colour::BrightWhite:
10274 return setColour("[1;37m");
10275 case Colour::BrightYellow:
10276 return setColour("[1;33m");
10278 case Colour::Bright:
10279 CATCH_INTERNAL_ERROR("not a colour");
10281 CATCH_INTERNAL_ERROR("Unknown colour requested");
10284 static IColourImpl* instance()
10286 static PosixColourImpl s_instance;
10287 return &s_instance;
10291 void setColour(const char* _escapeCode) { getCurrentContext().getConfig()->stream() << '\033' << _escapeCode; }
10294 bool useColourOnPlatform()
10297 #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
10298 !isDebuggerActive() &&
10300 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
10301 isatty(STDOUT_FILENO)
10307 IColourImpl* platformColourInstance()
10310 IConfigPtr config = getCurrentContext().getConfig();
10311 UseColour::YesOrNo colourMode = config ? config->useColour() : UseColour::Auto;
10312 if (colourMode == UseColour::Auto)
10313 colourMode = useColourOnPlatform() ? UseColour::Yes : UseColour::No;
10314 return colourMode == UseColour::Yes ? PosixColourImpl::instance() : NoColourImpl::instance();
10318 } // end namespace Catch
10320 #else // not Windows or ANSI ///////////////////////////////////////////////
10324 static IColourImpl* platformColourInstance()
10326 return NoColourImpl::instance();
10329 } // end namespace Catch
10331 #endif // Windows/ ANSI/ None
10335 Colour::Colour(Code _colourCode)
10339 Colour::Colour(Colour&& other) noexcept
10341 m_moved = other.m_moved;
10342 other.m_moved = true;
10344 Colour& Colour::operator=(Colour&& other) noexcept
10346 m_moved = other.m_moved;
10347 other.m_moved = true;
10357 void Colour::use(Code _colourCode)
10359 static IColourImpl* impl = platformColourInstance();
10360 // Strictly speaking, this cannot possibly happen.
10361 // However, under some conditions it does happen (see #1626),
10362 // and this change is small enough that we can let practicality
10363 // triumph over purity in this case.
10364 if (impl != nullptr) {
10365 impl->use(_colourCode);
10369 std::ostream& operator<<(std::ostream& os, Colour const&)
10374 } // end namespace Catch
10376 #if defined(__clang__)
10377 #pragma clang diagnostic pop
10380 // end catch_console_colour.cpp
10381 // start catch_context.cpp
10385 class Context : public IMutableContext, NonCopyable {
10387 public: // IContext
10388 IResultCapture* getResultCapture() override { return m_resultCapture; }
10389 IRunner* getRunner() override { return m_runner; }
10391 IConfigPtr const& getConfig() const override { return m_config; }
10393 ~Context() override;
10395 public: // IMutableContext
10396 void setResultCapture(IResultCapture* resultCapture) override { m_resultCapture = resultCapture; }
10397 void setRunner(IRunner* runner) override { m_runner = runner; }
10398 void setConfig(IConfigPtr const& config) override { m_config = config; }
10400 friend IMutableContext& getCurrentMutableContext();
10403 IConfigPtr m_config;
10404 IRunner* m_runner = nullptr;
10405 IResultCapture* m_resultCapture = nullptr;
10408 IMutableContext* IMutableContext::currentContext = nullptr;
10410 void IMutableContext::createContext()
10412 currentContext = new Context();
10415 void cleanUpContext()
10417 delete IMutableContext::currentContext;
10418 IMutableContext::currentContext = nullptr;
10420 IContext::~IContext() = default;
10421 IMutableContext::~IMutableContext() = default;
10422 Context::~Context() = default;
10426 static SimplePcg32 s_rng;
10430 } // namespace Catch
10431 // end catch_context.cpp
10432 // start catch_debug_console.cpp
10434 // start catch_debug_console.h
10439 void writeToDebugConsole(std::string const& text);
10442 // end catch_debug_console.h
10443 #if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
10444 #include <android/log.h>
10447 void writeToDebugConsole(std::string const& text)
10449 __android_log_write(ANDROID_LOG_DEBUG, "Catch", text.c_str());
10451 } // namespace Catch
10453 #elif defined(CATCH_PLATFORM_WINDOWS)
10456 void writeToDebugConsole(std::string const& text)
10458 ::OutputDebugStringA(text.c_str());
10460 } // namespace Catch
10465 void writeToDebugConsole(std::string const& text)
10467 // !TBD: Need a version for Mac/ XCode and other IDEs
10468 Catch::cout() << text;
10470 } // namespace Catch
10473 // end catch_debug_console.cpp
10474 // start catch_debugger.cpp
10476 #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
10481 #include <sys/types.h>
10482 #include <unistd.h>
10484 #ifdef __apple_build_version__
10485 // These headers will only compile with AppleClang (XCode)
10486 // For other compilers (Clang, GCC, ... ) we need to exclude them
10487 #include <sys/sysctl.h>
10491 #ifdef __apple_build_version__
10492 // The following function is taken directly from the following technical note:
10493 // https://developer.apple.com/library/archive/qa/qa1361/_index.html
10495 // Returns true if the current process is being debugged (either
10496 // running under the debugger or has a debugger attached post facto).
10497 bool isDebuggerActive()
10500 struct kinfo_proc info;
10503 // Initialize the flags so that, if sysctl fails for some bizarre
10504 // reason, we get a predictable result.
10506 info.kp_proc.p_flag = 0;
10508 // Initialize mib, which tells sysctl the info we want, in this case
10509 // we're looking for information about a specific process ID.
10512 mib[1] = KERN_PROC;
10513 mib[2] = KERN_PROC_PID;
10518 size = sizeof(info);
10519 if (sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0) {
10520 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
10524 // We're being debugged if the P_TRACED flag is set.
10526 return ((info.kp_proc.p_flag & P_TRACED) != 0);
10529 bool isDebuggerActive()
10531 // We need to find another way to determine this for non-appleclang compilers on macOS
10535 } // namespace Catch
10537 #elif defined(CATCH_PLATFORM_LINUX)
10542 // The standard POSIX way of detecting a debugger is to attempt to
10543 // ptrace() the process, but this needs to be done from a child and not
10544 // this process itself to still allow attaching to this process later
10545 // if wanted, so is rather heavy. Under Linux we have the PID of the
10546 // "debugger" (which doesn't need to be gdb, of course, it could also
10547 // be strace, for example) in /proc/$PID/status, so just get it from
10549 bool isDebuggerActive()
10551 // Libstdc++ has a bug, where std::ifstream sets errno to 0
10552 // This way our users can properly assert over errno values
10554 std::ifstream in("/proc/self/status");
10555 for (std::string line; std::getline(in, line);) {
10556 static const int PREFIX_LEN = 11;
10557 if (line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0) {
10558 // We're traced if the PID is not 0 and no other PID starts
10559 // with 0 digit, so it's enough to check for just a single
10561 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
10567 } // namespace Catch
10568 #elif defined(_MSC_VER)
10569 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
10571 bool isDebuggerActive()
10573 return IsDebuggerPresent() != 0;
10575 } // namespace Catch
10576 #elif defined(__MINGW32__)
10577 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
10579 bool isDebuggerActive()
10581 return IsDebuggerPresent() != 0;
10583 } // namespace Catch
10586 bool isDebuggerActive()
10590 } // namespace Catch
10592 // end catch_debugger.cpp
10593 // start catch_decomposer.cpp
10597 ITransientExpression::~ITransientExpression() = default;
10599 void formatReconstructedExpression(std::ostream& os, std::string const& lhs, StringRef op, std::string const& rhs)
10601 if (lhs.size() + rhs.size() < 40 && lhs.find('\n') == std::string::npos && rhs.find('\n') == std::string::npos)
10602 os << lhs << " " << op << " " << rhs;
10604 os << lhs << "\n" << op << "\n" << rhs;
10606 } // namespace Catch
10607 // end catch_decomposer.cpp
10608 // start catch_enforce.cpp
10610 #include <stdexcept>
10613 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
10614 [[noreturn]] void throw_exception(std::exception const& e)
10616 Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"
10617 << "The message was: " << e.what() << '\n';
10622 [[noreturn]] void throw_logic_error(std::string const& msg)
10624 throw_exception(std::logic_error(msg));
10627 [[noreturn]] void throw_domain_error(std::string const& msg)
10629 throw_exception(std::domain_error(msg));
10632 [[noreturn]] void throw_runtime_error(std::string const& msg)
10634 throw_exception(std::runtime_error(msg));
10637 } // namespace Catch
10638 // end catch_enforce.cpp
10639 // start catch_enum_values_registry.cpp
10640 // start catch_enum_values_registry.h
10649 std::unique_ptr<EnumInfo> makeEnumInfo(StringRef enumName, StringRef allValueNames, std::vector<int> const& values);
10651 class EnumValuesRegistry : public IMutableEnumValuesRegistry {
10653 std::vector<std::unique_ptr<EnumInfo>> m_enumInfos;
10655 EnumInfo const& registerEnum(StringRef enumName, StringRef allEnums, std::vector<int> const& values) override;
10658 std::vector<StringRef> parseEnums(StringRef enums);
10660 } // namespace Detail
10662 } // namespace Catch
10664 // end catch_enum_values_registry.h
10671 IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {}
10676 // Extracts the actual name part of an enum instance
10677 // In other words, it returns the Blue part of Bikeshed::Colour::Blue
10678 StringRef extractInstanceName(StringRef enumInstance)
10680 // Find last occurrence of ":"
10681 size_t name_start = enumInstance.size();
10682 while (name_start > 0 && enumInstance[name_start - 1] != ':') {
10685 return enumInstance.substr(name_start, enumInstance.size() - name_start);
10689 std::vector<StringRef> parseEnums(StringRef enums)
10691 auto enumValues = splitStringRef(enums, ',');
10692 std::vector<StringRef> parsed;
10693 parsed.reserve(enumValues.size());
10694 for (auto const& enumValue : enumValues) {
10695 parsed.push_back(trim(extractInstanceName(enumValue)));
10700 EnumInfo::~EnumInfo() {}
10702 StringRef EnumInfo::lookup(int value) const
10704 for (auto const& valueToName : m_values) {
10705 if (valueToName.first == value)
10706 return valueToName.second;
10708 return "{** unexpected enum value **}"_sr;
10711 std::unique_ptr<EnumInfo> makeEnumInfo(StringRef enumName, StringRef allValueNames, std::vector<int> const& values)
10713 std::unique_ptr<EnumInfo> enumInfo(new EnumInfo);
10714 enumInfo->m_name = enumName;
10715 enumInfo->m_values.reserve(values.size());
10717 const auto valueNames = Catch::Detail::parseEnums(allValueNames);
10718 assert(valueNames.size() == values.size());
10720 for (auto value : values)
10721 enumInfo->m_values.emplace_back(value, valueNames[i++]);
10726 EnumInfo const& EnumValuesRegistry::registerEnum(StringRef enumName, StringRef allValueNames,
10727 std::vector<int> const& values)
10729 m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
10730 return *m_enumInfos.back();
10733 } // namespace Detail
10734 } // namespace Catch
10736 // end catch_enum_values_registry.cpp
10737 // start catch_errno_guard.cpp
10742 ErrnoGuard::ErrnoGuard() : m_oldErrno(errno) {}
10743 ErrnoGuard::~ErrnoGuard()
10745 errno = m_oldErrno;
10747 } // namespace Catch
10748 // end catch_errno_guard.cpp
10749 // start catch_exception_translator_registry.cpp
10751 // start catch_exception_translator_registry.h
10759 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
10761 ~ExceptionTranslatorRegistry();
10762 virtual void registerTranslator(const IExceptionTranslator* translator);
10763 std::string translateActiveException() const override;
10764 std::string tryTranslators() const;
10767 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
10769 } // namespace Catch
10771 // end catch_exception_translator_registry.h
10773 #import "Foundation/Foundation.h"
10778 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {}
10780 void ExceptionTranslatorRegistry::registerTranslator(const IExceptionTranslator* translator)
10782 m_translators.push_back(std::unique_ptr<const IExceptionTranslator>(translator));
10785 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
10786 std::string ExceptionTranslatorRegistry::translateActiveException() const
10790 // In Objective-C try objective-c exceptions first
10792 return tryTranslators();
10793 } @catch (NSException* exception) {
10794 return Catch::Detail::stringify([exception description]);
10797 // Compiling a mixed mode project with MSVC means that CLR
10798 // exceptions will be caught in (...) as well. However, these
10799 // do not fill-in std::current_exception and thus lead to crash
10800 // when attempting rethrow.
10801 // /EHa switch also causes structured exceptions to be caught
10802 // here, but they fill-in current_exception properly, so
10803 // at worst the output should be a little weird, instead of
10804 // causing a crash.
10805 if (std::current_exception() == nullptr) {
10806 return "Non C++ exception. Possibly a CLR exception.";
10808 return tryTranslators();
10810 } catch (TestFailureException&) {
10811 std::rethrow_exception(std::current_exception());
10812 } catch (std::exception& ex) {
10814 } catch (std::string& msg) {
10816 } catch (const char* msg) {
10819 return "Unknown exception";
10823 std::string ExceptionTranslatorRegistry::tryTranslators() const
10825 if (m_translators.empty()) {
10826 std::rethrow_exception(std::current_exception());
10828 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
10832 #else // ^^ Exceptions are enabled // Exceptions are disabled vv
10833 std::string ExceptionTranslatorRegistry::translateActiveException() const
10835 CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
10838 std::string ExceptionTranslatorRegistry::tryTranslators() const
10840 CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
10844 } // namespace Catch
10845 // end catch_exception_translator_registry.cpp
10846 // start catch_fatal_condition.cpp
10848 #include <algorithm>
10850 #if !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
10854 // If neither SEH nor signal handling is required, the handler impls
10855 // do not have to do anything, and can be empty.
10856 FatalConditionHandler::engage_platform() {}
10857 FatalConditionHandler::disengage_platform() {}
10858 FatalConditionHandler::FatalConditionHandler() = default;
10859 FatalConditionHandler::~FatalConditionHandler() = default;
10861 } // end namespace Catch
10863 #endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS
10865 #if defined(CATCH_CONFIG_WINDOWS_SEH) && defined(CATCH_CONFIG_POSIX_SIGNALS)
10866 #error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"
10867 #endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS
10869 #if defined(CATCH_CONFIG_WINDOWS_SEH) || defined(CATCH_CONFIG_POSIX_SIGNALS)
10872 //! Signals fatal error message to the run context
10873 void reportFatal(char const* const message)
10875 Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition(message);
10878 //! Minimal size Catch2 needs for its own fatal error handling.
10879 //! Picked anecdotally, so it might not be sufficient on all
10880 //! platforms, and for all configurations.
10881 constexpr std::size_t minStackSizeForErrors = 32 * 1024;
10882 } // end unnamed namespace
10884 #endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS
10886 #if defined(CATCH_CONFIG_WINDOWS_SEH)
10890 struct SignalDefs {
10895 // There is no 1-1 mapping between signals and windows exceptions.
10896 // Windows can easily distinguish between SO and SigSegV,
10897 // but SigInt, SigTerm, etc are handled differently.
10898 static SignalDefs signalDefs[] = {
10899 {static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal"},
10900 {static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow"},
10901 {static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal"},
10902 {static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error"},
10905 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo)
10907 for (auto const& def : signalDefs) {
10908 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
10909 reportFatal(def.name);
10912 // If its not an exception we care about, pass it along.
10913 // This stops us from eating debugger breaks etc.
10914 return EXCEPTION_CONTINUE_SEARCH;
10917 // Since we do not support multiple instantiations, we put these
10918 // into global variables and rely on cleaning them up in outlined
10919 // constructors/destructors
10920 static PVOID exceptionHandlerHandle = nullptr;
10922 // For MSVC, we reserve part of the stack memory for handling
10923 // memory overflow structured exception.
10924 FatalConditionHandler::FatalConditionHandler()
10926 ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);
10927 if (!SetThreadStackGuarantee(&guaranteeSize)) {
10928 // We do not want to fully error out, because needing
10929 // the stack reserve should be rare enough anyway.
10930 Catch::cerr() << "Failed to reserve piece of stack."
10931 << " Stack overflows will not be reported successfully.";
10935 // We do not attempt to unset the stack guarantee, because
10936 // Windows does not support lowering the stack size guarantee.
10937 FatalConditionHandler::~FatalConditionHandler() = default;
10939 void FatalConditionHandler::engage_platform()
10941 // Register as first handler in current chain
10942 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
10943 if (!exceptionHandlerHandle) {
10944 CATCH_RUNTIME_ERROR("Could not register vectored exception handler");
10948 void FatalConditionHandler::disengage_platform()
10950 if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {
10951 CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler");
10953 exceptionHandlerHandle = nullptr;
10956 } // end namespace Catch
10958 #endif // CATCH_CONFIG_WINDOWS_SEH
10960 #if defined(CATCH_CONFIG_POSIX_SIGNALS)
10962 #include <signal.h>
10966 struct SignalDefs {
10971 static SignalDefs signalDefs[] = {
10972 {SIGINT, "SIGINT - Terminal interrupt signal"}, {SIGILL, "SIGILL - Illegal instruction signal"},
10973 {SIGFPE, "SIGFPE - Floating point error signal"}, {SIGSEGV, "SIGSEGV - Segmentation violation signal"},
10974 {SIGTERM, "SIGTERM - Termination request signal"}, {SIGABRT, "SIGABRT - Abort (abnormal termination) signal"}};
10976 // Older GCCs trigger -Wmissing-field-initializers for T foo = {}
10977 // which is zero initialization, but not explicit. We want to avoid
10979 #if defined(__GNUC__)
10980 #pragma GCC diagnostic push
10981 #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
10984 static char* altStackMem = nullptr;
10985 static std::size_t altStackSize = 0;
10986 static stack_t oldSigStack{};
10987 static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};
10989 static void restorePreviousSignalHandlers()
10991 // We set signal handlers back to the previous ones. Hopefully
10992 // nobody overwrote them in the meantime, and doesn't expect
10993 // their signal handlers to live past ours given that they
10994 // installed them after ours..
10995 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
10996 sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
10998 // Return the old stack
10999 sigaltstack(&oldSigStack, nullptr);
11002 static void handleSignal(int sig)
11004 char const* name = "<unknown signal>";
11005 for (auto const& def : signalDefs) {
11006 if (sig == def.id) {
11011 // We need to restore previous signal handlers and let them do
11012 // their thing, so that the users can have the debugger break
11013 // when a signal is raised, and so on.
11014 restorePreviousSignalHandlers();
11019 FatalConditionHandler::FatalConditionHandler()
11021 assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");
11022 if (altStackSize == 0) {
11023 altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);
11025 altStackMem = new char[altStackSize]();
11028 FatalConditionHandler::~FatalConditionHandler()
11030 delete[] altStackMem;
11031 // We signal that another instance can be constructed by zeroing
11032 // out the pointer.
11033 altStackMem = nullptr;
11036 void FatalConditionHandler::engage_platform()
11039 sigStack.ss_sp = altStackMem;
11040 sigStack.ss_size = altStackSize;
11041 sigStack.ss_flags = 0;
11042 sigaltstack(&sigStack, &oldSigStack);
11043 struct sigaction sa = {};
11045 sa.sa_handler = handleSignal;
11046 sa.sa_flags = SA_ONSTACK;
11047 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
11048 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
11052 #if defined(__GNUC__)
11053 #pragma GCC diagnostic pop
11056 void FatalConditionHandler::disengage_platform()
11058 restorePreviousSignalHandlers();
11061 } // end namespace Catch
11063 #endif // CATCH_CONFIG_POSIX_SIGNALS
11064 // end catch_fatal_condition.cpp
11065 // start catch_generators.cpp
11072 IGeneratorTracker::~IGeneratorTracker() {}
11074 const char* GeneratorException::what() const noexcept
11079 namespace Generators {
11081 GeneratorUntypedBase::~GeneratorUntypedBase() {}
11083 auto acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo) -> IGeneratorTracker&
11085 return getResultCapture().acquireGeneratorTracker(generatorName, lineInfo);
11088 } // namespace Generators
11089 } // namespace Catch
11090 // end catch_generators.cpp
11091 // start catch_interfaces_capture.cpp
11094 IResultCapture::~IResultCapture() = default;
11096 // end catch_interfaces_capture.cpp
11097 // start catch_interfaces_config.cpp
11100 IConfig::~IConfig() = default;
11102 // end catch_interfaces_config.cpp
11103 // start catch_interfaces_exception.cpp
11106 IExceptionTranslator::~IExceptionTranslator() = default;
11107 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;
11108 } // namespace Catch
11109 // end catch_interfaces_exception.cpp
11110 // start catch_interfaces_registry_hub.cpp
11113 IRegistryHub::~IRegistryHub() = default;
11114 IMutableRegistryHub::~IMutableRegistryHub() = default;
11115 } // namespace Catch
11116 // end catch_interfaces_registry_hub.cpp
11117 // start catch_interfaces_reporter.cpp
11119 // start catch_reporter_listening.h
11123 class ListeningReporter : public IStreamingReporter {
11124 using Reporters = std::vector<IStreamingReporterPtr>;
11125 Reporters m_listeners;
11126 IStreamingReporterPtr m_reporter = nullptr;
11127 ReporterPreferences m_preferences;
11130 ListeningReporter();
11132 void addListener(IStreamingReporterPtr&& listener);
11133 void addReporter(IStreamingReporterPtr&& reporter);
11135 public: // IStreamingReporter
11136 ReporterPreferences getPreferences() const override;
11138 void noMatchingTestCases(std::string const& spec) override;
11140 void reportInvalidArguments(std::string const& arg) override;
11142 static std::set<Verbosity> getSupportedVerbosities();
11144 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
11145 void benchmarkPreparing(std::string const& name) override;
11146 void benchmarkStarting(BenchmarkInfo const& benchmarkInfo) override;
11147 void benchmarkEnded(BenchmarkStats<> const& benchmarkStats) override;
11148 void benchmarkFailed(std::string const&) override;
11149 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
11151 void testRunStarting(TestRunInfo const& testRunInfo) override;
11152 void testGroupStarting(GroupInfo const& groupInfo) override;
11153 void testCaseStarting(TestCaseInfo const& testInfo) override;
11154 void sectionStarting(SectionInfo const& sectionInfo) override;
11155 void assertionStarting(AssertionInfo const& assertionInfo) override;
11157 // The return value indicates if the messages buffer should be cleared:
11158 bool assertionEnded(AssertionStats const& assertionStats) override;
11159 void sectionEnded(SectionStats const& sectionStats) override;
11160 void testCaseEnded(TestCaseStats const& testCaseStats) override;
11161 void testGroupEnded(TestGroupStats const& testGroupStats) override;
11162 void testRunEnded(TestRunStats const& testRunStats) override;
11164 void skipTest(TestCaseInfo const& testInfo) override;
11165 bool isMulti() const override;
11168 } // end namespace Catch
11170 // end catch_reporter_listening.h
11173 ReporterConfig::ReporterConfig(IConfigPtr const& _fullConfig)
11174 : m_stream(&_fullConfig->stream()), m_fullConfig(_fullConfig)
11178 ReporterConfig::ReporterConfig(IConfigPtr const& _fullConfig, std::ostream& _stream)
11179 : m_stream(&_stream), m_fullConfig(_fullConfig)
11183 std::ostream& ReporterConfig::stream() const
11187 IConfigPtr ReporterConfig::fullConfig() const
11189 return m_fullConfig;
11192 TestRunInfo::TestRunInfo(std::string const& _name) : name(_name) {}
11194 GroupInfo::GroupInfo(std::string const& _name, std::size_t _groupIndex, std::size_t _groupsCount)
11195 : name(_name), groupIndex(_groupIndex), groupsCounts(_groupsCount)
11199 AssertionStats::AssertionStats(AssertionResult const& _assertionResult, std::vector<MessageInfo> const& _infoMessages,
11200 Totals const& _totals)
11201 : assertionResult(_assertionResult), infoMessages(_infoMessages), totals(_totals)
11203 assertionResult.m_resultData.lazyExpression.m_transientExpression =
11204 _assertionResult.m_resultData.lazyExpression.m_transientExpression;
11206 if (assertionResult.hasMessage()) {
11207 // Copy message into messages list.
11208 // !TBD This should have been done earlier, somewhere
11209 MessageBuilder builder(assertionResult.getTestMacroName(), assertionResult.getSourceInfo(),
11210 assertionResult.getResultType());
11211 builder << assertionResult.getMessage();
11212 builder.m_info.message = builder.m_stream.str();
11214 infoMessages.push_back(builder.m_info);
11218 AssertionStats::~AssertionStats() = default;
11220 SectionStats::SectionStats(SectionInfo const& _sectionInfo, Counts const& _assertions, double _durationInSeconds,
11221 bool _missingAssertions)
11222 : sectionInfo(_sectionInfo)
11223 , assertions(_assertions)
11224 , durationInSeconds(_durationInSeconds)
11225 , missingAssertions(_missingAssertions)
11229 SectionStats::~SectionStats() = default;
11231 TestCaseStats::TestCaseStats(TestCaseInfo const& _testInfo, Totals const& _totals, std::string const& _stdOut,
11232 std::string const& _stdErr, bool _aborting)
11233 : testInfo(_testInfo), totals(_totals), stdOut(_stdOut), stdErr(_stdErr), aborting(_aborting)
11237 TestCaseStats::~TestCaseStats() = default;
11239 TestGroupStats::TestGroupStats(GroupInfo const& _groupInfo, Totals const& _totals, bool _aborting)
11240 : groupInfo(_groupInfo), totals(_totals), aborting(_aborting)
11244 TestGroupStats::TestGroupStats(GroupInfo const& _groupInfo) : groupInfo(_groupInfo), aborting(false) {}
11246 TestGroupStats::~TestGroupStats() = default;
11248 TestRunStats::TestRunStats(TestRunInfo const& _runInfo, Totals const& _totals, bool _aborting)
11249 : runInfo(_runInfo), totals(_totals), aborting(_aborting)
11253 TestRunStats::~TestRunStats() = default;
11255 void IStreamingReporter::fatalErrorEncountered(StringRef) {}
11256 bool IStreamingReporter::isMulti() const
11261 IReporterFactory::~IReporterFactory() = default;
11262 IReporterRegistry::~IReporterRegistry() = default;
11264 } // end namespace Catch
11265 // end catch_interfaces_reporter.cpp
11266 // start catch_interfaces_runner.cpp
11269 IRunner::~IRunner() = default;
11271 // end catch_interfaces_runner.cpp
11272 // start catch_interfaces_testcase.cpp
11275 ITestInvoker::~ITestInvoker() = default;
11276 ITestCaseRegistry::~ITestCaseRegistry() = default;
11277 } // namespace Catch
11278 // end catch_interfaces_testcase.cpp
11279 // start catch_leak_detector.cpp
11281 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG
11282 #include <crtdbg.h>
11286 LeakDetector::LeakDetector()
11288 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
11289 flag |= _CRTDBG_LEAK_CHECK_DF;
11290 flag |= _CRTDBG_ALLOC_MEM_DF;
11291 _CrtSetDbgFlag(flag);
11292 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
11293 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
11294 // Change this to leaking allocation's number to break there
11295 _CrtSetBreakAlloc(-1);
11297 } // namespace Catch
11301 Catch::LeakDetector::LeakDetector() {}
11305 Catch::LeakDetector::~LeakDetector()
11309 // end catch_leak_detector.cpp
11310 // start catch_list.cpp
11312 // start catch_list.h
11318 std::size_t listTests(Config const& config);
11320 std::size_t listTestsNamesOnly(Config const& config);
11323 void add(std::string const& spelling);
11324 std::string all() const;
11326 std::set<std::string> spellings;
11327 std::size_t count = 0;
11330 std::size_t listTags(Config const& config);
11332 std::size_t listReporters();
11334 Option<std::size_t> list(std::shared_ptr<Config> const& config);
11336 } // end namespace Catch
11338 // end catch_list.h
11339 // start catch_text.h
11342 using namespace clara::TextFlow;
11345 // end catch_text.h
11346 #include <algorithm>
11352 std::size_t listTests(Config const& config)
11354 TestSpec const& testSpec = config.testSpec();
11355 if (config.hasTestFilters())
11356 Catch::cout() << "Matching test cases:\n";
11358 Catch::cout() << "All available test cases:\n";
11361 auto matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
11362 for (auto const& testCaseInfo : matchedTestCases) {
11363 Colour::Code colour = testCaseInfo.isHidden() ? Colour::SecondaryText : Colour::None;
11364 Colour colourGuard(colour);
11366 Catch::cout() << Column(testCaseInfo.name).initialIndent(2).indent(4) << "\n";
11367 if (config.verbosity() >= Verbosity::High) {
11368 Catch::cout() << Column(Catch::Detail::stringify(testCaseInfo.lineInfo)).indent(4) << std::endl;
11369 std::string description = testCaseInfo.description;
11370 if (description.empty())
11371 description = "(NO DESCRIPTION)";
11372 Catch::cout() << Column(description).indent(4) << std::endl;
11374 if (!testCaseInfo.tags.empty())
11375 Catch::cout() << Column(testCaseInfo.tagsAsString()).indent(6) << "\n";
11378 if (!config.hasTestFilters())
11379 Catch::cout() << pluralise(matchedTestCases.size(), "test case") << '\n' << std::endl;
11381 Catch::cout() << pluralise(matchedTestCases.size(), "matching test case") << '\n' << std::endl;
11382 return matchedTestCases.size();
11385 std::size_t listTestsNamesOnly(Config const& config)
11387 TestSpec const& testSpec = config.testSpec();
11388 std::size_t matchedTests = 0;
11389 std::vector<TestCase> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
11390 for (auto const& testCaseInfo : matchedTestCases) {
11392 if (startsWith(testCaseInfo.name, '#'))
11393 Catch::cout() << '"' << testCaseInfo.name << '"';
11395 Catch::cout() << testCaseInfo.name;
11396 if (config.verbosity() >= Verbosity::High)
11397 Catch::cout() << "\t@" << testCaseInfo.lineInfo;
11398 Catch::cout() << std::endl;
11400 return matchedTests;
11403 void TagInfo::add(std::string const& spelling)
11406 spellings.insert(spelling);
11409 std::string TagInfo::all() const
11412 for (auto const& spelling : spellings) {
11413 // Add 2 for the brackes
11414 size += spelling.size() + 2;
11419 for (auto const& spelling : spellings) {
11427 std::size_t listTags(Config const& config)
11429 TestSpec const& testSpec = config.testSpec();
11430 if (config.hasTestFilters())
11431 Catch::cout() << "Tags for matching test cases:\n";
11433 Catch::cout() << "All available tags:\n";
11436 std::map<std::string, TagInfo> tagCounts;
11438 std::vector<TestCase> matchedTestCases = filterTests(getAllTestCasesSorted(config), testSpec, config);
11439 for (auto const& testCase : matchedTestCases) {
11440 for (auto const& tagName : testCase.getTestCaseInfo().tags) {
11441 std::string lcaseTagName = toLower(tagName);
11442 auto countIt = tagCounts.find(lcaseTagName);
11443 if (countIt == tagCounts.end())
11444 countIt = tagCounts.insert(std::make_pair(lcaseTagName, TagInfo())).first;
11445 countIt->second.add(tagName);
11449 for (auto const& tagCount : tagCounts) {
11450 ReusableStringStream rss;
11451 rss << " " << std::setw(2) << tagCount.second.count << " ";
11452 auto str = rss.str();
11454 Column(tagCount.second.all()).initialIndent(0).indent(str.size()).width(CATCH_CONFIG_CONSOLE_WIDTH - 10);
11455 Catch::cout() << str << wrapper << '\n';
11457 Catch::cout() << pluralise(tagCounts.size(), "tag") << '\n' << std::endl;
11458 return tagCounts.size();
11461 std::size_t listReporters()
11463 Catch::cout() << "Available reporters:\n";
11464 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
11465 std::size_t maxNameLen = 0;
11466 for (auto const& factoryKvp : factories)
11467 maxNameLen = (std::max)(maxNameLen, factoryKvp.first.size());
11469 for (auto const& factoryKvp : factories) {
11470 Catch::cout() << Column(factoryKvp.first + ":").indent(2).width(5 + maxNameLen) +
11471 Column(factoryKvp.second->getDescription())
11474 .width(CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8)
11477 Catch::cout() << std::endl;
11478 return factories.size();
11481 Option<std::size_t> list(std::shared_ptr<Config> const& config)
11483 Option<std::size_t> listedCount;
11484 getCurrentMutableContext().setConfig(config);
11485 if (config->listTests())
11486 listedCount = listedCount.valueOr(0) + listTests(*config);
11487 if (config->listTestNamesOnly())
11488 listedCount = listedCount.valueOr(0) + listTestsNamesOnly(*config);
11489 if (config->listTags())
11490 listedCount = listedCount.valueOr(0) + listTags(*config);
11491 if (config->listReporters())
11492 listedCount = listedCount.valueOr(0) + listReporters();
11493 return listedCount;
11496 } // end namespace Catch
11497 // end catch_list.cpp
11498 // start catch_matchers.cpp
11501 namespace Matchers {
11504 std::string MatcherUntypedBase::toString() const
11506 if (m_cachedToString.empty())
11507 m_cachedToString = describe();
11508 return m_cachedToString;
11511 MatcherUntypedBase::~MatcherUntypedBase() = default;
11513 } // namespace Impl
11514 } // namespace Matchers
11516 using namespace Matchers;
11517 using Matchers::Impl::MatcherBase;
11519 } // namespace Catch
11520 // end catch_matchers.cpp
11521 // start catch_matchers_exception.cpp
11524 namespace Matchers {
11525 namespace Exception {
11527 bool ExceptionMessageMatcher::match(std::exception const& ex) const
11529 return ex.what() == m_message;
11532 std::string ExceptionMessageMatcher::describe() const
11534 return "exception message matches \"" + m_message + "\"";
11537 } // namespace Exception
11538 Exception::ExceptionMessageMatcher Message(std::string const& message)
11540 return Exception::ExceptionMessageMatcher(message);
11543 // namespace Exception
11544 } // namespace Matchers
11545 } // namespace Catch
11546 // end catch_matchers_exception.cpp
11547 // start catch_matchers_floating.cpp
11549 // start catch_polyfills.hpp
11552 bool isnan(float f);
11553 bool isnan(double d);
11554 } // namespace Catch
11556 // end catch_polyfills.hpp
11557 // start catch_to_string.hpp
11562 template <typename T> std::string to_string(T const& t)
11564 #if defined(CATCH_CONFIG_CPP11_TO_STRING)
11565 return std::to_string(t);
11567 ReusableStringStream rss;
11572 } // end namespace Catch
11574 // end catch_to_string.hpp
11575 #include <algorithm>
11583 #include <type_traits>
11588 int32_t convert(float f)
11590 static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
11592 std::memcpy(&i, &f, sizeof(f));
11596 int64_t convert(double d)
11598 static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");
11600 std::memcpy(&i, &d, sizeof(d));
11604 template <typename FP> bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff)
11606 // Comparison with NaN should always be false.
11607 // This way we can rule it out before getting into the ugly details
11608 if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
11612 auto lc = convert(lhs);
11613 auto rc = convert(rhs);
11615 if ((lc < 0) != (rc < 0)) {
11616 // Potentially we can have +0 and -0
11620 // static cast as a workaround for IBM XLC
11621 auto ulpDiff = std::abs(static_cast<FP>(lc - rc));
11622 return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
11625 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
11627 float nextafter(float x, float y)
11629 return ::nextafterf(x, y);
11632 double nextafter(double x, double y)
11634 return ::nextafter(x, y);
11637 #endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^
11639 template <typename FP> FP step(FP start, FP direction, uint64_t steps)
11641 for (uint64_t i = 0; i < steps; ++i) {
11642 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
11643 start = Catch::nextafter(start, direction);
11645 start = std::nextafter(start, direction);
11651 // Performs equivalent check of std::fabs(lhs - rhs) <= margin
11652 // But without the subtraction to allow for INFINITY in comparison
11653 bool marginComparison(double lhs, double rhs, double margin)
11655 return (lhs + margin >= rhs) && (rhs + margin >= lhs);
11658 template <typename FloatingPoint> void write(std::ostream& out, FloatingPoint num)
11660 out << std::scientific << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1) << num;
11663 } // end anonymous namespace
11665 namespace Matchers {
11666 namespace Floating {
11668 enum class FloatingPointKind : uint8_t { Float, Double };
11670 WithinAbsMatcher::WithinAbsMatcher(double target, double margin) : m_target{target}, m_margin{margin}
11672 CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.' << " Margin has to be non-negative.");
11675 // Performs equivalent check of std::fabs(lhs - rhs) <= margin
11676 // But without the subtraction to allow for INFINITY in comparison
11677 bool WithinAbsMatcher::match(double const& matchee) const
11679 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
11682 std::string WithinAbsMatcher::describe() const
11684 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
11687 WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)
11688 : m_target{target}, m_ulps{ulps}, m_type{baseType}
11690 CATCH_ENFORCE(m_type == FloatingPointKind::Double || m_ulps < (std::numeric_limits<uint32_t>::max)(),
11691 "Provided ULP is impossibly large for a float comparison.");
11694 #if defined(__clang__)
11695 #pragma clang diagnostic push
11696 // Clang <3.5 reports on the default branch in the switch below
11697 #pragma clang diagnostic ignored "-Wunreachable-code"
11700 bool WithinUlpsMatcher::match(double const& matchee) const
11703 case FloatingPointKind::Float:
11704 return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
11705 case FloatingPointKind::Double:
11706 return almostEqualUlps<double>(matchee, m_target, m_ulps);
11708 CATCH_INTERNAL_ERROR("Unknown FloatingPointKind value");
11712 #if defined(__clang__)
11713 #pragma clang diagnostic pop
11716 std::string WithinUlpsMatcher::describe() const
11718 std::stringstream ret;
11720 ret << "is within " << m_ulps << " ULPs of ";
11722 if (m_type == FloatingPointKind::Float) {
11723 write(ret, static_cast<float>(m_target));
11726 write(ret, m_target);
11730 if (m_type == FloatingPointKind::Double) {
11731 write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps));
11733 write(ret, step(m_target, static_cast<double>(INFINITY), m_ulps));
11735 // We have to cast INFINITY to float because of MinGW, see #1782
11736 write(ret, step(static_cast<float>(m_target), static_cast<float>(-INFINITY), m_ulps));
11738 write(ret, step(static_cast<float>(m_target), static_cast<float>(INFINITY), m_ulps));
11745 WithinRelMatcher::WithinRelMatcher(double target, double epsilon) : m_target(target), m_epsilon(epsilon)
11747 CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon < 0 does not make sense.");
11748 CATCH_ENFORCE(m_epsilon < 1., "Relative comparison with epsilon >= 1 does not make sense.");
11751 bool WithinRelMatcher::match(double const& matchee) const
11753 const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));
11754 return marginComparison(matchee, m_target, std::isinf(relMargin) ? 0 : relMargin);
11757 std::string WithinRelMatcher::describe() const
11759 Catch::ReusableStringStream sstr;
11760 sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other";
11764 } // namespace Floating
11766 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff)
11768 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
11771 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff)
11773 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
11776 Floating::WithinAbsMatcher WithinAbs(double target, double margin)
11778 return Floating::WithinAbsMatcher(target, margin);
11781 Floating::WithinRelMatcher WithinRel(double target, double eps)
11783 return Floating::WithinRelMatcher(target, eps);
11786 Floating::WithinRelMatcher WithinRel(double target)
11788 return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
11791 Floating::WithinRelMatcher WithinRel(float target, float eps)
11793 return Floating::WithinRelMatcher(target, eps);
11796 Floating::WithinRelMatcher WithinRel(float target)
11798 return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
11801 } // namespace Matchers
11802 } // namespace Catch
11803 // end catch_matchers_floating.cpp
11804 // start catch_matchers_generic.cpp
11806 std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc)
11808 if (desc.empty()) {
11809 return "matches undescribed predicate";
11811 return "matches predicate: \"" + desc + '"';
11814 // end catch_matchers_generic.cpp
11815 // start catch_matchers_string.cpp
11820 namespace Matchers {
11822 namespace StdString {
11824 CasedString::CasedString(std::string const& str, CaseSensitive::Choice caseSensitivity)
11825 : m_caseSensitivity(caseSensitivity), m_str(adjustString(str))
11828 std::string CasedString::adjustString(std::string const& str) const
11830 return m_caseSensitivity == CaseSensitive::No ? toLower(str) : str;
11832 std::string CasedString::caseSensitivitySuffix() const
11834 return m_caseSensitivity == CaseSensitive::No ? " (case insensitive)" : std::string();
11837 StringMatcherBase::StringMatcherBase(std::string const& operation, CasedString const& comparator)
11838 : m_comparator(comparator), m_operation(operation)
11842 std::string StringMatcherBase::describe() const
11844 std::string description;
11845 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + m_comparator.caseSensitivitySuffix().size());
11846 description += m_operation;
11847 description += ": \"";
11848 description += m_comparator.m_str;
11849 description += "\"";
11850 description += m_comparator.caseSensitivitySuffix();
11851 return description;
11854 EqualsMatcher::EqualsMatcher(CasedString const& comparator) : StringMatcherBase("equals", comparator) {}
11856 bool EqualsMatcher::match(std::string const& source) const
11858 return m_comparator.adjustString(source) == m_comparator.m_str;
11861 ContainsMatcher::ContainsMatcher(CasedString const& comparator) : StringMatcherBase("contains", comparator) {}
11863 bool ContainsMatcher::match(std::string const& source) const
11865 return contains(m_comparator.adjustString(source), m_comparator.m_str);
11868 StartsWithMatcher::StartsWithMatcher(CasedString const& comparator) : StringMatcherBase("starts with", comparator) {}
11870 bool StartsWithMatcher::match(std::string const& source) const
11872 return startsWith(m_comparator.adjustString(source), m_comparator.m_str);
11875 EndsWithMatcher::EndsWithMatcher(CasedString const& comparator) : StringMatcherBase("ends with", comparator) {}
11877 bool EndsWithMatcher::match(std::string const& source) const
11879 return endsWith(m_comparator.adjustString(source), m_comparator.m_str);
11882 RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity)
11883 : m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity)
11887 bool RegexMatcher::match(std::string const& matchee) const
11889 auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway
11890 if (m_caseSensitivity == CaseSensitive::Choice::No) {
11891 flags |= std::regex::icase;
11893 auto reg = std::regex(m_regex, flags);
11894 return std::regex_match(matchee, reg);
11897 std::string RegexMatcher::describe() const
11899 return "matches " + ::Catch::Detail::stringify(m_regex) +
11900 ((m_caseSensitivity == CaseSensitive::Choice::Yes) ? " case sensitively" : " case insensitively");
11903 } // namespace StdString
11905 StdString::EqualsMatcher Equals(std::string const& str, CaseSensitive::Choice caseSensitivity)
11907 return StdString::EqualsMatcher(StdString::CasedString(str, caseSensitivity));
11909 StdString::ContainsMatcher Contains(std::string const& str, CaseSensitive::Choice caseSensitivity)
11911 return StdString::ContainsMatcher(StdString::CasedString(str, caseSensitivity));
11913 StdString::EndsWithMatcher EndsWith(std::string const& str, CaseSensitive::Choice caseSensitivity)
11915 return StdString::EndsWithMatcher(StdString::CasedString(str, caseSensitivity));
11917 StdString::StartsWithMatcher StartsWith(std::string const& str, CaseSensitive::Choice caseSensitivity)
11919 return StdString::StartsWithMatcher(StdString::CasedString(str, caseSensitivity));
11922 StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity)
11924 return StdString::RegexMatcher(regex, caseSensitivity);
11927 } // namespace Matchers
11928 } // namespace Catch
11929 // end catch_matchers_string.cpp
11930 // start catch_message.cpp
11932 // start catch_uncaught_exceptions.h
11935 bool uncaught_exceptions();
11936 } // end namespace Catch
11938 // end catch_uncaught_exceptions.h
11944 MessageInfo::MessageInfo(StringRef const& _macroName, SourceLineInfo const& _lineInfo, ResultWas::OfType _type)
11945 : macroName(_macroName), lineInfo(_lineInfo), type(_type), sequence(++globalCount)
11949 bool MessageInfo::operator==(MessageInfo const& other) const
11951 return sequence == other.sequence;
11954 bool MessageInfo::operator<(MessageInfo const& other) const
11956 return sequence < other.sequence;
11959 // This may need protecting if threading support is added
11960 unsigned int MessageInfo::globalCount = 0;
11962 ////////////////////////////////////////////////////////////////////////////
11964 Catch::MessageBuilder::MessageBuilder(StringRef const& macroName, SourceLineInfo const& lineInfo,
11965 ResultWas::OfType type)
11966 : m_info(macroName, lineInfo, type)
11970 ////////////////////////////////////////////////////////////////////////////
11972 ScopedMessage::ScopedMessage(MessageBuilder const& builder) : m_info(builder.m_info), m_moved()
11974 m_info.message = builder.m_stream.str();
11975 getResultCapture().pushScopedMessage(m_info);
11978 ScopedMessage::ScopedMessage(ScopedMessage&& old) : m_info(old.m_info), m_moved()
11980 old.m_moved = true;
11983 ScopedMessage::~ScopedMessage()
11985 if (!uncaught_exceptions() && !m_moved) {
11986 getResultCapture().popScopedMessage(m_info);
11990 Capturer::Capturer(StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names)
11992 auto trimmed = [&](size_t start, size_t end) {
11993 while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {
11996 while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) {
11999 return names.substr(start, end - start + 1);
12001 auto skipq = [&](size_t start, char quote) {
12002 for (auto i = start + 1; i < names.size(); ++i) {
12003 if (names[i] == quote)
12005 if (names[i] == '\\')
12008 CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote");
12012 std::stack<char> openings;
12013 for (size_t pos = 0; pos < names.size(); ++pos) {
12014 char c = names[pos];
12019 // It is basically impossible to disambiguate between
12020 // comparison and start of template args in this context
12032 pos = skipq(pos, c);
12035 if (start != pos && openings.empty()) {
12036 m_messages.emplace_back(macroName, lineInfo, resultType);
12037 m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
12038 m_messages.back().message += " := ";
12043 assert(openings.empty() && "Mismatched openings");
12044 m_messages.emplace_back(macroName, lineInfo, resultType);
12045 m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
12046 m_messages.back().message += " := ";
12048 Capturer::~Capturer()
12050 if (!uncaught_exceptions()) {
12051 assert(m_captured == m_messages.size());
12052 for (size_t i = 0; i < m_captured; ++i)
12053 m_resultCapture.popScopedMessage(m_messages[i]);
12057 void Capturer::captureValue(size_t index, std::string const& value)
12059 assert(index < m_messages.size());
12060 m_messages[index].message += value;
12061 m_resultCapture.pushScopedMessage(m_messages[index]);
12065 } // end namespace Catch
12066 // end catch_message.cpp
12067 // start catch_output_redirect.cpp
12069 // start catch_output_redirect.h
12070 #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
12071 #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
12079 class RedirectedStream {
12080 std::ostream& m_originalStream;
12081 std::ostream& m_redirectionStream;
12082 std::streambuf* m_prevBuf;
12085 RedirectedStream(std::ostream& originalStream, std::ostream& redirectionStream);
12086 ~RedirectedStream();
12089 class RedirectedStdOut {
12090 ReusableStringStream m_rss;
12091 RedirectedStream m_cout;
12094 RedirectedStdOut();
12095 auto str() const -> std::string;
12098 // StdErr has two constituent streams in C++, std::cerr and std::clog
12099 // This means that we need to redirect 2 streams into 1 to keep proper
12101 class RedirectedStdErr {
12102 ReusableStringStream m_rss;
12103 RedirectedStream m_cerr;
12104 RedirectedStream m_clog;
12107 RedirectedStdErr();
12108 auto str() const -> std::string;
12111 class RedirectedStreams {
12113 RedirectedStreams(RedirectedStreams const&) = delete;
12114 RedirectedStreams& operator=(RedirectedStreams const&) = delete;
12115 RedirectedStreams(RedirectedStreams&&) = delete;
12116 RedirectedStreams& operator=(RedirectedStreams&&) = delete;
12118 RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
12119 ~RedirectedStreams();
12122 std::string& m_redirectedCout;
12123 std::string& m_redirectedCerr;
12124 RedirectedStdOut m_redirectedStdOut;
12125 RedirectedStdErr m_redirectedStdErr;
12128 #if defined(CATCH_CONFIG_NEW_CAPTURE)
12130 // Windows's implementation of std::tmpfile is terrible (it tries
12131 // to create a file inside system folder, thus requiring elevated
12132 // privileges for the binary), so we have to use tmpnam(_s) and
12133 // create the file ourselves there.
12136 TempFile(TempFile const&) = delete;
12137 TempFile& operator=(TempFile const&) = delete;
12138 TempFile(TempFile&&) = delete;
12139 TempFile& operator=(TempFile&&) = delete;
12144 std::FILE* getFile();
12145 std::string getContents();
12148 std::FILE* m_file = nullptr;
12149 #if defined(_MSC_VER)
12150 char m_buffer[L_tmpnam] = {0};
12154 class OutputRedirect {
12156 OutputRedirect(OutputRedirect const&) = delete;
12157 OutputRedirect& operator=(OutputRedirect const&) = delete;
12158 OutputRedirect(OutputRedirect&&) = delete;
12159 OutputRedirect& operator=(OutputRedirect&&) = delete;
12161 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
12165 int m_originalStdout = -1;
12166 int m_originalStderr = -1;
12167 TempFile m_stdoutFile;
12168 TempFile m_stderrFile;
12169 std::string& m_stdoutDest;
12170 std::string& m_stderrDest;
12175 } // end namespace Catch
12177 #endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
12178 // end catch_output_redirect.h
12183 #include <stdexcept>
12185 #if defined(CATCH_CONFIG_NEW_CAPTURE)
12186 #if defined(_MSC_VER)
12187 #include <io.h> //_dup and _dup2
12190 #define fileno _fileno
12192 #include <unistd.h> // dup and dup2
12198 RedirectedStream::RedirectedStream(std::ostream& originalStream, std::ostream& redirectionStream)
12199 : m_originalStream(originalStream), m_redirectionStream(redirectionStream), m_prevBuf(m_originalStream.rdbuf())
12201 m_originalStream.rdbuf(m_redirectionStream.rdbuf());
12204 RedirectedStream::~RedirectedStream()
12206 m_originalStream.rdbuf(m_prevBuf);
12209 RedirectedStdOut::RedirectedStdOut() : m_cout(Catch::cout(), m_rss.get()) {}
12210 auto RedirectedStdOut::str() const -> std::string
12212 return m_rss.str();
12215 RedirectedStdErr::RedirectedStdErr() : m_cerr(Catch::cerr(), m_rss.get()), m_clog(Catch::clog(), m_rss.get()) {}
12216 auto RedirectedStdErr::str() const -> std::string
12218 return m_rss.str();
12221 RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
12222 : m_redirectedCout(redirectedCout), m_redirectedCerr(redirectedCerr)
12226 RedirectedStreams::~RedirectedStreams()
12228 m_redirectedCout += m_redirectedStdOut.str();
12229 m_redirectedCerr += m_redirectedStdErr.str();
12232 #if defined(CATCH_CONFIG_NEW_CAPTURE)
12234 #if defined(_MSC_VER)
12235 TempFile::TempFile()
12237 if (tmpnam_s(m_buffer)) {
12238 CATCH_RUNTIME_ERROR("Could not get a temp filename");
12240 if (fopen_s(&m_file, m_buffer, "w+")) {
12242 if (strerror_s(buffer, errno)) {
12243 CATCH_RUNTIME_ERROR("Could not translate errno to a string");
12245 CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer);
12249 TempFile::TempFile()
12251 m_file = std::tmpfile();
12253 CATCH_RUNTIME_ERROR("Could not create a temp file.");
12259 TempFile::~TempFile()
12261 // TBD: What to do about errors here?
12262 std::fclose(m_file);
12263 // We manually create the file on Windows only, on Linux
12264 // it will be autodeleted
12265 #if defined(_MSC_VER)
12266 std::remove(m_buffer);
12270 FILE* TempFile::getFile()
12275 std::string TempFile::getContents()
12277 std::stringstream sstr;
12278 char buffer[100] = {};
12279 std::rewind(m_file);
12280 while (std::fgets(buffer, sizeof(buffer), m_file)) {
12286 OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest)
12287 : m_originalStdout(dup(1)), m_originalStderr(dup(2)), m_stdoutDest(stdout_dest), m_stderrDest(stderr_dest)
12289 dup2(fileno(m_stdoutFile.getFile()), 1);
12290 dup2(fileno(m_stderrFile.getFile()), 2);
12293 OutputRedirect::~OutputRedirect()
12295 Catch::cout() << std::flush;
12297 // Since we support overriding these streams, we flush cerr
12298 // even though std::cerr is unbuffered
12299 Catch::cerr() << std::flush;
12300 Catch::clog() << std::flush;
12303 dup2(m_originalStdout, 1);
12304 dup2(m_originalStderr, 2);
12306 m_stdoutDest += m_stdoutFile.getContents();
12307 m_stderrDest += m_stderrFile.getContents();
12310 #endif // CATCH_CONFIG_NEW_CAPTURE
12312 } // namespace Catch
12314 #if defined(CATCH_CONFIG_NEW_CAPTURE)
12315 #if defined(_MSC_VER)
12321 // end catch_output_redirect.cpp
12322 // start catch_polyfills.cpp
12328 #if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
12329 bool isnan(float f)
12331 return std::isnan(f);
12333 bool isnan(double d)
12335 return std::isnan(d);
12338 // For now we only use this for embarcadero
12339 bool isnan(float f)
12341 return std::_isnan(f);
12343 bool isnan(double d)
12345 return std::_isnan(d);
12349 } // end namespace Catch
12350 // end catch_polyfills.cpp
12351 // start catch_random_number_generator.cpp
12357 #if defined(_MSC_VER)
12358 #pragma warning(push)
12359 #pragma warning(disable : 4146) // we negate uint32 during the rotate
12361 // Safe rotr implementation thanks to John Regehr
12362 uint32_t rotate_right(uint32_t val, uint32_t count)
12364 const uint32_t mask = 31;
12366 return (val >> count) | (val << (-count & mask));
12369 #if defined(_MSC_VER)
12370 #pragma warning(pop)
12375 SimplePcg32::SimplePcg32(result_type seed_)
12380 void SimplePcg32::seed(result_type seed_)
12388 void SimplePcg32::discard(uint64_t skip)
12390 // We could implement this to run in O(log n) steps, but this
12391 // should suffice for our use case.
12392 for (uint64_t s = 0; s < skip; ++s) {
12393 static_cast<void>((*this)());
12397 SimplePcg32::result_type SimplePcg32::operator()()
12399 // prepare the output value
12400 const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
12401 const auto output = rotate_right(xorshifted, m_state >> 59u);
12404 m_state = m_state * 6364136223846793005ULL + s_inc;
12409 bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs)
12411 return lhs.m_state == rhs.m_state;
12414 bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs)
12416 return lhs.m_state != rhs.m_state;
12418 } // namespace Catch
12419 // end catch_random_number_generator.cpp
12420 // start catch_registry_hub.cpp
12422 // start catch_test_case_registry_impl.h
12424 #include <algorithm>
12434 std::vector<TestCase> sortTests(IConfig const& config, std::vector<TestCase> const& unsortedTestCases);
12436 bool isThrowSafe(TestCase const& testCase, IConfig const& config);
12437 bool matchTest(TestCase const& testCase, TestSpec const& testSpec, IConfig const& config);
12439 void enforceNoDuplicateTestCases(std::vector<TestCase> const& functions);
12441 std::vector<TestCase> filterTests(std::vector<TestCase> const& testCases, TestSpec const& testSpec,
12442 IConfig const& config);
12443 std::vector<TestCase> const& getAllTestCasesSorted(IConfig const& config);
12445 class TestRegistry : public ITestCaseRegistry {
12447 virtual ~TestRegistry() = default;
12449 virtual void registerTest(TestCase const& testCase);
12451 std::vector<TestCase> const& getAllTests() const override;
12452 std::vector<TestCase> const& getAllTestsSorted(IConfig const& config) const override;
12455 std::vector<TestCase> m_functions;
12456 mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
12457 mutable std::vector<TestCase> m_sortedFunctions;
12458 std::size_t m_unnamedCount = 0;
12459 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
12462 ///////////////////////////////////////////////////////////////////////////
12464 class TestInvokerAsFunction : public ITestInvoker {
12465 void (*m_testAsFunction)();
12468 TestInvokerAsFunction(void (*testAsFunction)()) noexcept;
12470 void invoke() const override;
12473 std::string extractClassName(StringRef const& classOrQualifiedMethodName);
12475 ///////////////////////////////////////////////////////////////////////////
12477 } // end namespace Catch
12479 // end catch_test_case_registry_impl.h
12480 // start catch_reporter_registry.h
12486 class ReporterRegistry : public IReporterRegistry {
12489 ~ReporterRegistry() override;
12491 IStreamingReporterPtr create(std::string const& name, IConfigPtr const& config) const override;
12493 void registerReporter(std::string const& name, IReporterFactoryPtr const& factory);
12494 void registerListener(IReporterFactoryPtr const& factory);
12496 FactoryMap const& getFactories() const override;
12497 Listeners const& getListeners() const override;
12500 FactoryMap m_factories;
12501 Listeners m_listeners;
12503 } // namespace Catch
12505 // end catch_reporter_registry.h
12506 // start catch_tag_alias_registry.h
12508 // start catch_tag_alias.h
12515 TagAlias(std::string const& _tag, SourceLineInfo _lineInfo);
12518 SourceLineInfo lineInfo;
12521 } // end namespace Catch
12523 // end catch_tag_alias.h
12528 class TagAliasRegistry : public ITagAliasRegistry {
12530 ~TagAliasRegistry() override;
12531 TagAlias const* find(std::string const& alias) const override;
12532 std::string expandAliases(std::string const& unexpandedTestSpec) const override;
12533 void add(std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo);
12536 std::map<std::string, TagAlias> m_registry;
12539 } // end namespace Catch
12541 // end catch_tag_alias_registry.h
12542 // start catch_startup_exception_registry.h
12544 #include <exception>
12549 class StartupExceptionRegistry {
12550 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
12552 void add(std::exception_ptr const& exception) noexcept;
12553 std::vector<std::exception_ptr> const& getExceptions() const noexcept;
12556 std::vector<std::exception_ptr> m_exceptions;
12560 } // end namespace Catch
12562 // end catch_startup_exception_registry.h
12563 // start catch_singletons.hpp
12567 struct ISingleton {
12568 virtual ~ISingleton();
12571 void addSingleton(ISingleton* singleton);
12572 void cleanupSingletons();
12574 template <typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
12575 class Singleton : SingletonImplT, public ISingleton {
12577 static auto getInternal() -> Singleton*
12579 static Singleton* s_instance = nullptr;
12581 s_instance = new Singleton;
12582 addSingleton(s_instance);
12588 static auto get() -> InterfaceT const& { return *getInternal(); }
12589 static auto getMutable() -> MutableInterfaceT& { return *getInternal(); }
12592 } // namespace Catch
12594 // end catch_singletons.hpp
12599 class RegistryHub : public IRegistryHub, public IMutableRegistryHub, private NonCopyable {
12601 public: // IRegistryHub
12602 RegistryHub() = default;
12603 IReporterRegistry const& getReporterRegistry() const override { return m_reporterRegistry; }
12604 ITestCaseRegistry const& getTestCaseRegistry() const override { return m_testCaseRegistry; }
12605 IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override
12607 return m_exceptionTranslatorRegistry;
12609 ITagAliasRegistry const& getTagAliasRegistry() const override { return m_tagAliasRegistry; }
12610 StartupExceptionRegistry const& getStartupExceptionRegistry() const override { return m_exceptionRegistry; }
12612 public: // IMutableRegistryHub
12613 void registerReporter(std::string const& name, IReporterFactoryPtr const& factory) override
12615 m_reporterRegistry.registerReporter(name, factory);
12617 void registerListener(IReporterFactoryPtr const& factory) override { m_reporterRegistry.registerListener(factory); }
12618 void registerTest(TestCase const& testInfo) override { m_testCaseRegistry.registerTest(testInfo); }
12619 void registerTranslator(const IExceptionTranslator* translator) override
12621 m_exceptionTranslatorRegistry.registerTranslator(translator);
12623 void registerTagAlias(std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo) override
12625 m_tagAliasRegistry.add(alias, tag, lineInfo);
12627 void registerStartupException() noexcept override
12629 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
12630 m_exceptionRegistry.add(std::current_exception());
12632 CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
12635 IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override
12637 return m_enumValuesRegistry;
12641 TestRegistry m_testCaseRegistry;
12642 ReporterRegistry m_reporterRegistry;
12643 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
12644 TagAliasRegistry m_tagAliasRegistry;
12645 StartupExceptionRegistry m_exceptionRegistry;
12646 Detail::EnumValuesRegistry m_enumValuesRegistry;
12650 using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
12652 IRegistryHub const& getRegistryHub()
12654 return RegistryHubSingleton::get();
12656 IMutableRegistryHub& getMutableRegistryHub()
12658 return RegistryHubSingleton::getMutable();
12662 cleanupSingletons();
12665 std::string translateActiveException()
12667 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
12670 } // end namespace Catch
12671 // end catch_registry_hub.cpp
12672 // start catch_reporter_registry.cpp
12676 ReporterRegistry::~ReporterRegistry() = default;
12678 IStreamingReporterPtr ReporterRegistry::create(std::string const& name, IConfigPtr const& config) const
12680 auto it = m_factories.find(name);
12681 if (it == m_factories.end())
12683 return it->second->create(ReporterConfig(config));
12686 void ReporterRegistry::registerReporter(std::string const& name, IReporterFactoryPtr const& factory)
12688 m_factories.emplace(name, factory);
12690 void ReporterRegistry::registerListener(IReporterFactoryPtr const& factory)
12692 m_listeners.push_back(factory);
12695 IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const
12697 return m_factories;
12699 IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const
12701 return m_listeners;
12704 } // namespace Catch
12705 // end catch_reporter_registry.cpp
12706 // start catch_result_type.cpp
12710 bool isOk(ResultWas::OfType resultType)
12712 return (resultType & ResultWas::FailureBit) == 0;
12714 bool isJustInfo(int flags)
12716 return flags == ResultWas::Info;
12719 ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
12721 return static_cast<ResultDisposition::Flags>(static_cast<int>(lhs) | static_cast<int>(rhs));
12724 bool shouldContinueOnFailure(int flags)
12726 return (flags & ResultDisposition::ContinueOnFailure) != 0;
12728 bool shouldSuppressFailure(int flags)
12730 return (flags & ResultDisposition::SuppressFail) != 0;
12733 } // end namespace Catch
12734 // end catch_result_type.cpp
12735 // start catch_run_context.cpp
12737 #include <algorithm>
12743 namespace Generators {
12744 struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
12745 GeneratorBasePtr m_generator;
12747 GeneratorTracker(TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent)
12748 : TrackerBase(nameAndLocation, ctx, parent)
12751 ~GeneratorTracker();
12753 static GeneratorTracker& acquire(TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation)
12755 std::shared_ptr<GeneratorTracker> tracker;
12757 ITracker& currentTracker = ctx.currentTracker();
12758 // Under specific circumstances, the generator we want
12759 // to acquire is also the current tracker. If this is
12760 // the case, we have to avoid looking through current
12761 // tracker's children, and instead return the current
12763 // A case where this check is important is e.g.
12764 // for (int i = 0; i < 5; ++i) {
12765 // int n = GENERATE(1, 2);
12768 // without it, the code above creates 5 nested generators.
12769 if (currentTracker.nameAndLocation() == nameAndLocation) {
12770 auto thisTracker = currentTracker.parent().findChild(nameAndLocation);
12771 assert(thisTracker);
12772 assert(thisTracker->isGeneratorTracker());
12773 tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker);
12774 } else if (TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild(nameAndLocation)) {
12775 assert(childTracker);
12776 assert(childTracker->isGeneratorTracker());
12777 tracker = std::static_pointer_cast<GeneratorTracker>(childTracker);
12779 tracker = std::make_shared<GeneratorTracker>(nameAndLocation, ctx, ¤tTracker);
12780 currentTracker.addChild(tracker);
12783 if (!tracker->isComplete()) {
12790 // TrackerBase interface
12791 bool isGeneratorTracker() const override { return true; }
12792 auto hasGenerator() const -> bool override { return !!m_generator; }
12793 void close() override
12795 TrackerBase::close();
12796 // If a generator has a child (it is followed by a section)
12797 // and none of its children have started, then we must wait
12798 // until later to start consuming its values.
12799 // This catches cases where `GENERATE` is placed between two
12801 // **The check for m_children.empty cannot be removed**.
12802 // doing so would break `GENERATE` _not_ followed by `SECTION`s.
12803 const bool should_wait_for_child = [&]() {
12804 // No children -> nobody to wait for
12805 if (m_children.empty()) {
12808 // If at least one child started executing, don't wait
12809 if (std::find_if(m_children.begin(), m_children.end(), [](TestCaseTracking::ITrackerPtr tracker) {
12810 return tracker->hasStarted();
12811 }) != m_children.end()) {
12815 // No children have started. We need to check if they _can_
12816 // start, and thus we should wait for them, or they cannot
12817 // start (due to filters), and we shouldn't wait for them
12818 auto* parent = m_parent;
12819 // This is safe: there is always at least one section
12820 // tracker in a test case tracking tree
12821 while (!parent->isSectionTracker()) {
12822 parent = &(parent->parent());
12824 assert(parent && "Missing root (test case) level section");
12826 auto const& parentSection = static_cast<SectionTracker&>(*parent);
12827 auto const& filters = parentSection.getFilters();
12828 // No filters -> no restrictions on running sections
12829 if (filters.empty()) {
12833 for (auto const& child : m_children) {
12834 if (child->isSectionTracker() &&
12835 std::find(filters.begin(), filters.end(), static_cast<SectionTracker&>(*child).trimmedName()) !=
12843 // This check is a bit tricky, because m_generator->next()
12844 // has a side-effect, where it consumes generator's current
12845 // value, but we do not want to invoke the side-effect if
12846 // this generator is still waiting for any child to start.
12847 if (should_wait_for_child || (m_runState == CompletedSuccessfully && m_generator->next())) {
12848 m_children.clear();
12849 m_runState = Executing;
12853 // IGeneratorTracker interface
12854 auto getGenerator() const -> GeneratorBasePtr const& override { return m_generator; }
12855 void setGenerator(GeneratorBasePtr&& generator) override { m_generator = std::move(generator); }
12857 GeneratorTracker::~GeneratorTracker() {}
12858 } // namespace Generators
12860 RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
12861 : m_runInfo(_config->name())
12862 , m_context(getCurrentMutableContext())
12863 , m_config(_config)
12864 , m_reporter(std::move(reporter))
12865 , m_lastAssertionInfo{StringRef(), SourceLineInfo("", 0), StringRef(), ResultDisposition::Normal}
12866 , m_includeSuccessfulResults(m_config->includeSuccessfulResults() ||
12867 m_reporter->getPreferences().shouldReportAllAssertions)
12869 m_context.setRunner(this);
12870 m_context.setConfig(m_config);
12871 m_context.setResultCapture(this);
12872 m_reporter->testRunStarting(m_runInfo);
12875 RunContext::~RunContext()
12877 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
12880 void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount)
12882 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
12885 void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex,
12886 std::size_t groupsCount)
12888 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
12891 Totals RunContext::runTest(TestCase const& testCase)
12893 Totals prevTotals = m_totals;
12895 std::string redirectedCout;
12896 std::string redirectedCerr;
12898 auto const& testInfo = testCase.getTestCaseInfo();
12900 m_reporter->testCaseStarting(testInfo);
12902 m_activeTestCase = &testCase;
12904 ITracker& rootTracker = m_trackerContext.startRun();
12905 assert(rootTracker.isSectionTracker());
12906 static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
12908 m_trackerContext.startCycle();
12909 m_testCaseTracker =
12910 &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
12911 runCurrentTest(redirectedCout, redirectedCerr);
12912 } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
12914 Totals deltaTotals = m_totals.delta(prevTotals);
12915 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
12916 deltaTotals.assertions.failed++;
12917 deltaTotals.testCases.passed--;
12918 deltaTotals.testCases.failed++;
12920 m_totals.testCases += deltaTotals.testCases;
12921 m_reporter->testCaseEnded(TestCaseStats(testInfo, deltaTotals, redirectedCout, redirectedCerr, aborting()));
12923 m_activeTestCase = nullptr;
12924 m_testCaseTracker = nullptr;
12926 return deltaTotals;
12929 IConfigPtr RunContext::config() const
12934 IStreamingReporter& RunContext::reporter() const
12936 return *m_reporter;
12939 void RunContext::assertionEnded(AssertionResult const& result)
12941 if (result.getResultType() == ResultWas::Ok) {
12942 m_totals.assertions.passed++;
12943 m_lastAssertionPassed = true;
12944 } else if (!result.isOk()) {
12945 m_lastAssertionPassed = false;
12946 if (m_activeTestCase->getTestCaseInfo().okToFail())
12947 m_totals.assertions.failedButOk++;
12949 m_totals.assertions.failed++;
12951 m_lastAssertionPassed = true;
12954 // We have no use for the return value (whether messages should be cleared), because messages were made scoped
12955 // and should be let to clear themselves out.
12956 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
12958 if (result.getResultType() != ResultWas::Warning)
12959 m_messageScopes.clear();
12961 // Reset working state
12962 resetAssertionInfo();
12963 m_lastResult = result;
12965 void RunContext::resetAssertionInfo()
12967 m_lastAssertionInfo.macroName = StringRef();
12968 m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
12971 bool RunContext::sectionStarted(SectionInfo const& sectionInfo, Counts& assertions)
12973 ITracker& sectionTracker = SectionTracker::acquire(
12974 m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
12975 if (!sectionTracker.isOpen())
12977 m_activeSections.push_back(§ionTracker);
12979 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
12981 m_reporter->sectionStarting(sectionInfo);
12983 assertions = m_totals.assertions;
12987 auto RunContext::acquireGeneratorTracker(StringRef generatorName, SourceLineInfo const& lineInfo) -> IGeneratorTracker&
12989 using namespace Generators;
12990 GeneratorTracker& tracker = GeneratorTracker::acquire(
12991 m_trackerContext, TestCaseTracking::NameAndLocation(static_cast<std::string>(generatorName), lineInfo));
12992 m_lastAssertionInfo.lineInfo = lineInfo;
12996 bool RunContext::testForMissingAssertions(Counts& assertions)
12998 if (assertions.total() != 0)
13000 if (!m_config->warnAboutMissingAssertions())
13002 if (m_trackerContext.currentTracker().hasChildren())
13004 m_totals.assertions.failed++;
13005 assertions.failed++;
13009 void RunContext::sectionEnded(SectionEndInfo const& endInfo)
13011 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
13012 bool missingAssertions = testForMissingAssertions(assertions);
13014 if (!m_activeSections.empty()) {
13015 m_activeSections.back()->close();
13016 m_activeSections.pop_back();
13019 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
13020 m_messages.clear();
13021 m_messageScopes.clear();
13024 void RunContext::sectionEndedEarly(SectionEndInfo const& endInfo)
13026 if (m_unfinishedSections.empty())
13027 m_activeSections.back()->fail();
13029 m_activeSections.back()->close();
13030 m_activeSections.pop_back();
13032 m_unfinishedSections.push_back(endInfo);
13035 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
13036 void RunContext::benchmarkPreparing(std::string const& name)
13038 m_reporter->benchmarkPreparing(name);
13040 void RunContext::benchmarkStarting(BenchmarkInfo const& info)
13042 m_reporter->benchmarkStarting(info);
13044 void RunContext::benchmarkEnded(BenchmarkStats<> const& stats)
13046 m_reporter->benchmarkEnded(stats);
13048 void RunContext::benchmarkFailed(std::string const& error)
13050 m_reporter->benchmarkFailed(error);
13052 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
13054 void RunContext::pushScopedMessage(MessageInfo const& message)
13056 m_messages.push_back(message);
13059 void RunContext::popScopedMessage(MessageInfo const& message)
13061 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
13064 void RunContext::emplaceUnscopedMessage(MessageBuilder const& builder)
13066 m_messageScopes.emplace_back(builder);
13069 std::string RunContext::getCurrentTestName() const
13071 return m_activeTestCase ? m_activeTestCase->getTestCaseInfo().name : std::string();
13074 const AssertionResult* RunContext::getLastResult() const
13076 return &(*m_lastResult);
13079 void RunContext::exceptionEarlyReported()
13081 m_shouldReportUnexpected = false;
13084 void RunContext::handleFatalErrorCondition(StringRef message)
13086 // First notify reporter that bad things happened
13087 m_reporter->fatalErrorEncountered(message);
13089 // Don't rebuild the result -- the stringification itself can cause more fatal errors
13090 // Instead, fake a result data.
13091 AssertionResultData tempResult(ResultWas::FatalErrorCondition, {false});
13092 tempResult.message = static_cast<std::string>(message);
13093 AssertionResult result(m_lastAssertionInfo, tempResult);
13095 assertionEnded(result);
13097 handleUnfinishedSections();
13099 // Recreate section for test case (as we will lose the one that was in scope)
13100 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
13101 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
13104 assertions.failed = 1;
13105 SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
13106 m_reporter->sectionEnded(testCaseSectionStats);
13108 auto const& testInfo = m_activeTestCase->getTestCaseInfo();
13110 Totals deltaTotals;
13111 deltaTotals.testCases.failed = 1;
13112 deltaTotals.assertions.failed = 1;
13113 m_reporter->testCaseEnded(TestCaseStats(testInfo, deltaTotals, std::string(), std::string(), false));
13114 m_totals.testCases.failed++;
13115 testGroupEnded(std::string(), m_totals, 1, 1);
13116 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
13119 bool RunContext::lastAssertionPassed()
13121 return m_lastAssertionPassed;
13124 void RunContext::assertionPassed()
13126 m_lastAssertionPassed = true;
13127 ++m_totals.assertions.passed;
13128 resetAssertionInfo();
13129 m_messageScopes.clear();
13132 bool RunContext::aborting() const
13134 return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());
13137 void RunContext::runCurrentTest(std::string& redirectedCout, std::string& redirectedCerr)
13139 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
13140 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
13141 m_reporter->sectionStarting(testCaseSection);
13142 Counts prevAssertions = m_totals.assertions;
13143 double duration = 0;
13144 m_shouldReportUnexpected = true;
13145 m_lastAssertionInfo = {"TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal};
13147 seedRng(*m_config);
13152 if (m_reporter->getPreferences().shouldRedirectStdOut) {
13153 #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
13154 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
13157 invokeActiveTestCase();
13159 OutputRedirect r(redirectedCout, redirectedCerr);
13161 invokeActiveTestCase();
13165 invokeActiveTestCase();
13167 duration = timer.getElapsedSeconds();
13169 CATCH_CATCH_ANON(TestFailureException&)
13171 // This just means the test was aborted due to failure
13175 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
13176 // are reported without translation at the point of origin.
13177 if (m_shouldReportUnexpected) {
13178 AssertionReaction dummyReaction;
13179 handleUnexpectedInflightException(m_lastAssertionInfo, translateActiveException(), dummyReaction);
13182 Counts assertions = m_totals.assertions - prevAssertions;
13183 bool missingAssertions = testForMissingAssertions(assertions);
13185 m_testCaseTracker->close();
13186 handleUnfinishedSections();
13187 m_messages.clear();
13188 m_messageScopes.clear();
13190 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
13191 m_reporter->sectionEnded(testCaseSectionStats);
13194 void RunContext::invokeActiveTestCase()
13196 FatalConditionHandlerGuard _(&m_fatalConditionhandler);
13197 m_activeTestCase->invoke();
13200 void RunContext::handleUnfinishedSections()
13202 // If sections ended prematurely due to an exception we stored their
13203 // infos here so we can tear them down outside the unwind process.
13204 for (auto it = m_unfinishedSections.rbegin(), itEnd = m_unfinishedSections.rend(); it != itEnd; ++it)
13206 m_unfinishedSections.clear();
13209 void RunContext::handleExpr(AssertionInfo const& info, ITransientExpression const& expr, AssertionReaction& reaction)
13211 m_reporter->assertionStarting(info);
13213 bool negated = isFalseTest(info.resultDisposition);
13214 bool result = expr.getResult() != negated;
13217 if (!m_includeSuccessfulResults) {
13220 reportExpr(info, ResultWas::Ok, &expr, negated);
13223 reportExpr(info, ResultWas::ExpressionFailed, &expr, negated);
13224 populateReaction(reaction);
13227 void RunContext::reportExpr(AssertionInfo const& info, ResultWas::OfType resultType, ITransientExpression const* expr,
13231 m_lastAssertionInfo = info;
13232 AssertionResultData data(resultType, LazyExpression(negated));
13234 AssertionResult assertionResult{info, data};
13235 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
13237 assertionEnded(assertionResult);
13240 void RunContext::handleMessage(AssertionInfo const& info, ResultWas::OfType resultType, StringRef const& message,
13241 AssertionReaction& reaction)
13243 m_reporter->assertionStarting(info);
13245 m_lastAssertionInfo = info;
13247 AssertionResultData data(resultType, LazyExpression(false));
13248 data.message = static_cast<std::string>(message);
13249 AssertionResult assertionResult{m_lastAssertionInfo, data};
13250 assertionEnded(assertionResult);
13251 if (!assertionResult.isOk())
13252 populateReaction(reaction);
13254 void RunContext::handleUnexpectedExceptionNotThrown(AssertionInfo const& info, AssertionReaction& reaction)
13256 handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
13259 void RunContext::handleUnexpectedInflightException(AssertionInfo const& info, std::string const& message,
13260 AssertionReaction& reaction)
13262 m_lastAssertionInfo = info;
13264 AssertionResultData data(ResultWas::ThrewException, LazyExpression(false));
13265 data.message = message;
13266 AssertionResult assertionResult{info, data};
13267 assertionEnded(assertionResult);
13268 populateReaction(reaction);
13271 void RunContext::populateReaction(AssertionReaction& reaction)
13273 reaction.shouldDebugBreak = m_config->shouldDebugBreak();
13274 reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
13277 void RunContext::handleIncomplete(AssertionInfo const& info)
13279 m_lastAssertionInfo = info;
13281 AssertionResultData data(ResultWas::ThrewException, LazyExpression(false));
13282 data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
13283 AssertionResult assertionResult{info, data};
13284 assertionEnded(assertionResult);
13286 void RunContext::handleNonExpr(AssertionInfo const& info, ResultWas::OfType resultType, AssertionReaction& reaction)
13288 m_lastAssertionInfo = info;
13290 AssertionResultData data(resultType, LazyExpression(false));
13291 AssertionResult assertionResult{info, data};
13292 assertionEnded(assertionResult);
13294 if (!assertionResult.isOk())
13295 populateReaction(reaction);
13298 IResultCapture& getResultCapture()
13300 if (auto* capture = getCurrentContext().getResultCapture())
13303 CATCH_INTERNAL_ERROR("No result capture instance");
13306 void seedRng(IConfig const& config)
13308 if (config.rngSeed() != 0) {
13309 std::srand(config.rngSeed());
13310 rng().seed(config.rngSeed());
13314 unsigned int rngSeed()
13316 return getCurrentContext().getConfig()->rngSeed();
13319 } // namespace Catch
13320 // end catch_run_context.cpp
13321 // start catch_section.cpp
13325 Section::Section(SectionInfo const& info)
13326 : m_info(info), m_sectionIncluded(getResultCapture().sectionStarted(m_info, m_assertions))
13331 Section::~Section()
13333 if (m_sectionIncluded) {
13334 SectionEndInfo endInfo{m_info, m_assertions, m_timer.getElapsedSeconds()};
13335 if (uncaught_exceptions())
13336 getResultCapture().sectionEndedEarly(endInfo);
13338 getResultCapture().sectionEnded(endInfo);
13342 // This indicates whether the section should be executed or not
13343 Section::operator bool() const
13345 return m_sectionIncluded;
13348 } // end namespace Catch
13349 // end catch_section.cpp
13350 // start catch_section_info.cpp
13354 SectionInfo::SectionInfo(SourceLineInfo const& _lineInfo, std::string const& _name) : name(_name), lineInfo(_lineInfo)
13358 } // end namespace Catch
13359 // end catch_section_info.cpp
13360 // start catch_session.cpp
13362 // start catch_session.h
13368 class Session : NonCopyable {
13371 ~Session() override;
13373 void showHelp() const;
13374 void libIdentify();
13376 int applyCommandLine(int argc, char const* const* argv);
13377 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
13378 int applyCommandLine(int argc, wchar_t const* const* argv);
13381 void useConfigData(ConfigData const& configData);
13383 template <typename CharT> int run(int argc, CharT const* const argv[])
13385 if (m_startupExceptions)
13387 int returnCode = applyCommandLine(argc, argv);
13388 if (returnCode == 0)
13389 returnCode = run();
13395 clara::Parser const& cli() const;
13396 void cli(clara::Parser const& newParser);
13397 ConfigData& configData();
13403 clara::Parser m_cli;
13404 ConfigData m_configData;
13405 std::shared_ptr<Config> m_config;
13406 bool m_startupExceptions = false;
13409 } // end namespace Catch
13411 // end catch_session.h
13412 // start catch_version.h
13418 // Versioning information
13420 Version(Version const&) = delete;
13421 Version& operator=(Version const&) = delete;
13422 Version(unsigned int _majorVersion, unsigned int _minorVersion, unsigned int _patchNumber,
13423 char const* const _branchName, unsigned int _buildNumber);
13425 unsigned int const majorVersion;
13426 unsigned int const minorVersion;
13427 unsigned int const patchNumber;
13429 // buildNumber is only used if branchName is not null
13430 char const* const branchName;
13431 unsigned int const buildNumber;
13433 friend std::ostream& operator<<(std::ostream& os, Version const& version);
13436 Version const& libraryVersion();
13437 } // namespace Catch
13439 // end catch_version.h
13442 #include <iterator>
13448 const int MaxExitCode = 255;
13450 IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config)
13452 auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);
13453 CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'");
13458 IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config)
13460 if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
13461 return createReporter(config->getReporterName(), config);
13464 // On older platforms, returning std::unique_ptr<ListeningReporter>
13465 // when the return type is std::unique_ptr<IStreamingReporter>
13466 // doesn't compile without a std::move call. However, this causes
13467 // a warning on newer platforms. Thus, we have to work around
13468 // it a bit and downcast the pointer manually.
13469 auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter);
13470 auto& multi = static_cast<ListeningReporter&>(*ret);
13471 auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
13472 for (auto const& listener : listeners) {
13473 multi.addListener(listener->create(Catch::ReporterConfig(config)));
13475 multi.addReporter(createReporter(config->getReporterName(), config));
13481 explicit TestGroup(std::shared_ptr<Config> const& config) : m_config{config}, m_context{config, makeReporter(config)}
13483 auto const& allTestCases = getAllTestCasesSorted(*m_config);
13484 m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
13485 auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
13487 if (m_matches.empty() && invalidArgs.empty()) {
13488 for (auto const& test : allTestCases)
13489 if (!test.isHidden())
13490 m_tests.emplace(&test);
13492 for (auto const& match : m_matches)
13493 m_tests.insert(match.tests.begin(), match.tests.end());
13499 auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
13501 m_context.testGroupStarting(m_config->name(), 1, 1);
13502 for (auto const& testCase : m_tests) {
13503 if (!m_context.aborting())
13504 totals += m_context.runTest(*testCase);
13506 m_context.reporter().skipTest(*testCase);
13509 for (auto const& match : m_matches) {
13510 if (match.tests.empty()) {
13511 m_context.reporter().noMatchingTestCases(match.name);
13516 if (!invalidArgs.empty()) {
13517 for (auto const& invalidArg : invalidArgs)
13518 m_context.reporter().reportInvalidArguments(invalidArg);
13521 m_context.testGroupEnded(m_config->name(), totals, 1, 1);
13526 using Tests = std::set<TestCase const*>;
13528 std::shared_ptr<Config> m_config;
13529 RunContext m_context;
13531 TestSpec::Matches m_matches;
13534 void applyFilenamesAsTags(Catch::IConfig const& config)
13536 auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
13537 for (auto& testCase : tests) {
13538 auto tags = testCase.tags;
13540 std::string filename = testCase.lineInfo.file;
13541 auto lastSlash = filename.find_last_of("\\/");
13542 if (lastSlash != std::string::npos) {
13543 filename.erase(0, lastSlash);
13547 auto lastDot = filename.find_last_of('.');
13548 if (lastDot != std::string::npos) {
13549 filename.erase(lastDot);
13552 tags.push_back(std::move(filename));
13553 setTags(testCase, tags);
13561 static bool alreadyInstantiated = false;
13562 if (alreadyInstantiated) {
13565 CATCH_INTERNAL_ERROR("Only one instance of Catch::Session can ever be used");
13569 getMutableRegistryHub().registerStartupException();
13573 // There cannot be exceptions at startup in no-exception mode.
13574 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
13575 const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
13576 if (!exceptions.empty()) {
13578 getCurrentMutableContext().setConfig(m_config);
13580 m_startupExceptions = true;
13581 Colour colourGuard(Colour::Red);
13582 Catch::cerr() << "Errors occurred during startup!" << '\n';
13583 // iterate over all exceptions and notify user
13584 for (const auto& ex_ptr : exceptions) {
13586 std::rethrow_exception(ex_ptr);
13587 } catch (std::exception const& ex) {
13588 Catch::cerr() << Column(ex.what()).indent(2) << '\n';
13594 alreadyInstantiated = true;
13595 m_cli = makeCommandLineParser(m_configData);
13597 Session::~Session()
13602 void Session::showHelp() const
13604 Catch::cout() << "\nCatch v" << libraryVersion() << "\n"
13605 << m_cli << std::endl
13606 << "For more detailed usage please see the project docs\n"
13609 void Session::libIdentify()
13611 Catch::cout() << std::left << std::setw(16) << "description: "
13612 << "A Catch2 test executable\n"
13613 << std::left << std::setw(16) << "category: "
13614 << "testframework\n"
13615 << std::left << std::setw(16) << "framework: "
13617 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
13620 int Session::applyCommandLine(int argc, char const* const* argv)
13622 if (m_startupExceptions)
13625 auto result = m_cli.parse(clara::Args(argc, argv));
13628 getCurrentMutableContext().setConfig(m_config);
13629 Catch::cerr() << Colour(Colour::Red) << "\nError(s) in input:\n"
13630 << Column(result.errorMessage()).indent(2) << "\n\n";
13631 Catch::cerr() << "Run with -? for usage\n" << std::endl;
13632 return MaxExitCode;
13635 if (m_configData.showHelp)
13637 if (m_configData.libIdentify)
13643 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
13644 int Session::applyCommandLine(int argc, wchar_t const* const* argv)
13647 char** utf8Argv = new char*[argc];
13649 for (int i = 0; i < argc; ++i) {
13650 int bufSize = WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr);
13652 utf8Argv[i] = new char[bufSize];
13654 WideCharToMultiByte(CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr);
13657 int returnCode = applyCommandLine(argc, utf8Argv);
13659 for (int i = 0; i < argc; ++i)
13660 delete[] utf8Argv[i];
13668 void Session::useConfigData(ConfigData const& configData)
13670 m_configData = configData;
13676 if ((m_configData.waitForKeypress & WaitForKeypress::BeforeStart) != 0) {
13677 Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
13678 static_cast<void>(std::getchar());
13680 int exitCode = runInternal();
13681 if ((m_configData.waitForKeypress & WaitForKeypress::BeforeExit) != 0) {
13682 Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
13683 static_cast<void>(std::getchar());
13688 clara::Parser const& Session::cli() const
13692 void Session::cli(clara::Parser const& newParser)
13696 ConfigData& Session::configData()
13698 return m_configData;
13700 Config& Session::config()
13703 m_config = std::make_shared<Config>(m_configData);
13707 int Session::runInternal()
13709 if (m_startupExceptions)
13712 if (m_configData.showHelp || m_configData.libIdentify) {
13718 config(); // Force config to be constructed
13720 seedRng(*m_config);
13722 if (m_configData.filenamesAsTags)
13723 applyFilenamesAsTags(*m_config);
13725 // Handle list request
13726 if (Option<std::size_t> listed = list(m_config))
13727 return static_cast<int>(*listed);
13729 TestGroup tests{m_config};
13730 auto const totals = tests.execute();
13732 if (m_config->warnAboutNoTests() && totals.error == -1)
13735 // Note that on unices only the lower 8 bits are usually used, clamping
13736 // the return value to 255 prevents false negative when some multiple
13737 // of 256 tests has failed
13738 return (std::min)(MaxExitCode, (std::max)(totals.error, static_cast<int>(totals.assertions.failed)));
13740 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
13741 catch (std::exception& ex)
13743 Catch::cerr() << ex.what() << std::endl;
13744 return MaxExitCode;
13749 } // end namespace Catch
13750 // end catch_session.cpp
13751 // start catch_singletons.cpp
13758 static auto getSingletons() -> std::vector<ISingleton*>*&
13760 static std::vector<ISingleton*>* g_singletons = nullptr;
13762 g_singletons = new std::vector<ISingleton*>();
13763 return g_singletons;
13767 ISingleton::~ISingleton() {}
13769 void addSingleton(ISingleton* singleton)
13771 getSingletons()->push_back(singleton);
13773 void cleanupSingletons()
13775 auto& singletons = getSingletons();
13776 for (auto singleton : *singletons)
13779 singletons = nullptr;
13782 } // namespace Catch
13783 // end catch_singletons.cpp
13784 // start catch_startup_exception_registry.cpp
13786 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
13788 void StartupExceptionRegistry::add(std::exception_ptr const& exception) noexcept
13792 m_exceptions.push_back(exception);
13796 // If we run out of memory during start-up there's really not a lot more we can do about it
13801 std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept
13803 return m_exceptions;
13806 } // end namespace Catch
13808 // end catch_startup_exception_registry.cpp
13809 // start catch_stream.cpp
13813 #include <iostream>
13820 Catch::IStream::~IStream() = default;
13824 template <typename WriterF, std::size_t bufferSize = 256> class StreamBufImpl : public std::streambuf {
13825 char data[bufferSize];
13829 StreamBufImpl() { setp(data, data + sizeof(data)); }
13831 ~StreamBufImpl() noexcept { StreamBufImpl::sync(); }
13834 int overflow(int c) override
13839 if (pbase() == epptr())
13840 m_writer(std::string(1, static_cast<char>(c)));
13842 sputc(static_cast<char>(c));
13847 int sync() override
13849 if (pbase() != pptr()) {
13850 m_writer(std::string(pbase(), static_cast<std::string::size_type>(pptr() - pbase())));
13851 setp(pbase(), epptr());
13857 ///////////////////////////////////////////////////////////////////////////
13859 struct OutputDebugWriter {
13861 void operator()(std::string const& str) { writeToDebugConsole(str); }
13864 ///////////////////////////////////////////////////////////////////////////
13866 class FileStream : public IStream {
13867 mutable std::ofstream m_ofs;
13870 FileStream(StringRef filename)
13872 m_ofs.open(filename.c_str());
13873 CATCH_ENFORCE(!m_ofs.fail(), "Unable to open file: '" << filename << "'");
13875 ~FileStream() override = default;
13878 std::ostream& stream() const override { return m_ofs; }
13881 ///////////////////////////////////////////////////////////////////////////
13883 class CoutStream : public IStream {
13884 mutable std::ostream m_os;
13887 // Store the streambuf from cout up-front because
13888 // cout may get redirected when running tests
13889 CoutStream() : m_os(Catch::cout().rdbuf()) {}
13890 ~CoutStream() override = default;
13893 std::ostream& stream() const override { return m_os; }
13896 ///////////////////////////////////////////////////////////////////////////
13898 class DebugOutStream : public IStream {
13899 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
13900 mutable std::ostream m_os;
13903 DebugOutStream() : m_streamBuf(new StreamBufImpl<OutputDebugWriter>()), m_os(m_streamBuf.get()) {}
13905 ~DebugOutStream() override = default;
13908 std::ostream& stream() const override { return m_os; }
13912 } // namespace Detail
13914 ///////////////////////////////////////////////////////////////////////////
13916 auto makeStream(StringRef const& filename) -> IStream const*
13918 if (filename.empty())
13919 return new Detail::CoutStream();
13920 else if (filename[0] == '%') {
13921 if (filename == "%debug")
13922 return new Detail::DebugOutStream();
13924 CATCH_ERROR("Unrecognised stream: '" << filename << "'");
13926 return new Detail::FileStream(filename);
13929 // This class encapsulates the idea of a pool of ostringstreams that can be reused.
13930 struct StringStreams {
13931 std::vector<std::unique_ptr<std::ostringstream>> m_streams;
13932 std::vector<std::size_t> m_unused;
13933 std::ostringstream m_referenceStream; // Used for copy state/ flags from
13935 auto add() -> std::size_t
13937 if (m_unused.empty()) {
13938 m_streams.push_back(std::unique_ptr<std::ostringstream>(new std::ostringstream));
13939 return m_streams.size() - 1;
13941 auto index = m_unused.back();
13942 m_unused.pop_back();
13947 void release(std::size_t index)
13949 m_streams[index]->copyfmt(m_referenceStream); // Restore initial flags and other state
13950 m_unused.push_back(index);
13954 ReusableStringStream::ReusableStringStream()
13955 : m_index(Singleton<StringStreams>::getMutable().add())
13956 , m_oss(Singleton<StringStreams>::getMutable().m_streams[m_index].get())
13960 ReusableStringStream::~ReusableStringStream()
13962 static_cast<std::ostringstream*>(m_oss)->str("");
13964 Singleton<StringStreams>::getMutable().release(m_index);
13967 auto ReusableStringStream::str() const -> std::string
13969 return static_cast<std::ostringstream*>(m_oss)->str();
13972 ///////////////////////////////////////////////////////////////////////////
13974 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
13975 std::ostream& cout()
13979 std::ostream& cerr()
13983 std::ostream& clog()
13988 } // namespace Catch
13989 // end catch_stream.cpp
13990 // start catch_string_manip.cpp
13992 #include <algorithm>
14001 char toLowerCh(char c)
14003 return static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
14007 bool startsWith(std::string const& s, std::string const& prefix)
14009 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
14011 bool startsWith(std::string const& s, char prefix)
14013 return !s.empty() && s[0] == prefix;
14015 bool endsWith(std::string const& s, std::string const& suffix)
14017 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
14019 bool endsWith(std::string const& s, char suffix)
14021 return !s.empty() && s[s.size() - 1] == suffix;
14023 bool contains(std::string const& s, std::string const& infix)
14025 return s.find(infix) != std::string::npos;
14027 void toLowerInPlace(std::string& s)
14029 std::transform(s.begin(), s.end(), s.begin(), toLowerCh);
14031 std::string toLower(std::string const& s)
14033 std::string lc = s;
14034 toLowerInPlace(lc);
14037 std::string trim(std::string const& str)
14039 static char const* whitespaceChars = "\n\r\t ";
14040 std::string::size_type start = str.find_first_not_of(whitespaceChars);
14041 std::string::size_type end = str.find_last_not_of(whitespaceChars);
14043 return start != std::string::npos ? str.substr(start, 1 + end - start) : std::string();
14046 StringRef trim(StringRef ref)
14048 const auto is_ws = [](char c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r'; };
14049 size_t real_begin = 0;
14050 while (real_begin < ref.size() && is_ws(ref[real_begin])) {
14053 size_t real_end = ref.size();
14054 while (real_end > real_begin && is_ws(ref[real_end - 1])) {
14058 return ref.substr(real_begin, real_end - real_begin);
14061 bool replaceInPlace(std::string& str, std::string const& replaceThis, std::string const& withThis)
14063 bool replaced = false;
14064 std::size_t i = str.find(replaceThis);
14065 while (i != std::string::npos) {
14067 str = str.substr(0, i) + withThis + str.substr(i + replaceThis.size());
14068 if (i < str.size() - withThis.size())
14069 i = str.find(replaceThis, i + withThis.size());
14071 i = std::string::npos;
14076 std::vector<StringRef> splitStringRef(StringRef str, char delimiter)
14078 std::vector<StringRef> subStrings;
14079 std::size_t start = 0;
14080 for (std::size_t pos = 0; pos < str.size(); ++pos) {
14081 if (str[pos] == delimiter) {
14082 if (pos - start > 1)
14083 subStrings.push_back(str.substr(start, pos - start));
14087 if (start < str.size())
14088 subStrings.push_back(str.substr(start, str.size() - start));
14092 pluralise::pluralise(std::size_t count, std::string const& label) : m_count(count), m_label(label) {}
14094 std::ostream& operator<<(std::ostream& os, pluralise const& pluraliser)
14096 os << pluraliser.m_count << ' ' << pluraliser.m_label;
14097 if (pluraliser.m_count != 1)
14102 } // namespace Catch
14103 // end catch_string_manip.cpp
14104 // start catch_stringref.cpp
14106 #include <algorithm>
14112 StringRef::StringRef(char const* rawChars) noexcept
14113 : StringRef(rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars)))
14117 auto StringRef::c_str() const -> char const*
14119 CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance");
14122 auto StringRef::data() const noexcept -> char const*
14127 auto StringRef::substr(size_type start, size_type size) const noexcept -> StringRef
14129 if (start < m_size) {
14130 return StringRef(m_start + start, (std::min)(m_size - start, size));
14132 return StringRef();
14135 auto StringRef::operator==(StringRef const& other) const noexcept -> bool
14137 return m_size == other.m_size && (std::memcmp(m_start, other.m_start, m_size) == 0);
14140 auto operator<<(std::ostream& os, StringRef const& str) -> std::ostream&
14142 return os.write(str.data(), str.size());
14145 auto operator+=(std::string& lhs, StringRef const& rhs) -> std::string&
14147 lhs.append(rhs.data(), rhs.size());
14151 } // namespace Catch
14152 // end catch_stringref.cpp
14153 // start catch_tag_alias.cpp
14156 TagAlias::TagAlias(std::string const& _tag, SourceLineInfo _lineInfo) : tag(_tag), lineInfo(_lineInfo) {}
14157 } // namespace Catch
14158 // end catch_tag_alias.cpp
14159 // start catch_tag_alias_autoregistrar.cpp
14163 RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo)
14167 getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
14171 // Do not throw when constructing global objects, instead register the exception to be processed later
14172 getMutableRegistryHub().registerStartupException();
14176 } // namespace Catch
14177 // end catch_tag_alias_autoregistrar.cpp
14178 // start catch_tag_alias_registry.cpp
14184 TagAliasRegistry::~TagAliasRegistry() {}
14186 TagAlias const* TagAliasRegistry::find(std::string const& alias) const
14188 auto it = m_registry.find(alias);
14189 if (it != m_registry.end())
14190 return &(it->second);
14195 std::string TagAliasRegistry::expandAliases(std::string const& unexpandedTestSpec) const
14197 std::string expandedTestSpec = unexpandedTestSpec;
14198 for (auto const& registryKvp : m_registry) {
14199 std::size_t pos = expandedTestSpec.find(registryKvp.first);
14200 if (pos != std::string::npos) {
14201 expandedTestSpec = expandedTestSpec.substr(0, pos) + registryKvp.second.tag +
14202 expandedTestSpec.substr(pos + registryKvp.first.size());
14205 return expandedTestSpec;
14208 void TagAliasRegistry::add(std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo)
14210 CATCH_ENFORCE(startsWith(alias, "[@") && endsWith(alias, ']'), "error: tag alias, '"
14211 << alias << "' is not of the form [@alias name].\n"
14214 CATCH_ENFORCE(m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
14215 "error: tag alias, '" << alias << "' already registered.\n"
14216 << "\tFirst seen at: " << find(alias)->lineInfo << "\n"
14217 << "\tRedefined at: " << lineInfo);
14220 ITagAliasRegistry::~ITagAliasRegistry() {}
14222 ITagAliasRegistry const& ITagAliasRegistry::get()
14224 return getRegistryHub().getTagAliasRegistry();
14227 } // end namespace Catch
14228 // end catch_tag_alias_registry.cpp
14229 // start catch_test_case_info.cpp
14231 #include <algorithm>
14233 #include <exception>
14239 TestCaseInfo::SpecialProperties parseSpecialTag(std::string const& tag)
14241 if (startsWith(tag, '.') || tag == "!hide")
14242 return TestCaseInfo::IsHidden;
14243 else if (tag == "!throws")
14244 return TestCaseInfo::Throws;
14245 else if (tag == "!shouldfail")
14246 return TestCaseInfo::ShouldFail;
14247 else if (tag == "!mayfail")
14248 return TestCaseInfo::MayFail;
14249 else if (tag == "!nonportable")
14250 return TestCaseInfo::NonPortable;
14251 else if (tag == "!benchmark")
14252 return static_cast<TestCaseInfo::SpecialProperties>(TestCaseInfo::Benchmark | TestCaseInfo::IsHidden);
14254 return TestCaseInfo::None;
14256 bool isReservedTag(std::string const& tag)
14258 return parseSpecialTag(tag) == TestCaseInfo::None && tag.size() > 0 &&
14259 !std::isalnum(static_cast<unsigned char>(tag[0]));
14261 void enforceNotReservedTag(std::string const& tag, SourceLineInfo const& _lineInfo)
14263 CATCH_ENFORCE(!isReservedTag(tag), "Tag name: ["
14264 << tag << "] is not allowed.\n"
14265 << "Tag names starting with non alphanumeric characters are reserved\n"
14270 TestCase makeTestCase(ITestInvoker* _testCase, std::string const& _className, NameAndTags const& nameAndTags,
14271 SourceLineInfo const& _lineInfo)
14273 bool isHidden = false;
14276 std::vector<std::string> tags;
14277 std::string desc, tag;
14278 bool inTag = false;
14279 for (char c : nameAndTags.tags) {
14287 TestCaseInfo::SpecialProperties prop = parseSpecialTag(tag);
14288 if ((prop & TestCaseInfo::IsHidden) != 0)
14290 else if (prop == TestCaseInfo::None)
14291 enforceNotReservedTag(tag, _lineInfo);
14293 // Merged hide tags like `[.approvals]` should be added as
14294 // `[.][approvals]`. The `[.]` is added at later point, so
14295 // we only strip the prefix
14296 if (startsWith(tag, '.') && tag.size() > 1) {
14299 tags.push_back(tag);
14307 // Add all "hidden" tags to make them behave identically
14308 tags.insert(tags.end(), {".", "!hide"});
14311 TestCaseInfo info(static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo);
14312 return TestCase(_testCase, std::move(info));
14315 void setTags(TestCaseInfo& testCaseInfo, std::vector<std::string> tags)
14317 std::sort(begin(tags), end(tags));
14318 tags.erase(std::unique(begin(tags), end(tags)), end(tags));
14319 testCaseInfo.lcaseTags.clear();
14321 for (auto const& tag : tags) {
14322 std::string lcaseTag = toLower(tag);
14323 testCaseInfo.properties =
14324 static_cast<TestCaseInfo::SpecialProperties>(testCaseInfo.properties | parseSpecialTag(lcaseTag));
14325 testCaseInfo.lcaseTags.push_back(lcaseTag);
14327 testCaseInfo.tags = std::move(tags);
14330 TestCaseInfo::TestCaseInfo(std::string const& _name, std::string const& _className, std::string const& _description,
14331 std::vector<std::string> const& _tags, SourceLineInfo const& _lineInfo)
14332 : name(_name), className(_className), description(_description), lineInfo(_lineInfo), properties(None)
14334 setTags(*this, _tags);
14337 bool TestCaseInfo::isHidden() const
14339 return (properties & IsHidden) != 0;
14341 bool TestCaseInfo::throws() const
14343 return (properties & Throws) != 0;
14345 bool TestCaseInfo::okToFail() const
14347 return (properties & (ShouldFail | MayFail)) != 0;
14349 bool TestCaseInfo::expectedToFail() const
14351 return (properties & (ShouldFail)) != 0;
14354 std::string TestCaseInfo::tagsAsString() const
14357 // '[' and ']' per tag
14358 std::size_t full_size = 2 * tags.size();
14359 for (const auto& tag : tags) {
14360 full_size += tag.size();
14362 ret.reserve(full_size);
14363 for (const auto& tag : tags) {
14364 ret.push_back('[');
14366 ret.push_back(']');
14372 TestCase::TestCase(ITestInvoker* testCase, TestCaseInfo&& info) : TestCaseInfo(std::move(info)), test(testCase) {}
14374 TestCase TestCase::withName(std::string const& _newName) const
14376 TestCase other(*this);
14377 other.name = _newName;
14381 void TestCase::invoke() const
14386 bool TestCase::operator==(TestCase const& other) const
14388 return test.get() == other.test.get() && name == other.name && className == other.className;
14391 bool TestCase::operator<(TestCase const& other) const
14393 return name < other.name;
14396 TestCaseInfo const& TestCase::getTestCaseInfo() const
14401 } // end namespace Catch
14402 // end catch_test_case_info.cpp
14403 // start catch_test_case_registry_impl.cpp
14405 #include <algorithm>
14411 struct TestHasher {
14412 using hash_t = uint64_t;
14414 explicit TestHasher(hash_t hashSuffix) : m_hashSuffix{hashSuffix} {}
14416 uint32_t operator()(TestCase const& t) const
14418 // FNV-1a hash with multiplication fold.
14419 const hash_t prime = 1099511628211u;
14420 hash_t hash = 14695981039346656037u;
14421 for (const char c : t.name) {
14425 hash ^= m_hashSuffix;
14427 const uint32_t low{static_cast<uint32_t>(hash)};
14428 const uint32_t high{static_cast<uint32_t>(hash >> 32)};
14433 hash_t m_hashSuffix;
14435 } // end unnamed namespace
14437 std::vector<TestCase> sortTests(IConfig const& config, std::vector<TestCase> const& unsortedTestCases)
14439 switch (config.runOrder()) {
14440 case RunTests::InDeclarationOrder:
14441 // already in declaration order
14444 case RunTests::InLexicographicalOrder: {
14445 std::vector<TestCase> sorted = unsortedTestCases;
14446 std::sort(sorted.begin(), sorted.end());
14450 case RunTests::InRandomOrder: {
14452 TestHasher h{config.rngSeed()};
14454 using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>;
14455 std::vector<hashedTest> indexed_tests;
14456 indexed_tests.reserve(unsortedTestCases.size());
14458 for (auto const& testCase : unsortedTestCases) {
14459 indexed_tests.emplace_back(h(testCase), &testCase);
14462 std::sort(indexed_tests.begin(), indexed_tests.end(), [](hashedTest const& lhs, hashedTest const& rhs) {
14463 if (lhs.first == rhs.first) {
14464 return lhs.second->name < rhs.second->name;
14466 return lhs.first < rhs.first;
14469 std::vector<TestCase> sorted;
14470 sorted.reserve(indexed_tests.size());
14472 for (auto const& hashed : indexed_tests) {
14473 sorted.emplace_back(*hashed.second);
14479 return unsortedTestCases;
14482 bool isThrowSafe(TestCase const& testCase, IConfig const& config)
14484 return !testCase.throws() || config.allowThrows();
14487 bool matchTest(TestCase const& testCase, TestSpec const& testSpec, IConfig const& config)
14489 return testSpec.matches(testCase) && isThrowSafe(testCase, config);
14492 void enforceNoDuplicateTestCases(std::vector<TestCase> const& functions)
14494 std::set<TestCase> seenFunctions;
14495 for (auto const& function : functions) {
14496 auto prev = seenFunctions.insert(function);
14497 CATCH_ENFORCE(prev.second, "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n"
14498 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo
14500 << "\tRedefined at " << function.getTestCaseInfo().lineInfo);
14504 std::vector<TestCase> filterTests(std::vector<TestCase> const& testCases, TestSpec const& testSpec,
14505 IConfig const& config)
14507 std::vector<TestCase> filtered;
14508 filtered.reserve(testCases.size());
14509 for (auto const& testCase : testCases) {
14510 if ((!testSpec.hasFilters() && !testCase.isHidden()) ||
14511 (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
14512 filtered.push_back(testCase);
14517 std::vector<TestCase> const& getAllTestCasesSorted(IConfig const& config)
14519 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted(config);
14522 void TestRegistry::registerTest(TestCase const& testCase)
14524 std::string name = testCase.getTestCaseInfo().name;
14525 if (name.empty()) {
14526 ReusableStringStream rss;
14527 rss << "Anonymous test case " << ++m_unnamedCount;
14528 return registerTest(testCase.withName(rss.str()));
14530 m_functions.push_back(testCase);
14533 std::vector<TestCase> const& TestRegistry::getAllTests() const
14535 return m_functions;
14537 std::vector<TestCase> const& TestRegistry::getAllTestsSorted(IConfig const& config) const
14539 if (m_sortedFunctions.empty())
14540 enforceNoDuplicateTestCases(m_functions);
14542 if (m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty()) {
14543 m_sortedFunctions = sortTests(config, m_functions);
14544 m_currentSortOrder = config.runOrder();
14546 return m_sortedFunctions;
14549 ///////////////////////////////////////////////////////////////////////////
14550 TestInvokerAsFunction::TestInvokerAsFunction(void (*testAsFunction)()) noexcept : m_testAsFunction(testAsFunction) {}
14552 void TestInvokerAsFunction::invoke() const
14554 m_testAsFunction();
14557 std::string extractClassName(StringRef const& classOrQualifiedMethodName)
14559 std::string className(classOrQualifiedMethodName);
14560 if (startsWith(className, '&')) {
14561 std::size_t lastColons = className.rfind("::");
14562 std::size_t penultimateColons = className.rfind("::", lastColons - 1);
14563 if (penultimateColons == std::string::npos)
14564 penultimateColons = 1;
14565 className = className.substr(penultimateColons, lastColons - penultimateColons);
14570 } // end namespace Catch
14571 // end catch_test_case_registry_impl.cpp
14572 // start catch_test_case_tracker.cpp
14574 #include <algorithm>
14578 #include <stdexcept>
14580 #if defined(__clang__)
14581 #pragma clang diagnostic push
14582 #pragma clang diagnostic ignored "-Wexit-time-destructors"
14586 namespace TestCaseTracking {
14588 NameAndLocation::NameAndLocation(std::string const& _name, SourceLineInfo const& _location)
14589 : name(_name), location(_location)
14593 ITracker::~ITracker() = default;
14595 ITracker& TrackerContext::startRun()
14597 m_rootTracker = std::make_shared<SectionTracker>(NameAndLocation("{root}", CATCH_INTERNAL_LINEINFO), *this, nullptr);
14598 m_currentTracker = nullptr;
14599 m_runState = Executing;
14600 return *m_rootTracker;
14603 void TrackerContext::endRun()
14605 m_rootTracker.reset();
14606 m_currentTracker = nullptr;
14607 m_runState = NotStarted;
14610 void TrackerContext::startCycle()
14612 m_currentTracker = m_rootTracker.get();
14613 m_runState = Executing;
14615 void TrackerContext::completeCycle()
14617 m_runState = CompletedCycle;
14620 bool TrackerContext::completedCycle() const
14622 return m_runState == CompletedCycle;
14624 ITracker& TrackerContext::currentTracker()
14626 return *m_currentTracker;
14628 void TrackerContext::setCurrentTracker(ITracker* tracker)
14630 m_currentTracker = tracker;
14633 TrackerBase::TrackerBase(NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent)
14634 : ITracker(nameAndLocation), m_ctx(ctx), m_parent(parent)
14638 bool TrackerBase::isComplete() const
14640 return m_runState == CompletedSuccessfully || m_runState == Failed;
14642 bool TrackerBase::isSuccessfullyCompleted() const
14644 return m_runState == CompletedSuccessfully;
14646 bool TrackerBase::isOpen() const
14648 return m_runState != NotStarted && !isComplete();
14650 bool TrackerBase::hasChildren() const
14652 return !m_children.empty();
14655 void TrackerBase::addChild(ITrackerPtr const& child)
14657 m_children.push_back(child);
14660 ITrackerPtr TrackerBase::findChild(NameAndLocation const& nameAndLocation)
14662 auto it = std::find_if(m_children.begin(), m_children.end(), [&nameAndLocation](ITrackerPtr const& tracker) {
14663 return tracker->nameAndLocation().location == nameAndLocation.location &&
14664 tracker->nameAndLocation().name == nameAndLocation.name;
14666 return (it != m_children.end()) ? *it : nullptr;
14668 ITracker& TrackerBase::parent()
14670 assert(m_parent); // Should always be non-null except for root
14674 void TrackerBase::openChild()
14676 if (m_runState != ExecutingChildren) {
14677 m_runState = ExecutingChildren;
14679 m_parent->openChild();
14683 bool TrackerBase::isSectionTracker() const
14687 bool TrackerBase::isGeneratorTracker() const
14692 void TrackerBase::open()
14694 m_runState = Executing;
14697 m_parent->openChild();
14700 void TrackerBase::close()
14703 // Close any still open children (e.g. generators)
14704 while (&m_ctx.currentTracker() != this)
14705 m_ctx.currentTracker().close();
14707 switch (m_runState) {
14708 case NeedsAnotherRun:
14712 m_runState = CompletedSuccessfully;
14714 case ExecutingChildren:
14715 if (std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t) { return t->isComplete(); }))
14716 m_runState = CompletedSuccessfully;
14720 case CompletedSuccessfully:
14722 CATCH_INTERNAL_ERROR("Illogical state: " << m_runState);
14725 CATCH_INTERNAL_ERROR("Unknown state: " << m_runState);
14728 m_ctx.completeCycle();
14730 void TrackerBase::fail()
14732 m_runState = Failed;
14734 m_parent->markAsNeedingAnotherRun();
14736 m_ctx.completeCycle();
14738 void TrackerBase::markAsNeedingAnotherRun()
14740 m_runState = NeedsAnotherRun;
14743 void TrackerBase::moveToParent()
14746 m_ctx.setCurrentTracker(m_parent);
14748 void TrackerBase::moveToThis()
14750 m_ctx.setCurrentTracker(this);
14753 SectionTracker::SectionTracker(NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent)
14754 : TrackerBase(nameAndLocation, ctx, parent), m_trimmed_name(trim(nameAndLocation.name))
14757 while (!parent->isSectionTracker())
14758 parent = &parent->parent();
14760 SectionTracker& parentSection = static_cast<SectionTracker&>(*parent);
14761 addNextFilters(parentSection.m_filters);
14765 bool SectionTracker::isComplete() const
14767 bool complete = true;
14769 if (m_filters.empty() || m_filters[0] == "" ||
14770 std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
14771 complete = TrackerBase::isComplete();
14776 bool SectionTracker::isSectionTracker() const
14781 SectionTracker& SectionTracker::acquire(TrackerContext& ctx, NameAndLocation const& nameAndLocation)
14783 std::shared_ptr<SectionTracker> section;
14785 ITracker& currentTracker = ctx.currentTracker();
14786 if (ITrackerPtr childTracker = currentTracker.findChild(nameAndLocation)) {
14787 assert(childTracker);
14788 assert(childTracker->isSectionTracker());
14789 section = std::static_pointer_cast<SectionTracker>(childTracker);
14791 section = std::make_shared<SectionTracker>(nameAndLocation, ctx, ¤tTracker);
14792 currentTracker.addChild(section);
14794 if (!ctx.completedCycle())
14795 section->tryOpen();
14799 void SectionTracker::tryOpen()
14805 void SectionTracker::addInitialFilters(std::vector<std::string> const& filters)
14807 if (!filters.empty()) {
14808 m_filters.reserve(m_filters.size() + filters.size() + 2);
14809 m_filters.emplace_back(""); // Root - should never be consulted
14810 m_filters.emplace_back(""); // Test Case - not a section filter
14811 m_filters.insert(m_filters.end(), filters.begin(), filters.end());
14814 void SectionTracker::addNextFilters(std::vector<std::string> const& filters)
14816 if (filters.size() > 1)
14817 m_filters.insert(m_filters.end(), filters.begin() + 1, filters.end());
14820 std::vector<std::string> const& SectionTracker::getFilters() const
14825 std::string const& SectionTracker::trimmedName() const
14827 return m_trimmed_name;
14830 } // namespace TestCaseTracking
14832 using TestCaseTracking::ITracker;
14833 using TestCaseTracking::SectionTracker;
14834 using TestCaseTracking::TrackerContext;
14836 } // namespace Catch
14838 #if defined(__clang__)
14839 #pragma clang diagnostic pop
14841 // end catch_test_case_tracker.cpp
14842 // start catch_test_registry.cpp
14846 auto makeTestInvoker(void (*testAsFunction)()) noexcept -> ITestInvoker*
14848 return new (std::nothrow) TestInvokerAsFunction(testAsFunction);
14851 NameAndTags::NameAndTags(StringRef const& name_, StringRef const& tags_) noexcept : name(name_), tags(tags_) {}
14853 AutoReg::AutoReg(ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod,
14854 NameAndTags const& nameAndTags) noexcept
14858 getMutableRegistryHub().registerTest(makeTestCase(invoker, extractClassName(classOrMethod), nameAndTags, lineInfo));
14862 // Do not throw when constructing global objects, instead register the exception to be processed later
14863 getMutableRegistryHub().registerStartupException();
14867 AutoReg::~AutoReg() = default;
14868 } // namespace Catch
14869 // end catch_test_registry.cpp
14870 // start catch_test_spec.cpp
14872 #include <algorithm>
14879 TestSpec::Pattern::Pattern(std::string const& name) : m_name(name) {}
14881 TestSpec::Pattern::~Pattern() = default;
14883 std::string const& TestSpec::Pattern::name() const
14888 TestSpec::NamePattern::NamePattern(std::string const& name, std::string const& filterString)
14889 : Pattern(filterString), m_wildcardPattern(toLower(name), CaseSensitive::No)
14893 bool TestSpec::NamePattern::matches(TestCaseInfo const& testCase) const
14895 return m_wildcardPattern.matches(testCase.name);
14898 TestSpec::TagPattern::TagPattern(std::string const& tag, std::string const& filterString)
14899 : Pattern(filterString), m_tag(toLower(tag))
14903 bool TestSpec::TagPattern::matches(TestCaseInfo const& testCase) const
14905 return std::find(begin(testCase.lcaseTags), end(testCase.lcaseTags), m_tag) != end(testCase.lcaseTags);
14908 TestSpec::ExcludedPattern::ExcludedPattern(PatternPtr const& underlyingPattern)
14909 : Pattern(underlyingPattern->name()), m_underlyingPattern(underlyingPattern)
14913 bool TestSpec::ExcludedPattern::matches(TestCaseInfo const& testCase) const
14915 return !m_underlyingPattern->matches(testCase);
14918 bool TestSpec::Filter::matches(TestCaseInfo const& testCase) const
14920 return std::all_of(m_patterns.begin(), m_patterns.end(), [&](PatternPtr const& p) { return p->matches(testCase); });
14923 std::string TestSpec::Filter::name() const
14926 for (auto const& p : m_patterns)
14931 bool TestSpec::hasFilters() const
14933 return !m_filters.empty();
14936 bool TestSpec::matches(TestCaseInfo const& testCase) const
14938 return std::any_of(m_filters.begin(), m_filters.end(), [&](Filter const& f) { return f.matches(testCase); });
14941 TestSpec::Matches TestSpec::matchesByFilter(std::vector<TestCase> const& testCases, IConfig const& config) const
14943 Matches matches(m_filters.size());
14944 std::transform(m_filters.begin(), m_filters.end(), matches.begin(), [&](Filter const& filter) {
14945 std::vector<TestCase const*> currentMatches;
14946 for (auto const& test : testCases)
14947 if (isThrowSafe(test, config) && filter.matches(test))
14948 currentMatches.emplace_back(&test);
14949 return FilterMatch{filter.name(), currentMatches};
14954 const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const
14956 return (m_invalidArgs);
14959 } // namespace Catch
14960 // end catch_test_spec.cpp
14961 // start catch_test_spec_parser.cpp
14965 TestSpecParser::TestSpecParser(ITagAliasRegistry const& tagAliases) : m_tagAliases(&tagAliases) {}
14967 TestSpecParser& TestSpecParser::parse(std::string const& arg)
14970 m_exclusion = false;
14971 m_arg = m_tagAliases->expandAliases(arg);
14972 m_escapeChars.clear();
14973 m_substring.reserve(m_arg.size());
14974 m_patternName.reserve(m_arg.size());
14975 m_realPatternPos = 0;
14977 for (m_pos = 0; m_pos < m_arg.size(); ++m_pos)
14978 // if visitChar fails
14979 if (!visitChar(m_arg[m_pos])) {
14980 m_testSpec.m_invalidArgs.push_back(arg);
14986 TestSpec TestSpecParser::testSpec()
14991 bool TestSpecParser::visitChar(char c)
14993 if ((m_mode != EscapedName) && (c == '\\')) {
14995 addCharToPattern(c);
14997 } else if ((m_mode != EscapedName) && (c == ',')) {
15003 if (processNoneChar(c))
15007 processNameChar(c);
15011 addCharToPattern(c);
15016 if (processOtherChar(c))
15022 if (!isControlChar(c)) {
15023 m_patternName += c;
15024 m_realPatternPos++;
15028 // Two of the processing methods return true to signal the caller to return
15029 // without adding the given character to the current pattern strings
15030 bool TestSpecParser::processNoneChar(char c)
15036 m_exclusion = true;
15042 startNewMode(QuotedName);
15045 startNewMode(Name);
15049 void TestSpecParser::processNameChar(char c)
15052 if (m_substring == "exclude:")
15053 m_exclusion = true;
15059 bool TestSpecParser::processOtherChar(char c)
15061 if (!isControlChar(c))
15067 void TestSpecParser::startNewMode(Mode mode)
15071 void TestSpecParser::endMode()
15076 return addNamePattern();
15078 return addTagPattern();
15080 revertBackToLastMode();
15084 return startNewMode(None);
15087 void TestSpecParser::escape()
15090 m_mode = EscapedName;
15091 m_escapeChars.push_back(m_realPatternPos);
15093 bool TestSpecParser::isControlChar(char c) const
15107 return c == '[' || c == ']';
15111 void TestSpecParser::addFilter()
15113 if (!m_currentFilter.m_patterns.empty()) {
15114 m_testSpec.m_filters.push_back(m_currentFilter);
15115 m_currentFilter = TestSpec::Filter();
15119 void TestSpecParser::saveLastMode()
15124 void TestSpecParser::revertBackToLastMode()
15129 bool TestSpecParser::separate()
15131 if ((m_mode == QuotedName) || (m_mode == Tag)) {
15132 // invalid argument, signal failure to previous scope.
15134 m_pos = m_arg.size();
15135 m_substring.clear();
15136 m_patternName.clear();
15137 m_realPatternPos = 0;
15142 return true; // success
15145 std::string TestSpecParser::preprocessPattern()
15147 std::string token = m_patternName;
15148 for (std::size_t i = 0; i < m_escapeChars.size(); ++i)
15149 token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);
15150 m_escapeChars.clear();
15151 if (startsWith(token, "exclude:")) {
15152 m_exclusion = true;
15153 token = token.substr(8);
15156 m_patternName.clear();
15157 m_realPatternPos = 0;
15162 void TestSpecParser::addNamePattern()
15164 auto token = preprocessPattern();
15166 if (!token.empty()) {
15167 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring);
15169 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
15170 m_currentFilter.m_patterns.push_back(pattern);
15172 m_substring.clear();
15173 m_exclusion = false;
15177 void TestSpecParser::addTagPattern()
15179 auto token = preprocessPattern();
15181 if (!token.empty()) {
15182 // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])
15183 // we have to create a separate hide tag and shorten the real one
15184 if (token.size() > 1 && token[0] == '.') {
15185 token.erase(token.begin());
15186 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring);
15188 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
15190 m_currentFilter.m_patterns.push_back(pattern);
15193 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring);
15196 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
15198 m_currentFilter.m_patterns.push_back(pattern);
15200 m_substring.clear();
15201 m_exclusion = false;
15205 TestSpec parseTestSpec(std::string const& arg)
15207 return TestSpecParser(ITagAliasRegistry::get()).parse(arg).testSpec();
15210 } // namespace Catch
15211 // end catch_test_spec_parser.cpp
15212 // start catch_timer.cpp
15216 static const uint64_t nanosecondsInSecond = 1000000000;
15220 auto getCurrentNanosecondsSinceEpoch() -> uint64_t
15222 return std::chrono::duration_cast<std::chrono::nanoseconds>(
15223 std::chrono::high_resolution_clock::now().time_since_epoch())
15228 auto estimateClockResolution() -> uint64_t
15231 static const uint64_t iterations = 1000000;
15233 auto startTime = getCurrentNanosecondsSinceEpoch();
15235 for (std::size_t i = 0; i < iterations; ++i) {
15238 uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
15240 ticks = getCurrentNanosecondsSinceEpoch();
15241 } while (ticks == baseTicks);
15243 auto delta = ticks - baseTicks;
15246 // If we have been calibrating for over 3 seconds -- the clock
15247 // is terrible and we should move on.
15248 // TBD: How to signal that the measured resolution is probably wrong?
15249 if (ticks > startTime + 3 * nanosecondsInSecond) {
15250 return sum / (i + 1u);
15254 // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers
15255 // - and potentially do more iterations if there's a high variance.
15256 return sum / iterations;
15259 auto getEstimatedClockResolution() -> uint64_t
15261 static auto s_resolution = estimateClockResolution();
15262 return s_resolution;
15265 void Timer::start()
15267 m_nanoseconds = getCurrentNanosecondsSinceEpoch();
15269 auto Timer::getElapsedNanoseconds() const -> uint64_t
15271 return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;
15273 auto Timer::getElapsedMicroseconds() const -> uint64_t
15275 return getElapsedNanoseconds() / 1000;
15277 auto Timer::getElapsedMilliseconds() const -> unsigned int
15279 return static_cast<unsigned int>(getElapsedMicroseconds() / 1000);
15281 auto Timer::getElapsedSeconds() const -> double
15283 return getElapsedMicroseconds() / 1000000.0;
15286 } // namespace Catch
15287 // end catch_timer.cpp
15288 // start catch_tostring.cpp
15290 #if defined(__clang__)
15291 #pragma clang diagnostic push
15292 #pragma clang diagnostic ignored "-Wexit-time-destructors"
15293 #pragma clang diagnostic ignored "-Wglobal-constructors"
15296 // Enable specific decls locally
15297 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
15298 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
15308 const std::string unprintableString = "{?}";
15311 const int hexThreshold = 255;
15313 struct Endianness {
15314 enum Arch { Big, Little };
15316 static Arch which()
15319 // If the lowest byte we read is non-zero, we can assume
15320 // that little endian format is used.
15321 auto value = *reinterpret_cast<char*>(&one);
15322 return value ? Little : Big;
15327 std::string rawMemoryToString(const void* object, std::size_t size)
15329 // Reverse order for little endian architectures
15330 int i = 0, end = static_cast<int>(size), inc = 1;
15331 if (Endianness::which() == Endianness::Little) {
15336 unsigned char const* bytes = static_cast<unsigned char const*>(object);
15337 ReusableStringStream rss;
15338 rss << "0x" << std::setfill('0') << std::hex;
15339 for (; i != end; i += inc)
15340 rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
15343 } // namespace Detail
15345 template <typename T> std::string fpToString(T value, int precision)
15347 if (Catch::isnan(value)) {
15351 ReusableStringStream rss;
15352 rss << std::setprecision(precision) << std::fixed << value;
15353 std::string d = rss.str();
15354 std::size_t i = d.find_last_not_of('0');
15355 if (i != std::string::npos && i != d.size() - 1) {
15358 d = d.substr(0, i + 1);
15363 //// ======================================================= ////
15365 // Out-of-line defs for full specialization of StringMaker
15367 //// ======================================================= ////
15369 std::string StringMaker<std::string>::convert(const std::string& str)
15371 if (!getCurrentContext().getConfig()->showInvisibles()) {
15372 return '"' + str + '"';
15375 std::string s("\"");
15376 for (char c : str) {
15393 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
15394 std::string StringMaker<std::string_view>::convert(std::string_view str)
15396 return ::Catch::Detail::stringify(std::string{str});
15400 std::string StringMaker<char const*>::convert(char const* str)
15403 return ::Catch::Detail::stringify(std::string{str});
15405 return {"{null string}"};
15408 std::string StringMaker<char*>::convert(char* str)
15411 return ::Catch::Detail::stringify(std::string{str});
15413 return {"{null string}"};
15417 #ifdef CATCH_CONFIG_WCHAR
15418 std::string StringMaker<std::wstring>::convert(const std::wstring& wstr)
15421 s.reserve(wstr.size());
15422 for (auto c : wstr) {
15423 s += (c <= 0xff) ? static_cast<char>(c) : '?';
15425 return ::Catch::Detail::stringify(s);
15428 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
15429 std::string StringMaker<std::wstring_view>::convert(std::wstring_view str)
15431 return StringMaker<std::wstring>::convert(std::wstring(str));
15435 std::string StringMaker<wchar_t const*>::convert(wchar_t const* str)
15438 return ::Catch::Detail::stringify(std::wstring{str});
15440 return {"{null string}"};
15443 std::string StringMaker<wchar_t*>::convert(wchar_t* str)
15446 return ::Catch::Detail::stringify(std::wstring{str});
15448 return {"{null string}"};
15453 #if defined(CATCH_CONFIG_CPP17_BYTE)
15455 std::string StringMaker<std::byte>::convert(std::byte value)
15457 return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value));
15459 #endif // defined(CATCH_CONFIG_CPP17_BYTE)
15461 std::string StringMaker<int>::convert(int value)
15463 return ::Catch::Detail::stringify(static_cast<long long>(value));
15465 std::string StringMaker<long>::convert(long value)
15467 return ::Catch::Detail::stringify(static_cast<long long>(value));
15469 std::string StringMaker<long long>::convert(long long value)
15471 ReusableStringStream rss;
15473 if (value > Detail::hexThreshold) {
15474 rss << " (0x" << std::hex << value << ')';
15479 std::string StringMaker<unsigned int>::convert(unsigned int value)
15481 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
15483 std::string StringMaker<unsigned long>::convert(unsigned long value)
15485 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
15487 std::string StringMaker<unsigned long long>::convert(unsigned long long value)
15489 ReusableStringStream rss;
15491 if (value > Detail::hexThreshold) {
15492 rss << " (0x" << std::hex << value << ')';
15497 std::string StringMaker<bool>::convert(bool b)
15499 return b ? "true" : "false";
15502 std::string StringMaker<signed char>::convert(signed char value)
15504 if (value == '\r') {
15506 } else if (value == '\f') {
15508 } else if (value == '\n') {
15510 } else if (value == '\t') {
15512 } else if ('\0' <= value && value < ' ') {
15513 return ::Catch::Detail::stringify(static_cast<unsigned int>(value));
15515 char chstr[] = "' '";
15520 std::string StringMaker<char>::convert(char c)
15522 return ::Catch::Detail::stringify(static_cast<signed char>(c));
15524 std::string StringMaker<unsigned char>::convert(unsigned char c)
15526 return ::Catch::Detail::stringify(static_cast<char>(c));
15529 std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t)
15534 int StringMaker<float>::precision = 5;
15536 std::string StringMaker<float>::convert(float value)
15538 return fpToString(value, precision) + 'f';
15541 int StringMaker<double>::precision = 10;
15543 std::string StringMaker<double>::convert(double value)
15545 return fpToString(value, precision);
15548 std::string ratio_string<std::atto>::symbol()
15552 std::string ratio_string<std::femto>::symbol()
15556 std::string ratio_string<std::pico>::symbol()
15560 std::string ratio_string<std::nano>::symbol()
15564 std::string ratio_string<std::micro>::symbol()
15568 std::string ratio_string<std::milli>::symbol()
15573 } // end namespace Catch
15575 #if defined(__clang__)
15576 #pragma clang diagnostic pop
15579 // end catch_tostring.cpp
15580 // start catch_totals.cpp
15584 Counts Counts::operator-(Counts const& other) const
15587 diff.passed = passed - other.passed;
15588 diff.failed = failed - other.failed;
15589 diff.failedButOk = failedButOk - other.failedButOk;
15593 Counts& Counts::operator+=(Counts const& other)
15595 passed += other.passed;
15596 failed += other.failed;
15597 failedButOk += other.failedButOk;
15601 std::size_t Counts::total() const
15603 return passed + failed + failedButOk;
15605 bool Counts::allPassed() const
15607 return failed == 0 && failedButOk == 0;
15609 bool Counts::allOk() const
15611 return failed == 0;
15614 Totals Totals::operator-(Totals const& other) const
15617 diff.assertions = assertions - other.assertions;
15618 diff.testCases = testCases - other.testCases;
15622 Totals& Totals::operator+=(Totals const& other)
15624 assertions += other.assertions;
15625 testCases += other.testCases;
15629 Totals Totals::delta(Totals const& prevTotals) const
15631 Totals diff = *this - prevTotals;
15632 if (diff.assertions.failed > 0)
15633 ++diff.testCases.failed;
15634 else if (diff.assertions.failedButOk > 0)
15635 ++diff.testCases.failedButOk;
15637 ++diff.testCases.passed;
15641 } // namespace Catch
15642 // end catch_totals.cpp
15643 // start catch_uncaught_exceptions.cpp
15645 // start catch_config_uncaught_exceptions.hpp
15647 // Copyright Catch2 Authors
15648 // Distributed under the Boost Software License, Version 1.0.
15649 // (See accompanying file LICENSE_1_0.txt or copy at
15650 // https://www.boost.org/LICENSE_1_0.txt)
15652 // SPDX-License-Identifier: BSL-1.0
15654 #ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
15655 #define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
15657 #if defined(_MSC_VER)
15658 #if _MSC_VER >= 1900 // Visual Studio 2015 or newer
15659 #define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
15663 #include <exception>
15665 #if defined(__cpp_lib_uncaught_exceptions) && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
15667 #define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
15668 #endif // __cpp_lib_uncaught_exceptions
15670 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && \
15671 !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
15673 #define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
15676 #endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP
15677 // end catch_config_uncaught_exceptions.hpp
15678 #include <exception>
15681 bool uncaught_exceptions()
15683 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
15685 #elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
15686 return std::uncaught_exceptions() > 0;
15688 return std::uncaught_exception();
15691 } // end namespace Catch
15692 // end catch_uncaught_exceptions.cpp
15693 // start catch_version.cpp
15699 Version::Version(unsigned int _majorVersion, unsigned int _minorVersion, unsigned int _patchNumber,
15700 char const* const _branchName, unsigned int _buildNumber)
15701 : majorVersion(_majorVersion)
15702 , minorVersion(_minorVersion)
15703 , patchNumber(_patchNumber)
15704 , branchName(_branchName)
15705 , buildNumber(_buildNumber)
15709 std::ostream& operator<<(std::ostream& os, Version const& version)
15711 os << version.majorVersion << '.' << version.minorVersion << '.' << version.patchNumber;
15712 // branchName is never null -> 0th char is \0 if it is empty
15713 if (version.branchName[0]) {
15714 os << '-' << version.branchName << '.' << version.buildNumber;
15719 Version const& libraryVersion()
15721 static Version version(2, 13, 5, "", 0);
15725 } // namespace Catch
15726 // end catch_version.cpp
15727 // start catch_wildcard_pattern.cpp
15731 WildcardPattern::WildcardPattern(std::string const& pattern, CaseSensitive::Choice caseSensitivity)
15732 : m_caseSensitivity(caseSensitivity), m_pattern(normaliseString(pattern))
15734 if (startsWith(m_pattern, '*')) {
15735 m_pattern = m_pattern.substr(1);
15736 m_wildcard = WildcardAtStart;
15738 if (endsWith(m_pattern, '*')) {
15739 m_pattern = m_pattern.substr(0, m_pattern.size() - 1);
15740 m_wildcard = static_cast<WildcardPosition>(m_wildcard | WildcardAtEnd);
15744 bool WildcardPattern::matches(std::string const& str) const
15746 switch (m_wildcard) {
15748 return m_pattern == normaliseString(str);
15749 case WildcardAtStart:
15750 return endsWith(normaliseString(str), m_pattern);
15751 case WildcardAtEnd:
15752 return startsWith(normaliseString(str), m_pattern);
15753 case WildcardAtBothEnds:
15754 return contains(normaliseString(str), m_pattern);
15756 CATCH_INTERNAL_ERROR("Unknown enum");
15760 std::string WildcardPattern::normaliseString(std::string const& str) const
15762 return trim(m_caseSensitivity == CaseSensitive::No ? toLower(str) : str);
15764 } // namespace Catch
15765 // end catch_wildcard_pattern.cpp
15766 // start catch_xmlwriter.cpp
15769 #include <type_traits>
15775 size_t trailingBytes(unsigned char c)
15777 if ((c & 0xE0) == 0xC0) {
15780 if ((c & 0xF0) == 0xE0) {
15783 if ((c & 0xF8) == 0xF0) {
15786 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
15789 uint32_t headerValue(unsigned char c)
15791 if ((c & 0xE0) == 0xC0) {
15794 if ((c & 0xF0) == 0xE0) {
15797 if ((c & 0xF8) == 0xF0) {
15800 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
15803 void hexEscapeChar(std::ostream& os, unsigned char c)
15805 std::ios_base::fmtflags f(os.flags());
15806 os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(c);
15810 bool shouldNewline(XmlFormatting fmt)
15812 return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Newline));
15815 bool shouldIndent(XmlFormatting fmt)
15817 return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Indent));
15820 } // anonymous namespace
15822 XmlFormatting operator|(XmlFormatting lhs, XmlFormatting rhs)
15824 return static_cast<XmlFormatting>(static_cast<std::underlying_type<XmlFormatting>::type>(lhs) |
15825 static_cast<std::underlying_type<XmlFormatting>::type>(rhs));
15828 XmlFormatting operator&(XmlFormatting lhs, XmlFormatting rhs)
15830 return static_cast<XmlFormatting>(static_cast<std::underlying_type<XmlFormatting>::type>(lhs) &
15831 static_cast<std::underlying_type<XmlFormatting>::type>(rhs));
15834 XmlEncode::XmlEncode(std::string const& str, ForWhat forWhat) : m_str(str), m_forWhat(forWhat) {}
15836 void XmlEncode::encodeTo(std::ostream& os) const
15838 // Apostrophe escaping not necessary if we always use " to write attributes
15839 // (see: http://www.w3.org/TR/xml/#syntax)
15841 for (std::size_t idx = 0; idx < m_str.size(); ++idx) {
15842 unsigned char c = m_str[idx];
15852 // See: http://www.w3.org/TR/xml/#syntax
15853 if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
15860 if (m_forWhat == ForAttributes)
15867 // Check for control characters and invalid utf-8
15869 // Escape control characters in standard ascii
15870 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
15871 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
15872 hexEscapeChar(os, c);
15876 // Plain ASCII: Write it to stream
15883 // Check if the encoding is valid and if it is not, hex escape bytes.
15884 // Important: We do not check the exact decoded values for validity, only the encoding format
15885 // First check that this bytes is a valid lead byte:
15886 // This means that it is not encoded as 1111 1XXX
15888 if (c < 0xC0 || c >= 0xF8) {
15889 hexEscapeChar(os, c);
15893 auto encBytes = trailingBytes(c);
15894 // Are there enough bytes left to avoid accessing out-of-bounds memory?
15895 if (idx + encBytes - 1 >= m_str.size()) {
15896 hexEscapeChar(os, c);
15899 // The header is valid, check data
15900 // The next encBytes bytes must together be a valid utf-8
15901 // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
15903 uint32_t value = headerValue(c);
15904 for (std::size_t n = 1; n < encBytes; ++n) {
15905 unsigned char nc = m_str[idx + n];
15906 valid &= ((nc & 0xC0) == 0x80);
15907 value = (value << 6) | (nc & 0x3F);
15911 // Wrong bit pattern of following bytes
15913 // Overlong encodings
15914 (value < 0x80) || (0x80 <= value && value < 0x800 && encBytes > 2) ||
15915 (0x800 < value && value < 0x10000 && encBytes > 3) ||
15916 // Encoded value out of range
15917 (value >= 0x110000)) {
15918 hexEscapeChar(os, c);
15922 // If we got here, this is in fact a valid(ish) utf-8 sequence
15923 for (std::size_t n = 0; n < encBytes; ++n) {
15924 os << m_str[idx + n];
15926 idx += encBytes - 1;
15932 std::ostream& operator<<(std::ostream& os, XmlEncode const& xmlEncode)
15934 xmlEncode.encodeTo(os);
15938 XmlWriter::ScopedElement::ScopedElement(XmlWriter* writer, XmlFormatting fmt) : m_writer(writer), m_fmt(fmt) {}
15940 XmlWriter::ScopedElement::ScopedElement(ScopedElement&& other) noexcept : m_writer(other.m_writer), m_fmt(other.m_fmt)
15942 other.m_writer = nullptr;
15943 other.m_fmt = XmlFormatting::None;
15945 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=(ScopedElement&& other) noexcept
15948 m_writer->endElement();
15950 m_writer = other.m_writer;
15951 other.m_writer = nullptr;
15952 m_fmt = other.m_fmt;
15953 other.m_fmt = XmlFormatting::None;
15957 XmlWriter::ScopedElement::~ScopedElement()
15960 m_writer->endElement(m_fmt);
15964 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText(std::string const& text, XmlFormatting fmt)
15966 m_writer->writeText(text, fmt);
15970 XmlWriter::XmlWriter(std::ostream& os) : m_os(os)
15972 writeDeclaration();
15975 XmlWriter::~XmlWriter()
15977 while (!m_tags.empty()) {
15980 newlineIfNecessary();
15983 XmlWriter& XmlWriter::startElement(std::string const& name, XmlFormatting fmt)
15986 newlineIfNecessary();
15987 if (shouldIndent(fmt)) {
15991 m_os << '<' << name;
15992 m_tags.push_back(name);
15993 m_tagIsOpen = true;
15994 applyFormatting(fmt);
15998 XmlWriter::ScopedElement XmlWriter::scopedElement(std::string const& name, XmlFormatting fmt)
16000 ScopedElement scoped(this, fmt);
16001 startElement(name, fmt);
16005 XmlWriter& XmlWriter::endElement(XmlFormatting fmt)
16007 m_indent = m_indent.substr(0, m_indent.size() - 2);
16011 m_tagIsOpen = false;
16013 newlineIfNecessary();
16014 if (shouldIndent(fmt)) {
16017 m_os << "</" << m_tags.back() << ">";
16019 m_os << std::flush;
16020 applyFormatting(fmt);
16025 XmlWriter& XmlWriter::writeAttribute(std::string const& name, std::string const& attribute)
16027 if (!name.empty() && !attribute.empty())
16028 m_os << ' ' << name << "=\"" << XmlEncode(attribute, XmlEncode::ForAttributes) << '"';
16032 XmlWriter& XmlWriter::writeAttribute(std::string const& name, bool attribute)
16034 m_os << ' ' << name << "=\"" << (attribute ? "true" : "false") << '"';
16038 XmlWriter& XmlWriter::writeText(std::string const& text, XmlFormatting fmt)
16040 if (!text.empty()) {
16041 bool tagWasOpen = m_tagIsOpen;
16043 if (tagWasOpen && shouldIndent(fmt)) {
16046 m_os << XmlEncode(text);
16047 applyFormatting(fmt);
16052 XmlWriter& XmlWriter::writeComment(std::string const& text, XmlFormatting fmt)
16055 if (shouldIndent(fmt)) {
16058 m_os << "<!--" << text << "-->";
16059 applyFormatting(fmt);
16063 void XmlWriter::writeStylesheetRef(std::string const& url)
16065 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
16068 XmlWriter& XmlWriter::writeBlankLine()
16075 void XmlWriter::ensureTagClosed()
16078 m_os << '>' << std::flush;
16079 newlineIfNecessary();
16080 m_tagIsOpen = false;
16084 void XmlWriter::applyFormatting(XmlFormatting fmt)
16086 m_needsNewline = shouldNewline(fmt);
16089 void XmlWriter::writeDeclaration()
16091 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
16094 void XmlWriter::newlineIfNecessary()
16096 if (m_needsNewline) {
16098 m_needsNewline = false;
16101 } // namespace Catch
16102 // end catch_xmlwriter.cpp
16103 // start catch_reporter_bases.cpp
16112 void prepareExpandedExpression(AssertionResult& result)
16114 result.getExpandedExpression();
16117 // Because formatting using c++ streams is stateful, drop down to C is required
16118 // Alternatively we could use stringstream, but its performance is... not good.
16119 std::string getFormattedDuration(double duration)
16121 // Max exponent + 1 is required to represent the whole part
16122 // + 1 for decimal point
16123 // + 3 for the 3 decimal places
16124 // + 1 for null terminator
16125 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
16126 char buffer[maxDoubleSize];
16128 // Save previous errno, to prevent sprintf from overwriting it
16131 sprintf_s(buffer, "%.3f", duration);
16133 std::sprintf(buffer, "%.3f", duration);
16135 return std::string(buffer);
16138 bool shouldShowDuration(IConfig const& config, double duration)
16140 if (config.showDurations() == ShowDurations::Always) {
16143 if (config.showDurations() == ShowDurations::Never) {
16146 const double min = config.minDuration();
16147 return min >= 0 && duration >= min;
16150 std::string serializeFilters(std::vector<std::string> const& container)
16152 ReusableStringStream oss;
16154 for (auto&& filter : container) {
16165 TestEventListenerBase::TestEventListenerBase(ReporterConfig const& _config) : StreamingReporterBase(_config) {}
16167 std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities()
16169 return {Verbosity::Quiet, Verbosity::Normal, Verbosity::High};
16172 void TestEventListenerBase::assertionStarting(AssertionInfo const&) {}
16174 bool TestEventListenerBase::assertionEnded(AssertionStats const&)
16179 } // end namespace Catch
16180 // end catch_reporter_bases.cpp
16181 // start catch_reporter_compact.cpp
16185 #ifdef CATCH_PLATFORM_MAC
16186 const char* failedString()
16190 const char* passedString()
16195 const char* failedString()
16199 const char* passedString()
16205 // Colour::LightGrey
16206 Catch::Colour::Code dimColour()
16208 return Catch::Colour::FileName;
16211 std::string bothOrAll(std::size_t count)
16213 return count == 1 ? std::string() : count == 2 ? "both " : "all ";
16220 // Colour, message variants:
16221 // - white: No tests ran.
16222 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
16223 // - white: Passed [both/all] N test cases (no assertions).
16224 // - red: Failed N tests cases, failed M assertions.
16225 // - green: Passed [both/all] N tests cases with M assertions.
16226 void printTotals(std::ostream& out, const Totals& totals)
16228 if (totals.testCases.total() == 0) {
16229 out << "No tests ran.";
16230 } else if (totals.testCases.failed == totals.testCases.total()) {
16231 Colour colour(Colour::ResultError);
16232 const std::string qualify_assertions_failed =
16233 totals.assertions.failed == totals.assertions.total() ? bothOrAll(totals.assertions.failed) : std::string();
16234 out << "Failed " << bothOrAll(totals.testCases.failed) << pluralise(totals.testCases.failed, "test case")
16237 << qualify_assertions_failed << pluralise(totals.assertions.failed, "assertion") << '.';
16238 } else if (totals.assertions.total() == 0) {
16239 out << "Passed " << bothOrAll(totals.testCases.total()) << pluralise(totals.testCases.total(), "test case")
16240 << " (no assertions).";
16241 } else if (totals.assertions.failed) {
16242 Colour colour(Colour::ResultError);
16243 out << "Failed " << pluralise(totals.testCases.failed, "test case")
16246 << pluralise(totals.assertions.failed, "assertion") << '.';
16248 Colour colour(Colour::ResultSuccess);
16249 out << "Passed " << bothOrAll(totals.testCases.passed) << pluralise(totals.testCases.passed, "test case")
16250 << " with " << pluralise(totals.assertions.passed, "assertion") << '.';
16254 // Implementation of CompactReporter formatting
16255 class AssertionPrinter {
16257 AssertionPrinter& operator=(AssertionPrinter const&) = delete;
16258 AssertionPrinter(AssertionPrinter const&) = delete;
16259 AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
16261 , result(_stats.assertionResult)
16262 , messages(_stats.infoMessages)
16263 , itMessage(_stats.infoMessages.begin())
16264 , printInfoMessages(_printInfoMessages)
16272 itMessage = messages.begin();
16274 switch (result.getResultType()) {
16275 case ResultWas::Ok:
16276 printResultType(Colour::ResultSuccess, passedString());
16277 printOriginalExpression();
16278 printReconstructedExpression();
16279 if (!result.hasExpression())
16280 printRemainingMessages(Colour::None);
16282 printRemainingMessages();
16284 case ResultWas::ExpressionFailed:
16286 printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok"));
16288 printResultType(Colour::Error, failedString());
16289 printOriginalExpression();
16290 printReconstructedExpression();
16291 printRemainingMessages();
16293 case ResultWas::ThrewException:
16294 printResultType(Colour::Error, failedString());
16295 printIssue("unexpected exception with message:");
16297 printExpressionWas();
16298 printRemainingMessages();
16300 case ResultWas::FatalErrorCondition:
16301 printResultType(Colour::Error, failedString());
16302 printIssue("fatal error condition with message:");
16304 printExpressionWas();
16305 printRemainingMessages();
16307 case ResultWas::DidntThrowException:
16308 printResultType(Colour::Error, failedString());
16309 printIssue("expected exception, got none");
16310 printExpressionWas();
16311 printRemainingMessages();
16313 case ResultWas::Info:
16314 printResultType(Colour::None, "info");
16316 printRemainingMessages();
16318 case ResultWas::Warning:
16319 printResultType(Colour::None, "warning");
16321 printRemainingMessages();
16323 case ResultWas::ExplicitFailure:
16324 printResultType(Colour::Error, failedString());
16325 printIssue("explicitly");
16326 printRemainingMessages(Colour::None);
16328 // These cases are here to prevent compiler warnings
16329 case ResultWas::Unknown:
16330 case ResultWas::FailureBit:
16331 case ResultWas::Exception:
16332 printResultType(Colour::Error, "** internal error **");
16338 void printSourceInfo() const
16340 Colour colourGuard(Colour::FileName);
16341 stream << result.getSourceInfo() << ':';
16344 void printResultType(Colour::Code colour, std::string const& passOrFail) const
16346 if (!passOrFail.empty()) {
16348 Colour colourGuard(colour);
16349 stream << ' ' << passOrFail;
16355 void printIssue(std::string const& issue) const { stream << ' ' << issue; }
16357 void printExpressionWas()
16359 if (result.hasExpression()) {
16362 Colour colour(dimColour());
16363 stream << " expression was:";
16365 printOriginalExpression();
16369 void printOriginalExpression() const
16371 if (result.hasExpression()) {
16372 stream << ' ' << result.getExpression();
16376 void printReconstructedExpression() const
16378 if (result.hasExpandedExpression()) {
16380 Colour colour(dimColour());
16381 stream << " for: ";
16383 stream << result.getExpandedExpression();
16387 void printMessage()
16389 if (itMessage != messages.end()) {
16390 stream << " '" << itMessage->message << '\'';
16395 void printRemainingMessages(Colour::Code colour = dimColour())
16397 if (itMessage == messages.end())
16400 const auto itEnd = messages.cend();
16401 const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
16404 Colour colourGuard(colour);
16405 stream << " with " << pluralise(N, "message") << ':';
16408 while (itMessage != itEnd) {
16409 // If this assertion is a warning ignore any INFO messages
16410 if (printInfoMessages || itMessage->type != ResultWas::Info) {
16412 if (itMessage != itEnd) {
16413 Colour colourGuard(dimColour());
16423 std::ostream& stream;
16424 AssertionResult const& result;
16425 std::vector<MessageInfo> messages;
16426 std::vector<MessageInfo>::const_iterator itMessage;
16427 bool printInfoMessages;
16432 std::string CompactReporter::getDescription()
16434 return "Reports test results on a single line, suitable for IDEs";
16437 void CompactReporter::noMatchingTestCases(std::string const& spec)
16439 stream << "No test cases matched '" << spec << '\'' << std::endl;
16442 void CompactReporter::assertionStarting(AssertionInfo const&) {}
16444 bool CompactReporter::assertionEnded(AssertionStats const& _assertionStats)
16446 AssertionResult const& result = _assertionStats.assertionResult;
16448 bool printInfoMessages = true;
16450 // Drop out if result was successful and we're not printing those
16451 if (!m_config->includeSuccessfulResults() && result.isOk()) {
16452 if (result.getResultType() != ResultWas::Warning)
16454 printInfoMessages = false;
16457 AssertionPrinter printer(stream, _assertionStats, printInfoMessages);
16460 stream << std::endl;
16464 void CompactReporter::sectionEnded(SectionStats const& _sectionStats)
16466 double dur = _sectionStats.durationInSeconds;
16467 if (shouldShowDuration(*m_config, dur)) {
16468 stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl;
16472 void CompactReporter::testRunEnded(TestRunStats const& _testRunStats)
16474 printTotals(stream, _testRunStats.totals);
16475 stream << '\n' << std::endl;
16476 StreamingReporterBase::testRunEnded(_testRunStats);
16479 CompactReporter::~CompactReporter() {}
16481 CATCH_REGISTER_REPORTER("compact", CompactReporter)
16483 } // end namespace Catch
16484 // end catch_reporter_compact.cpp
16485 // start catch_reporter_console.cpp
16490 #if defined(_MSC_VER)
16491 #pragma warning(push)
16492 #pragma warning(disable : 4061) // Not all labels are EXPLICITLY handled in switch
16493 // Note that 4062 (not all labels are handled and default is missing) is enabled
16496 #if defined(__clang__)
16497 #pragma clang diagnostic push
16498 // For simplicity, benchmarking-only helpers are always enabled
16499 #pragma clang diagnostic ignored "-Wunused-function"
16506 // Formatter impl for ConsoleReporter
16507 class ConsoleAssertionPrinter {
16509 ConsoleAssertionPrinter& operator=(ConsoleAssertionPrinter const&) = delete;
16510 ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete;
16511 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
16514 , result(_stats.assertionResult)
16515 , colour(Colour::None)
16516 , message(result.getMessage())
16517 , messages(_stats.infoMessages)
16518 , printInfoMessages(_printInfoMessages)
16520 switch (result.getResultType()) {
16521 case ResultWas::Ok:
16522 colour = Colour::Success;
16523 passOrFail = "PASSED";
16524 // if( result.hasMessage() )
16525 if (_stats.infoMessages.size() == 1)
16526 messageLabel = "with message";
16527 if (_stats.infoMessages.size() > 1)
16528 messageLabel = "with messages";
16530 case ResultWas::ExpressionFailed:
16531 if (result.isOk()) {
16532 colour = Colour::Success;
16533 passOrFail = "FAILED - but was ok";
16535 colour = Colour::Error;
16536 passOrFail = "FAILED";
16538 if (_stats.infoMessages.size() == 1)
16539 messageLabel = "with message";
16540 if (_stats.infoMessages.size() > 1)
16541 messageLabel = "with messages";
16543 case ResultWas::ThrewException:
16544 colour = Colour::Error;
16545 passOrFail = "FAILED";
16546 messageLabel = "due to unexpected exception with ";
16547 if (_stats.infoMessages.size() == 1)
16548 messageLabel += "message";
16549 if (_stats.infoMessages.size() > 1)
16550 messageLabel += "messages";
16552 case ResultWas::FatalErrorCondition:
16553 colour = Colour::Error;
16554 passOrFail = "FAILED";
16555 messageLabel = "due to a fatal error condition";
16557 case ResultWas::DidntThrowException:
16558 colour = Colour::Error;
16559 passOrFail = "FAILED";
16560 messageLabel = "because no exception was thrown where one was expected";
16562 case ResultWas::Info:
16563 messageLabel = "info";
16565 case ResultWas::Warning:
16566 messageLabel = "warning";
16568 case ResultWas::ExplicitFailure:
16569 passOrFail = "FAILED";
16570 colour = Colour::Error;
16571 if (_stats.infoMessages.size() == 1)
16572 messageLabel = "explicitly with message";
16573 if (_stats.infoMessages.size() > 1)
16574 messageLabel = "explicitly with messages";
16576 // These cases are here to prevent compiler warnings
16577 case ResultWas::Unknown:
16578 case ResultWas::FailureBit:
16579 case ResultWas::Exception:
16580 passOrFail = "** internal error **";
16581 colour = Colour::Error;
16589 if (stats.totals.assertions.total() > 0) {
16591 printOriginalExpression();
16592 printReconstructedExpression();
16600 void printResultType() const
16602 if (!passOrFail.empty()) {
16603 Colour colourGuard(colour);
16604 stream << passOrFail << ":\n";
16607 void printOriginalExpression() const
16609 if (result.hasExpression()) {
16610 Colour colourGuard(Colour::OriginalExpression);
16612 stream << result.getExpressionInMacro();
16616 void printReconstructedExpression() const
16618 if (result.hasExpandedExpression()) {
16619 stream << "with expansion:\n";
16620 Colour colourGuard(Colour::ReconstructedExpression);
16621 stream << Column(result.getExpandedExpression()).indent(2) << '\n';
16624 void printMessage() const
16626 if (!messageLabel.empty())
16627 stream << messageLabel << ':' << '\n';
16628 for (auto const& msg : messages) {
16629 // If this assertion is a warning ignore any INFO messages
16630 if (printInfoMessages || msg.type != ResultWas::Info)
16631 stream << Column(msg.message).indent(2) << '\n';
16634 void printSourceInfo() const
16636 Colour colourGuard(Colour::FileName);
16637 stream << result.getSourceInfo() << ": ";
16640 std::ostream& stream;
16641 AssertionStats const& stats;
16642 AssertionResult const& result;
16643 Colour::Code colour;
16644 std::string passOrFail;
16645 std::string messageLabel;
16646 std::string message;
16647 std::vector<MessageInfo> messages;
16648 bool printInfoMessages;
16651 std::size_t makeRatio(std::size_t number, std::size_t total)
16653 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
16654 return (ratio == 0 && number > 0) ? 1 : ratio;
16657 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k)
16659 if (i > j && i > k)
16667 struct ColumnInfo {
16668 enum Justification { Left, Right };
16671 Justification justification;
16673 struct ColumnBreak {};
16674 struct RowBreak {};
16677 enum class Unit { Auto, Nanoseconds, Microseconds, Milliseconds, Seconds, Minutes };
16678 static const uint64_t s_nanosecondsInAMicrosecond = 1000;
16679 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
16680 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
16681 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
16683 double m_inNanoseconds;
16687 explicit Duration(double inNanoseconds, Unit units = Unit::Auto) : m_inNanoseconds(inNanoseconds), m_units(units)
16689 if (m_units == Unit::Auto) {
16690 if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
16691 m_units = Unit::Nanoseconds;
16692 else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
16693 m_units = Unit::Microseconds;
16694 else if (m_inNanoseconds < s_nanosecondsInASecond)
16695 m_units = Unit::Milliseconds;
16696 else if (m_inNanoseconds < s_nanosecondsInAMinute)
16697 m_units = Unit::Seconds;
16699 m_units = Unit::Minutes;
16703 auto value() const -> double
16706 case Unit::Microseconds:
16707 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond);
16708 case Unit::Milliseconds:
16709 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond);
16710 case Unit::Seconds:
16711 return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond);
16712 case Unit::Minutes:
16713 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
16715 return m_inNanoseconds;
16718 auto unitsAsString() const -> std::string
16721 case Unit::Nanoseconds:
16723 case Unit::Microseconds:
16725 case Unit::Milliseconds:
16727 case Unit::Seconds:
16729 case Unit::Minutes:
16732 return "** internal error **";
16735 friend auto operator<<(std::ostream& os, Duration const& duration) -> std::ostream&
16737 return os << duration.value() << ' ' << duration.unitsAsString();
16742 class TablePrinter {
16743 std::ostream& m_os;
16744 std::vector<ColumnInfo> m_columnInfos;
16745 std::ostringstream m_oss;
16746 int m_currentColumn = -1;
16747 bool m_isOpen = false;
16750 TablePrinter(std::ostream& os, std::vector<ColumnInfo> columnInfos) : m_os(os), m_columnInfos(std::move(columnInfos))
16754 auto columnInfos() const -> std::vector<ColumnInfo> const& { return m_columnInfos; }
16760 *this << RowBreak();
16762 Columns headerCols;
16764 for (auto const& info : m_columnInfos) {
16765 headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2));
16766 headerCols += spacer;
16768 m_os << headerCols << '\n';
16770 m_os << Catch::getLineOfChars<'-'>() << '\n';
16776 *this << RowBreak();
16782 template <typename T> friend TablePrinter& operator<<(TablePrinter& tp, T const& value)
16788 friend TablePrinter& operator<<(TablePrinter& tp, ColumnBreak)
16790 auto colStr = tp.m_oss.str();
16791 const auto strSize = colStr.size();
16794 if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
16795 tp.m_currentColumn = -1;
16798 tp.m_currentColumn++;
16800 auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
16801 auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width))
16802 ? std::string(colInfo.width - (strSize + 1), ' ')
16804 if (colInfo.justification == ColumnInfo::Left)
16805 tp.m_os << colStr << padding << ' ';
16807 tp.m_os << padding << colStr << ' ';
16811 friend TablePrinter& operator<<(TablePrinter& tp, RowBreak)
16813 if (tp.m_currentColumn > 0) {
16815 tp.m_currentColumn = -1;
16821 ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
16822 : StreamingReporterBase(config)
16823 , m_tablePrinter(new TablePrinter(config.stream(), [&config]() -> std::vector<ColumnInfo> {
16824 if (config.fullConfig()->benchmarkNoAnalysis()) {
16825 return {{"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left},
16826 {" samples", 14, ColumnInfo::Right},
16827 {" iterations", 14, ColumnInfo::Right},
16828 {" mean", 14, ColumnInfo::Right}};
16830 return {{"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left},
16831 {"samples mean std dev", 14, ColumnInfo::Right},
16832 {"iterations low mean low std dev", 14, ColumnInfo::Right},
16833 {"estimated high mean high std dev", 14, ColumnInfo::Right}};
16838 ConsoleReporter::~ConsoleReporter() = default;
16840 std::string ConsoleReporter::getDescription()
16842 return "Reports test results as plain lines of text";
16845 void ConsoleReporter::noMatchingTestCases(std::string const& spec)
16847 stream << "No test cases matched '" << spec << '\'' << std::endl;
16850 void ConsoleReporter::reportInvalidArguments(std::string const& arg)
16852 stream << "Invalid Filter: " << arg << std::endl;
16855 void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
16857 bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats)
16859 AssertionResult const& result = _assertionStats.assertionResult;
16861 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
16863 // Drop out if result was successful but we're not printing them.
16864 if (!includeResults && result.getResultType() != ResultWas::Warning)
16869 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
16871 stream << std::endl;
16875 void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo)
16877 m_tablePrinter->close();
16878 m_headerPrinted = false;
16879 StreamingReporterBase::sectionStarting(_sectionInfo);
16881 void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats)
16883 m_tablePrinter->close();
16884 if (_sectionStats.missingAssertions) {
16886 Colour colour(Colour::ResultError);
16887 if (m_sectionStack.size() > 1)
16888 stream << "\nNo assertions in section";
16890 stream << "\nNo assertions in test case";
16891 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
16893 double dur = _sectionStats.durationInSeconds;
16894 if (shouldShowDuration(*m_config, dur)) {
16895 stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl;
16897 if (m_headerPrinted) {
16898 m_headerPrinted = false;
16900 StreamingReporterBase::sectionEnded(_sectionStats);
16903 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
16904 void ConsoleReporter::benchmarkPreparing(std::string const& name)
16906 lazyPrintWithoutClosingBenchmarkTable();
16908 auto nameCol = Column(name).width(static_cast<std::size_t>(m_tablePrinter->columnInfos()[0].width - 2));
16910 bool firstLine = true;
16911 for (auto line : nameCol) {
16913 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
16917 (*m_tablePrinter) << line << ColumnBreak();
16921 void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info)
16923 (*m_tablePrinter) << info.samples << ColumnBreak() << info.iterations << ColumnBreak();
16924 if (!m_config->benchmarkNoAnalysis())
16925 (*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak();
16927 void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats)
16929 if (m_config->benchmarkNoAnalysis()) {
16930 (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
16932 (*m_tablePrinter) << ColumnBreak() << Duration(stats.mean.point.count()) << ColumnBreak()
16933 << Duration(stats.mean.lower_bound.count()) << ColumnBreak()
16934 << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()
16935 << Duration(stats.standardDeviation.point.count()) << ColumnBreak()
16936 << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()
16937 << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak()
16938 << ColumnBreak() << ColumnBreak() << ColumnBreak();
16942 void ConsoleReporter::benchmarkFailed(std::string const& error)
16944 Colour colour(Colour::Red);
16945 (*m_tablePrinter) << "Benchmark failed (" << error << ')' << ColumnBreak() << RowBreak();
16947 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
16949 void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats)
16951 m_tablePrinter->close();
16952 StreamingReporterBase::testCaseEnded(_testCaseStats);
16953 m_headerPrinted = false;
16955 void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats)
16957 if (currentGroupInfo.used) {
16958 printSummaryDivider();
16959 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
16960 printTotals(_testGroupStats.totals);
16961 stream << '\n' << std::endl;
16963 StreamingReporterBase::testGroupEnded(_testGroupStats);
16965 void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats)
16967 printTotalsDivider(_testRunStats.totals);
16968 printTotals(_testRunStats.totals);
16969 stream << std::endl;
16970 StreamingReporterBase::testRunEnded(_testRunStats);
16972 void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo)
16974 StreamingReporterBase::testRunStarting(_testInfo);
16975 printTestFilters();
16978 void ConsoleReporter::lazyPrint()
16981 m_tablePrinter->close();
16982 lazyPrintWithoutClosingBenchmarkTable();
16985 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable()
16988 if (!currentTestRunInfo.used)
16989 lazyPrintRunInfo();
16990 if (!currentGroupInfo.used)
16991 lazyPrintGroupInfo();
16993 if (!m_headerPrinted) {
16994 printTestCaseAndSectionHeader();
16995 m_headerPrinted = true;
16998 void ConsoleReporter::lazyPrintRunInfo()
17000 stream << '\n' << getLineOfChars<'~'>() << '\n';
17001 Colour colour(Colour::SecondaryText);
17002 stream << currentTestRunInfo->name << " is a Catch v" << libraryVersion() << " host application.\n"
17003 << "Run with -? for options\n\n";
17005 if (m_config->rngSeed() != 0)
17006 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
17008 currentTestRunInfo.used = true;
17010 void ConsoleReporter::lazyPrintGroupInfo()
17012 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
17013 printClosedHeader("Group: " + currentGroupInfo->name);
17014 currentGroupInfo.used = true;
17017 void ConsoleReporter::printTestCaseAndSectionHeader()
17019 assert(!m_sectionStack.empty());
17020 printOpenHeader(currentTestCaseInfo->name);
17022 if (m_sectionStack.size() > 1) {
17023 Colour colourGuard(Colour::Headers);
17025 auto it = m_sectionStack.begin() + 1, // Skip first section (test case)
17026 itEnd = m_sectionStack.end();
17027 for (; it != itEnd; ++it)
17028 printHeaderString(it->name, 2);
17031 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
17033 stream << getLineOfChars<'-'>() << '\n';
17034 Colour colourGuard(Colour::FileName);
17035 stream << lineInfo << '\n';
17036 stream << getLineOfChars<'.'>() << '\n' << std::endl;
17039 void ConsoleReporter::printClosedHeader(std::string const& _name)
17041 printOpenHeader(_name);
17042 stream << getLineOfChars<'.'>() << '\n';
17044 void ConsoleReporter::printOpenHeader(std::string const& _name)
17046 stream << getLineOfChars<'-'>() << '\n';
17048 Colour colourGuard(Colour::Headers);
17049 printHeaderString(_name);
17053 // if string has a : in first line will set indent to follow it on
17054 // subsequent lines
17055 void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent)
17057 std::size_t i = _string.find(": ");
17058 if (i != std::string::npos)
17062 stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n';
17065 struct SummaryColumn {
17067 SummaryColumn(std::string _label, Colour::Code _colour) : label(std::move(_label)), colour(_colour) {}
17068 SummaryColumn addRow(std::size_t count)
17070 ReusableStringStream rss;
17072 std::string row = rss.str();
17073 for (auto& oldRow : rows) {
17074 while (oldRow.size() < row.size())
17075 oldRow = ' ' + oldRow;
17076 while (oldRow.size() > row.size())
17079 rows.push_back(row);
17084 Colour::Code colour;
17085 std::vector<std::string> rows;
17088 void ConsoleReporter::printTotals(Totals const& totals)
17090 if (totals.testCases.total() == 0) {
17091 stream << Colour(Colour::Warning) << "No tests ran\n";
17092 } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {
17093 stream << Colour(Colour::ResultSuccess) << "All tests passed";
17094 stream << " (" << pluralise(totals.assertions.passed, "assertion") << " in "
17095 << pluralise(totals.testCases.passed, "test case") << ')' << '\n';
17098 std::vector<SummaryColumn> columns;
17100 SummaryColumn("", Colour::None).addRow(totals.testCases.total()).addRow(totals.assertions.total()));
17102 SummaryColumn("passed", Colour::Success).addRow(totals.testCases.passed).addRow(totals.assertions.passed));
17104 SummaryColumn("failed", Colour::ResultError).addRow(totals.testCases.failed).addRow(totals.assertions.failed));
17105 columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure)
17106 .addRow(totals.testCases.failedButOk)
17107 .addRow(totals.assertions.failedButOk));
17109 printSummaryRow("test cases", columns, 0);
17110 printSummaryRow("assertions", columns, 1);
17113 void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row)
17115 for (auto col : cols) {
17116 std::string value = col.rows[row];
17117 if (col.label.empty()) {
17118 stream << label << ": ";
17122 stream << Colour(Colour::Warning) << "- none -";
17123 } else if (value != "0") {
17124 stream << Colour(Colour::LightGrey) << " | ";
17125 stream << Colour(col.colour) << value << ' ' << col.label;
17131 void ConsoleReporter::printTotalsDivider(Totals const& totals)
17133 if (totals.testCases.total() > 0) {
17134 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
17135 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
17136 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
17137 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
17138 findMax(failedRatio, failedButOkRatio, passedRatio)++;
17139 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
17140 findMax(failedRatio, failedButOkRatio, passedRatio)--;
17142 stream << Colour(Colour::Error) << std::string(failedRatio, '=');
17143 stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '=');
17144 if (totals.testCases.allPassed())
17145 stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '=');
17147 stream << Colour(Colour::Success) << std::string(passedRatio, '=');
17149 stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '=');
17153 void ConsoleReporter::printSummaryDivider()
17155 stream << getLineOfChars<'-'>() << '\n';
17158 void ConsoleReporter::printTestFilters()
17160 if (m_config->testSpec().hasFilters()) {
17161 Colour guard(Colour::BrightYellow);
17162 stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) << '\n';
17166 CATCH_REGISTER_REPORTER("console", ConsoleReporter)
17168 } // end namespace Catch
17170 #if defined(_MSC_VER)
17171 #pragma warning(pop)
17174 #if defined(__clang__)
17175 #pragma clang diagnostic pop
17177 // end catch_reporter_console.cpp
17178 // start catch_reporter_junit.cpp
17180 #include <algorithm>
17188 std::string getCurrentTimestamp()
17190 // Beware, this is not reentrant because of backward compatibility issues
17191 // Also, UTC only, again because of backward compatibility (%z is C++11)
17193 std::time(&rawtime);
17194 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
17197 std::tm timeInfo = {};
17198 gmtime_s(&timeInfo, &rawtime);
17201 timeInfo = std::gmtime(&rawtime);
17204 char timeStamp[timeStampSize];
17205 const char* const fmt = "%Y-%m-%dT%H:%M:%SZ";
17208 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
17210 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
17212 return std::string(timeStamp);
17215 std::string fileNameTag(const std::vector<std::string>& tags)
17217 auto it = std::find_if(begin(tags), end(tags), [](std::string const& tag) { return tag.front() == '#'; });
17218 if (it != tags.end())
17219 return it->substr(1);
17220 return std::string();
17222 } // anonymous namespace
17224 JunitReporter::JunitReporter(ReporterConfig const& _config) : CumulativeReporterBase(_config), xml(_config.stream())
17226 m_reporterPrefs.shouldRedirectStdOut = true;
17227 m_reporterPrefs.shouldReportAllAssertions = true;
17230 JunitReporter::~JunitReporter() {}
17232 std::string JunitReporter::getDescription()
17234 return "Reports test results in an XML format that looks like Ant's junitreport target";
17237 void JunitReporter::noMatchingTestCases(std::string const& /*spec*/) {}
17239 void JunitReporter::testRunStarting(TestRunInfo const& runInfo)
17241 CumulativeReporterBase::testRunStarting(runInfo);
17242 xml.startElement("testsuites");
17245 void JunitReporter::testGroupStarting(GroupInfo const& groupInfo)
17247 suiteTimer.start();
17248 stdOutForSuite.clear();
17249 stdErrForSuite.clear();
17250 unexpectedExceptions = 0;
17251 CumulativeReporterBase::testGroupStarting(groupInfo);
17254 void JunitReporter::testCaseStarting(TestCaseInfo const& testCaseInfo)
17256 m_okToFail = testCaseInfo.okToFail();
17259 bool JunitReporter::assertionEnded(AssertionStats const& assertionStats)
17261 if (assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail)
17262 unexpectedExceptions++;
17263 return CumulativeReporterBase::assertionEnded(assertionStats);
17266 void JunitReporter::testCaseEnded(TestCaseStats const& testCaseStats)
17268 stdOutForSuite += testCaseStats.stdOut;
17269 stdErrForSuite += testCaseStats.stdErr;
17270 CumulativeReporterBase::testCaseEnded(testCaseStats);
17273 void JunitReporter::testGroupEnded(TestGroupStats const& testGroupStats)
17275 double suiteTime = suiteTimer.getElapsedSeconds();
17276 CumulativeReporterBase::testGroupEnded(testGroupStats);
17277 writeGroup(*m_testGroups.back(), suiteTime);
17280 void JunitReporter::testRunEndedCumulative()
17285 void JunitReporter::writeGroup(TestGroupNode const& groupNode, double suiteTime)
17287 XmlWriter::ScopedElement e = xml.scopedElement("testsuite");
17289 TestGroupStats const& stats = groupNode.value;
17290 xml.writeAttribute("name", stats.groupInfo.name);
17291 xml.writeAttribute("errors", unexpectedExceptions);
17292 xml.writeAttribute("failures", stats.totals.assertions.failed - unexpectedExceptions);
17293 xml.writeAttribute("tests", stats.totals.assertions.total());
17294 xml.writeAttribute("hostname", "tbd"); // !TBD
17295 if (m_config->showDurations() == ShowDurations::Never)
17296 xml.writeAttribute("time", "");
17298 xml.writeAttribute("time", suiteTime);
17299 xml.writeAttribute("timestamp", getCurrentTimestamp());
17301 // Write properties if there are any
17302 if (m_config->hasTestFilters() || m_config->rngSeed() != 0) {
17303 auto properties = xml.scopedElement("properties");
17304 if (m_config->hasTestFilters()) {
17305 xml.scopedElement("property")
17306 .writeAttribute("name", "filters")
17307 .writeAttribute("value", serializeFilters(m_config->getTestsOrTags()));
17309 if (m_config->rngSeed() != 0) {
17310 xml.scopedElement("property").writeAttribute("name", "random-seed").writeAttribute("value", m_config->rngSeed());
17314 // Write test cases
17315 for (auto const& child : groupNode.children)
17316 writeTestCase(*child);
17318 xml.scopedElement("system-out").writeText(trim(stdOutForSuite), XmlFormatting::Newline);
17319 xml.scopedElement("system-err").writeText(trim(stdErrForSuite), XmlFormatting::Newline);
17322 void JunitReporter::writeTestCase(TestCaseNode const& testCaseNode)
17324 TestCaseStats const& stats = testCaseNode.value;
17326 // All test cases have exactly one section - which represents the
17327 // test case itself. That section may have 0-n nested sections
17328 assert(testCaseNode.children.size() == 1);
17329 SectionNode const& rootSection = *testCaseNode.children.front();
17331 std::string className = stats.testInfo.className;
17333 if (className.empty()) {
17334 className = fileNameTag(stats.testInfo.tags);
17335 if (className.empty())
17336 className = "global";
17339 if (!m_config->name().empty())
17340 className = m_config->name() + "." + className;
17342 writeSection(className, "", rootSection);
17345 void JunitReporter::writeSection(std::string const& className, std::string const& rootName,
17346 SectionNode const& sectionNode)
17348 std::string name = trim(sectionNode.stats.sectionInfo.name);
17349 if (!rootName.empty())
17350 name = rootName + '/' + name;
17352 if (!sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || !sectionNode.stdErr.empty()) {
17353 XmlWriter::ScopedElement e = xml.scopedElement("testcase");
17354 if (className.empty()) {
17355 xml.writeAttribute("classname", name);
17356 xml.writeAttribute("name", "root");
17358 xml.writeAttribute("classname", className);
17359 xml.writeAttribute("name", name);
17361 xml.writeAttribute("time", ::Catch::Detail::stringify(sectionNode.stats.durationInSeconds));
17362 // This is not ideal, but it should be enough to mimic gtest's
17364 // Ideally the JUnit reporter would also handle `skipTest`
17365 // events and write those out appropriately.
17366 xml.writeAttribute("status", "run");
17368 writeAssertions(sectionNode);
17370 if (!sectionNode.stdOut.empty())
17371 xml.scopedElement("system-out").writeText(trim(sectionNode.stdOut), XmlFormatting::Newline);
17372 if (!sectionNode.stdErr.empty())
17373 xml.scopedElement("system-err").writeText(trim(sectionNode.stdErr), XmlFormatting::Newline);
17375 for (auto const& childNode : sectionNode.childSections)
17376 if (className.empty())
17377 writeSection(name, "", *childNode);
17379 writeSection(className, name, *childNode);
17382 void JunitReporter::writeAssertions(SectionNode const& sectionNode)
17384 for (auto const& assertion : sectionNode.assertions)
17385 writeAssertion(assertion);
17388 void JunitReporter::writeAssertion(AssertionStats const& stats)
17390 AssertionResult const& result = stats.assertionResult;
17391 if (!result.isOk()) {
17392 std::string elementName;
17393 switch (result.getResultType()) {
17394 case ResultWas::ThrewException:
17395 case ResultWas::FatalErrorCondition:
17396 elementName = "error";
17398 case ResultWas::ExplicitFailure:
17399 case ResultWas::ExpressionFailed:
17400 case ResultWas::DidntThrowException:
17401 elementName = "failure";
17404 // We should never see these here:
17405 case ResultWas::Info:
17406 case ResultWas::Warning:
17407 case ResultWas::Ok:
17408 case ResultWas::Unknown:
17409 case ResultWas::FailureBit:
17410 case ResultWas::Exception:
17411 elementName = "internalError";
17415 XmlWriter::ScopedElement e = xml.scopedElement(elementName);
17417 xml.writeAttribute("message", result.getExpression());
17418 xml.writeAttribute("type", result.getTestMacroName());
17420 ReusableStringStream rss;
17421 if (stats.totals.assertions.total() > 0) {
17424 if (result.hasExpression()) {
17426 rss << result.getExpressionInMacro();
17429 if (result.hasExpandedExpression()) {
17430 rss << "with expansion:\n";
17431 rss << Column(result.getExpandedExpression()).indent(2) << '\n';
17437 if (!result.getMessage().empty())
17438 rss << result.getMessage() << '\n';
17439 for (auto const& msg : stats.infoMessages)
17440 if (msg.type == ResultWas::Info)
17441 rss << msg.message << '\n';
17443 rss << "at " << result.getSourceInfo();
17444 xml.writeText(rss.str(), XmlFormatting::Newline);
17448 CATCH_REGISTER_REPORTER("junit", JunitReporter)
17450 } // end namespace Catch
17451 // end catch_reporter_junit.cpp
17452 // start catch_reporter_listening.cpp
17458 ListeningReporter::ListeningReporter()
17460 // We will assume that listeners will always want all assertions
17461 m_preferences.shouldReportAllAssertions = true;
17464 void ListeningReporter::addListener(IStreamingReporterPtr&& listener)
17466 m_listeners.push_back(std::move(listener));
17469 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter)
17471 assert(!m_reporter && "Listening reporter can wrap only 1 real reporter");
17472 m_reporter = std::move(reporter);
17473 m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;
17476 ReporterPreferences ListeningReporter::getPreferences() const
17478 return m_preferences;
17481 std::set<Verbosity> ListeningReporter::getSupportedVerbosities()
17483 return std::set<Verbosity>{};
17486 void ListeningReporter::noMatchingTestCases(std::string const& spec)
17488 for (auto const& listener : m_listeners) {
17489 listener->noMatchingTestCases(spec);
17491 m_reporter->noMatchingTestCases(spec);
17494 void ListeningReporter::reportInvalidArguments(std::string const& arg)
17496 for (auto const& listener : m_listeners) {
17497 listener->reportInvalidArguments(arg);
17499 m_reporter->reportInvalidArguments(arg);
17502 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
17503 void ListeningReporter::benchmarkPreparing(std::string const& name)
17505 for (auto const& listener : m_listeners) {
17506 listener->benchmarkPreparing(name);
17508 m_reporter->benchmarkPreparing(name);
17510 void ListeningReporter::benchmarkStarting(BenchmarkInfo const& benchmarkInfo)
17512 for (auto const& listener : m_listeners) {
17513 listener->benchmarkStarting(benchmarkInfo);
17515 m_reporter->benchmarkStarting(benchmarkInfo);
17517 void ListeningReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats)
17519 for (auto const& listener : m_listeners) {
17520 listener->benchmarkEnded(benchmarkStats);
17522 m_reporter->benchmarkEnded(benchmarkStats);
17525 void ListeningReporter::benchmarkFailed(std::string const& error)
17527 for (auto const& listener : m_listeners) {
17528 listener->benchmarkFailed(error);
17530 m_reporter->benchmarkFailed(error);
17532 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
17534 void ListeningReporter::testRunStarting(TestRunInfo const& testRunInfo)
17536 for (auto const& listener : m_listeners) {
17537 listener->testRunStarting(testRunInfo);
17539 m_reporter->testRunStarting(testRunInfo);
17542 void ListeningReporter::testGroupStarting(GroupInfo const& groupInfo)
17544 for (auto const& listener : m_listeners) {
17545 listener->testGroupStarting(groupInfo);
17547 m_reporter->testGroupStarting(groupInfo);
17550 void ListeningReporter::testCaseStarting(TestCaseInfo const& testInfo)
17552 for (auto const& listener : m_listeners) {
17553 listener->testCaseStarting(testInfo);
17555 m_reporter->testCaseStarting(testInfo);
17558 void ListeningReporter::sectionStarting(SectionInfo const& sectionInfo)
17560 for (auto const& listener : m_listeners) {
17561 listener->sectionStarting(sectionInfo);
17563 m_reporter->sectionStarting(sectionInfo);
17566 void ListeningReporter::assertionStarting(AssertionInfo const& assertionInfo)
17568 for (auto const& listener : m_listeners) {
17569 listener->assertionStarting(assertionInfo);
17571 m_reporter->assertionStarting(assertionInfo);
17574 // The return value indicates if the messages buffer should be cleared:
17575 bool ListeningReporter::assertionEnded(AssertionStats const& assertionStats)
17577 for (auto const& listener : m_listeners) {
17578 static_cast<void>(listener->assertionEnded(assertionStats));
17580 return m_reporter->assertionEnded(assertionStats);
17583 void ListeningReporter::sectionEnded(SectionStats const& sectionStats)
17585 for (auto const& listener : m_listeners) {
17586 listener->sectionEnded(sectionStats);
17588 m_reporter->sectionEnded(sectionStats);
17591 void ListeningReporter::testCaseEnded(TestCaseStats const& testCaseStats)
17593 for (auto const& listener : m_listeners) {
17594 listener->testCaseEnded(testCaseStats);
17596 m_reporter->testCaseEnded(testCaseStats);
17599 void ListeningReporter::testGroupEnded(TestGroupStats const& testGroupStats)
17601 for (auto const& listener : m_listeners) {
17602 listener->testGroupEnded(testGroupStats);
17604 m_reporter->testGroupEnded(testGroupStats);
17607 void ListeningReporter::testRunEnded(TestRunStats const& testRunStats)
17609 for (auto const& listener : m_listeners) {
17610 listener->testRunEnded(testRunStats);
17612 m_reporter->testRunEnded(testRunStats);
17615 void ListeningReporter::skipTest(TestCaseInfo const& testInfo)
17617 for (auto const& listener : m_listeners) {
17618 listener->skipTest(testInfo);
17620 m_reporter->skipTest(testInfo);
17623 bool ListeningReporter::isMulti() const
17628 } // end namespace Catch
17629 // end catch_reporter_listening.cpp
17630 // start catch_reporter_xml.cpp
17632 #if defined(_MSC_VER)
17633 #pragma warning(push)
17634 #pragma warning(disable : 4061) // Not all labels are EXPLICITLY handled in switch
17635 // Note that 4062 (not all labels are handled
17636 // and default is missing) is enabled
17640 XmlReporter::XmlReporter(ReporterConfig const& _config) : StreamingReporterBase(_config), m_xml(_config.stream())
17642 m_reporterPrefs.shouldRedirectStdOut = true;
17643 m_reporterPrefs.shouldReportAllAssertions = true;
17646 XmlReporter::~XmlReporter() = default;
17648 std::string XmlReporter::getDescription()
17650 return "Reports test results as an XML document";
17653 std::string XmlReporter::getStylesheetRef() const
17655 return std::string();
17658 void XmlReporter::writeSourceInfo(SourceLineInfo const& sourceInfo)
17660 m_xml.writeAttribute("filename", sourceInfo.file).writeAttribute("line", sourceInfo.line);
17663 void XmlReporter::noMatchingTestCases(std::string const& s)
17665 StreamingReporterBase::noMatchingTestCases(s);
17668 void XmlReporter::testRunStarting(TestRunInfo const& testInfo)
17670 StreamingReporterBase::testRunStarting(testInfo);
17671 std::string stylesheetRef = getStylesheetRef();
17672 if (!stylesheetRef.empty())
17673 m_xml.writeStylesheetRef(stylesheetRef);
17674 m_xml.startElement("Catch");
17675 if (!m_config->name().empty())
17676 m_xml.writeAttribute("name", m_config->name());
17677 if (m_config->testSpec().hasFilters())
17678 m_xml.writeAttribute("filters", serializeFilters(m_config->getTestsOrTags()));
17679 if (m_config->rngSeed() != 0)
17680 m_xml.scopedElement("Randomness").writeAttribute("seed", m_config->rngSeed());
17683 void XmlReporter::testGroupStarting(GroupInfo const& groupInfo)
17685 StreamingReporterBase::testGroupStarting(groupInfo);
17686 m_xml.startElement("Group").writeAttribute("name", groupInfo.name);
17689 void XmlReporter::testCaseStarting(TestCaseInfo const& testInfo)
17691 StreamingReporterBase::testCaseStarting(testInfo);
17692 m_xml.startElement("TestCase")
17693 .writeAttribute("name", trim(testInfo.name))
17694 .writeAttribute("description", testInfo.description)
17695 .writeAttribute("tags", testInfo.tagsAsString());
17697 writeSourceInfo(testInfo.lineInfo);
17699 if (m_config->showDurations() == ShowDurations::Always)
17700 m_testCaseTimer.start();
17701 m_xml.ensureTagClosed();
17704 void XmlReporter::sectionStarting(SectionInfo const& sectionInfo)
17706 StreamingReporterBase::sectionStarting(sectionInfo);
17707 if (m_sectionDepth++ > 0) {
17708 m_xml.startElement("Section").writeAttribute("name", trim(sectionInfo.name));
17709 writeSourceInfo(sectionInfo.lineInfo);
17710 m_xml.ensureTagClosed();
17714 void XmlReporter::assertionStarting(AssertionInfo const&) {}
17716 bool XmlReporter::assertionEnded(AssertionStats const& assertionStats)
17719 AssertionResult const& result = assertionStats.assertionResult;
17721 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
17723 if (includeResults || result.getResultType() == ResultWas::Warning) {
17724 // Print any info messages in <Info> tags.
17725 for (auto const& msg : assertionStats.infoMessages) {
17726 if (msg.type == ResultWas::Info && includeResults) {
17727 m_xml.scopedElement("Info").writeText(msg.message);
17728 } else if (msg.type == ResultWas::Warning) {
17729 m_xml.scopedElement("Warning").writeText(msg.message);
17734 // Drop out if result was successful but we're not printing them.
17735 if (!includeResults && result.getResultType() != ResultWas::Warning)
17738 // Print the expression if there is one.
17739 if (result.hasExpression()) {
17740 m_xml.startElement("Expression")
17741 .writeAttribute("success", result.succeeded())
17742 .writeAttribute("type", result.getTestMacroName());
17744 writeSourceInfo(result.getSourceInfo());
17746 m_xml.scopedElement("Original").writeText(result.getExpression());
17747 m_xml.scopedElement("Expanded").writeText(result.getExpandedExpression());
17750 // And... Print a result applicable to each result type.
17751 switch (result.getResultType()) {
17752 case ResultWas::ThrewException:
17753 m_xml.startElement("Exception");
17754 writeSourceInfo(result.getSourceInfo());
17755 m_xml.writeText(result.getMessage());
17756 m_xml.endElement();
17758 case ResultWas::FatalErrorCondition:
17759 m_xml.startElement("FatalErrorCondition");
17760 writeSourceInfo(result.getSourceInfo());
17761 m_xml.writeText(result.getMessage());
17762 m_xml.endElement();
17764 case ResultWas::Info:
17765 m_xml.scopedElement("Info").writeText(result.getMessage());
17767 case ResultWas::Warning:
17768 // Warning will already have been written
17770 case ResultWas::ExplicitFailure:
17771 m_xml.startElement("Failure");
17772 writeSourceInfo(result.getSourceInfo());
17773 m_xml.writeText(result.getMessage());
17774 m_xml.endElement();
17780 if (result.hasExpression())
17781 m_xml.endElement();
17786 void XmlReporter::sectionEnded(SectionStats const& sectionStats)
17788 StreamingReporterBase::sectionEnded(sectionStats);
17789 if (--m_sectionDepth > 0) {
17790 XmlWriter::ScopedElement e = m_xml.scopedElement("OverallResults");
17791 e.writeAttribute("successes", sectionStats.assertions.passed);
17792 e.writeAttribute("failures", sectionStats.assertions.failed);
17793 e.writeAttribute("expectedFailures", sectionStats.assertions.failedButOk);
17795 if (m_config->showDurations() == ShowDurations::Always)
17796 e.writeAttribute("durationInSeconds", sectionStats.durationInSeconds);
17798 m_xml.endElement();
17802 void XmlReporter::testCaseEnded(TestCaseStats const& testCaseStats)
17804 StreamingReporterBase::testCaseEnded(testCaseStats);
17805 XmlWriter::ScopedElement e = m_xml.scopedElement("OverallResult");
17806 e.writeAttribute("success", testCaseStats.totals.assertions.allOk());
17808 if (m_config->showDurations() == ShowDurations::Always)
17809 e.writeAttribute("durationInSeconds", m_testCaseTimer.getElapsedSeconds());
17811 if (!testCaseStats.stdOut.empty())
17812 m_xml.scopedElement("StdOut").writeText(trim(testCaseStats.stdOut), XmlFormatting::Newline);
17813 if (!testCaseStats.stdErr.empty())
17814 m_xml.scopedElement("StdErr").writeText(trim(testCaseStats.stdErr), XmlFormatting::Newline);
17816 m_xml.endElement();
17819 void XmlReporter::testGroupEnded(TestGroupStats const& testGroupStats)
17821 StreamingReporterBase::testGroupEnded(testGroupStats);
17822 // TODO: Check testGroupStats.aborting and act accordingly.
17823 m_xml.scopedElement("OverallResults")
17824 .writeAttribute("successes", testGroupStats.totals.assertions.passed)
17825 .writeAttribute("failures", testGroupStats.totals.assertions.failed)
17826 .writeAttribute("expectedFailures", testGroupStats.totals.assertions.failedButOk);
17827 m_xml.scopedElement("OverallResultsCases")
17828 .writeAttribute("successes", testGroupStats.totals.testCases.passed)
17829 .writeAttribute("failures", testGroupStats.totals.testCases.failed)
17830 .writeAttribute("expectedFailures", testGroupStats.totals.testCases.failedButOk);
17831 m_xml.endElement();
17834 void XmlReporter::testRunEnded(TestRunStats const& testRunStats)
17836 StreamingReporterBase::testRunEnded(testRunStats);
17837 m_xml.scopedElement("OverallResults")
17838 .writeAttribute("successes", testRunStats.totals.assertions.passed)
17839 .writeAttribute("failures", testRunStats.totals.assertions.failed)
17840 .writeAttribute("expectedFailures", testRunStats.totals.assertions.failedButOk);
17841 m_xml.scopedElement("OverallResultsCases")
17842 .writeAttribute("successes", testRunStats.totals.testCases.passed)
17843 .writeAttribute("failures", testRunStats.totals.testCases.failed)
17844 .writeAttribute("expectedFailures", testRunStats.totals.testCases.failedButOk);
17845 m_xml.endElement();
17848 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
17849 void XmlReporter::benchmarkPreparing(std::string const& name)
17851 m_xml.startElement("BenchmarkResults").writeAttribute("name", name);
17854 void XmlReporter::benchmarkStarting(BenchmarkInfo const& info)
17856 m_xml.writeAttribute("samples", info.samples)
17857 .writeAttribute("resamples", info.resamples)
17858 .writeAttribute("iterations", info.iterations)
17859 .writeAttribute("clockResolution", info.clockResolution)
17860 .writeAttribute("estimatedDuration", info.estimatedDuration)
17861 .writeComment("All values in nano seconds");
17864 void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats)
17866 m_xml.startElement("mean")
17867 .writeAttribute("value", benchmarkStats.mean.point.count())
17868 .writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count())
17869 .writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count())
17870 .writeAttribute("ci", benchmarkStats.mean.confidence_interval);
17871 m_xml.endElement();
17872 m_xml.startElement("standardDeviation")
17873 .writeAttribute("value", benchmarkStats.standardDeviation.point.count())
17874 .writeAttribute("lowerBound", benchmarkStats.standardDeviation.lower_bound.count())
17875 .writeAttribute("upperBound", benchmarkStats.standardDeviation.upper_bound.count())
17876 .writeAttribute("ci", benchmarkStats.standardDeviation.confidence_interval);
17877 m_xml.endElement();
17878 m_xml.startElement("outliers")
17879 .writeAttribute("variance", benchmarkStats.outlierVariance)
17880 .writeAttribute("lowMild", benchmarkStats.outliers.low_mild)
17881 .writeAttribute("lowSevere", benchmarkStats.outliers.low_severe)
17882 .writeAttribute("highMild", benchmarkStats.outliers.high_mild)
17883 .writeAttribute("highSevere", benchmarkStats.outliers.high_severe);
17884 m_xml.endElement();
17885 m_xml.endElement();
17888 void XmlReporter::benchmarkFailed(std::string const& error)
17890 m_xml.scopedElement("failed").writeAttribute("message", error);
17891 m_xml.endElement();
17893 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
17895 CATCH_REGISTER_REPORTER("xml", XmlReporter)
17897 } // end namespace Catch
17899 #if defined(_MSC_VER)
17900 #pragma warning(pop)
17902 // end catch_reporter_xml.cpp
17905 LeakDetector leakDetector;
17909 #pragma clang diagnostic pop
17912 // end catch_impl.hpp
17915 #ifdef CATCH_CONFIG_MAIN
17916 // start catch_default_main.hpp
17920 #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
17921 // Standard C/C++ Win32 Unicode wmain entry point
17922 extern "C" int wmain(int argc, wchar_t* argv[], wchar_t*[])
17925 // Standard C/C++ main entry point
17926 int main(int argc, char* argv[])
17930 return Catch::Session().run(argc, argv);
17935 // Objective-C entry point
17936 int main(int argc, char* const argv[])
17938 #if !CATCH_ARC_ENABLED
17939 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
17942 Catch::registerTestMethods();
17943 int result = Catch::Session().run(argc, (char**)argv);
17945 #if !CATCH_ARC_ENABLED
17954 // end catch_default_main.hpp
17957 #if !defined(CATCH_CONFIG_IMPL_ONLY)
17959 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
17960 #undef CLARA_CONFIG_MAIN
17963 #if !defined(CATCH_CONFIG_DISABLE)
17965 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
17966 #ifdef CATCH_CONFIG_PREFIX_ALL
17968 #define CATCH_REQUIRE(...) INTERNAL_CATCH_TEST("CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__)
17969 #define CATCH_REQUIRE_FALSE(...) \
17970 INTERNAL_CATCH_TEST("CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, \
17973 #define CATCH_REQUIRE_THROWS(...) \
17974 INTERNAL_CATCH_THROWS("CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__)
17975 #define CATCH_REQUIRE_THROWS_AS(expr, exceptionType) \
17976 INTERNAL_CATCH_THROWS_AS("CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr)
17977 #define CATCH_REQUIRE_THROWS_WITH(expr, matcher) \
17978 INTERNAL_CATCH_THROWS_STR_MATCHES("CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr)
17979 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17980 #define CATCH_REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) \
17981 INTERNAL_CATCH_THROWS_MATCHES("CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, \
17983 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17984 #define CATCH_REQUIRE_NOTHROW(...) \
17985 INTERNAL_CATCH_NO_THROW("CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__)
17987 #define CATCH_CHECK(...) INTERNAL_CATCH_TEST("CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
17988 #define CATCH_CHECK_FALSE(...) \
17989 INTERNAL_CATCH_TEST("CATCH_CHECK_FALSE", \
17990 Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__)
17991 #define CATCH_CHECKED_IF(...) \
17992 INTERNAL_CATCH_IF("CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
17993 #define CATCH_CHECKED_ELSE(...) \
17994 INTERNAL_CATCH_ELSE("CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
17995 #define CATCH_CHECK_NOFAIL(...) \
17996 INTERNAL_CATCH_TEST("CATCH_CHECK_NOFAIL", \
17997 Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, \
18000 #define CATCH_CHECK_THROWS(...) \
18001 INTERNAL_CATCH_THROWS("CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
18002 #define CATCH_CHECK_THROWS_AS(expr, exceptionType) \
18003 INTERNAL_CATCH_THROWS_AS("CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr)
18004 #define CATCH_CHECK_THROWS_WITH(expr, matcher) \
18005 INTERNAL_CATCH_THROWS_STR_MATCHES("CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, \
18007 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18008 #define CATCH_CHECK_THROWS_MATCHES(expr, exceptionType, matcher) \
18009 INTERNAL_CATCH_THROWS_MATCHES("CATCH_CHECK_THROWS_MATCHES", exceptionType, \
18010 Catch::ResultDisposition::ContinueOnFailure, matcher, expr)
18011 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18012 #define CATCH_CHECK_NOTHROW(...) \
18013 INTERNAL_CATCH_NO_THROW("CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
18015 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18016 #define CATCH_CHECK_THAT(arg, matcher) \
18017 INTERNAL_CHECK_THAT("CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg)
18019 #define CATCH_REQUIRE_THAT(arg, matcher) \
18020 INTERNAL_CHECK_THAT("CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg)
18021 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18023 #define CATCH_INFO(msg) INTERNAL_CATCH_INFO("CATCH_INFO", msg)
18024 #define CATCH_UNSCOPED_INFO(msg) INTERNAL_CATCH_UNSCOPED_INFO("CATCH_UNSCOPED_INFO", msg)
18025 #define CATCH_WARN(msg) \
18026 INTERNAL_CATCH_MSG("CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg)
18027 #define CATCH_CAPTURE(...) INTERNAL_CATCH_CAPTURE(INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__)
18029 #define CATCH_TEST_CASE(...) INTERNAL_CATCH_TESTCASE(__VA_ARGS__)
18030 #define CATCH_TEST_CASE_METHOD(className, ...) INTERNAL_CATCH_TEST_CASE_METHOD(className, __VA_ARGS__)
18031 #define CATCH_METHOD_AS_TEST_CASE(method, ...) INTERNAL_CATCH_METHOD_AS_TEST_CASE(method, __VA_ARGS__)
18032 #define CATCH_REGISTER_TEST_CASE(Function, ...) INTERNAL_CATCH_REGISTER_TESTCASE(Function, __VA_ARGS__)
18033 #define CATCH_SECTION(...) INTERNAL_CATCH_SECTION(__VA_ARGS__)
18034 #define CATCH_DYNAMIC_SECTION(...) INTERNAL_CATCH_DYNAMIC_SECTION(__VA_ARGS__)
18035 #define CATCH_FAIL(...) \
18036 INTERNAL_CATCH_MSG("CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__)
18037 #define CATCH_FAIL_CHECK(...) \
18038 INTERNAL_CATCH_MSG("CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, \
18039 Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
18040 #define CATCH_SUCCEED(...) \
18041 INTERNAL_CATCH_MSG("CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
18043 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
18045 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18046 #define CATCH_TEMPLATE_TEST_CASE(...) INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)
18047 #define CATCH_TEMPLATE_TEST_CASE_SIG(...) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(__VA_ARGS__)
18048 #define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)
18049 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \
18050 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, __VA_ARGS__)
18051 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE(...) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(__VA_ARGS__)
18052 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(...) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(__VA_ARGS__)
18053 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \
18054 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, __VA_ARGS__)
18055 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \
18056 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, __VA_ARGS__)
18058 #define CATCH_TEMPLATE_TEST_CASE(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__))
18059 #define CATCH_TEMPLATE_TEST_CASE_SIG(...) \
18060 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(__VA_ARGS__))
18061 #define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \
18062 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__))
18063 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \
18064 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, __VA_ARGS__))
18065 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE(...) \
18066 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(__VA_ARGS__))
18067 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(...) \
18068 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(__VA_ARGS__))
18069 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \
18070 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, __VA_ARGS__))
18071 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \
18072 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, __VA_ARGS__))
18075 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
18076 #define CATCH_STATIC_REQUIRE(...) \
18077 static_assert(__VA_ARGS__, #__VA_ARGS__); \
18078 CATCH_SUCCEED(#__VA_ARGS__)
18079 #define CATCH_STATIC_REQUIRE_FALSE(...) \
18080 static_assert(!(__VA_ARGS__), "!(" #__VA_ARGS__ ")"); \
18081 CATCH_SUCCEED(#__VA_ARGS__)
18083 #define CATCH_STATIC_REQUIRE(...) CATCH_REQUIRE(__VA_ARGS__)
18084 #define CATCH_STATIC_REQUIRE_FALSE(...) CATCH_REQUIRE_FALSE(__VA_ARGS__)
18087 // "BDD-style" convenience wrappers
18088 #define CATCH_SCENARIO(...) CATCH_TEST_CASE("Scenario: " __VA_ARGS__)
18089 #define CATCH_SCENARIO_METHOD(className, ...) INTERNAL_CATCH_TEST_CASE_METHOD(className, "Scenario: " __VA_ARGS__)
18090 #define CATCH_GIVEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Given: " << desc)
18091 #define CATCH_AND_GIVEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION("And given: " << desc)
18092 #define CATCH_WHEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" When: " << desc)
18093 #define CATCH_AND_WHEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" And when: " << desc)
18094 #define CATCH_THEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Then: " << desc)
18095 #define CATCH_AND_THEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" And: " << desc)
18097 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
18098 #define CATCH_BENCHMARK(...) \
18099 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), \
18100 INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__, , ), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__, , ))
18101 #define CATCH_BENCHMARK_ADVANCED(name) \
18102 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name)
18103 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
18105 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
18108 #define REQUIRE(...) INTERNAL_CATCH_TEST("REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__)
18109 #define REQUIRE_FALSE(...) \
18110 INTERNAL_CATCH_TEST("REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, \
18113 #define REQUIRE_THROWS(...) INTERNAL_CATCH_THROWS("REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__)
18114 #define REQUIRE_THROWS_AS(expr, exceptionType) \
18115 INTERNAL_CATCH_THROWS_AS("REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr)
18116 #define REQUIRE_THROWS_WITH(expr, matcher) \
18117 INTERNAL_CATCH_THROWS_STR_MATCHES("REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr)
18118 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18119 #define REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) \
18120 INTERNAL_CATCH_THROWS_MATCHES("REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, \
18122 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18123 #define REQUIRE_NOTHROW(...) INTERNAL_CATCH_NO_THROW("REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__)
18125 #define CHECK(...) INTERNAL_CATCH_TEST("CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
18126 #define CHECK_FALSE(...) \
18127 INTERNAL_CATCH_TEST("CHECK_FALSE", \
18128 Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__)
18129 #define CHECKED_IF(...) INTERNAL_CATCH_IF("CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
18130 #define CHECKED_ELSE(...) INTERNAL_CATCH_ELSE("CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
18131 #define CHECK_NOFAIL(...) \
18132 INTERNAL_CATCH_TEST("CHECK_NOFAIL", \
18133 Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, \
18136 #define CHECK_THROWS(...) \
18137 INTERNAL_CATCH_THROWS("CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
18138 #define CHECK_THROWS_AS(expr, exceptionType) \
18139 INTERNAL_CATCH_THROWS_AS("CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr)
18140 #define CHECK_THROWS_WITH(expr, matcher) \
18141 INTERNAL_CATCH_THROWS_STR_MATCHES("CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr)
18142 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18143 #define CHECK_THROWS_MATCHES(expr, exceptionType, matcher) \
18144 INTERNAL_CATCH_THROWS_MATCHES("CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, \
18146 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18147 #define CHECK_NOTHROW(...) \
18148 INTERNAL_CATCH_NO_THROW("CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
18150 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18151 #define CHECK_THAT(arg, matcher) \
18152 INTERNAL_CHECK_THAT("CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg)
18154 #define REQUIRE_THAT(arg, matcher) INTERNAL_CHECK_THAT("REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg)
18155 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18157 #define INFO(msg) INTERNAL_CATCH_INFO("INFO", msg)
18158 #define UNSCOPED_INFO(msg) INTERNAL_CATCH_UNSCOPED_INFO("UNSCOPED_INFO", msg)
18159 #define WARN(msg) \
18160 INTERNAL_CATCH_MSG("WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg)
18161 #define CAPTURE(...) INTERNAL_CATCH_CAPTURE(INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__)
18163 #define TEST_CASE(...) INTERNAL_CATCH_TESTCASE(__VA_ARGS__)
18164 #define TEST_CASE_METHOD(className, ...) INTERNAL_CATCH_TEST_CASE_METHOD(className, __VA_ARGS__)
18165 #define METHOD_AS_TEST_CASE(method, ...) INTERNAL_CATCH_METHOD_AS_TEST_CASE(method, __VA_ARGS__)
18166 #define REGISTER_TEST_CASE(Function, ...) INTERNAL_CATCH_REGISTER_TESTCASE(Function, __VA_ARGS__)
18167 #define SECTION(...) INTERNAL_CATCH_SECTION(__VA_ARGS__)
18168 #define DYNAMIC_SECTION(...) INTERNAL_CATCH_DYNAMIC_SECTION(__VA_ARGS__)
18169 #define FAIL(...) \
18170 INTERNAL_CATCH_MSG("FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__)
18171 #define FAIL_CHECK(...) \
18172 INTERNAL_CATCH_MSG("FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, \
18174 #define SUCCEED(...) \
18175 INTERNAL_CATCH_MSG("SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__)
18176 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
18178 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18179 #define TEMPLATE_TEST_CASE(...) INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)
18180 #define TEMPLATE_TEST_CASE_SIG(...) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(__VA_ARGS__)
18181 #define TEMPLATE_TEST_CASE_METHOD(className, ...) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)
18182 #define TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \
18183 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, __VA_ARGS__)
18184 #define TEMPLATE_PRODUCT_TEST_CASE(...) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(__VA_ARGS__)
18185 #define TEMPLATE_PRODUCT_TEST_CASE_SIG(...) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(__VA_ARGS__)
18186 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \
18187 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, __VA_ARGS__)
18188 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \
18189 INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, __VA_ARGS__)
18190 #define TEMPLATE_LIST_TEST_CASE(...) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
18191 #define TEMPLATE_LIST_TEST_CASE_METHOD(className, ...) \
18192 INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(className, __VA_ARGS__)
18194 #define TEMPLATE_TEST_CASE(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__))
18195 #define TEMPLATE_TEST_CASE_SIG(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(__VA_ARGS__))
18196 #define TEMPLATE_TEST_CASE_METHOD(className, ...) \
18197 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__))
18198 #define TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \
18199 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, __VA_ARGS__))
18200 #define TEMPLATE_PRODUCT_TEST_CASE(...) \
18201 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(__VA_ARGS__))
18202 #define TEMPLATE_PRODUCT_TEST_CASE_SIG(...) \
18203 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(__VA_ARGS__))
18204 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) \
18205 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, __VA_ARGS__))
18206 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \
18207 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, __VA_ARGS__))
18208 #define TEMPLATE_LIST_TEST_CASE(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__))
18209 #define TEMPLATE_LIST_TEST_CASE_METHOD(className, ...) \
18210 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(className, __VA_ARGS__))
18213 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
18214 #define STATIC_REQUIRE(...) \
18215 static_assert(__VA_ARGS__, #__VA_ARGS__); \
18216 SUCCEED(#__VA_ARGS__)
18217 #define STATIC_REQUIRE_FALSE(...) \
18218 static_assert(!(__VA_ARGS__), "!(" #__VA_ARGS__ ")"); \
18219 SUCCEED("!(" #__VA_ARGS__ ")")
18221 #define STATIC_REQUIRE(...) REQUIRE(__VA_ARGS__)
18222 #define STATIC_REQUIRE_FALSE(...) REQUIRE_FALSE(__VA_ARGS__)
18227 #define CATCH_TRANSLATE_EXCEPTION(signature) INTERNAL_CATCH_TRANSLATE_EXCEPTION(signature)
18229 // "BDD-style" convenience wrappers
18230 #define SCENARIO(...) TEST_CASE("Scenario: " __VA_ARGS__)
18231 #define SCENARIO_METHOD(className, ...) INTERNAL_CATCH_TEST_CASE_METHOD(className, "Scenario: " __VA_ARGS__)
18233 #define GIVEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Given: " << desc)
18234 #define AND_GIVEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION("And given: " << desc)
18235 #define WHEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" When: " << desc)
18236 #define AND_WHEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" And when: " << desc)
18237 #define THEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" Then: " << desc)
18238 #define AND_THEN(desc) INTERNAL_CATCH_DYNAMIC_SECTION(" And: " << desc)
18240 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
18241 #define BENCHMARK(...) \
18242 INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), \
18243 INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__, , ), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__, , ))
18244 #define BENCHMARK_ADVANCED(name) \
18245 INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name)
18246 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
18248 using Catch::Detail::Approx;
18250 #else // CATCH_CONFIG_DISABLE
18253 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
18254 #ifdef CATCH_CONFIG_PREFIX_ALL
18256 #define CATCH_REQUIRE(...) (void)(0)
18257 #define CATCH_REQUIRE_FALSE(...) (void)(0)
18259 #define CATCH_REQUIRE_THROWS(...) (void)(0)
18260 #define CATCH_REQUIRE_THROWS_AS(expr, exceptionType) (void)(0)
18261 #define CATCH_REQUIRE_THROWS_WITH(expr, matcher) (void)(0)
18262 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18263 #define CATCH_REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0)
18264 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18265 #define CATCH_REQUIRE_NOTHROW(...) (void)(0)
18267 #define CATCH_CHECK(...) (void)(0)
18268 #define CATCH_CHECK_FALSE(...) (void)(0)
18269 #define CATCH_CHECKED_IF(...) if (__VA_ARGS__)
18270 #define CATCH_CHECKED_ELSE(...) if (!(__VA_ARGS__))
18271 #define CATCH_CHECK_NOFAIL(...) (void)(0)
18273 #define CATCH_CHECK_THROWS(...) (void)(0)
18274 #define CATCH_CHECK_THROWS_AS(expr, exceptionType) (void)(0)
18275 #define CATCH_CHECK_THROWS_WITH(expr, matcher) (void)(0)
18276 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18277 #define CATCH_CHECK_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0)
18278 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18279 #define CATCH_CHECK_NOTHROW(...) (void)(0)
18281 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18282 #define CATCH_CHECK_THAT(arg, matcher) (void)(0)
18284 #define CATCH_REQUIRE_THAT(arg, matcher) (void)(0)
18285 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18287 #define CATCH_INFO(msg) (void)(0)
18288 #define CATCH_UNSCOPED_INFO(msg) (void)(0)
18289 #define CATCH_WARN(msg) (void)(0)
18290 #define CATCH_CAPTURE(msg) (void)(0)
18292 #define CATCH_TEST_CASE(...) \
18293 INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____))
18294 #define CATCH_TEST_CASE_METHOD(className, ...) \
18295 INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____))
18296 #define CATCH_METHOD_AS_TEST_CASE(method, ...)
18297 #define CATCH_REGISTER_TEST_CASE(Function, ...) (void)(0)
18298 #define CATCH_SECTION(...)
18299 #define CATCH_DYNAMIC_SECTION(...)
18300 #define CATCH_FAIL(...) (void)(0)
18301 #define CATCH_FAIL_CHECK(...) (void)(0)
18302 #define CATCH_SUCCEED(...) (void)(0)
18304 #define CATCH_ANON_TEST_CASE() \
18305 INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____))
18307 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18308 #define CATCH_TEMPLATE_TEST_CASE(...) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
18309 #define CATCH_TEMPLATE_TEST_CASE_SIG(...) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
18310 #define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \
18311 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
18312 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \
18313 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__)
18314 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE(...) CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)
18315 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(...) CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)
18316 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)
18317 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \
18318 CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)
18320 #define CATCH_TEMPLATE_TEST_CASE(...) \
18321 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__))
18322 #define CATCH_TEMPLATE_TEST_CASE_SIG(...) \
18323 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__))
18324 #define CATCH_TEMPLATE_TEST_CASE_METHOD(className, ...) \
18325 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__))
18326 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \
18327 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__))
18328 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE(...) CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)
18329 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(...) CATCH_TEMPLATE_TEST_CASE(__VA_ARGS__)
18330 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)
18331 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) \
18332 CATCH_TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)
18335 // "BDD-style" convenience wrappers
18336 #define CATCH_SCENARIO(...) \
18337 INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____))
18338 #define CATCH_SCENARIO_METHOD(className, ...) \
18339 INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____), className)
18340 #define CATCH_GIVEN(desc)
18341 #define CATCH_AND_GIVEN(desc)
18342 #define CATCH_WHEN(desc)
18343 #define CATCH_AND_WHEN(desc)
18344 #define CATCH_THEN(desc)
18345 #define CATCH_AND_THEN(desc)
18347 #define CATCH_STATIC_REQUIRE(...) (void)(0)
18348 #define CATCH_STATIC_REQUIRE_FALSE(...) (void)(0)
18350 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
18353 #define REQUIRE(...) (void)(0)
18354 #define REQUIRE_FALSE(...) (void)(0)
18356 #define REQUIRE_THROWS(...) (void)(0)
18357 #define REQUIRE_THROWS_AS(expr, exceptionType) (void)(0)
18358 #define REQUIRE_THROWS_WITH(expr, matcher) (void)(0)
18359 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18360 #define REQUIRE_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0)
18361 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18362 #define REQUIRE_NOTHROW(...) (void)(0)
18364 #define CHECK(...) (void)(0)
18365 #define CHECK_FALSE(...) (void)(0)
18366 #define CHECKED_IF(...) if (__VA_ARGS__)
18367 #define CHECKED_ELSE(...) if (!(__VA_ARGS__))
18368 #define CHECK_NOFAIL(...) (void)(0)
18370 #define CHECK_THROWS(...) (void)(0)
18371 #define CHECK_THROWS_AS(expr, exceptionType) (void)(0)
18372 #define CHECK_THROWS_WITH(expr, matcher) (void)(0)
18373 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18374 #define CHECK_THROWS_MATCHES(expr, exceptionType, matcher) (void)(0)
18375 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18376 #define CHECK_NOTHROW(...) (void)(0)
18378 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
18379 #define CHECK_THAT(arg, matcher) (void)(0)
18381 #define REQUIRE_THAT(arg, matcher) (void)(0)
18382 #endif // CATCH_CONFIG_DISABLE_MATCHERS
18384 #define INFO(msg) (void)(0)
18385 #define UNSCOPED_INFO(msg) (void)(0)
18386 #define WARN(msg) (void)(0)
18387 #define CAPTURE(msg) (void)(0)
18389 #define TEST_CASE(...) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____))
18390 #define TEST_CASE_METHOD(className, ...) \
18391 INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____))
18392 #define METHOD_AS_TEST_CASE(method, ...)
18393 #define REGISTER_TEST_CASE(Function, ...) (void)(0)
18394 #define SECTION(...)
18395 #define DYNAMIC_SECTION(...)
18396 #define FAIL(...) (void)(0)
18397 #define FAIL_CHECK(...) (void)(0)
18398 #define SUCCEED(...) (void)(0)
18399 #define ANON_TEST_CASE() \
18400 INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____))
18402 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
18403 #define TEMPLATE_TEST_CASE(...) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
18404 #define TEMPLATE_TEST_CASE_SIG(...) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
18405 #define TEMPLATE_TEST_CASE_METHOD(className, ...) \
18406 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
18407 #define TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \
18408 INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__)
18409 #define TEMPLATE_PRODUCT_TEST_CASE(...) TEMPLATE_TEST_CASE(__VA_ARGS__)
18410 #define TEMPLATE_PRODUCT_TEST_CASE_SIG(...) TEMPLATE_TEST_CASE(__VA_ARGS__)
18411 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)
18412 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)
18414 #define TEMPLATE_TEST_CASE(...) \
18415 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__))
18416 #define TEMPLATE_TEST_CASE_SIG(...) \
18417 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__))
18418 #define TEMPLATE_TEST_CASE_METHOD(className, ...) \
18419 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__))
18420 #define TEMPLATE_TEST_CASE_METHOD_SIG(className, ...) \
18421 INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__))
18422 #define TEMPLATE_PRODUCT_TEST_CASE(...) TEMPLATE_TEST_CASE(__VA_ARGS__)
18423 #define TEMPLATE_PRODUCT_TEST_CASE_SIG(...) TEMPLATE_TEST_CASE(__VA_ARGS__)
18424 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD(className, ...) TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)
18425 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG(className, ...) TEMPLATE_TEST_CASE_METHOD(className, __VA_ARGS__)
18428 #define STATIC_REQUIRE(...) (void)(0)
18429 #define STATIC_REQUIRE_FALSE(...) (void)(0)
18433 #define CATCH_TRANSLATE_EXCEPTION(signature) \
18434 INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG(INTERNAL_CATCH_UNIQUE_NAME(catch_internal_ExceptionTranslator), signature)
18436 // "BDD-style" convenience wrappers
18437 #define SCENARIO(...) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____))
18438 #define SCENARIO_METHOD(className, ...) \
18439 INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____T_E_S_T____), className)
18441 #define GIVEN(desc)
18442 #define AND_GIVEN(desc)
18444 #define AND_WHEN(desc)
18446 #define AND_THEN(desc)
18448 using Catch::Detail::Approx;
18452 #endif // ! CATCH_CONFIG_IMPL_ONLY
18454 // start catch_reenable_warnings.h
18457 #ifdef __ICC // icpc defines the __clang__ macro
18458 #pragma warning(pop)
18460 #pragma clang diagnostic pop
18462 #elif defined __GNUC__
18463 #pragma GCC diagnostic pop
18466 // end catch_reenable_warnings.h
18468 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED