1 /*
2  *  Catch v2.11.3
3  *  Generated: 2020-03-19 13:44:21.042491
4  *  ----------------------------------------------------------
5  *  This file has been merged from multiple headers. Please don't edit it directly
6  *  Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved.
7  *
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)
10  */
11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
13 // start catch.hpp
14 
15 
16 #define CATCH_VERSION_MAJOR 2
17 #define CATCH_VERSION_MINOR 11
18 #define CATCH_VERSION_PATCH 3
19 
20 #ifdef __clang__
21 #    pragma clang system_header
22 #elif defined __GNUC__
23 #    pragma GCC system_header
24 #endif
25 
26 // start catch_suppress_warnings.h
27 
28 #ifdef __clang__
29 #   ifdef __ICC // icpc defines the __clang__ macro
30 #       pragma warning(push)
31 #       pragma warning(disable: 161 1682)
32 #   else // __ICC
33 #       pragma clang diagnostic push
34 #       pragma clang diagnostic ignored "-Wpadded"
35 #       pragma clang diagnostic ignored "-Wswitch-enum"
36 #       pragma clang diagnostic ignored "-Wcovered-switch-default"
37 #    endif
38 #elif defined __GNUC__
39      // Because REQUIREs trigger GCC's -Wparentheses, and because still
40      // supported version of g++ have only buggy support for _Pragmas,
41      // Wparentheses have to be suppressed globally.
42 #    pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details
43 
44 #    pragma GCC diagnostic push
45 #    pragma GCC diagnostic ignored "-Wunused-variable"
46 #    pragma GCC diagnostic ignored "-Wpadded"
47 #endif
48 // end catch_suppress_warnings.h
49 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
50 #  define CATCH_IMPL
51 #  define CATCH_CONFIG_ALL_PARTS
52 #endif
53 
54 // In the impl file, we want to have access to all parts of the headers
55 // Can also be used to sanely support PCHs
56 #if defined(CATCH_CONFIG_ALL_PARTS)
57 #  define CATCH_CONFIG_EXTERNAL_INTERFACES
58 #  if defined(CATCH_CONFIG_DISABLE_MATCHERS)
59 #    undef CATCH_CONFIG_DISABLE_MATCHERS
60 #  endif
61 #  if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
62 #    define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
63 #  endif
64 #endif
65 
66 #if !defined(CATCH_CONFIG_IMPL_ONLY)
67 // start catch_platform.h
68 
69 #ifdef __APPLE__
70 # include <TargetConditionals.h>
71 # if TARGET_OS_OSX == 1
72 #  define CATCH_PLATFORM_MAC
73 # elif TARGET_OS_IPHONE == 1
74 #  define CATCH_PLATFORM_IPHONE
75 # endif
76 
77 #elif defined(linux) || defined(__linux) || defined(__linux__)
78 #  define CATCH_PLATFORM_LINUX
79 
80 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
81 #  define CATCH_PLATFORM_WINDOWS
82 #endif
83 
84 // end catch_platform.h
85 
86 #ifdef CATCH_IMPL
87 #  ifndef CLARA_CONFIG_MAIN
88 #    define CLARA_CONFIG_MAIN_NOT_DEFINED
89 #    define CLARA_CONFIG_MAIN
90 #  endif
91 #endif
92 
93 // start catch_user_interfaces.h
94 
95 namespace Catch {
96     unsigned int rngSeed();
97 }
98 
99 // end catch_user_interfaces.h
100 // start catch_tag_alias_autoregistrar.h
101 
102 // start catch_common.h
103 
104 // start catch_compiler_capabilities.h
105 
106 // Detect a number of compiler features - by compiler
107 // The following features are defined:
108 //
109 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
110 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
111 // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
112 // CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?
113 // ****************
114 // Note to maintainers: if new toggles are added please document them
115 // in configuration.md, too
116 // ****************
117 
118 // In general each macro has a _NO_<feature name> form
119 // (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
120 // Many features, at point of detection, define an _INTERNAL_ macro, so they
121 // can be combined, en-mass, with the _NO_ forms later.
122 
123 #ifdef __cplusplus
124 
125 #  if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
126 #    define CATCH_CPP14_OR_GREATER
127 #  endif
128 
129 #  if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
130 #    define CATCH_CPP17_OR_GREATER
131 #  endif
132 
133 #endif
134 
135 #if defined(CATCH_CPP17_OR_GREATER)
136 #  define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
137 #endif
138 
139 // We have to avoid both ICC and Clang, because they try to mask themselves
140 // as gcc, and we want only GCC in this block
141 #if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC)
142 #    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )
143 #    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "GCC diagnostic pop" )
144 
145 #    define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
146 
147 #endif
148 
149 #if defined(__clang__)
150 
151 #    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )
152 #    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "clang diagnostic pop" )
153 
154 #    define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)
155 
156 #    define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
157          _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
158          _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
159 
160 #    define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
161          _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
162 
163 #    define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
164          _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
165 
166 #    define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
167          _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )
168 
169 #    define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
170          _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )
171 
172 #endif // __clang__
173 
174 ////////////////////////////////////////////////////////////////////////////////
175 // Assume that non-Windows platforms support posix signals by default
176 #if !defined(CATCH_PLATFORM_WINDOWS)
177     #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
178 #endif
179 
180 ////////////////////////////////////////////////////////////////////////////////
181 // We know some environments not to support full POSIX signals
182 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
183     #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
184 #endif
185 
186 #ifdef __OS400__
187 #       define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
188 #       define CATCH_CONFIG_COLOUR_NONE
189 #endif
190 
191 ////////////////////////////////////////////////////////////////////////////////
192 // Android somehow still does not support std::to_string
193 #if defined(__ANDROID__)
194 #    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
195 #    define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE
196 #endif
197 
198 ////////////////////////////////////////////////////////////////////////////////
199 // Not all Windows environments support SEH properly
200 #if defined(__MINGW32__)
201 #    define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
202 #endif
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 // PS4
206 #if defined(__ORBIS__)
207 #    define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
208 #endif
209 
210 ////////////////////////////////////////////////////////////////////////////////
211 // Cygwin
212 #ifdef __CYGWIN__
213 
214 // Required for some versions of Cygwin to declare gettimeofday
215 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
216 #   define _BSD_SOURCE
217 // some versions of cygwin (most) do not support std::to_string. Use the libstd check.
218 // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
219 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
220            && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
221 
222 #    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
223 
224 # endif
225 #endif // __CYGWIN__
226 
227 ////////////////////////////////////////////////////////////////////////////////
228 // Visual C++
229 #if defined(_MSC_VER)
230 
231 #  define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )
232 #  define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  __pragma( warning(pop) )
233 
234 #  if _MSC_VER >= 1900 // Visual Studio 2015 or newer
235 #    define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
236 #  endif
237 
238 // Universal Windows platform does not support SEH
239 // Or console colours (or console at all...)
240 #  if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
241 #    define CATCH_CONFIG_COLOUR_NONE
242 #  else
243 #    define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
244 #  endif
245 
246 // MSVC traditional preprocessor needs some workaround for __VA_ARGS__
247 // _MSVC_TRADITIONAL == 0 means new conformant preprocessor
248 // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
249 #  if !defined(__clang__) // Handle Clang masquerading for msvc
250 #    if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
251 #      define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
252 #    endif // MSVC_TRADITIONAL
253 #  endif // __clang__
254 
255 #endif // _MSC_VER
256 
257 #if defined(_REENTRANT) || defined(_MSC_VER)
258 // Enable async processing, as -pthread is specified or no additional linking is required
259 # define CATCH_INTERNAL_CONFIG_USE_ASYNC
260 #endif // _MSC_VER
261 
262 ////////////////////////////////////////////////////////////////////////////////
263 // Check if we are compiled with -fno-exceptions or equivalent
264 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
265 #  define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
266 #endif
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 // DJGPP
270 #ifdef __DJGPP__
271 #  define CATCH_INTERNAL_CONFIG_NO_WCHAR
272 #endif // __DJGPP__
273 
274 ////////////////////////////////////////////////////////////////////////////////
275 // Embarcadero C++Build
276 #if defined(__BORLANDC__)
277     #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
278 #endif
279 
280 ////////////////////////////////////////////////////////////////////////////////
281 
282 // Use of __COUNTER__ is suppressed during code analysis in
283 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
284 // handled by it.
285 // Otherwise all supported compilers support COUNTER macro,
286 // but user still might want to turn it off
287 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
288     #define CATCH_INTERNAL_CONFIG_COUNTER
289 #endif
290 
291 ////////////////////////////////////////////////////////////////////////////////
292 
293 // RTX is a special version of Windows that is real time.
294 // This means that it is detected as Windows, but does not provide
295 // the same set of capabilities as real Windows does.
296 #if defined(UNDER_RTSS) || defined(RTX64_BUILD)
297     #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
298     #define CATCH_INTERNAL_CONFIG_NO_ASYNC
299     #define CATCH_CONFIG_COLOUR_NONE
300 #endif
301 
302 #if !defined(_GLIBCXX_USE_C99_MATH_TR1)
303 #define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER
304 #endif
305 
306 // Various stdlib support checks that require __has_include
307 #if defined(__has_include)
308   // Check if string_view is available and usable
309   #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
310   #    define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
311   #endif
312 
313   // Check if optional is available and usable
314   #  if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
315   #    define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
316   #  endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
317 
318   // Check if byte is available and usable
319   #  if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
320   #    define CATCH_INTERNAL_CONFIG_CPP17_BYTE
321   #  endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)
322 
323   // Check if variant is available and usable
324   #  if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
325   #    if defined(__clang__) && (__clang_major__ < 8)
326          // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
327          // fix should be in clang 8, workaround in libstdc++ 8.2
328   #      include <ciso646>
329   #      if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
330   #        define CATCH_CONFIG_NO_CPP17_VARIANT
331   #      else
332   #        define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
333   #      endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
334   #    else
335   #      define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
336   #    endif // defined(__clang__) && (__clang_major__ < 8)
337   #  endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
338 #endif // defined(__has_include)
339 
340 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
341 #   define CATCH_CONFIG_COUNTER
342 #endif
343 #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
344 #   define CATCH_CONFIG_WINDOWS_SEH
345 #endif
346 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
347 #if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
348 #   define CATCH_CONFIG_POSIX_SIGNALS
349 #endif
350 // This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
351 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
352 #   define CATCH_CONFIG_WCHAR
353 #endif
354 
355 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
356 #    define CATCH_CONFIG_CPP11_TO_STRING
357 #endif
358 
359 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
360 #  define CATCH_CONFIG_CPP17_OPTIONAL
361 #endif
362 
363 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
364 #  define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
365 #endif
366 
367 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
368 #  define CATCH_CONFIG_CPP17_STRING_VIEW
369 #endif
370 
371 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
372 #  define CATCH_CONFIG_CPP17_VARIANT
373 #endif
374 
375 #if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)
376 #  define CATCH_CONFIG_CPP17_BYTE
377 #endif
378 
379 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
380 #  define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
381 #endif
382 
383 #if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
384 #  define CATCH_CONFIG_NEW_CAPTURE
385 #endif
386 
387 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
388 #  define CATCH_CONFIG_DISABLE_EXCEPTIONS
389 #endif
390 
391 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
392 #  define CATCH_CONFIG_POLYFILL_ISNAN
393 #endif
394 
395 #if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC)  && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)
396 #  define CATCH_CONFIG_USE_ASYNC
397 #endif
398 
399 #if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE)
400 #  define CATCH_CONFIG_ANDROID_LOGWRITE
401 #endif
402 
403 #if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
404 #  define CATCH_CONFIG_GLOBAL_NEXTAFTER
405 #endif
406 
407 // Even if we do not think the compiler has that warning, we still have
408 // to provide a macro that can be used by the code.
409 #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)
410 #   define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
411 #endif
412 #if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)
413 #   define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
414 #endif
415 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
416 #   define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
417 #endif
418 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
419 #   define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
420 #endif
421 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
422 #   define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
423 #endif
424 #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)
425 #   define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS
426 #endif
427 
428 // The goal of this macro is to avoid evaluation of the arguments, but
429 // still have the compiler warn on problems inside...
430 #if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)
431 #   define CATCH_INTERNAL_IGNORE_BUT_WARN(...)
432 #endif
433 
434 #if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)
435 #   undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
436 #elif defined(__clang__) && (__clang_major__ < 5)
437 #   undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
438 #endif
439 
440 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)
441 #   define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS
442 #endif
443 
444 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
445 #define CATCH_TRY if ((true))
446 #define CATCH_CATCH_ALL if ((false))
447 #define CATCH_CATCH_ANON(type) if ((false))
448 #else
449 #define CATCH_TRY try
450 #define CATCH_CATCH_ALL catch (...)
451 #define CATCH_CATCH_ANON(type) catch (type)
452 #endif
453 
454 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
455 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
456 #endif
457 
458 // end catch_compiler_capabilities.h
459 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
460 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
461 #ifdef CATCH_CONFIG_COUNTER
462 #  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
463 #else
464 #  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
465 #endif
466 
467 #include <iosfwd>
468 #include <string>
469 #include <cstdint>
470 
471 // We need a dummy global operator<< so we can bring it into Catch namespace later
472 struct Catch_global_namespace_dummy {};
473 std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
474 
475 namespace Catch {
476 
477     struct CaseSensitive { enum Choice {
478         Yes,
479         No
480     }; };
481 
482     class NonCopyable {
483         NonCopyable( NonCopyable const& )              = delete;
484         NonCopyable( NonCopyable && )                  = delete;
485         NonCopyable& operator = ( NonCopyable const& ) = delete;
486         NonCopyable& operator = ( NonCopyable && )     = delete;
487 
488     protected:
489         NonCopyable();
490         virtual ~NonCopyable();
491     };
492 
493     struct SourceLineInfo {
494 
495         SourceLineInfo() = delete;
SourceLineInfoCatch::SourceLineInfo496         SourceLineInfo( char const* _file, std::size_t _line ) noexcept
497         :   file( _file ),
498             line( _line )
499         {}
500 
501         SourceLineInfo( SourceLineInfo const& other )            = default;
502         SourceLineInfo& operator = ( SourceLineInfo const& )     = default;
503         SourceLineInfo( SourceLineInfo&& )              noexcept = default;
504         SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
505 
emptyCatch::SourceLineInfo506         bool empty() const noexcept { return file[0] == '\0'; }
507         bool operator == ( SourceLineInfo const& other ) const noexcept;
508         bool operator < ( SourceLineInfo const& other ) const noexcept;
509 
510         char const* file;
511         std::size_t line;
512     };
513 
514     std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
515 
516     // Bring in operator<< from global namespace into Catch namespace
517     // This is necessary because the overload of operator<< above makes
518     // lookup stop at namespace Catch
519     using ::operator<<;
520 
521     // Use this in variadic streaming macros to allow
522     //    >> +StreamEndStop
523     // as well as
524     //    >> stuff +StreamEndStop
525     struct StreamEndStop {
526         std::string operator+() const;
527     };
528     template<typename T>
operator +(T const & value,StreamEndStop)529     T const& operator + ( T const& value, StreamEndStop ) {
530         return value;
531     }
532 }
533 
534 #define CATCH_INTERNAL_LINEINFO \
535     ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
536 
537 // end catch_common.h
538 namespace Catch {
539 
540     struct RegistrarForTagAliases {
541         RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
542     };
543 
544 } // end namespace Catch
545 
546 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
547     CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
548     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
549     namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
550     CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
551 
552 // end catch_tag_alias_autoregistrar.h
553 // start catch_test_registry.h
554 
555 // start catch_interfaces_testcase.h
556 
557 #include <vector>
558 
559 namespace Catch {
560 
561     class TestSpec;
562 
563     struct ITestInvoker {
564         virtual void invoke () const = 0;
565         virtual ~ITestInvoker();
566     };
567 
568     class TestCase;
569     struct IConfig;
570 
571     struct ITestCaseRegistry {
572         virtual ~ITestCaseRegistry();
573         virtual std::vector<TestCase> const& getAllTests() const = 0;
574         virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
575     };
576 
577     bool isThrowSafe( TestCase const& testCase, IConfig const& config );
578     bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
579     std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
580     std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
581 
582 }
583 
584 // end catch_interfaces_testcase.h
585 // start catch_stringref.h
586 
587 #include <cstddef>
588 #include <string>
589 #include <iosfwd>
590 #include <cassert>
591 
592 namespace Catch {
593 
594     /// A non-owning string class (similar to the forthcoming std::string_view)
595     /// Note that, because a StringRef may be a substring of another string,
596     /// it may not be null terminated.
597     class StringRef {
598     public:
599         using size_type = std::size_t;
600         using const_iterator = const char*;
601 
602     private:
603         static constexpr char const* const s_empty = "";
604 
605         char const* m_start = s_empty;
606         size_type m_size = 0;
607 
608     public: // construction
609         constexpr StringRef() noexcept = default;
610 
611         StringRef( char const* rawChars ) noexcept;
612 
StringRef(char const * rawChars,size_type size)613         constexpr StringRef( char const* rawChars, size_type size ) noexcept
614         :   m_start( rawChars ),
615             m_size( size )
616         {}
617 
StringRef(std::string const & stdString)618         StringRef( std::string const& stdString ) noexcept
619         :   m_start( stdString.c_str() ),
620             m_size( stdString.size() )
621         {}
622 
operator std::string() const623         explicit operator std::string() const {
624             return std::string(m_start, m_size);
625         }
626 
627     public: // operators
628         auto operator == ( StringRef const& other ) const noexcept -> bool;
operator !=(StringRef const & other) const629         auto operator != (StringRef const& other) const noexcept -> bool {
630             return !(*this == other);
631         }
632 
operator [](size_type index) const633         auto operator[] ( size_type index ) const noexcept -> char {
634             assert(index < m_size);
635             return m_start[index];
636         }
637 
638     public: // named queries
empty() const639         constexpr auto empty() const noexcept -> bool {
640             return m_size == 0;
641         }
size() const642         constexpr auto size() const noexcept -> size_type {
643             return m_size;
644         }
645 
646         // Returns the current start pointer. If the StringRef is not
647         // null-terminated, throws std::domain_exception
648         auto c_str() const -> char const*;
649 
650     public: // substrings and searches
651         // Returns a substring of [start, start + length).
652         // If start + length > size(), then the substring is [start, size()).
653         // If start > size(), then the substring is empty.
654         auto substr( size_type start, size_type length ) const noexcept -> StringRef;
655 
656         // Returns the current start pointer. May not be null-terminated.
657         auto data() const noexcept -> char const*;
658 
isNullTerminated() const659         constexpr auto isNullTerminated() const noexcept -> bool {
660             return m_start[m_size] == '\0';
661         }
662 
663     public: // iterators
begin() const664         constexpr const_iterator begin() const { return m_start; }
end() const665         constexpr const_iterator end() const { return m_start + m_size; }
666     };
667 
668     auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
669     auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
670 
operator ""_sr(char const * rawChars,std::size_t size)671     constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
672         return StringRef( rawChars, size );
673     }
674 } // namespace Catch
675 
operator ""_catch_sr(char const * rawChars,std::size_t size)676 constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
677     return Catch::StringRef( rawChars, size );
678 }
679 
680 // end catch_stringref.h
681 // start catch_preprocessor.hpp
682 
683 
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__)))
690 
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__))
696 #else
697 #define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL5(__VA_ARGS__)
698 #endif
699 
700 #define CATCH_REC_END(...)
701 #define CATCH_REC_OUT
702 
703 #define CATCH_EMPTY()
704 #define CATCH_DEFER(id) id CATCH_EMPTY()
705 
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)
712 
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__ )
716 
717 #define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
718 #define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )
719 #define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...)   f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
720 
721 // Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
722 // and passes userdata as the first parameter to each invocation,
723 // e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
724 #define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
725 
726 #define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
727 
728 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
729 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
730 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
731 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
732 #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
733 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
734 #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
735 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
736 #else
737 // MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
738 #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
739 #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
740 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
741 #endif
742 
743 #define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__
744 #define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)
745 
746 #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
747 
748 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
749 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())
750 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
751 #else
752 #define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()))
753 #define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
754 #endif
755 
756 #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\
757     CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__)
758 
759 #define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)
760 #define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)
761 #define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)
762 #define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3)
763 #define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4)
764 #define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5)
765 #define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6)
766 #define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7)
767 #define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8)
768 #define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9)
769 #define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10)
770 
771 #define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
772 
773 #define INTERNAL_CATCH_TYPE_GEN\
774     template<typename...> struct TypeList {};\
775     template<typename...Ts>\
776     constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\
777     template<template<typename...> class...> struct TemplateTypeList{};\
778     template<template<typename...> class...Cs>\
779     constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\
780     template<typename...>\
781     struct append;\
782     template<typename...>\
783     struct rewrap;\
784     template<template<typename...> class, typename...>\
785     struct create;\
786     template<template<typename...> class, typename>\
787     struct convert;\
788     \
789     template<typename T> \
790     struct append<T> { using type = T; };\
791     template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\
792     struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\
793     template< template<typename...> class L1, typename...E1, typename...Rest>\
794     struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\
795     \
796     template< template<typename...> class Container, template<typename...> class List, typename...elems>\
797     struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\
798     template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\
799     struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\
800     \
801     template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\
802     struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\
803     template<template <typename...> class Final, template <typename...> class List, typename...Ts>\
804     struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };
805 
806 #define INTERNAL_CATCH_NTTP_1(signature, ...)\
807     template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\
808     template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
809     constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \
810     template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\
811     template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\
812     constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \
813     \
814     template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\
815     struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\
816     template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\
817     struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\
818     template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\
819     struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };
820 
821 #define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)
822 #define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\
823     template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
824     static void TestName()
825 #define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\
826     template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
827     static void TestName()
828 
829 #define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)
830 #define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\
831     template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
832     static void TestName()
833 #define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\
834     template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
835     static void TestName()
836 
837 #define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\
838     template<typename Type>\
839     void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\
840     {\
841         Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
842     }
843 
844 #define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\
845     template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
846     void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\
847     {\
848         Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\
849     }
850 
851 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\
852     template<typename Type>\
853     void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
854     {\
855         Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
856     }
857 
858 #define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\
859     template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\
860     void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\
861     {\
862         Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\
863     }
864 
865 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)
866 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\
867     template<typename TestType> \
868     struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \
869         void test();\
870     }
871 
872 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\
873     template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
874     struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \
875         void test();\
876     }
877 
878 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)
879 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\
880     template<typename TestType> \
881     void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test()
882 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\
883     template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \
884     void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()
885 
886 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
887 #define INTERNAL_CATCH_NTTP_0
888 #define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__),INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_0)
889 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)
890 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)
891 #define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)
892 #define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)
893 #define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)
894 #define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)
895 #define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)
896 #else
897 #define INTERNAL_CATCH_NTTP_0(signature)
898 #define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1,INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_0)( __VA_ARGS__))
899 #define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__))
900 #define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__))
901 #define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__))
902 #define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__))
903 #define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__))
904 #define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__))
905 #define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__))
906 #endif
907 
908 // end catch_preprocessor.hpp
909 // start catch_meta.hpp
910 
911 
912 #include <type_traits>
913 
914 namespace Catch {
915     template<typename T>
916     struct always_false : std::false_type {};
917 
918     template <typename> struct true_given : std::true_type {};
919     struct is_callable_tester {
920         template <typename Fun, typename... Args>
921         true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int);
922         template <typename...>
923         std::false_type static test(...);
924     };
925 
926     template <typename T>
927     struct is_callable;
928 
929     template <typename Fun, typename... Args>
930     struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};
931 
932 #if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
933     // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
934     // replaced with std::invoke_result here. Also *_t format is preferred over
935     // typename *::type format.
936     template <typename Func, typename U>
937     using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>;
938 #else
939     template <typename Func, typename U>
940     using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U)>::type>::type>::type;
941 #endif
942 
943 } // namespace Catch
944 
945 namespace mpl_{
946     struct na;
947 }
948 
949 // end catch_meta.hpp
950 namespace Catch {
951 
952 template<typename C>
953 class TestInvokerAsMethod : public ITestInvoker {
954     void (C::*m_testAsMethod)();
955 public:
TestInvokerAsMethod(void (C::* testAsMethod)())956     TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
957 
invoke() const958     void invoke() const override {
959         C obj;
960         (obj.*m_testAsMethod)();
961     }
962 };
963 
964 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;
965 
966 template<typename C>
makeTestInvoker(void (C::* testAsMethod)())967 auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
968     return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod );
969 }
970 
971 struct NameAndTags {
972     NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
973     StringRef name;
974     StringRef tags;
975 };
976 
977 struct AutoReg : NonCopyable {
978     AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
979     ~AutoReg();
980 };
981 
982 } // end namespace Catch
983 
984 #if defined(CATCH_CONFIG_DISABLE)
985     #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
986         static void TestName()
987     #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
988         namespace{                        \
989             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
990                 void test();              \
991             };                            \
992         }                                 \
993         void TestName::test()
994     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... )  \
995         INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))
996     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... )    \
997         namespace{                                                                                  \
998             namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) {                                      \
999             INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
1000         }                                                                                           \
1001         }                                                                                           \
1002         INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1003 
1004     #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1005         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
1006             INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ )
1007     #else
1008         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \
1009             INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
1010     #endif
1011 
1012     #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1013         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
1014             INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ )
1015     #else
1016         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \
1017             INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )
1018     #endif
1019 
1020     #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1021         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
1022             INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
1023     #else
1024         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \
1025             INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
1026     #endif
1027 
1028     #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1029         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
1030             INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
1031     #else
1032         #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \
1033             INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
1034     #endif
1035 #endif
1036 
1037     ///////////////////////////////////////////////////////////////////////////////
1038     #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
1039         static void TestName(); \
1040         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1041         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1042         namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
1043         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1044         static void TestName()
1045     #define INTERNAL_CATCH_TESTCASE( ... ) \
1046         INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
1047 
1048     ///////////////////////////////////////////////////////////////////////////////
1049     #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
1050         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1051         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1052         namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
1053         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
1054 
1055     ///////////////////////////////////////////////////////////////////////////////
1056     #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
1057         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1058         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1059         namespace{ \
1060             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
1061                 void test(); \
1062             }; \
1063             Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
1064         } \
1065         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1066         void TestName::test()
1067     #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
1068         INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
1069 
1070     ///////////////////////////////////////////////////////////////////////////////
1071     #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
1072         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1073         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1074         Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
1075         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
1076 
1077     ///////////////////////////////////////////////////////////////////////////////
1078     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\
1079         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1080         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1081         CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1082         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1083         INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
1084         namespace {\
1085         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
1086             INTERNAL_CATCH_TYPE_GEN\
1087             INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1088             INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1089             template<typename...Types> \
1090             struct TestName{\
1091                 TestName(){\
1092                     int index = 0;                                    \
1093                     constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
1094                     using expander = int[];\
1095                     (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \
1096                 }\
1097             };\
1098             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1099             TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
1100             return 0;\
1101         }();\
1102         }\
1103         }\
1104         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1105         INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))
1106 
1107 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1108     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
1109         INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ )
1110 #else
1111     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
1112         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) )
1113 #endif
1114 
1115 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1116     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
1117         INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ )
1118 #else
1119     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \
1120         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )
1121 #endif
1122 
1123     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \
1124         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                      \
1125         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                      \
1126         CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS                \
1127         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS              \
1128         template<typename TestType> static void TestFuncName();       \
1129         namespace {\
1130         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) {                                     \
1131             INTERNAL_CATCH_TYPE_GEN                                                  \
1132             INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))         \
1133             template<typename... Types>                               \
1134             struct TestName {                                         \
1135                 void reg_tests() {                                          \
1136                     int index = 0;                                    \
1137                     using expander = int[];                           \
1138                     constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
1139                     constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
1140                     constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
1141                     (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\
1142                 }                                                     \
1143             };                                                        \
1144             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
1145                 using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \
1146                 TestInit t;                                           \
1147                 t.reg_tests();                                        \
1148                 return 0;                                             \
1149             }();                                                      \
1150         }                                                             \
1151         }                                                             \
1152         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                       \
1153         template<typename TestType>                                   \
1154         static void TestFuncName()
1155 
1156 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1157     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
1158         INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T,__VA_ARGS__)
1159 #else
1160     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
1161         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T, __VA_ARGS__ ) )
1162 #endif
1163 
1164 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1165     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
1166         INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__)
1167 #else
1168     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\
1169         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )
1170 #endif
1171 
1172     #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\
1173         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1174         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1175         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1176         template<typename TestType> static void TestFunc();       \
1177         namespace {\
1178         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\
1179         INTERNAL_CATCH_TYPE_GEN\
1180         template<typename... Types>                               \
1181         struct TestName {                                         \
1182             void reg_tests() {                                          \
1183                 int index = 0;                                    \
1184                 using expander = int[];                           \
1185                 (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */\
1186             }                                                     \
1187         };\
1188         static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
1189                 using TestInit = typename convert<TestName, TmplList>::type; \
1190                 TestInit t;                                           \
1191                 t.reg_tests();                                        \
1192                 return 0;                                             \
1193             }();                                                      \
1194         }}\
1195         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                       \
1196         template<typename TestType>                                   \
1197         static void TestFunc()
1198 
1199     #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \
1200         INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, TmplList )
1201 
1202     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \
1203         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1204         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1205         CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1206         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1207         namespace {\
1208         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
1209             INTERNAL_CATCH_TYPE_GEN\
1210             INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1211             INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\
1212             INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1213             template<typename...Types> \
1214             struct TestNameClass{\
1215                 TestNameClass(){\
1216                     int index = 0;                                    \
1217                     constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\
1218                     using expander = int[];\
1219                     (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++, 0)... };/* NOLINT */ \
1220                 }\
1221             };\
1222             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1223                 TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\
1224                 return 0;\
1225         }();\
1226         }\
1227         }\
1228         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1229         INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))
1230 
1231 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1232     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
1233         INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )
1234 #else
1235     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
1236         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )
1237 #endif
1238 
1239 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1240     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
1241         INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )
1242 #else
1243     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \
1244         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )
1245 #endif
1246 
1247     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\
1248         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1249         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1250         CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \
1251         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1252         template<typename TestType> \
1253             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
1254                 void test();\
1255             };\
1256         namespace {\
1257         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\
1258             INTERNAL_CATCH_TYPE_GEN                  \
1259             INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\
1260             template<typename...Types>\
1261             struct TestNameClass{\
1262                 void reg_tests(){\
1263                     int index = 0;\
1264                     using expander = int[];\
1265                     constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
1266                     constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
1267                     constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
1268                     (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \
1269                 }\
1270             };\
1271             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1272                 using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\
1273                 TestInit t;\
1274                 t.reg_tests();\
1275                 return 0;\
1276             }(); \
1277         }\
1278         }\
1279         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1280         template<typename TestType> \
1281         void TestName<TestType>::test()
1282 
1283 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1284     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
1285         INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )
1286 #else
1287     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
1288         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )
1289 #endif
1290 
1291 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1292     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
1293         INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )
1294 #else
1295     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\
1296         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )
1297 #endif
1298 
1299     #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \
1300         CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
1301         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1302         CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \
1303         template<typename TestType> \
1304         struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
1305             void test();\
1306         };\
1307         namespace {\
1308         namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \
1309             INTERNAL_CATCH_TYPE_GEN\
1310             template<typename...Types>\
1311             struct TestNameClass{\
1312                 void reg_tests(){\
1313                     int index = 0;\
1314                     using expander = int[];\
1315                     (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++, 0)... };/* NOLINT */ \
1316                 }\
1317             };\
1318             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1319                 using TestInit = typename convert<TestNameClass, TmplList>::type;\
1320                 TestInit t;\
1321                 t.reg_tests();\
1322                 return 0;\
1323             }(); \
1324         }}\
1325         CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
1326         template<typename TestType> \
1327         void TestName<TestType>::test()
1328 
1329 #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \
1330         INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, TmplList )
1331 
1332 // end catch_test_registry.h
1333 // start catch_capture.hpp
1334 
1335 // start catch_assertionhandler.h
1336 
1337 // start catch_assertioninfo.h
1338 
1339 // start catch_result_type.h
1340 
1341 namespace Catch {
1342 
1343     // ResultWas::OfType enum
1344     struct ResultWas { enum OfType {
1345         Unknown = -1,
1346         Ok = 0,
1347         Info = 1,
1348         Warning = 2,
1349 
1350         FailureBit = 0x10,
1351 
1352         ExpressionFailed = FailureBit | 1,
1353         ExplicitFailure = FailureBit | 2,
1354 
1355         Exception = 0x100 | FailureBit,
1356 
1357         ThrewException = Exception | 1,
1358         DidntThrowException = Exception | 2,
1359 
1360         FatalErrorCondition = 0x200 | FailureBit
1361 
1362     }; };
1363 
1364     bool isOk( ResultWas::OfType resultType );
1365     bool isJustInfo( int flags );
1366 
1367     // ResultDisposition::Flags enum
1368     struct ResultDisposition { enum Flags {
1369         Normal = 0x01,
1370 
1371         ContinueOnFailure = 0x02,   // Failures fail test, but execution continues
1372         FalseTest = 0x04,           // Prefix expression with !
1373         SuppressFail = 0x08         // Failures are reported but do not fail the test
1374     }; };
1375 
1376     ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs );
1377 
1378     bool shouldContinueOnFailure( int flags );
isFalseTest(int flags)1379     inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
1380     bool shouldSuppressFailure( int flags );
1381 
1382 } // end namespace Catch
1383 
1384 // end catch_result_type.h
1385 namespace Catch {
1386 
1387     struct AssertionInfo
1388     {
1389         StringRef macroName;
1390         SourceLineInfo lineInfo;
1391         StringRef capturedExpression;
1392         ResultDisposition::Flags resultDisposition;
1393 
1394         // We want to delete this constructor but a compiler bug in 4.8 means
1395         // the struct is then treated as non-aggregate
1396         //AssertionInfo() = delete;
1397     };
1398 
1399 } // end namespace Catch
1400 
1401 // end catch_assertioninfo.h
1402 // start catch_decomposer.h
1403 
1404 // start catch_tostring.h
1405 
1406 #include <vector>
1407 #include <cstddef>
1408 #include <type_traits>
1409 #include <string>
1410 // start catch_stream.h
1411 
1412 #include <iosfwd>
1413 #include <cstddef>
1414 #include <ostream>
1415 
1416 namespace Catch {
1417 
1418     std::ostream& cout();
1419     std::ostream& cerr();
1420     std::ostream& clog();
1421 
1422     class StringRef;
1423 
1424     struct IStream {
1425         virtual ~IStream();
1426         virtual std::ostream& stream() const = 0;
1427     };
1428 
1429     auto makeStream( StringRef const &filename ) -> IStream const*;
1430 
1431     class ReusableStringStream : NonCopyable {
1432         std::size_t m_index;
1433         std::ostream* m_oss;
1434     public:
1435         ReusableStringStream();
1436         ~ReusableStringStream();
1437 
1438         auto str() const -> std::string;
1439 
1440         template<typename T>
operator <<(T const & value)1441         auto operator << ( T const& value ) -> ReusableStringStream& {
1442             *m_oss << value;
1443             return *this;
1444         }
get()1445         auto get() -> std::ostream& { return *m_oss; }
1446     };
1447 }
1448 
1449 // end catch_stream.h
1450 // start catch_interfaces_enum_values_registry.h
1451 
1452 #include <vector>
1453 
1454 namespace Catch {
1455 
1456     namespace Detail {
1457         struct EnumInfo {
1458             StringRef m_name;
1459             std::vector<std::pair<int, StringRef>> m_values;
1460 
1461             ~EnumInfo();
1462 
1463             StringRef lookup( int value ) const;
1464         };
1465     } // namespace Detail
1466 
1467     struct IMutableEnumValuesRegistry {
1468         virtual ~IMutableEnumValuesRegistry();
1469 
1470         virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;
1471 
1472         template<typename E>
registerEnumCatch::IMutableEnumValuesRegistry1473         Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {
1474             static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");
1475             std::vector<int> intValues;
1476             intValues.reserve( values.size() );
1477             for( auto enumValue : values )
1478                 intValues.push_back( static_cast<int>( enumValue ) );
1479             return registerEnum( enumName, allEnums, intValues );
1480         }
1481     };
1482 
1483 } // Catch
1484 
1485 // end catch_interfaces_enum_values_registry.h
1486 
1487 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1488 #include <string_view>
1489 #endif
1490 
1491 #ifdef __OBJC__
1492 // start catch_objc_arc.hpp
1493 
1494 #import <Foundation/Foundation.h>
1495 
1496 #ifdef __has_feature
1497 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1498 #else
1499 #define CATCH_ARC_ENABLED 0
1500 #endif
1501 
1502 void arcSafeRelease( NSObject* obj );
1503 id performOptionalSelector( id obj, SEL sel );
1504 
1505 #if !CATCH_ARC_ENABLED
arcSafeRelease(NSObject * obj)1506 inline void arcSafeRelease( NSObject* obj ) {
1507     [obj release];
1508 }
performOptionalSelector(id obj,SEL sel)1509 inline id performOptionalSelector( id obj, SEL sel ) {
1510     if( [obj respondsToSelector: sel] )
1511         return [obj performSelector: sel];
1512     return nil;
1513 }
1514 #define CATCH_UNSAFE_UNRETAINED
1515 #define CATCH_ARC_STRONG
1516 #else
arcSafeRelease(NSObject *)1517 inline void arcSafeRelease( NSObject* ){}
performOptionalSelector(id obj,SEL sel)1518 inline id performOptionalSelector( id obj, SEL sel ) {
1519 #ifdef __clang__
1520 #pragma clang diagnostic push
1521 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1522 #endif
1523     if( [obj respondsToSelector: sel] )
1524         return [obj performSelector: sel];
1525 #ifdef __clang__
1526 #pragma clang diagnostic pop
1527 #endif
1528     return nil;
1529 }
1530 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1531 #define CATCH_ARC_STRONG __strong
1532 #endif
1533 
1534 // end catch_objc_arc.hpp
1535 #endif
1536 
1537 #ifdef _MSC_VER
1538 #pragma warning(push)
1539 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
1540 #endif
1541 
1542 namespace Catch {
1543     namespace Detail {
1544 
1545         extern const std::string unprintableString;
1546 
1547         std::string rawMemoryToString( const void *object, std::size_t size );
1548 
1549         template<typename T>
rawMemoryToString(const T & object)1550         std::string rawMemoryToString( const T& object ) {
1551           return rawMemoryToString( &object, sizeof(object) );
1552         }
1553 
1554         template<typename T>
1555         class IsStreamInsertable {
1556             template<typename Stream, typename U>
1557             static auto test(int)
1558                 -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());
1559 
1560             template<typename, typename>
1561             static auto test(...)->std::false_type;
1562 
1563         public:
1564             static const bool value = decltype(test<std::ostream, const T&>(0))::value;
1565         };
1566 
1567         template<typename E>
1568         std::string convertUnknownEnumToString( E e );
1569 
1570         template<typename T>
1571         typename std::enable_if<
1572             !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
convertUnstreamable(T const &)1573         std::string>::type convertUnstreamable( T const& ) {
1574             return Detail::unprintableString;
1575         }
1576         template<typename T>
1577         typename std::enable_if<
1578             !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
convertUnstreamable(T const & ex)1579          std::string>::type convertUnstreamable(T const& ex) {
1580             return ex.what();
1581         }
1582 
1583         template<typename T>
1584         typename std::enable_if<
1585             std::is_enum<T>::value
convertUnstreamable(T const & value)1586         , std::string>::type convertUnstreamable( T const& value ) {
1587             return convertUnknownEnumToString( value );
1588         }
1589 
1590 #if defined(_MANAGED)
1591         //! Convert a CLR string to a utf8 std::string
1592         template<typename T>
1593         std::string clrReferenceToString( T^ ref ) {
1594             if (ref == nullptr)
1595                 return std::string("null");
1596             auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
1597             cli::pin_ptr<System::Byte> p = &bytes[0];
1598             return std::string(reinterpret_cast<char const *>(p), bytes->Length);
1599         }
1600 #endif
1601 
1602     } // namespace Detail
1603 
1604     // If we decide for C++14, change these to enable_if_ts
1605     template <typename T, typename = void>
1606     struct StringMaker {
1607         template <typename Fake = T>
1608         static
1609         typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
convertCatch::StringMaker1610             convert(const Fake& value) {
1611                 ReusableStringStream rss;
1612                 // NB: call using the function-like syntax to avoid ambiguity with
1613                 // user-defined templated operator<< under clang.
1614                 rss.operator<<(value);
1615                 return rss.str();
1616         }
1617 
1618         template <typename Fake = T>
1619         static
1620         typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
convertCatch::StringMaker1621             convert( const Fake& value ) {
1622 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
1623             return Detail::convertUnstreamable(value);
1624 #else
1625             return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
1626 #endif
1627         }
1628     };
1629 
1630     namespace Detail {
1631 
1632         // This function dispatches all stringification requests inside of Catch.
1633         // Should be preferably called fully qualified, like ::Catch::Detail::stringify
1634         template <typename T>
stringify(const T & e)1635         std::string stringify(const T& e) {
1636             return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e);
1637         }
1638 
1639         template<typename E>
convertUnknownEnumToString(E e)1640         std::string convertUnknownEnumToString( E e ) {
1641             return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));
1642         }
1643 
1644 #if defined(_MANAGED)
1645         template <typename T>
1646         std::string stringify( T^ e ) {
1647             return ::Catch::StringMaker<T^>::convert(e);
1648         }
1649 #endif
1650 
1651     } // namespace Detail
1652 
1653     // Some predefined specializations
1654 
1655     template<>
1656     struct StringMaker<std::string> {
1657         static std::string convert(const std::string& str);
1658     };
1659 
1660 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1661     template<>
1662     struct StringMaker<std::string_view> {
1663         static std::string convert(std::string_view str);
1664     };
1665 #endif
1666 
1667     template<>
1668     struct StringMaker<char const *> {
1669         static std::string convert(char const * str);
1670     };
1671     template<>
1672     struct StringMaker<char *> {
1673         static std::string convert(char * str);
1674     };
1675 
1676 #ifdef CATCH_CONFIG_WCHAR
1677     template<>
1678     struct StringMaker<std::wstring> {
1679         static std::string convert(const std::wstring& wstr);
1680     };
1681 
1682 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1683     template<>
1684     struct StringMaker<std::wstring_view> {
1685         static std::string convert(std::wstring_view str);
1686     };
1687 # endif
1688 
1689     template<>
1690     struct StringMaker<wchar_t const *> {
1691         static std::string convert(wchar_t const * str);
1692     };
1693     template<>
1694     struct StringMaker<wchar_t *> {
1695         static std::string convert(wchar_t * str);
1696     };
1697 #endif
1698 
1699     // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
1700     //      while keeping string semantics?
1701     template<int SZ>
1702     struct StringMaker<char[SZ]> {
convertCatch::StringMaker1703         static std::string convert(char const* str) {
1704             return ::Catch::Detail::stringify(std::string{ str });
1705         }
1706     };
1707     template<int SZ>
1708     struct StringMaker<signed char[SZ]> {
convertCatch::StringMaker1709         static std::string convert(signed char const* str) {
1710             return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
1711         }
1712     };
1713     template<int SZ>
1714     struct StringMaker<unsigned char[SZ]> {
convertCatch::StringMaker1715         static std::string convert(unsigned char const* str) {
1716             return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
1717         }
1718     };
1719 
1720 #if defined(CATCH_CONFIG_CPP17_BYTE)
1721     template<>
1722     struct StringMaker<std::byte> {
1723         static std::string convert(std::byte value);
1724     };
1725 #endif // defined(CATCH_CONFIG_CPP17_BYTE)
1726     template<>
1727     struct StringMaker<int> {
1728         static std::string convert(int value);
1729     };
1730     template<>
1731     struct StringMaker<long> {
1732         static std::string convert(long value);
1733     };
1734     template<>
1735     struct StringMaker<long long> {
1736         static std::string convert(long long value);
1737     };
1738     template<>
1739     struct StringMaker<unsigned int> {
1740         static std::string convert(unsigned int value);
1741     };
1742     template<>
1743     struct StringMaker<unsigned long> {
1744         static std::string convert(unsigned long value);
1745     };
1746     template<>
1747     struct StringMaker<unsigned long long> {
1748         static std::string convert(unsigned long long value);
1749     };
1750 
1751     template<>
1752     struct StringMaker<bool> {
1753         static std::string convert(bool b);
1754     };
1755 
1756     template<>
1757     struct StringMaker<char> {
1758         static std::string convert(char c);
1759     };
1760     template<>
1761     struct StringMaker<signed char> {
1762         static std::string convert(signed char c);
1763     };
1764     template<>
1765     struct StringMaker<unsigned char> {
1766         static std::string convert(unsigned char c);
1767     };
1768 
1769     template<>
1770     struct StringMaker<std::nullptr_t> {
1771         static std::string convert(std::nullptr_t);
1772     };
1773 
1774     template<>
1775     struct StringMaker<float> {
1776         static std::string convert(float value);
1777         static int precision;
1778     };
1779 
1780     template<>
1781     struct StringMaker<double> {
1782         static std::string convert(double value);
1783         static int precision;
1784     };
1785 
1786     template <typename T>
1787     struct StringMaker<T*> {
1788         template <typename U>
convertCatch::StringMaker1789         static std::string convert(U* p) {
1790             if (p) {
1791                 return ::Catch::Detail::rawMemoryToString(p);
1792             } else {
1793                 return "nullptr";
1794             }
1795         }
1796     };
1797 
1798     template <typename R, typename C>
1799     struct StringMaker<R C::*> {
convertCatch::StringMaker1800         static std::string convert(R C::* p) {
1801             if (p) {
1802                 return ::Catch::Detail::rawMemoryToString(p);
1803             } else {
1804                 return "nullptr";
1805             }
1806         }
1807     };
1808 
1809 #if defined(_MANAGED)
1810     template <typename T>
1811     struct StringMaker<T^> {
1812         static std::string convert( T^ ref ) {
1813             return ::Catch::Detail::clrReferenceToString(ref);
1814         }
1815     };
1816 #endif
1817 
1818     namespace Detail {
1819         template<typename InputIterator>
rangeToString(InputIterator first,InputIterator last)1820         std::string rangeToString(InputIterator first, InputIterator last) {
1821             ReusableStringStream rss;
1822             rss << "{ ";
1823             if (first != last) {
1824                 rss << ::Catch::Detail::stringify(*first);
1825                 for (++first; first != last; ++first)
1826                     rss << ", " << ::Catch::Detail::stringify(*first);
1827             }
1828             rss << " }";
1829             return rss.str();
1830         }
1831     }
1832 
1833 #ifdef __OBJC__
1834     template<>
1835     struct StringMaker<NSString*> {
convertCatch::StringMaker1836         static std::string convert(NSString * nsstring) {
1837             if (!nsstring)
1838                 return "nil";
1839             return std::string("@") + [nsstring UTF8String];
1840         }
1841     };
1842     template<>
1843     struct StringMaker<NSObject*> {
convertCatch::StringMaker1844         static std::string convert(NSObject* nsObject) {
1845             return ::Catch::Detail::stringify([nsObject description]);
1846         }
1847 
1848     };
1849     namespace Detail {
stringify(NSString * nsstring)1850         inline std::string stringify( NSString* nsstring ) {
1851             return StringMaker<NSString*>::convert( nsstring );
1852         }
1853 
1854     } // namespace Detail
1855 #endif // __OBJC__
1856 
1857 } // namespace Catch
1858 
1859 //////////////////////////////////////////////////////
1860 // Separate std-lib types stringification, so it can be selectively enabled
1861 // This means that we do not bring in
1862 
1863 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
1864 #  define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
1865 #  define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
1866 #  define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
1867 #  define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
1868 #  define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
1869 #endif
1870 
1871 // Separate std::pair specialization
1872 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
1873 #include <utility>
1874 namespace Catch {
1875     template<typename T1, typename T2>
1876     struct StringMaker<std::pair<T1, T2> > {
convertCatch::StringMaker1877         static std::string convert(const std::pair<T1, T2>& pair) {
1878             ReusableStringStream rss;
1879             rss << "{ "
1880                 << ::Catch::Detail::stringify(pair.first)
1881                 << ", "
1882                 << ::Catch::Detail::stringify(pair.second)
1883                 << " }";
1884             return rss.str();
1885         }
1886     };
1887 }
1888 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
1889 
1890 #if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
1891 #include <optional>
1892 namespace Catch {
1893     template<typename T>
1894     struct StringMaker<std::optional<T> > {
convertCatch::StringMaker1895         static std::string convert(const std::optional<T>& optional) {
1896             ReusableStringStream rss;
1897             if (optional.has_value()) {
1898                 rss << ::Catch::Detail::stringify(*optional);
1899             } else {
1900                 rss << "{ }";
1901             }
1902             return rss.str();
1903         }
1904     };
1905 }
1906 #endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
1907 
1908 // Separate std::tuple specialization
1909 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
1910 #include <tuple>
1911 namespace Catch {
1912     namespace Detail {
1913         template<
1914             typename Tuple,
1915             std::size_t N = 0,
1916             bool = (N < std::tuple_size<Tuple>::value)
1917             >
1918             struct TupleElementPrinter {
printCatch::Detail::TupleElementPrinter1919             static void print(const Tuple& tuple, std::ostream& os) {
1920                 os << (N ? ", " : " ")
1921                     << ::Catch::Detail::stringify(std::get<N>(tuple));
1922                 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
1923             }
1924         };
1925 
1926         template<
1927             typename Tuple,
1928             std::size_t N
1929         >
1930             struct TupleElementPrinter<Tuple, N, false> {
printCatch::Detail::TupleElementPrinter1931             static void print(const Tuple&, std::ostream&) {}
1932         };
1933 
1934     }
1935 
1936     template<typename ...Types>
1937     struct StringMaker<std::tuple<Types...>> {
convertCatch::StringMaker1938         static std::string convert(const std::tuple<Types...>& tuple) {
1939             ReusableStringStream rss;
1940             rss << '{';
1941             Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
1942             rss << " }";
1943             return rss.str();
1944         }
1945     };
1946 }
1947 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
1948 
1949 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
1950 #include <variant>
1951 namespace Catch {
1952     template<>
1953     struct StringMaker<std::monostate> {
convertCatch::StringMaker1954         static std::string convert(const std::monostate&) {
1955             return "{ }";
1956         }
1957     };
1958 
1959     template<typename... Elements>
1960     struct StringMaker<std::variant<Elements...>> {
convertCatch::StringMaker1961         static std::string convert(const std::variant<Elements...>& variant) {
1962             if (variant.valueless_by_exception()) {
1963                 return "{valueless variant}";
1964             } else {
1965                 return std::visit(
1966                     [](const auto& value) {
1967                         return ::Catch::Detail::stringify(value);
1968                     },
1969                     variant
1970                 );
1971             }
1972         }
1973     };
1974 }
1975 #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
1976 
1977 namespace Catch {
1978     struct not_this_one {}; // Tag type for detecting which begin/ end are being selected
1979 
1980     // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace
1981     using std::begin;
1982     using std::end;
1983 
1984     not_this_one begin( ... );
1985     not_this_one end( ... );
1986 
1987     template <typename T>
1988     struct is_range {
1989         static const bool value =
1990             !std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value &&
1991             !std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;
1992     };
1993 
1994 #if defined(_MANAGED) // Managed types are never ranges
1995     template <typename T>
1996     struct is_range<T^> {
1997         static const bool value = false;
1998     };
1999 #endif
2000 
2001     template<typename Range>
rangeToString(Range const & range)2002     std::string rangeToString( Range const& range ) {
2003         return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
2004     }
2005 
2006     // Handle vector<bool> specially
2007     template<typename Allocator>
rangeToString(std::vector<bool,Allocator> const & v)2008     std::string rangeToString( std::vector<bool, Allocator> const& v ) {
2009         ReusableStringStream rss;
2010         rss << "{ ";
2011         bool first = true;
2012         for( bool b : v ) {
2013             if( first )
2014                 first = false;
2015             else
2016                 rss << ", ";
2017             rss << ::Catch::Detail::stringify( b );
2018         }
2019         rss << " }";
2020         return rss.str();
2021     }
2022 
2023     template<typename R>
2024     struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
convertCatch::StringMaker2025         static std::string convert( R const& range ) {
2026             return rangeToString( range );
2027         }
2028     };
2029 
2030     template <typename T, int SZ>
2031     struct StringMaker<T[SZ]> {
convertCatch::StringMaker2032         static std::string convert(T const(&arr)[SZ]) {
2033             return rangeToString(arr);
2034         }
2035     };
2036 
2037 } // namespace Catch
2038 
2039 // Separate std::chrono::duration specialization
2040 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
2041 #include <ctime>
2042 #include <ratio>
2043 #include <chrono>
2044 
2045 namespace Catch {
2046 
2047 template <class Ratio>
2048 struct ratio_string {
2049     static std::string symbol();
2050 };
2051 
2052 template <class Ratio>
symbol()2053 std::string ratio_string<Ratio>::symbol() {
2054     Catch::ReusableStringStream rss;
2055     rss << '[' << Ratio::num << '/'
2056         << Ratio::den << ']';
2057     return rss.str();
2058 }
2059 template <>
2060 struct ratio_string<std::atto> {
2061     static std::string symbol();
2062 };
2063 template <>
2064 struct ratio_string<std::femto> {
2065     static std::string symbol();
2066 };
2067 template <>
2068 struct ratio_string<std::pico> {
2069     static std::string symbol();
2070 };
2071 template <>
2072 struct ratio_string<std::nano> {
2073     static std::string symbol();
2074 };
2075 template <>
2076 struct ratio_string<std::micro> {
2077     static std::string symbol();
2078 };
2079 template <>
2080 struct ratio_string<std::milli> {
2081     static std::string symbol();
2082 };
2083 
2084     ////////////
2085     // std::chrono::duration specializations
2086     template<typename Value, typename Ratio>
2087     struct StringMaker<std::chrono::duration<Value, Ratio>> {
convertCatch::StringMaker2088         static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
2089             ReusableStringStream rss;
2090             rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
2091             return rss.str();
2092         }
2093     };
2094     template<typename Value>
2095     struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
convertCatch::StringMaker2096         static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
2097             ReusableStringStream rss;
2098             rss << duration.count() << " s";
2099             return rss.str();
2100         }
2101     };
2102     template<typename Value>
2103     struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
convertCatch::StringMaker2104         static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
2105             ReusableStringStream rss;
2106             rss << duration.count() << " m";
2107             return rss.str();
2108         }
2109     };
2110     template<typename Value>
2111     struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
convertCatch::StringMaker2112         static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
2113             ReusableStringStream rss;
2114             rss << duration.count() << " h";
2115             return rss.str();
2116         }
2117     };
2118 
2119     ////////////
2120     // std::chrono::time_point specialization
2121     // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
2122     template<typename Clock, typename Duration>
2123     struct StringMaker<std::chrono::time_point<Clock, Duration>> {
convertCatch::StringMaker2124         static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
2125             return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
2126         }
2127     };
2128     // std::chrono::time_point<system_clock> specialization
2129     template<typename Duration>
2130     struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
convertCatch::StringMaker2131         static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
2132             auto converted = std::chrono::system_clock::to_time_t(time_point);
2133 
2134 #ifdef _MSC_VER
2135             std::tm timeInfo = {};
2136             gmtime_s(&timeInfo, &converted);
2137 #else
2138             std::tm* timeInfo = std::gmtime(&converted);
2139 #endif
2140 
2141             auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
2142             char timeStamp[timeStampSize];
2143             const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
2144 
2145 #ifdef _MSC_VER
2146             std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
2147 #else
2148             std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
2149 #endif
2150             return std::string(timeStamp);
2151         }
2152     };
2153 }
2154 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
2155 
2156 #define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \
2157 namespace Catch { \
2158     template<> struct StringMaker<enumName> { \
2159         static std::string convert( enumName value ) { \
2160             static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \
2161             return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \
2162         } \
2163     }; \
2164 }
2165 
2166 #define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )
2167 
2168 #ifdef _MSC_VER
2169 #pragma warning(pop)
2170 #endif
2171 
2172 // end catch_tostring.h
2173 #include <iosfwd>
2174 
2175 #ifdef _MSC_VER
2176 #pragma warning(push)
2177 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
2178 #pragma warning(disable:4018) // more "signed/unsigned mismatch"
2179 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
2180 #pragma warning(disable:4180) // qualifier applied to function type has no meaning
2181 #pragma warning(disable:4800) // Forcing result to true or false
2182 #endif
2183 
2184 namespace Catch {
2185 
2186     struct ITransientExpression {
isBinaryExpressionCatch::ITransientExpression2187         auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
getResultCatch::ITransientExpression2188         auto getResult() const -> bool { return m_result; }
2189         virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
2190 
ITransientExpressionCatch::ITransientExpression2191         ITransientExpression( bool isBinaryExpression, bool result )
2192         :   m_isBinaryExpression( isBinaryExpression ),
2193             m_result( result )
2194         {}
2195 
2196         // We don't actually need a virtual destructor, but many static analysers
2197         // complain if it's not here :-(
2198         virtual ~ITransientExpression();
2199 
2200         bool m_isBinaryExpression;
2201         bool m_result;
2202 
2203     };
2204 
2205     void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
2206 
2207     template<typename LhsT, typename RhsT>
2208     class BinaryExpr  : public ITransientExpression {
2209         LhsT m_lhs;
2210         StringRef m_op;
2211         RhsT m_rhs;
2212 
streamReconstructedExpression(std::ostream & os) const2213         void streamReconstructedExpression( std::ostream &os ) const override {
2214             formatReconstructedExpression
2215                     ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
2216         }
2217 
2218     public:
BinaryExpr(bool comparisonResult,LhsT lhs,StringRef op,RhsT rhs)2219         BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
2220         :   ITransientExpression{ true, comparisonResult },
2221             m_lhs( lhs ),
2222             m_op( op ),
2223             m_rhs( rhs )
2224         {}
2225 
2226         template<typename T>
operator &&(T) const2227         auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
2228             static_assert(always_false<T>::value,
2229             "chained comparisons are not supported inside assertions, "
2230             "wrap the expression inside parentheses, or decompose it");
2231         }
2232 
2233         template<typename T>
operator ||(T) const2234         auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
2235             static_assert(always_false<T>::value,
2236             "chained comparisons are not supported inside assertions, "
2237             "wrap the expression inside parentheses, or decompose it");
2238         }
2239 
2240         template<typename T>
operator ==(T) const2241         auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
2242             static_assert(always_false<T>::value,
2243             "chained comparisons are not supported inside assertions, "
2244             "wrap the expression inside parentheses, or decompose it");
2245         }
2246 
2247         template<typename T>
operator !=(T) const2248         auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
2249             static_assert(always_false<T>::value,
2250             "chained comparisons are not supported inside assertions, "
2251             "wrap the expression inside parentheses, or decompose it");
2252         }
2253 
2254         template<typename T>
operator >(T) const2255         auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
2256             static_assert(always_false<T>::value,
2257             "chained comparisons are not supported inside assertions, "
2258             "wrap the expression inside parentheses, or decompose it");
2259         }
2260 
2261         template<typename T>
operator <(T) const2262         auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
2263             static_assert(always_false<T>::value,
2264             "chained comparisons are not supported inside assertions, "
2265             "wrap the expression inside parentheses, or decompose it");
2266         }
2267 
2268         template<typename T>
operator >=(T) const2269         auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
2270             static_assert(always_false<T>::value,
2271             "chained comparisons are not supported inside assertions, "
2272             "wrap the expression inside parentheses, or decompose it");
2273         }
2274 
2275         template<typename T>
operator <=(T) const2276         auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
2277             static_assert(always_false<T>::value,
2278             "chained comparisons are not supported inside assertions, "
2279             "wrap the expression inside parentheses, or decompose it");
2280         }
2281     };
2282 
2283     template<typename LhsT>
2284     class UnaryExpr : public ITransientExpression {
2285         LhsT m_lhs;
2286 
streamReconstructedExpression(std::ostream & os) const2287         void streamReconstructedExpression( std::ostream &os ) const override {
2288             os << Catch::Detail::stringify( m_lhs );
2289         }
2290 
2291     public:
UnaryExpr(LhsT lhs)2292         explicit UnaryExpr( LhsT lhs )
2293         :   ITransientExpression{ false, static_cast<bool>(lhs) },
2294             m_lhs( lhs )
2295         {}
2296     };
2297 
2298     // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
2299     template<typename LhsT, typename RhsT>
compareEqual(LhsT const & lhs,RhsT const & rhs)2300     auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }
2301     template<typename T>
compareEqual(T * const & lhs,int rhs)2302     auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
2303     template<typename T>
compareEqual(T * const & lhs,long rhs)2304     auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
2305     template<typename T>
compareEqual(int lhs,T * const & rhs)2306     auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
2307     template<typename T>
compareEqual(long lhs,T * const & rhs)2308     auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
2309 
2310     template<typename LhsT, typename RhsT>
compareNotEqual(LhsT const & lhs,RhsT && rhs)2311     auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }
2312     template<typename T>
compareNotEqual(T * const & lhs,int rhs)2313     auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
2314     template<typename T>
compareNotEqual(T * const & lhs,long rhs)2315     auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
2316     template<typename T>
compareNotEqual(int lhs,T * const & rhs)2317     auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
2318     template<typename T>
compareNotEqual(long lhs,T * const & rhs)2319     auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
2320 
2321     template<typename LhsT>
2322     class ExprLhs {
2323         LhsT m_lhs;
2324     public:
ExprLhs(LhsT lhs)2325         explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
2326 
2327         template<typename RhsT>
operator ==(RhsT const & rhs)2328         auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2329             return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs };
2330         }
operator ==(bool rhs)2331         auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
2332             return { m_lhs == rhs, m_lhs, "==", rhs };
2333         }
2334 
2335         template<typename RhsT>
operator !=(RhsT const & rhs)2336         auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2337             return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs };
2338         }
operator !=(bool rhs)2339         auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
2340             return { m_lhs != rhs, m_lhs, "!=", rhs };
2341         }
2342 
2343         template<typename RhsT>
operator >(RhsT const & rhs)2344         auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2345             return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };
2346         }
2347         template<typename RhsT>
operator <(RhsT const & rhs)2348         auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2349             return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };
2350         }
2351         template<typename RhsT>
operator >=(RhsT const & rhs)2352         auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2353             return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };
2354         }
2355         template<typename RhsT>
operator <=(RhsT const & rhs)2356         auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2357             return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
2358         }
2359 
2360         template<typename RhsT>
operator &&(RhsT const &)2361         auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
2362             static_assert(always_false<RhsT>::value,
2363             "operator&& is not supported inside assertions, "
2364             "wrap the expression inside parentheses, or decompose it");
2365         }
2366 
2367         template<typename RhsT>
operator ||(RhsT const &)2368         auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
2369             static_assert(always_false<RhsT>::value,
2370             "operator|| is not supported inside assertions, "
2371             "wrap the expression inside parentheses, or decompose it");
2372         }
2373 
makeUnaryExpr() const2374         auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
2375             return UnaryExpr<LhsT>{ m_lhs };
2376         }
2377     };
2378 
2379     void handleExpression( ITransientExpression const& expr );
2380 
2381     template<typename T>
handleExpression(ExprLhs<T> const & expr)2382     void handleExpression( ExprLhs<T> const& expr ) {
2383         handleExpression( expr.makeUnaryExpr() );
2384     }
2385 
2386     struct Decomposer {
2387         template<typename T>
operator <=Catch::Decomposer2388         auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
2389             return ExprLhs<T const&>{ lhs };
2390         }
2391 
operator <=Catch::Decomposer2392         auto operator <=( bool value ) -> ExprLhs<bool> {
2393             return ExprLhs<bool>{ value };
2394         }
2395     };
2396 
2397 } // end namespace Catch
2398 
2399 #ifdef _MSC_VER
2400 #pragma warning(pop)
2401 #endif
2402 
2403 // end catch_decomposer.h
2404 // start catch_interfaces_capture.h
2405 
2406 #include <string>
2407 #include <chrono>
2408 
2409 namespace Catch {
2410 
2411     class AssertionResult;
2412     struct AssertionInfo;
2413     struct SectionInfo;
2414     struct SectionEndInfo;
2415     struct MessageInfo;
2416     struct MessageBuilder;
2417     struct Counts;
2418     struct AssertionReaction;
2419     struct SourceLineInfo;
2420 
2421     struct ITransientExpression;
2422     struct IGeneratorTracker;
2423 
2424 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
2425     struct BenchmarkInfo;
2426     template <typename Duration = std::chrono::duration<double, std::nano>>
2427     struct BenchmarkStats;
2428 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
2429 
2430     struct IResultCapture {
2431 
2432         virtual ~IResultCapture();
2433 
2434         virtual bool sectionStarted(    SectionInfo const& sectionInfo,
2435                                         Counts& assertions ) = 0;
2436         virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
2437         virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
2438 
2439         virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
2440 
2441 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
2442         virtual void benchmarkPreparing( std::string const& name ) = 0;
2443         virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
2444         virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;
2445         virtual void benchmarkFailed( std::string const& error ) = 0;
2446 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
2447 
2448         virtual void pushScopedMessage( MessageInfo const& message ) = 0;
2449         virtual void popScopedMessage( MessageInfo const& message ) = 0;
2450 
2451         virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;
2452 
2453         virtual void handleFatalErrorCondition( StringRef message ) = 0;
2454 
2455         virtual void handleExpr
2456                 (   AssertionInfo const& info,
2457                     ITransientExpression const& expr,
2458                     AssertionReaction& reaction ) = 0;
2459         virtual void handleMessage
2460                 (   AssertionInfo const& info,
2461                     ResultWas::OfType resultType,
2462                     StringRef const& message,
2463                     AssertionReaction& reaction ) = 0;
2464         virtual void handleUnexpectedExceptionNotThrown
2465                 (   AssertionInfo const& info,
2466                     AssertionReaction& reaction ) = 0;
2467         virtual void handleUnexpectedInflightException
2468                 (   AssertionInfo const& info,
2469                     std::string const& message,
2470                     AssertionReaction& reaction ) = 0;
2471         virtual void handleIncomplete
2472                 (   AssertionInfo const& info ) = 0;
2473         virtual void handleNonExpr
2474                 (   AssertionInfo const &info,
2475                     ResultWas::OfType resultType,
2476                     AssertionReaction &reaction ) = 0;
2477 
2478         virtual bool lastAssertionPassed() = 0;
2479         virtual void assertionPassed() = 0;
2480 
2481         // Deprecated, do not use:
2482         virtual std::string getCurrentTestName() const = 0;
2483         virtual const AssertionResult* getLastResult() const = 0;
2484         virtual void exceptionEarlyReported() = 0;
2485     };
2486 
2487     IResultCapture& getResultCapture();
2488 }
2489 
2490 // end catch_interfaces_capture.h
2491 namespace Catch {
2492 
2493     struct TestFailureException{};
2494     struct AssertionResultData;
2495     struct IResultCapture;
2496     class RunContext;
2497 
2498     class LazyExpression {
2499         friend class AssertionHandler;
2500         friend struct AssertionStats;
2501         friend class RunContext;
2502 
2503         ITransientExpression const* m_transientExpression = nullptr;
2504         bool m_isNegated;
2505     public:
2506         LazyExpression( bool isNegated );
2507         LazyExpression( LazyExpression const& other );
2508         LazyExpression& operator = ( LazyExpression const& ) = delete;
2509 
2510         explicit operator bool() const;
2511 
2512         friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
2513     };
2514 
2515     struct AssertionReaction {
2516         bool shouldDebugBreak = false;
2517         bool shouldThrow = false;
2518     };
2519 
2520     class AssertionHandler {
2521         AssertionInfo m_assertionInfo;
2522         AssertionReaction m_reaction;
2523         bool m_completed = false;
2524         IResultCapture& m_resultCapture;
2525 
2526     public:
2527         AssertionHandler
2528             (   StringRef const& macroName,
2529                 SourceLineInfo const& lineInfo,
2530                 StringRef capturedExpression,
2531                 ResultDisposition::Flags resultDisposition );
~AssertionHandler()2532         ~AssertionHandler() {
2533             if ( !m_completed ) {
2534                 m_resultCapture.handleIncomplete( m_assertionInfo );
2535             }
2536         }
2537 
2538         template<typename T>
handleExpr(ExprLhs<T> const & expr)2539         void handleExpr( ExprLhs<T> const& expr ) {
2540             handleExpr( expr.makeUnaryExpr() );
2541         }
2542         void handleExpr( ITransientExpression const& expr );
2543 
2544         void handleMessage(ResultWas::OfType resultType, StringRef const& message);
2545 
2546         void handleExceptionThrownAsExpected();
2547         void handleUnexpectedExceptionNotThrown();
2548         void handleExceptionNotThrownAsExpected();
2549         void handleThrowingCallSkipped();
2550         void handleUnexpectedInflightException();
2551 
2552         void complete();
2553         void setCompleted();
2554 
2555         // query
2556         auto allowThrows() const -> bool;
2557     };
2558 
2559     void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString );
2560 
2561 } // namespace Catch
2562 
2563 // end catch_assertionhandler.h
2564 // start catch_message.h
2565 
2566 #include <string>
2567 #include <vector>
2568 
2569 namespace Catch {
2570 
2571     struct MessageInfo {
2572         MessageInfo(    StringRef const& _macroName,
2573                         SourceLineInfo const& _lineInfo,
2574                         ResultWas::OfType _type );
2575 
2576         StringRef macroName;
2577         std::string message;
2578         SourceLineInfo lineInfo;
2579         ResultWas::OfType type;
2580         unsigned int sequence;
2581 
2582         bool operator == ( MessageInfo const& other ) const;
2583         bool operator < ( MessageInfo const& other ) const;
2584     private:
2585         static unsigned int globalCount;
2586     };
2587 
2588     struct MessageStream {
2589 
2590         template<typename T>
operator <<Catch::MessageStream2591         MessageStream& operator << ( T const& value ) {
2592             m_stream << value;
2593             return *this;
2594         }
2595 
2596         ReusableStringStream m_stream;
2597     };
2598 
2599     struct MessageBuilder : MessageStream {
2600         MessageBuilder( StringRef const& macroName,
2601                         SourceLineInfo const& lineInfo,
2602                         ResultWas::OfType type );
2603 
2604         template<typename T>
operator <<Catch::MessageBuilder2605         MessageBuilder& operator << ( T const& value ) {
2606             m_stream << value;
2607             return *this;
2608         }
2609 
2610         MessageInfo m_info;
2611     };
2612 
2613     class ScopedMessage {
2614     public:
2615         explicit ScopedMessage( MessageBuilder const& builder );
2616         ScopedMessage( ScopedMessage& duplicate ) = delete;
2617         ScopedMessage( ScopedMessage&& old );
2618         ~ScopedMessage();
2619 
2620         MessageInfo m_info;
2621         bool m_moved;
2622     };
2623 
2624     class Capturer {
2625         std::vector<MessageInfo> m_messages;
2626         IResultCapture& m_resultCapture = getResultCapture();
2627         size_t m_captured = 0;
2628     public:
2629         Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
2630         ~Capturer();
2631 
2632         void captureValue( size_t index, std::string const& value );
2633 
2634         template<typename T>
captureValues(size_t index,T const & value)2635         void captureValues( size_t index, T const& value ) {
2636             captureValue( index, Catch::Detail::stringify( value ) );
2637         }
2638 
2639         template<typename T, typename... Ts>
captureValues(size_t index,T const & value,Ts const &...values)2640         void captureValues( size_t index, T const& value, Ts const&... values ) {
2641             captureValue( index, Catch::Detail::stringify(value) );
2642             captureValues( index+1, values... );
2643         }
2644     };
2645 
2646 } // end namespace Catch
2647 
2648 // end catch_message.h
2649 #if !defined(CATCH_CONFIG_DISABLE)
2650 
2651 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
2652   #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
2653 #else
2654   #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
2655 #endif
2656 
2657 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
2658 
2659 ///////////////////////////////////////////////////////////////////////////////
2660 // Another way to speed-up compilation is to omit local try-catch for REQUIRE*
2661 // macros.
2662 #define INTERNAL_CATCH_TRY
2663 #define INTERNAL_CATCH_CATCH( capturer )
2664 
2665 #else // CATCH_CONFIG_FAST_COMPILE
2666 
2667 #define INTERNAL_CATCH_TRY try
2668 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
2669 
2670 #endif
2671 
2672 #define INTERNAL_CATCH_REACT( handler ) handler.complete();
2673 
2674 ///////////////////////////////////////////////////////////////////////////////
2675 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
2676     do { \
2677         CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \
2678         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
2679         INTERNAL_CATCH_TRY { \
2680             CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
2681             CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2682             catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
2683             CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
2684         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
2685         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2686     } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) )
2687 
2688 ///////////////////////////////////////////////////////////////////////////////
2689 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
2690     INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
2691     if( Catch::getResultCapture().lastAssertionPassed() )
2692 
2693 ///////////////////////////////////////////////////////////////////////////////
2694 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
2695     INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
2696     if( !Catch::getResultCapture().lastAssertionPassed() )
2697 
2698 ///////////////////////////////////////////////////////////////////////////////
2699 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
2700     do { \
2701         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
2702         try { \
2703             static_cast<void>(__VA_ARGS__); \
2704             catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
2705         } \
2706         catch( ... ) { \
2707             catchAssertionHandler.handleUnexpectedInflightException(); \
2708         } \
2709         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2710     } while( false )
2711 
2712 ///////////////////////////////////////////////////////////////////////////////
2713 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
2714     do { \
2715         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
2716         if( catchAssertionHandler.allowThrows() ) \
2717             try { \
2718                 static_cast<void>(__VA_ARGS__); \
2719                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2720             } \
2721             catch( ... ) { \
2722                 catchAssertionHandler.handleExceptionThrownAsExpected(); \
2723             } \
2724         else \
2725             catchAssertionHandler.handleThrowingCallSkipped(); \
2726         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2727     } while( false )
2728 
2729 ///////////////////////////////////////////////////////////////////////////////
2730 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
2731     do { \
2732         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
2733         if( catchAssertionHandler.allowThrows() ) \
2734             try { \
2735                 static_cast<void>(expr); \
2736                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2737             } \
2738             catch( exceptionType const& ) { \
2739                 catchAssertionHandler.handleExceptionThrownAsExpected(); \
2740             } \
2741             catch( ... ) { \
2742                 catchAssertionHandler.handleUnexpectedInflightException(); \
2743             } \
2744         else \
2745             catchAssertionHandler.handleThrowingCallSkipped(); \
2746         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2747     } while( false )
2748 
2749 ///////////////////////////////////////////////////////////////////////////////
2750 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
2751     do { \
2752         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
2753         catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
2754         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2755     } while( false )
2756 
2757 ///////////////////////////////////////////////////////////////////////////////
2758 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
2759     auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
2760     varName.captureValues( 0, __VA_ARGS__ )
2761 
2762 ///////////////////////////////////////////////////////////////////////////////
2763 #define INTERNAL_CATCH_INFO( macroName, log ) \
2764     Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
2765 
2766 ///////////////////////////////////////////////////////////////////////////////
2767 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
2768     Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
2769 
2770 ///////////////////////////////////////////////////////////////////////////////
2771 // Although this is matcher-based, it can be used with just a string
2772 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
2773     do { \
2774         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
2775         if( catchAssertionHandler.allowThrows() ) \
2776             try { \
2777                 static_cast<void>(__VA_ARGS__); \
2778                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2779             } \
2780             catch( ... ) { \
2781                 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \
2782             } \
2783         else \
2784             catchAssertionHandler.handleThrowingCallSkipped(); \
2785         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2786     } while( false )
2787 
2788 #endif // CATCH_CONFIG_DISABLE
2789 
2790 // end catch_capture.hpp
2791 // start catch_section.h
2792 
2793 // start catch_section_info.h
2794 
2795 // start catch_totals.h
2796 
2797 #include <cstddef>
2798 
2799 namespace Catch {
2800 
2801     struct Counts {
2802         Counts operator - ( Counts const& other ) const;
2803         Counts& operator += ( Counts const& other );
2804 
2805         std::size_t total() const;
2806         bool allPassed() const;
2807         bool allOk() const;
2808 
2809         std::size_t passed = 0;
2810         std::size_t failed = 0;
2811         std::size_t failedButOk = 0;
2812     };
2813 
2814     struct Totals {
2815 
2816         Totals operator - ( Totals const& other ) const;
2817         Totals& operator += ( Totals const& other );
2818 
2819         Totals delta( Totals const& prevTotals ) const;
2820 
2821         int error = 0;
2822         Counts assertions;
2823         Counts testCases;
2824     };
2825 }
2826 
2827 // end catch_totals.h
2828 #include <string>
2829 
2830 namespace Catch {
2831 
2832     struct SectionInfo {
2833         SectionInfo
2834             (   SourceLineInfo const& _lineInfo,
2835                 std::string const& _name );
2836 
2837         // Deprecated
SectionInfoCatch::SectionInfo2838         SectionInfo
2839             (   SourceLineInfo const& _lineInfo,
2840                 std::string const& _name,
2841                 std::string const& ) : SectionInfo( _lineInfo, _name ) {}
2842 
2843         std::string name;
2844         std::string description; // !Deprecated: this will always be empty
2845         SourceLineInfo lineInfo;
2846     };
2847 
2848     struct SectionEndInfo {
2849         SectionInfo sectionInfo;
2850         Counts prevAssertions;
2851         double durationInSeconds;
2852     };
2853 
2854 } // end namespace Catch
2855 
2856 // end catch_section_info.h
2857 // start catch_timer.h
2858 
2859 #include <cstdint>
2860 
2861 namespace Catch {
2862 
2863     auto getCurrentNanosecondsSinceEpoch() -> uint64_t;
2864     auto getEstimatedClockResolution() -> uint64_t;
2865 
2866     class Timer {
2867         uint64_t m_nanoseconds = 0;
2868     public:
2869         void start();
2870         auto getElapsedNanoseconds() const -> uint64_t;
2871         auto getElapsedMicroseconds() const -> uint64_t;
2872         auto getElapsedMilliseconds() const -> unsigned int;
2873         auto getElapsedSeconds() const -> double;
2874     };
2875 
2876 } // namespace Catch
2877 
2878 // end catch_timer.h
2879 #include <string>
2880 
2881 namespace Catch {
2882 
2883     class Section : NonCopyable {
2884     public:
2885         Section( SectionInfo const& info );
2886         ~Section();
2887 
2888         // This indicates whether the section should be executed or not
2889         explicit operator bool() const;
2890 
2891     private:
2892         SectionInfo m_info;
2893 
2894         std::string m_name;
2895         Counts m_assertions;
2896         bool m_sectionIncluded;
2897         Timer m_timer;
2898     };
2899 
2900 } // end namespace Catch
2901 
2902 #define INTERNAL_CATCH_SECTION( ... ) \
2903     CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
2904     CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
2905     if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
2906     CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
2907 
2908 #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
2909     CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
2910     CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
2911     if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
2912     CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
2913 
2914 // end catch_section.h
2915 // start catch_interfaces_exception.h
2916 
2917 // start catch_interfaces_registry_hub.h
2918 
2919 #include <string>
2920 #include <memory>
2921 
2922 namespace Catch {
2923 
2924     class TestCase;
2925     struct ITestCaseRegistry;
2926     struct IExceptionTranslatorRegistry;
2927     struct IExceptionTranslator;
2928     struct IReporterRegistry;
2929     struct IReporterFactory;
2930     struct ITagAliasRegistry;
2931     struct IMutableEnumValuesRegistry;
2932 
2933     class StartupExceptionRegistry;
2934 
2935     using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
2936 
2937     struct IRegistryHub {
2938         virtual ~IRegistryHub();
2939 
2940         virtual IReporterRegistry const& getReporterRegistry() const = 0;
2941         virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2942         virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
2943         virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
2944 
2945         virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
2946     };
2947 
2948     struct IMutableRegistryHub {
2949         virtual ~IMutableRegistryHub();
2950         virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;
2951         virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;
2952         virtual void registerTest( TestCase const& testInfo ) = 0;
2953         virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2954         virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
2955         virtual void registerStartupException() noexcept = 0;
2956         virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;
2957     };
2958 
2959     IRegistryHub const& getRegistryHub();
2960     IMutableRegistryHub& getMutableRegistryHub();
2961     void cleanUp();
2962     std::string translateActiveException();
2963 
2964 }
2965 
2966 // end catch_interfaces_registry_hub.h
2967 #if defined(CATCH_CONFIG_DISABLE)
2968     #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
2969         static std::string translatorName( signature )
2970 #endif
2971 
2972 #include <exception>
2973 #include <string>
2974 #include <vector>
2975 
2976 namespace Catch {
2977     using exceptionTranslateFunction = std::string(*)();
2978 
2979     struct IExceptionTranslator;
2980     using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;
2981 
2982     struct IExceptionTranslator {
2983         virtual ~IExceptionTranslator();
2984         virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
2985     };
2986 
2987     struct IExceptionTranslatorRegistry {
2988         virtual ~IExceptionTranslatorRegistry();
2989 
2990         virtual std::string translateActiveException() const = 0;
2991     };
2992 
2993     class ExceptionTranslatorRegistrar {
2994         template<typename T>
2995         class ExceptionTranslator : public IExceptionTranslator {
2996         public:
2997 
ExceptionTranslator(std::string (* translateFunction)(T &))2998             ExceptionTranslator( std::string(*translateFunction)( T& ) )
2999             : m_translateFunction( translateFunction )
3000             {}
3001 
translate(ExceptionTranslators::const_iterator it,ExceptionTranslators::const_iterator itEnd) const3002             std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
3003                 try {
3004                     if( it == itEnd )
3005                         std::rethrow_exception(std::current_exception());
3006                     else
3007                         return (*it)->translate( it+1, itEnd );
3008                 }
3009                 catch( T& ex ) {
3010                     return m_translateFunction( ex );
3011                 }
3012             }
3013 
3014         protected:
3015             std::string(*m_translateFunction)( T& );
3016         };
3017 
3018     public:
3019         template<typename T>
ExceptionTranslatorRegistrar(std::string (* translateFunction)(T &))3020         ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
3021             getMutableRegistryHub().registerTranslator
3022                 ( new ExceptionTranslator<T>( translateFunction ) );
3023         }
3024     };
3025 }
3026 
3027 ///////////////////////////////////////////////////////////////////////////////
3028 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
3029     static std::string translatorName( signature ); \
3030     CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \
3031     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
3032     namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
3033     CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \
3034     static std::string translatorName( signature )
3035 
3036 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
3037 
3038 // end catch_interfaces_exception.h
3039 // start catch_approx.h
3040 
3041 #include <type_traits>
3042 
3043 namespace Catch {
3044 namespace Detail {
3045 
3046     class Approx {
3047     private:
3048         bool equalityComparisonImpl(double other) const;
3049         // Validates the new margin (margin >= 0)
3050         // out-of-line to avoid including stdexcept in the header
3051         void setMargin(double margin);
3052         // Validates the new epsilon (0 < epsilon < 1)
3053         // out-of-line to avoid including stdexcept in the header
3054         void setEpsilon(double epsilon);
3055 
3056     public:
3057         explicit Approx ( double value );
3058 
3059         static Approx custom();
3060 
3061         Approx operator-() const;
3062 
3063         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator ()(T const & value)3064         Approx operator()( T const& value ) {
3065             Approx approx( static_cast<double>(value) );
3066             approx.m_epsilon = m_epsilon;
3067             approx.m_margin = m_margin;
3068             approx.m_scale = m_scale;
3069             return approx;
3070         }
3071 
3072         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx(T const & value)3073         explicit Approx( T const& value ): Approx(static_cast<double>(value))
3074         {}
3075 
3076         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator ==(const T & lhs,Approx const & rhs)3077         friend bool operator == ( const T& lhs, Approx const& rhs ) {
3078             auto lhs_v = static_cast<double>(lhs);
3079             return rhs.equalityComparisonImpl(lhs_v);
3080         }
3081 
3082         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator ==(Approx const & lhs,const T & rhs)3083         friend bool operator == ( Approx const& lhs, const T& rhs ) {
3084             return operator==( rhs, lhs );
3085         }
3086 
3087         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator !=(T const & lhs,Approx const & rhs)3088         friend bool operator != ( T const& lhs, Approx const& rhs ) {
3089             return !operator==( lhs, rhs );
3090         }
3091 
3092         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator !=(Approx const & lhs,T const & rhs)3093         friend bool operator != ( Approx const& lhs, T const& rhs ) {
3094             return !operator==( rhs, lhs );
3095         }
3096 
3097         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator <=(T const & lhs,Approx const & rhs)3098         friend bool operator <= ( T const& lhs, Approx const& rhs ) {
3099             return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
3100         }
3101 
3102         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator <=(Approx const & lhs,T const & rhs)3103         friend bool operator <= ( Approx const& lhs, T const& rhs ) {
3104             return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
3105         }
3106 
3107         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator >=(T const & lhs,Approx const & rhs)3108         friend bool operator >= ( T const& lhs, Approx const& rhs ) {
3109             return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
3110         }
3111 
3112         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator >=(Approx const & lhs,T const & rhs)3113         friend bool operator >= ( Approx const& lhs, T const& rhs ) {
3114             return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
3115         }
3116 
3117         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
epsilon(T const & newEpsilon)3118         Approx& epsilon( T const& newEpsilon ) {
3119             double epsilonAsDouble = static_cast<double>(newEpsilon);
3120             setEpsilon(epsilonAsDouble);
3121             return *this;
3122         }
3123 
3124         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
margin(T const & newMargin)3125         Approx& margin( T const& newMargin ) {
3126             double marginAsDouble = static_cast<double>(newMargin);
3127             setMargin(marginAsDouble);
3128             return *this;
3129         }
3130 
3131         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
scale(T const & newScale)3132         Approx& scale( T const& newScale ) {
3133             m_scale = static_cast<double>(newScale);
3134             return *this;
3135         }
3136 
3137         std::string toString() const;
3138 
3139     private:
3140         double m_epsilon;
3141         double m_margin;
3142         double m_scale;
3143         double m_value;
3144     };
3145 } // end namespace Detail
3146 
3147 namespace literals {
3148     Detail::Approx operator "" _a(long double val);
3149     Detail::Approx operator "" _a(unsigned long long val);
3150 } // end namespace literals
3151 
3152 template<>
3153 struct StringMaker<Catch::Detail::Approx> {
3154     static std::string convert(Catch::Detail::Approx const& value);
3155 };
3156 
3157 } // end namespace Catch
3158 
3159 // end catch_approx.h
3160 // start catch_string_manip.h
3161 
3162 #include <string>
3163 #include <iosfwd>
3164 #include <vector>
3165 
3166 namespace Catch {
3167 
3168     bool startsWith( std::string const& s, std::string const& prefix );
3169     bool startsWith( std::string const& s, char prefix );
3170     bool endsWith( std::string const& s, std::string const& suffix );
3171     bool endsWith( std::string const& s, char suffix );
3172     bool contains( std::string const& s, std::string const& infix );
3173     void toLowerInPlace( std::string& s );
3174     std::string toLower( std::string const& s );
3175     //! Returns a new string without whitespace at the start/end
3176     std::string trim( std::string const& str );
3177     //! Returns a substring of the original ref without whitespace. Beware lifetimes!
3178     StringRef trim(StringRef ref);
3179 
3180     // !!! Be aware, returns refs into original string - make sure original string outlives them
3181     std::vector<StringRef> splitStringRef( StringRef str, char delimiter );
3182     bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
3183 
3184     struct pluralise {
3185         pluralise( std::size_t count, std::string const& label );
3186 
3187         friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
3188 
3189         std::size_t m_count;
3190         std::string m_label;
3191     };
3192 }
3193 
3194 // end catch_string_manip.h
3195 #ifndef CATCH_CONFIG_DISABLE_MATCHERS
3196 // start catch_capture_matchers.h
3197 
3198 // start catch_matchers.h
3199 
3200 #include <string>
3201 #include <vector>
3202 
3203 namespace Catch {
3204 namespace Matchers {
3205     namespace Impl {
3206 
3207         template<typename ArgT> struct MatchAllOf;
3208         template<typename ArgT> struct MatchAnyOf;
3209         template<typename ArgT> struct MatchNotOf;
3210 
3211         class MatcherUntypedBase {
3212         public:
3213             MatcherUntypedBase() = default;
3214             MatcherUntypedBase ( MatcherUntypedBase const& ) = default;
3215             MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;
3216             std::string toString() const;
3217 
3218         protected:
3219             virtual ~MatcherUntypedBase();
3220             virtual std::string describe() const = 0;
3221             mutable std::string m_cachedToString;
3222         };
3223 
3224 #ifdef __clang__
3225 #    pragma clang diagnostic push
3226 #    pragma clang diagnostic ignored "-Wnon-virtual-dtor"
3227 #endif
3228 
3229         template<typename ObjectT>
3230         struct MatcherMethod {
3231             virtual bool match( ObjectT const& arg ) const = 0;
3232         };
3233 
3234 #if defined(__OBJC__)
3235         // Hack to fix Catch GH issue #1661. Could use id for generic Object support.
3236         // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation
3237         template<>
3238         struct MatcherMethod<NSString*> {
3239             virtual bool match( NSString* arg ) const = 0;
3240         };
3241 #endif
3242 
3243 #ifdef __clang__
3244 #    pragma clang diagnostic pop
3245 #endif
3246 
3247         template<typename T>
3248         struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {
3249 
3250             MatchAllOf<T> operator && ( MatcherBase const& other ) const;
3251             MatchAnyOf<T> operator || ( MatcherBase const& other ) const;
3252             MatchNotOf<T> operator ! () const;
3253         };
3254 
3255         template<typename ArgT>
3256         struct MatchAllOf : MatcherBase<ArgT> {
matchCatch::Matchers::Impl::MatchAllOf3257             bool match( ArgT const& arg ) const override {
3258                 for( auto matcher : m_matchers ) {
3259                     if (!matcher->match(arg))
3260                         return false;
3261                 }
3262                 return true;
3263             }
describeCatch::Matchers::Impl::MatchAllOf3264             std::string describe() const override {
3265                 std::string description;
3266                 description.reserve( 4 + m_matchers.size()*32 );
3267                 description += "( ";
3268                 bool first = true;
3269                 for( auto matcher : m_matchers ) {
3270                     if( first )
3271                         first = false;
3272                     else
3273                         description += " and ";
3274                     description += matcher->toString();
3275                 }
3276                 description += " )";
3277                 return description;
3278             }
3279 
operator &&Catch::Matchers::Impl::MatchAllOf3280             MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) {
3281                 auto copy(*this);
3282                 copy.m_matchers.push_back( &other );
3283                 return copy;
3284             }
3285 
3286             std::vector<MatcherBase<ArgT> const*> m_matchers;
3287         };
3288         template<typename ArgT>
3289         struct MatchAnyOf : MatcherBase<ArgT> {
3290 
matchCatch::Matchers::Impl::MatchAnyOf3291             bool match( ArgT const& arg ) const override {
3292                 for( auto matcher : m_matchers ) {
3293                     if (matcher->match(arg))
3294                         return true;
3295                 }
3296                 return false;
3297             }
describeCatch::Matchers::Impl::MatchAnyOf3298             std::string describe() const override {
3299                 std::string description;
3300                 description.reserve( 4 + m_matchers.size()*32 );
3301                 description += "( ";
3302                 bool first = true;
3303                 for( auto matcher : m_matchers ) {
3304                     if( first )
3305                         first = false;
3306                     else
3307                         description += " or ";
3308                     description += matcher->toString();
3309                 }
3310                 description += " )";
3311                 return description;
3312             }
3313 
operator ||Catch::Matchers::Impl::MatchAnyOf3314             MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) {
3315                 auto copy(*this);
3316                 copy.m_matchers.push_back( &other );
3317                 return copy;
3318             }
3319 
3320             std::vector<MatcherBase<ArgT> const*> m_matchers;
3321         };
3322 
3323         template<typename ArgT>
3324         struct MatchNotOf : MatcherBase<ArgT> {
3325 
MatchNotOfCatch::Matchers::Impl::MatchNotOf3326             MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
3327 
matchCatch::Matchers::Impl::MatchNotOf3328             bool match( ArgT const& arg ) const override {
3329                 return !m_underlyingMatcher.match( arg );
3330             }
3331 
describeCatch::Matchers::Impl::MatchNotOf3332             std::string describe() const override {
3333                 return "not " + m_underlyingMatcher.toString();
3334             }
3335             MatcherBase<ArgT> const& m_underlyingMatcher;
3336         };
3337 
3338         template<typename T>
operator &&(MatcherBase const & other) const3339         MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const {
3340             return MatchAllOf<T>() && *this && other;
3341         }
3342         template<typename T>
operator ||(MatcherBase const & other) const3343         MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const {
3344             return MatchAnyOf<T>() || *this || other;
3345         }
3346         template<typename T>
operator !() const3347         MatchNotOf<T> MatcherBase<T>::operator ! () const {
3348             return MatchNotOf<T>( *this );
3349         }
3350 
3351     } // namespace Impl
3352 
3353 } // namespace Matchers
3354 
3355 using namespace Matchers;
3356 using Matchers::Impl::MatcherBase;
3357 
3358 } // namespace Catch
3359 
3360 // end catch_matchers.h
3361 // start catch_matchers_exception.hpp
3362 
3363 namespace Catch {
3364 namespace Matchers {
3365 namespace Exception {
3366 
3367 class ExceptionMessageMatcher : public MatcherBase<std::exception> {
3368     std::string m_message;
3369 public:
3370 
ExceptionMessageMatcher(std::string const & message)3371     ExceptionMessageMatcher(std::string const& message):
3372         m_message(message)
3373     {}
3374 
3375     bool match(std::exception const& ex) const override;
3376 
3377     std::string describe() const override;
3378 };
3379 
3380 } // namespace Exception
3381 
3382 Exception::ExceptionMessageMatcher Message(std::string const& message);
3383 
3384 } // namespace Matchers
3385 } // namespace Catch
3386 
3387 // end catch_matchers_exception.hpp
3388 // start catch_matchers_floating.h
3389 
3390 namespace Catch {
3391 namespace Matchers {
3392 
3393     namespace Floating {
3394 
3395         enum class FloatingPointKind : uint8_t;
3396 
3397         struct WithinAbsMatcher : MatcherBase<double> {
3398             WithinAbsMatcher(double target, double margin);
3399             bool match(double const& matchee) const override;
3400             std::string describe() const override;
3401         private:
3402             double m_target;
3403             double m_margin;
3404         };
3405 
3406         struct WithinUlpsMatcher : MatcherBase<double> {
3407             WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType);
3408             bool match(double const& matchee) const override;
3409             std::string describe() const override;
3410         private:
3411             double m_target;
3412             uint64_t m_ulps;
3413             FloatingPointKind m_type;
3414         };
3415 
3416         // Given IEEE-754 format for floats and doubles, we can assume
3417         // that float -> double promotion is lossless. Given this, we can
3418         // assume that if we do the standard relative comparison of
3419         // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get
3420         // the same result if we do this for floats, as if we do this for
3421         // doubles that were promoted from floats.
3422         struct WithinRelMatcher : MatcherBase<double> {
3423             WithinRelMatcher(double target, double epsilon);
3424             bool match(double const& matchee) const override;
3425             std::string describe() const override;
3426         private:
3427             double m_target;
3428             double m_epsilon;
3429         };
3430 
3431     } // namespace Floating
3432 
3433     // The following functions create the actual matcher objects.
3434     // This allows the types to be inferred
3435     Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);
3436     Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);
3437     Floating::WithinAbsMatcher WithinAbs(double target, double margin);
3438     Floating::WithinRelMatcher WithinRel(double target, double eps);
3439     // defaults epsilon to 100*numeric_limits<double>::epsilon()
3440     Floating::WithinRelMatcher WithinRel(double target);
3441     Floating::WithinRelMatcher WithinRel(float target, float eps);
3442     // defaults epsilon to 100*numeric_limits<float>::epsilon()
3443     Floating::WithinRelMatcher WithinRel(float target);
3444 
3445 } // namespace Matchers
3446 } // namespace Catch
3447 
3448 // end catch_matchers_floating.h
3449 // start catch_matchers_generic.hpp
3450 
3451 #include <functional>
3452 #include <string>
3453 
3454 namespace Catch {
3455 namespace Matchers {
3456 namespace Generic {
3457 
3458 namespace Detail {
3459     std::string finalizeDescription(const std::string& desc);
3460 }
3461 
3462 template <typename T>
3463 class PredicateMatcher : public MatcherBase<T> {
3464     std::function<bool(T const&)> m_predicate;
3465     std::string m_description;
3466 public:
3467 
PredicateMatcher(std::function<bool (T const &)> const & elem,std::string const & descr)3468     PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
3469         :m_predicate(std::move(elem)),
3470         m_description(Detail::finalizeDescription(descr))
3471     {}
3472 
match(T const & item) const3473     bool match( T const& item ) const override {
3474         return m_predicate(item);
3475     }
3476 
describe() const3477     std::string describe() const override {
3478         return m_description;
3479     }
3480 };
3481 
3482 } // namespace Generic
3483 
3484     // The following functions create the actual matcher objects.
3485     // The user has to explicitly specify type to the function, because
3486     // inferring std::function<bool(T const&)> is hard (but possible) and
3487     // requires a lot of TMP.
3488     template<typename T>
Predicate(std::function<bool (T const &)> const & predicate,std::string const & description="")3489     Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
3490         return Generic::PredicateMatcher<T>(predicate, description);
3491     }
3492 
3493 } // namespace Matchers
3494 } // namespace Catch
3495 
3496 // end catch_matchers_generic.hpp
3497 // start catch_matchers_string.h
3498 
3499 #include <string>
3500 
3501 namespace Catch {
3502 namespace Matchers {
3503 
3504     namespace StdString {
3505 
3506         struct CasedString
3507         {
3508             CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
3509             std::string adjustString( std::string const& str ) const;
3510             std::string caseSensitivitySuffix() const;
3511 
3512             CaseSensitive::Choice m_caseSensitivity;
3513             std::string m_str;
3514         };
3515 
3516         struct StringMatcherBase : MatcherBase<std::string> {
3517             StringMatcherBase( std::string const& operation, CasedString const& comparator );
3518             std::string describe() const override;
3519 
3520             CasedString m_comparator;
3521             std::string m_operation;
3522         };
3523 
3524         struct EqualsMatcher : StringMatcherBase {
3525             EqualsMatcher( CasedString const& comparator );
3526             bool match( std::string const& source ) const override;
3527         };
3528         struct ContainsMatcher : StringMatcherBase {
3529             ContainsMatcher( CasedString const& comparator );
3530             bool match( std::string const& source ) const override;
3531         };
3532         struct StartsWithMatcher : StringMatcherBase {
3533             StartsWithMatcher( CasedString const& comparator );
3534             bool match( std::string const& source ) const override;
3535         };
3536         struct EndsWithMatcher : StringMatcherBase {
3537             EndsWithMatcher( CasedString const& comparator );
3538             bool match( std::string const& source ) const override;
3539         };
3540 
3541         struct RegexMatcher : MatcherBase<std::string> {
3542             RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity );
3543             bool match( std::string const& matchee ) const override;
3544             std::string describe() const override;
3545 
3546         private:
3547             std::string m_regex;
3548             CaseSensitive::Choice m_caseSensitivity;
3549         };
3550 
3551     } // namespace StdString
3552 
3553     // The following functions create the actual matcher objects.
3554     // This allows the types to be inferred
3555 
3556     StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3557     StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3558     StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3559     StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3560     StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3561 
3562 } // namespace Matchers
3563 } // namespace Catch
3564 
3565 // end catch_matchers_string.h
3566 // start catch_matchers_vector.h
3567 
3568 #include <algorithm>
3569 
3570 namespace Catch {
3571 namespace Matchers {
3572 
3573     namespace Vector {
3574         template<typename T>
3575         struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
3576 
ContainsElementMatcherCatch::Matchers::Vector::ContainsElementMatcher3577             ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
3578 
matchCatch::Matchers::Vector::ContainsElementMatcher3579             bool match(std::vector<T> const &v) const override {
3580                 for (auto const& el : v) {
3581                     if (el == m_comparator) {
3582                         return true;
3583                     }
3584                 }
3585                 return false;
3586             }
3587 
describeCatch::Matchers::Vector::ContainsElementMatcher3588             std::string describe() const override {
3589                 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
3590             }
3591 
3592             T const& m_comparator;
3593         };
3594 
3595         template<typename T>
3596         struct ContainsMatcher : MatcherBase<std::vector<T>> {
3597 
ContainsMatcherCatch::Matchers::Vector::ContainsMatcher3598             ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3599 
matchCatch::Matchers::Vector::ContainsMatcher3600             bool match(std::vector<T> const &v) const override {
3601                 // !TBD: see note in EqualsMatcher
3602                 if (m_comparator.size() > v.size())
3603                     return false;
3604                 for (auto const& comparator : m_comparator) {
3605                     auto present = false;
3606                     for (const auto& el : v) {
3607                         if (el == comparator) {
3608                             present = true;
3609                             break;
3610                         }
3611                     }
3612                     if (!present) {
3613                         return false;
3614                     }
3615                 }
3616                 return true;
3617             }
describeCatch::Matchers::Vector::ContainsMatcher3618             std::string describe() const override {
3619                 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
3620             }
3621 
3622             std::vector<T> const& m_comparator;
3623         };
3624 
3625         template<typename T>
3626         struct EqualsMatcher : MatcherBase<std::vector<T>> {
3627 
EqualsMatcherCatch::Matchers::Vector::EqualsMatcher3628             EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3629 
matchCatch::Matchers::Vector::EqualsMatcher3630             bool match(std::vector<T> const &v) const override {
3631                 // !TBD: This currently works if all elements can be compared using !=
3632                 // - a more general approach would be via a compare template that defaults
3633                 // to using !=. but could be specialised for, e.g. std::vector<T> etc
3634                 // - then just call that directly
3635                 if (m_comparator.size() != v.size())
3636                     return false;
3637                 for (std::size_t i = 0; i < v.size(); ++i)
3638                     if (m_comparator[i] != v[i])
3639                         return false;
3640                 return true;
3641             }
describeCatch::Matchers::Vector::EqualsMatcher3642             std::string describe() const override {
3643                 return "Equals: " + ::Catch::Detail::stringify( m_comparator );
3644             }
3645             std::vector<T> const& m_comparator;
3646         };
3647 
3648         template<typename T>
3649         struct ApproxMatcher : MatcherBase<std::vector<T>> {
3650 
ApproxMatcherCatch::Matchers::Vector::ApproxMatcher3651             ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {}
3652 
matchCatch::Matchers::Vector::ApproxMatcher3653             bool match(std::vector<T> const &v) const override {
3654                 if (m_comparator.size() != v.size())
3655                     return false;
3656                 for (std::size_t i = 0; i < v.size(); ++i)
3657                     if (m_comparator[i] != approx(v[i]))
3658                         return false;
3659                 return true;
3660             }
describeCatch::Matchers::Vector::ApproxMatcher3661             std::string describe() const override {
3662                 return "is approx: " + ::Catch::Detail::stringify( m_comparator );
3663             }
3664             template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
epsilonCatch::Matchers::Vector::ApproxMatcher3665             ApproxMatcher& epsilon( T const& newEpsilon ) {
3666                 approx.epsilon(newEpsilon);
3667                 return *this;
3668             }
3669             template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
marginCatch::Matchers::Vector::ApproxMatcher3670             ApproxMatcher& margin( T const& newMargin ) {
3671                 approx.margin(newMargin);
3672                 return *this;
3673             }
3674             template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
scaleCatch::Matchers::Vector::ApproxMatcher3675             ApproxMatcher& scale( T const& newScale ) {
3676                 approx.scale(newScale);
3677                 return *this;
3678             }
3679 
3680             std::vector<T> const& m_comparator;
3681             mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
3682         };
3683 
3684         template<typename T>
3685         struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
UnorderedEqualsMatcherCatch::Matchers::Vector::UnorderedEqualsMatcher3686             UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
matchCatch::Matchers::Vector::UnorderedEqualsMatcher3687             bool match(std::vector<T> const& vec) const override {
3688                 // Note: This is a reimplementation of std::is_permutation,
3689                 //       because I don't want to include <algorithm> inside the common path
3690                 if (m_target.size() != vec.size()) {
3691                     return false;
3692                 }
3693                 return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
3694             }
3695 
describeCatch::Matchers::Vector::UnorderedEqualsMatcher3696             std::string describe() const override {
3697                 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
3698             }
3699         private:
3700             std::vector<T> const& m_target;
3701         };
3702 
3703     } // namespace Vector
3704 
3705     // The following functions create the actual matcher objects.
3706     // This allows the types to be inferred
3707 
3708     template<typename T>
Contains(std::vector<T> const & comparator)3709     Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
3710         return Vector::ContainsMatcher<T>( comparator );
3711     }
3712 
3713     template<typename T>
VectorContains(T const & comparator)3714     Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
3715         return Vector::ContainsElementMatcher<T>( comparator );
3716     }
3717 
3718     template<typename T>
Equals(std::vector<T> const & comparator)3719     Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
3720         return Vector::EqualsMatcher<T>( comparator );
3721     }
3722 
3723     template<typename T>
Approx(std::vector<T> const & comparator)3724     Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) {
3725         return Vector::ApproxMatcher<T>( comparator );
3726     }
3727 
3728     template<typename T>
UnorderedEquals(std::vector<T> const & target)3729     Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
3730         return Vector::UnorderedEqualsMatcher<T>(target);
3731     }
3732 
3733 } // namespace Matchers
3734 } // namespace Catch
3735 
3736 // end catch_matchers_vector.h
3737 namespace Catch {
3738 
3739     template<typename ArgT, typename MatcherT>
3740     class MatchExpr : public ITransientExpression {
3741         ArgT const& m_arg;
3742         MatcherT m_matcher;
3743         StringRef m_matcherString;
3744     public:
MatchExpr(ArgT const & arg,MatcherT const & matcher,StringRef const & matcherString)3745         MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )
3746         :   ITransientExpression{ true, matcher.match( arg ) },
3747             m_arg( arg ),
3748             m_matcher( matcher ),
3749             m_matcherString( matcherString )
3750         {}
3751 
streamReconstructedExpression(std::ostream & os) const3752         void streamReconstructedExpression( std::ostream &os ) const override {
3753             auto matcherAsString = m_matcher.toString();
3754             os << Catch::Detail::stringify( m_arg ) << ' ';
3755             if( matcherAsString == Detail::unprintableString )
3756                 os << m_matcherString;
3757             else
3758                 os << matcherAsString;
3759         }
3760     };
3761 
3762     using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
3763 
3764     void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  );
3765 
3766     template<typename ArgT, typename MatcherT>
makeMatchExpr(ArgT const & arg,MatcherT const & matcher,StringRef const & matcherString)3767     auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString  ) -> MatchExpr<ArgT, MatcherT> {
3768         return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
3769     }
3770 
3771 } // namespace Catch
3772 
3773 ///////////////////////////////////////////////////////////////////////////////
3774 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
3775     do { \
3776         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3777         INTERNAL_CATCH_TRY { \
3778             catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \
3779         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
3780         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3781     } while( false )
3782 
3783 ///////////////////////////////////////////////////////////////////////////////
3784 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
3785     do { \
3786         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3787         if( catchAssertionHandler.allowThrows() ) \
3788             try { \
3789                 static_cast<void>(__VA_ARGS__ ); \
3790                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
3791             } \
3792             catch( exceptionType const& ex ) { \
3793                 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \
3794             } \
3795             catch( ... ) { \
3796                 catchAssertionHandler.handleUnexpectedInflightException(); \
3797             } \
3798         else \
3799             catchAssertionHandler.handleThrowingCallSkipped(); \
3800         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3801     } while( false )
3802 
3803 // end catch_capture_matchers.h
3804 #endif
3805 // start catch_generators.hpp
3806 
3807 // start catch_interfaces_generatortracker.h
3808 
3809 
3810 #include <memory>
3811 
3812 namespace Catch {
3813 
3814     namespace Generators {
3815         class GeneratorUntypedBase {
3816         public:
3817             GeneratorUntypedBase() = default;
3818             virtual ~GeneratorUntypedBase();
3819             // Attempts to move the generator to the next element
3820              //
3821              // Returns true iff the move succeeded (and a valid element
3822              // can be retrieved).
3823             virtual bool next() = 0;
3824         };
3825         using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;
3826 
3827     } // namespace Generators
3828 
3829     struct IGeneratorTracker {
3830         virtual ~IGeneratorTracker();
3831         virtual auto hasGenerator() const -> bool = 0;
3832         virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
3833         virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
3834     };
3835 
3836 } // namespace Catch
3837 
3838 // end catch_interfaces_generatortracker.h
3839 // start catch_enforce.h
3840 
3841 #include <exception>
3842 
3843 namespace Catch {
3844 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
3845     template <typename Ex>
3846     [[noreturn]]
throw_exception(Ex const & e)3847     void throw_exception(Ex const& e) {
3848         throw e;
3849     }
3850 #else // ^^ Exceptions are enabled //  Exceptions are disabled vv
3851     [[noreturn]]
3852     void throw_exception(std::exception const& e);
3853 #endif
3854 
3855     [[noreturn]]
3856     void throw_logic_error(std::string const& msg);
3857     [[noreturn]]
3858     void throw_domain_error(std::string const& msg);
3859     [[noreturn]]
3860     void throw_runtime_error(std::string const& msg);
3861 
3862 } // namespace Catch;
3863 
3864 #define CATCH_MAKE_MSG(...) \
3865     (Catch::ReusableStringStream() << __VA_ARGS__).str()
3866 
3867 #define CATCH_INTERNAL_ERROR(...) \
3868     Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))
3869 
3870 #define CATCH_ERROR(...) \
3871     Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
3872 
3873 #define CATCH_RUNTIME_ERROR(...) \
3874     Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))
3875 
3876 #define CATCH_ENFORCE( condition, ... ) \
3877     do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)
3878 
3879 // end catch_enforce.h
3880 #include <memory>
3881 #include <vector>
3882 #include <cassert>
3883 
3884 #include <utility>
3885 #include <exception>
3886 
3887 namespace Catch {
3888 
3889 class GeneratorException : public std::exception {
3890     const char* const m_msg = "";
3891 
3892 public:
GeneratorException(const char * msg)3893     GeneratorException(const char* msg):
3894         m_msg(msg)
3895     {}
3896 
3897     const char* what() const noexcept override final;
3898 };
3899 
3900 namespace Generators {
3901 
3902     // !TBD move this into its own location?
3903     namespace pf{
3904         template<typename T, typename... Args>
make_unique(Args &&...args)3905         std::unique_ptr<T> make_unique( Args&&... args ) {
3906             return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
3907         }
3908     }
3909 
3910     template<typename T>
3911     struct IGenerator : GeneratorUntypedBase {
3912         virtual ~IGenerator() = default;
3913 
3914         // Returns the current element of the generator
3915         //
3916         // \Precondition The generator is either freshly constructed,
3917         // or the last call to `next()` returned true
3918         virtual T const& get() const = 0;
3919         using type = T;
3920     };
3921 
3922     template<typename T>
3923     class SingleValueGenerator final : public IGenerator<T> {
3924         T m_value;
3925     public:
SingleValueGenerator(T && value)3926         SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
3927 
get() const3928         T const& get() const override {
3929             return m_value;
3930         }
next()3931         bool next() override {
3932             return false;
3933         }
3934     };
3935 
3936     template<typename T>
3937     class FixedValuesGenerator final : public IGenerator<T> {
3938         static_assert(!std::is_same<T, bool>::value,
3939             "FixedValuesGenerator does not support bools because of std::vector<bool>"
3940             "specialization, use SingleValue Generator instead.");
3941         std::vector<T> m_values;
3942         size_t m_idx = 0;
3943     public:
FixedValuesGenerator(std::initializer_list<T> values)3944         FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
3945 
get() const3946         T const& get() const override {
3947             return m_values[m_idx];
3948         }
next()3949         bool next() override {
3950             ++m_idx;
3951             return m_idx < m_values.size();
3952         }
3953     };
3954 
3955     template <typename T>
3956     class GeneratorWrapper final {
3957         std::unique_ptr<IGenerator<T>> m_generator;
3958     public:
GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator)3959         GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator):
3960             m_generator(std::move(generator))
3961         {}
get() const3962         T const& get() const {
3963             return m_generator->get();
3964         }
next()3965         bool next() {
3966             return m_generator->next();
3967         }
3968     };
3969 
3970     template <typename T>
value(T && value)3971     GeneratorWrapper<T> value(T&& value) {
3972         return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value)));
3973     }
3974     template <typename T>
values(std::initializer_list<T> values)3975     GeneratorWrapper<T> values(std::initializer_list<T> values) {
3976         return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));
3977     }
3978 
3979     template<typename T>
3980     class Generators : public IGenerator<T> {
3981         std::vector<GeneratorWrapper<T>> m_generators;
3982         size_t m_current = 0;
3983 
populate(GeneratorWrapper<T> && generator)3984         void populate(GeneratorWrapper<T>&& generator) {
3985             m_generators.emplace_back(std::move(generator));
3986         }
populate(T && val)3987         void populate(T&& val) {
3988             m_generators.emplace_back(value(std::forward<T>(val)));
3989         }
3990         template<typename U>
populate(U && val)3991         void populate(U&& val) {
3992             populate(T(std::forward<U>(val)));
3993         }
3994         template<typename U, typename... Gs>
populate(U && valueOrGenerator,Gs &&...moreGenerators)3995         void populate(U&& valueOrGenerator, Gs &&... moreGenerators) {
3996             populate(std::forward<U>(valueOrGenerator));
3997             populate(std::forward<Gs>(moreGenerators)...);
3998         }
3999 
4000     public:
4001         template <typename... Gs>
Generators(Gs &&...moreGenerators)4002         Generators(Gs &&... moreGenerators) {
4003             m_generators.reserve(sizeof...(Gs));
4004             populate(std::forward<Gs>(moreGenerators)...);
4005         }
4006 
get() const4007         T const& get() const override {
4008             return m_generators[m_current].get();
4009         }
4010 
next()4011         bool next() override {
4012             if (m_current >= m_generators.size()) {
4013                 return false;
4014             }
4015             const bool current_status = m_generators[m_current].next();
4016             if (!current_status) {
4017                 ++m_current;
4018             }
4019             return m_current < m_generators.size();
4020         }
4021     };
4022 
4023     template<typename... Ts>
table(std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples)4024     GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) {
4025         return values<std::tuple<Ts...>>( tuples );
4026     }
4027 
4028     // Tag type to signal that a generator sequence should convert arguments to a specific type
4029     template <typename T>
4030     struct as {};
4031 
4032     template<typename T, typename... Gs>
makeGenerators(GeneratorWrapper<T> && generator,Gs &&...moreGenerators)4033     auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {
4034         return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
4035     }
4036     template<typename T>
makeGenerators(GeneratorWrapper<T> && generator)4037     auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
4038         return Generators<T>(std::move(generator));
4039     }
4040     template<typename T, typename... Gs>
makeGenerators(T && val,Gs &&...moreGenerators)4041     auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> {
4042         return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
4043     }
4044     template<typename T, typename U, typename... Gs>
makeGenerators(as<T>,U && val,Gs &&...moreGenerators)4045     auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {
4046         return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
4047     }
4048 
4049     auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
4050 
4051     template<typename L>
4052     // Note: The type after -> is weird, because VS2015 cannot parse
4053     //       the expression used in the typedef inside, when it is in
4054     //       return type. Yeah.
generate(SourceLineInfo const & lineInfo,L const & generatorExpression)4055     auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
4056         using UnderlyingType = typename decltype(generatorExpression())::type;
4057 
4058         IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
4059         if (!tracker.hasGenerator()) {
4060             tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
4061         }
4062 
4063         auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );
4064         return generator.get();
4065     }
4066 
4067 } // namespace Generators
4068 } // namespace Catch
4069 
4070 #define GENERATE( ... ) \
4071     Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
4072 #define GENERATE_COPY( ... ) \
4073     Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
4074 #define GENERATE_REF( ... ) \
4075     Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)
4076 
4077 // end catch_generators.hpp
4078 // start catch_generators_generic.hpp
4079 
4080 namespace Catch {
4081 namespace Generators {
4082 
4083     template <typename T>
4084     class TakeGenerator : public IGenerator<T> {
4085         GeneratorWrapper<T> m_generator;
4086         size_t m_returned = 0;
4087         size_t m_target;
4088     public:
TakeGenerator(size_t target,GeneratorWrapper<T> && generator)4089         TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
4090             m_generator(std::move(generator)),
4091             m_target(target)
4092         {
4093             assert(target != 0 && "Empty generators are not allowed");
4094         }
get() const4095         T const& get() const override {
4096             return m_generator.get();
4097         }
next()4098         bool next() override {
4099             ++m_returned;
4100             if (m_returned >= m_target) {
4101                 return false;
4102             }
4103 
4104             const auto success = m_generator.next();
4105             // If the underlying generator does not contain enough values
4106             // then we cut short as well
4107             if (!success) {
4108                 m_returned = m_target;
4109             }
4110             return success;
4111         }
4112     };
4113 
4114     template <typename T>
take(size_t target,GeneratorWrapper<T> && generator)4115     GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
4116         return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
4117     }
4118 
4119     template <typename T, typename Predicate>
4120     class FilterGenerator : public IGenerator<T> {
4121         GeneratorWrapper<T> m_generator;
4122         Predicate m_predicate;
4123     public:
4124         template <typename P = Predicate>
FilterGenerator(P && pred,GeneratorWrapper<T> && generator)4125         FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
4126             m_generator(std::move(generator)),
4127             m_predicate(std::forward<P>(pred))
4128         {
4129             if (!m_predicate(m_generator.get())) {
4130                 // It might happen that there are no values that pass the
4131                 // filter. In that case we throw an exception.
4132                 auto has_initial_value = next();
4133                 if (!has_initial_value) {
4134                     Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
4135                 }
4136             }
4137         }
4138 
get() const4139         T const& get() const override {
4140             return m_generator.get();
4141         }
4142 
next()4143         bool next() override {
4144             bool success = m_generator.next();
4145             if (!success) {
4146                 return false;
4147             }
4148             while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
4149             return success;
4150         }
4151     };
4152 
4153     template <typename T, typename Predicate>
filter(Predicate && pred,GeneratorWrapper<T> && generator)4154     GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
4155         return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
4156     }
4157 
4158     template <typename T>
4159     class RepeatGenerator : public IGenerator<T> {
4160         static_assert(!std::is_same<T, bool>::value,
4161             "RepeatGenerator currently does not support bools"
4162             "because of std::vector<bool> specialization");
4163         GeneratorWrapper<T> m_generator;
4164         mutable std::vector<T> m_returned;
4165         size_t m_target_repeats;
4166         size_t m_current_repeat = 0;
4167         size_t m_repeat_index = 0;
4168     public:
RepeatGenerator(size_t repeats,GeneratorWrapper<T> && generator)4169         RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
4170             m_generator(std::move(generator)),
4171             m_target_repeats(repeats)
4172         {
4173             assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
4174         }
4175 
get() const4176         T const& get() const override {
4177             if (m_current_repeat == 0) {
4178                 m_returned.push_back(m_generator.get());
4179                 return m_returned.back();
4180             }
4181             return m_returned[m_repeat_index];
4182         }
4183 
next()4184         bool next() override {
4185             // There are 2 basic cases:
4186             // 1) We are still reading the generator
4187             // 2) We are reading our own cache
4188 
4189             // In the first case, we need to poke the underlying generator.
4190             // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
4191             if (m_current_repeat == 0) {
4192                 const auto success = m_generator.next();
4193                 if (!success) {
4194                     ++m_current_repeat;
4195                 }
4196                 return m_current_repeat < m_target_repeats;
4197             }
4198 
4199             // In the second case, we need to move indices forward and check that we haven't run up against the end
4200             ++m_repeat_index;
4201             if (m_repeat_index == m_returned.size()) {
4202                 m_repeat_index = 0;
4203                 ++m_current_repeat;
4204             }
4205             return m_current_repeat < m_target_repeats;
4206         }
4207     };
4208 
4209     template <typename T>
repeat(size_t repeats,GeneratorWrapper<T> && generator)4210     GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
4211         return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
4212     }
4213 
4214     template <typename T, typename U, typename Func>
4215     class MapGenerator : public IGenerator<T> {
4216         // TBD: provide static assert for mapping function, for friendly error message
4217         GeneratorWrapper<U> m_generator;
4218         Func m_function;
4219         // To avoid returning dangling reference, we have to save the values
4220         T m_cache;
4221     public:
4222         template <typename F2 = Func>
MapGenerator(F2 && function,GeneratorWrapper<U> && generator)4223         MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
4224             m_generator(std::move(generator)),
4225             m_function(std::forward<F2>(function)),
4226             m_cache(m_function(m_generator.get()))
4227         {}
4228 
get() const4229         T const& get() const override {
4230             return m_cache;
4231         }
next()4232         bool next() override {
4233             const auto success = m_generator.next();
4234             if (success) {
4235                 m_cache = m_function(m_generator.get());
4236             }
4237             return success;
4238         }
4239     };
4240 
4241     template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>
map(Func && function,GeneratorWrapper<U> && generator)4242     GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
4243         return GeneratorWrapper<T>(
4244             pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
4245         );
4246     }
4247 
4248     template <typename T, typename U, typename Func>
map(Func && function,GeneratorWrapper<U> && generator)4249     GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
4250         return GeneratorWrapper<T>(
4251             pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
4252         );
4253     }
4254 
4255     template <typename T>
4256     class ChunkGenerator final : public IGenerator<std::vector<T>> {
4257         std::vector<T> m_chunk;
4258         size_t m_chunk_size;
4259         GeneratorWrapper<T> m_generator;
4260         bool m_used_up = false;
4261     public:
ChunkGenerator(size_t size,GeneratorWrapper<T> generator)4262         ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
4263             m_chunk_size(size), m_generator(std::move(generator))
4264         {
4265             m_chunk.reserve(m_chunk_size);
4266             if (m_chunk_size != 0) {
4267                 m_chunk.push_back(m_generator.get());
4268                 for (size_t i = 1; i < m_chunk_size; ++i) {
4269                     if (!m_generator.next()) {
4270                         Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));
4271                     }
4272                     m_chunk.push_back(m_generator.get());
4273                 }
4274             }
4275         }
get() const4276         std::vector<T> const& get() const override {
4277             return m_chunk;
4278         }
next()4279         bool next() override {
4280             m_chunk.clear();
4281             for (size_t idx = 0; idx < m_chunk_size; ++idx) {
4282                 if (!m_generator.next()) {
4283                     return false;
4284                 }
4285                 m_chunk.push_back(m_generator.get());
4286             }
4287             return true;
4288         }
4289     };
4290 
4291     template <typename T>
chunk(size_t size,GeneratorWrapper<T> && generator)4292     GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {
4293         return GeneratorWrapper<std::vector<T>>(
4294             pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
4295         );
4296     }
4297 
4298 } // namespace Generators
4299 } // namespace Catch
4300 
4301 // end catch_generators_generic.hpp
4302 // start catch_generators_specific.hpp
4303 
4304 // start catch_context.h
4305 
4306 #include <memory>
4307 
4308 namespace Catch {
4309 
4310     struct IResultCapture;
4311     struct IRunner;
4312     struct IConfig;
4313     struct IMutableContext;
4314 
4315     using IConfigPtr = std::shared_ptr<IConfig const>;
4316 
4317     struct IContext
4318     {
4319         virtual ~IContext();
4320 
4321         virtual IResultCapture* getResultCapture() = 0;
4322         virtual IRunner* getRunner() = 0;
4323         virtual IConfigPtr const& getConfig() const = 0;
4324     };
4325 
4326     struct IMutableContext : IContext
4327     {
4328         virtual ~IMutableContext();
4329         virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
4330         virtual void setRunner( IRunner* runner ) = 0;
4331         virtual void setConfig( IConfigPtr const& config ) = 0;
4332 
4333     private:
4334         static IMutableContext *currentContext;
4335         friend IMutableContext& getCurrentMutableContext();
4336         friend void cleanUpContext();
4337         static void createContext();
4338     };
4339 
getCurrentMutableContext()4340     inline IMutableContext& getCurrentMutableContext()
4341     {
4342         if( !IMutableContext::currentContext )
4343             IMutableContext::createContext();
4344         // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)
4345         return *IMutableContext::currentContext;
4346     }
4347 
getCurrentContext()4348     inline IContext& getCurrentContext()
4349     {
4350         return getCurrentMutableContext();
4351     }
4352 
4353     void cleanUpContext();
4354 
4355     class SimplePcg32;
4356     SimplePcg32& rng();
4357 }
4358 
4359 // end catch_context.h
4360 // start catch_interfaces_config.h
4361 
4362 // start catch_option.hpp
4363 
4364 namespace Catch {
4365 
4366     // An optional type
4367     template<typename T>
4368     class Option {
4369     public:
Option()4370         Option() : nullableValue( nullptr ) {}
Option(T const & _value)4371         Option( T const& _value )
4372         : nullableValue( new( storage ) T( _value ) )
4373         {}
Option(Option const & _other)4374         Option( Option const& _other )
4375         : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )
4376         {}
4377 
~Option()4378         ~Option() {
4379             reset();
4380         }
4381 
operator =(Option const & _other)4382         Option& operator= ( Option const& _other ) {
4383             if( &_other != this ) {
4384                 reset();
4385                 if( _other )
4386                     nullableValue = new( storage ) T( *_other );
4387             }
4388             return *this;
4389         }
operator =(T const & _value)4390         Option& operator = ( T const& _value ) {
4391             reset();
4392             nullableValue = new( storage ) T( _value );
4393             return *this;
4394         }
4395 
reset()4396         void reset() {
4397             if( nullableValue )
4398                 nullableValue->~T();
4399             nullableValue = nullptr;
4400         }
4401 
operator *()4402         T& operator*() { return *nullableValue; }
operator *() const4403         T const& operator*() const { return *nullableValue; }
operator ->()4404         T* operator->() { return nullableValue; }
operator ->() const4405         const T* operator->() const { return nullableValue; }
4406 
valueOr(T const & defaultValue) const4407         T valueOr( T const& defaultValue ) const {
4408             return nullableValue ? *nullableValue : defaultValue;
4409         }
4410 
some() const4411         bool some() const { return nullableValue != nullptr; }
none() const4412         bool none() const { return nullableValue == nullptr; }
4413 
operator !() const4414         bool operator !() const { return nullableValue == nullptr; }
operator bool() const4415         explicit operator bool() const {
4416             return some();
4417         }
4418 
4419     private:
4420         T *nullableValue;
4421         alignas(alignof(T)) char storage[sizeof(T)];
4422     };
4423 
4424 } // end namespace Catch
4425 
4426 // end catch_option.hpp
4427 #include <chrono>
4428 #include <iosfwd>
4429 #include <string>
4430 #include <vector>
4431 #include <memory>
4432 
4433 namespace Catch {
4434 
4435     enum class Verbosity {
4436         Quiet = 0,
4437         Normal,
4438         High
4439     };
4440 
4441     struct WarnAbout { enum What {
4442         Nothing = 0x00,
4443         NoAssertions = 0x01,
4444         NoTests = 0x02
4445     }; };
4446 
4447     struct ShowDurations { enum OrNot {
4448         DefaultForReporter,
4449         Always,
4450         Never
4451     }; };
4452     struct RunTests { enum InWhatOrder {
4453         InDeclarationOrder,
4454         InLexicographicalOrder,
4455         InRandomOrder
4456     }; };
4457     struct UseColour { enum YesOrNo {
4458         Auto,
4459         Yes,
4460         No
4461     }; };
4462     struct WaitForKeypress { enum When {
4463         Never,
4464         BeforeStart = 1,
4465         BeforeExit = 2,
4466         BeforeStartAndExit = BeforeStart | BeforeExit
4467     }; };
4468 
4469     class TestSpec;
4470 
4471     struct IConfig : NonCopyable {
4472 
4473         virtual ~IConfig();
4474 
4475         virtual bool allowThrows() const = 0;
4476         virtual std::ostream& stream() const = 0;
4477         virtual std::string name() const = 0;
4478         virtual bool includeSuccessfulResults() const = 0;
4479         virtual bool shouldDebugBreak() const = 0;
4480         virtual bool warnAboutMissingAssertions() const = 0;
4481         virtual bool warnAboutNoTests() const = 0;
4482         virtual int abortAfter() const = 0;
4483         virtual bool showInvisibles() const = 0;
4484         virtual ShowDurations::OrNot showDurations() const = 0;
4485         virtual TestSpec const& testSpec() const = 0;
4486         virtual bool hasTestFilters() const = 0;
4487         virtual std::vector<std::string> const& getTestsOrTags() const = 0;
4488         virtual RunTests::InWhatOrder runOrder() const = 0;
4489         virtual unsigned int rngSeed() const = 0;
4490         virtual UseColour::YesOrNo useColour() const = 0;
4491         virtual std::vector<std::string> const& getSectionsToRun() const = 0;
4492         virtual Verbosity verbosity() const = 0;
4493 
4494         virtual bool benchmarkNoAnalysis() const = 0;
4495         virtual int benchmarkSamples() const = 0;
4496         virtual double benchmarkConfidenceInterval() const = 0;
4497         virtual unsigned int benchmarkResamples() const = 0;
4498         virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;
4499     };
4500 
4501     using IConfigPtr = std::shared_ptr<IConfig const>;
4502 }
4503 
4504 // end catch_interfaces_config.h
4505 // start catch_random_number_generator.h
4506 
4507 #include <cstdint>
4508 
4509 namespace Catch {
4510 
4511     // This is a simple implementation of C++11 Uniform Random Number
4512     // Generator. It does not provide all operators, because Catch2
4513     // does not use it, but it should behave as expected inside stdlib's
4514     // distributions.
4515     // The implementation is based on the PCG family (http://pcg-random.org)
4516     class SimplePcg32 {
4517         using state_type = std::uint64_t;
4518     public:
4519         using result_type = std::uint32_t;
result_type(min)4520         static constexpr result_type (min)() {
4521             return 0;
4522         }
result_type(max)4523         static constexpr result_type (max)() {
4524             return static_cast<result_type>(-1);
4525         }
4526 
4527         // Provide some default initial state for the default constructor
SimplePcg32()4528         SimplePcg32():SimplePcg32(0xed743cc4U) {}
4529 
4530         explicit SimplePcg32(result_type seed_);
4531 
4532         void seed(result_type seed_);
4533         void discard(uint64_t skip);
4534 
4535         result_type operator()();
4536 
4537     private:
4538         friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
4539         friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);
4540 
4541         // In theory we also need operator<< and operator>>
4542         // In practice we do not use them, so we will skip them for now
4543 
4544         std::uint64_t m_state;
4545         // This part of the state determines which "stream" of the numbers
4546         // is chosen -- we take it as a constant for Catch2, so we only
4547         // need to deal with seeding the main state.
4548         // Picked by reading 8 bytes from `/dev/random` :-)
4549         static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;
4550     };
4551 
4552 } // end namespace Catch
4553 
4554 // end catch_random_number_generator.h
4555 #include <random>
4556 
4557 namespace Catch {
4558 namespace Generators {
4559 
4560 template <typename Float>
4561 class RandomFloatingGenerator final : public IGenerator<Float> {
4562     Catch::SimplePcg32& m_rng;
4563     std::uniform_real_distribution<Float> m_dist;
4564     Float m_current_number;
4565 public:
4566 
RandomFloatingGenerator(Float a,Float b)4567     RandomFloatingGenerator(Float a, Float b):
4568         m_rng(rng()),
4569         m_dist(a, b) {
4570         static_cast<void>(next());
4571     }
4572 
get() const4573     Float const& get() const override {
4574         return m_current_number;
4575     }
next()4576     bool next() override {
4577         m_current_number = m_dist(m_rng);
4578         return true;
4579     }
4580 };
4581 
4582 template <typename Integer>
4583 class RandomIntegerGenerator final : public IGenerator<Integer> {
4584     Catch::SimplePcg32& m_rng;
4585     std::uniform_int_distribution<Integer> m_dist;
4586     Integer m_current_number;
4587 public:
4588 
RandomIntegerGenerator(Integer a,Integer b)4589     RandomIntegerGenerator(Integer a, Integer b):
4590         m_rng(rng()),
4591         m_dist(a, b) {
4592         static_cast<void>(next());
4593     }
4594 
get() const4595     Integer const& get() const override {
4596         return m_current_number;
4597     }
next()4598     bool next() override {
4599         m_current_number = m_dist(m_rng);
4600         return true;
4601     }
4602 };
4603 
4604 // TODO: Ideally this would be also constrained against the various char types,
4605 //       but I don't expect users to run into that in practice.
4606 template <typename T>
4607 typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value,
4608 GeneratorWrapper<T>>::type
random(T a,T b)4609 random(T a, T b) {
4610     return GeneratorWrapper<T>(
4611         pf::make_unique<RandomIntegerGenerator<T>>(a, b)
4612     );
4613 }
4614 
4615 template <typename T>
4616 typename std::enable_if<std::is_floating_point<T>::value,
4617 GeneratorWrapper<T>>::type
random(T a,T b)4618 random(T a, T b) {
4619     return GeneratorWrapper<T>(
4620         pf::make_unique<RandomFloatingGenerator<T>>(a, b)
4621     );
4622 }
4623 
4624 template <typename T>
4625 class RangeGenerator final : public IGenerator<T> {
4626     T m_current;
4627     T m_end;
4628     T m_step;
4629     bool m_positive;
4630 
4631 public:
RangeGenerator(T const & start,T const & end,T const & step)4632     RangeGenerator(T const& start, T const& end, T const& step):
4633         m_current(start),
4634         m_end(end),
4635         m_step(step),
4636         m_positive(m_step > T(0))
4637     {
4638         assert(m_current != m_end && "Range start and end cannot be equal");
4639         assert(m_step != T(0) && "Step size cannot be zero");
4640         assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
4641     }
4642 
RangeGenerator(T const & start,T const & end)4643     RangeGenerator(T const& start, T const& end):
4644         RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
4645     {}
4646 
get() const4647     T const& get() const override {
4648         return m_current;
4649     }
4650 
next()4651     bool next() override {
4652         m_current += m_step;
4653         return (m_positive) ? (m_current < m_end) : (m_current > m_end);
4654     }
4655 };
4656 
4657 template <typename T>
range(T const & start,T const & end,T const & step)4658 GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
4659     static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");
4660     return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
4661 }
4662 
4663 template <typename T>
range(T const & start,T const & end)4664 GeneratorWrapper<T> range(T const& start, T const& end) {
4665     static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
4666     return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end));
4667 }
4668 
4669 template <typename T>
4670 class IteratorGenerator final : public IGenerator<T> {
4671     static_assert(!std::is_same<T, bool>::value,
4672         "IteratorGenerator currently does not support bools"
4673         "because of std::vector<bool> specialization");
4674 
4675     std::vector<T> m_elems;
4676     size_t m_current = 0;
4677 public:
4678     template <typename InputIterator, typename InputSentinel>
IteratorGenerator(InputIterator first,InputSentinel last)4679     IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) {
4680         if (m_elems.empty()) {
4681             Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values"));
4682         }
4683     }
4684 
get() const4685     T const& get() const override {
4686         return m_elems[m_current];
4687     }
4688 
next()4689     bool next() override {
4690         ++m_current;
4691         return m_current != m_elems.size();
4692     }
4693 };
4694 
4695 template <typename InputIterator,
4696           typename InputSentinel,
4697           typename ResultType = typename std::iterator_traits<InputIterator>::value_type>
from_range(InputIterator from,InputSentinel to)4698 GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) {
4699     return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to));
4700 }
4701 
4702 template <typename Container,
4703           typename ResultType = typename Container::value_type>
from_range(Container const & cnt)4704 GeneratorWrapper<ResultType> from_range(Container const& cnt) {
4705     return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(cnt.begin(), cnt.end()));
4706 }
4707 
4708 } // namespace Generators
4709 } // namespace Catch
4710 
4711 // end catch_generators_specific.hpp
4712 
4713 // These files are included here so the single_include script doesn't put them
4714 // in the conditionally compiled sections
4715 // start catch_test_case_info.h
4716 
4717 #include <string>
4718 #include <vector>
4719 #include <memory>
4720 
4721 #ifdef __clang__
4722 #pragma clang diagnostic push
4723 #pragma clang diagnostic ignored "-Wpadded"
4724 #endif
4725 
4726 namespace Catch {
4727 
4728     struct ITestInvoker;
4729 
4730     struct TestCaseInfo {
4731         enum SpecialProperties{
4732             None = 0,
4733             IsHidden = 1 << 1,
4734             ShouldFail = 1 << 2,
4735             MayFail = 1 << 3,
4736             Throws = 1 << 4,
4737             NonPortable = 1 << 5,
4738             Benchmark = 1 << 6
4739         };
4740 
4741         TestCaseInfo(   std::string const& _name,
4742                         std::string const& _className,
4743                         std::string const& _description,
4744                         std::vector<std::string> const& _tags,
4745                         SourceLineInfo const& _lineInfo );
4746 
4747         friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags );
4748 
4749         bool isHidden() const;
4750         bool throws() const;
4751         bool okToFail() const;
4752         bool expectedToFail() const;
4753 
4754         std::string tagsAsString() const;
4755 
4756         std::string name;
4757         std::string className;
4758         std::string description;
4759         std::vector<std::string> tags;
4760         std::vector<std::string> lcaseTags;
4761         SourceLineInfo lineInfo;
4762         SpecialProperties properties;
4763     };
4764 
4765     class TestCase : public TestCaseInfo {
4766     public:
4767 
4768         TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
4769 
4770         TestCase withName( std::string const& _newName ) const;
4771 
4772         void invoke() const;
4773 
4774         TestCaseInfo const& getTestCaseInfo() const;
4775 
4776         bool operator == ( TestCase const& other ) const;
4777         bool operator < ( TestCase const& other ) const;
4778 
4779     private:
4780         std::shared_ptr<ITestInvoker> test;
4781     };
4782 
4783     TestCase makeTestCase(  ITestInvoker* testCase,
4784                             std::string const& className,
4785                             NameAndTags const& nameAndTags,
4786                             SourceLineInfo const& lineInfo );
4787 }
4788 
4789 #ifdef __clang__
4790 #pragma clang diagnostic pop
4791 #endif
4792 
4793 // end catch_test_case_info.h
4794 // start catch_interfaces_runner.h
4795 
4796 namespace Catch {
4797 
4798     struct IRunner {
4799         virtual ~IRunner();
4800         virtual bool aborting() const = 0;
4801     };
4802 }
4803 
4804 // end catch_interfaces_runner.h
4805 
4806 #ifdef __OBJC__
4807 // start catch_objc.hpp
4808 
4809 #import <objc/runtime.h>
4810 
4811 #include <string>
4812 
4813 // NB. Any general catch headers included here must be included
4814 // in catch.hpp first to make sure they are included by the single
4815 // header for non obj-usage
4816 
4817 ///////////////////////////////////////////////////////////////////////////////
4818 // This protocol is really only here for (self) documenting purposes, since
4819 // all its methods are optional.
4820 @protocol OcFixture
4821 
4822 @optional
4823 
4824 -(void) setUp;
4825 -(void) tearDown;
4826 
4827 @end
4828 
4829 namespace Catch {
4830 
4831     class OcMethod : public ITestInvoker {
4832 
4833     public:
OcMethod(Class cls,SEL sel)4834         OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
4835 
invoke() const4836         virtual void invoke() const {
4837             id obj = [[m_cls alloc] init];
4838 
4839             performOptionalSelector( obj, @selector(setUp)  );
4840             performOptionalSelector( obj, m_sel );
4841             performOptionalSelector( obj, @selector(tearDown)  );
4842 
4843             arcSafeRelease( obj );
4844         }
4845     private:
~OcMethod()4846         virtual ~OcMethod() {}
4847 
4848         Class m_cls;
4849         SEL m_sel;
4850     };
4851 
4852     namespace Detail{
4853 
getAnnotation(Class cls,std::string const & annotationName,std::string const & testCaseName)4854         inline std::string getAnnotation(   Class cls,
4855                                             std::string const& annotationName,
4856                                             std::string const& testCaseName ) {
4857             NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
4858             SEL sel = NSSelectorFromString( selStr );
4859             arcSafeRelease( selStr );
4860             id value = performOptionalSelector( cls, sel );
4861             if( value )
4862                 return [(NSString*)value UTF8String];
4863             return "";
4864         }
4865     }
4866 
registerTestMethods()4867     inline std::size_t registerTestMethods() {
4868         std::size_t noTestMethods = 0;
4869         int noClasses = objc_getClassList( nullptr, 0 );
4870 
4871         Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
4872         objc_getClassList( classes, noClasses );
4873 
4874         for( int c = 0; c < noClasses; c++ ) {
4875             Class cls = classes[c];
4876             {
4877                 u_int count;
4878                 Method* methods = class_copyMethodList( cls, &count );
4879                 for( u_int m = 0; m < count ; m++ ) {
4880                     SEL selector = method_getName(methods[m]);
4881                     std::string methodName = sel_getName(selector);
4882                     if( startsWith( methodName, "Catch_TestCase_" ) ) {
4883                         std::string testCaseName = methodName.substr( 15 );
4884                         std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
4885                         std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
4886                         const char* className = class_getName( cls );
4887 
4888                         getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
4889                         noTestMethods++;
4890                     }
4891                 }
4892                 free(methods);
4893             }
4894         }
4895         return noTestMethods;
4896     }
4897 
4898 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
4899 
4900     namespace Matchers {
4901         namespace Impl {
4902         namespace NSStringMatchers {
4903 
4904             struct StringHolder : MatcherBase<NSString*>{
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder4905                 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder4906                 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder4907                 StringHolder() {
4908                     arcSafeRelease( m_substr );
4909                 }
4910 
matchCatch::Matchers::Impl::NSStringMatchers::StringHolder4911                 bool match( NSString* str ) const override {
4912                     return false;
4913                 }
4914 
4915                 NSString* CATCH_ARC_STRONG m_substr;
4916             };
4917 
4918             struct Equals : StringHolder {
EqualsCatch::Matchers::Impl::NSStringMatchers::Equals4919                 Equals( NSString* substr ) : StringHolder( substr ){}
4920 
matchCatch::Matchers::Impl::NSStringMatchers::Equals4921                 bool match( NSString* str ) const override {
4922                     return  (str != nil || m_substr == nil ) &&
4923                             [str isEqualToString:m_substr];
4924                 }
4925 
describeCatch::Matchers::Impl::NSStringMatchers::Equals4926                 std::string describe() const override {
4927                     return "equals string: " + Catch::Detail::stringify( m_substr );
4928                 }
4929             };
4930 
4931             struct Contains : StringHolder {
ContainsCatch::Matchers::Impl::NSStringMatchers::Contains4932                 Contains( NSString* substr ) : StringHolder( substr ){}
4933 
matchCatch::Matchers::Impl::NSStringMatchers::Contains4934                 bool match( NSString* str ) const override {
4935                     return  (str != nil || m_substr == nil ) &&
4936                             [str rangeOfString:m_substr].location != NSNotFound;
4937                 }
4938 
describeCatch::Matchers::Impl::NSStringMatchers::Contains4939                 std::string describe() const override {
4940                     return "contains string: " + Catch::Detail::stringify( m_substr );
4941                 }
4942             };
4943 
4944             struct StartsWith : StringHolder {
StartsWithCatch::Matchers::Impl::NSStringMatchers::StartsWith4945                 StartsWith( NSString* substr ) : StringHolder( substr ){}
4946 
matchCatch::Matchers::Impl::NSStringMatchers::StartsWith4947                 bool match( NSString* str ) const override {
4948                     return  (str != nil || m_substr == nil ) &&
4949                             [str rangeOfString:m_substr].location == 0;
4950                 }
4951 
describeCatch::Matchers::Impl::NSStringMatchers::StartsWith4952                 std::string describe() const override {
4953                     return "starts with: " + Catch::Detail::stringify( m_substr );
4954                 }
4955             };
4956             struct EndsWith : StringHolder {
EndsWithCatch::Matchers::Impl::NSStringMatchers::EndsWith4957                 EndsWith( NSString* substr ) : StringHolder( substr ){}
4958 
matchCatch::Matchers::Impl::NSStringMatchers::EndsWith4959                 bool match( NSString* str ) const override {
4960                     return  (str != nil || m_substr == nil ) &&
4961                             [str rangeOfString:m_substr].location == [str length] - [m_substr length];
4962                 }
4963 
describeCatch::Matchers::Impl::NSStringMatchers::EndsWith4964                 std::string describe() const override {
4965                     return "ends with: " + Catch::Detail::stringify( m_substr );
4966                 }
4967             };
4968 
4969         } // namespace NSStringMatchers
4970         } // namespace Impl
4971 
4972         inline Impl::NSStringMatchers::Equals
Equals(NSString * substr)4973             Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
4974 
4975         inline Impl::NSStringMatchers::Contains
Contains(NSString * substr)4976             Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
4977 
4978         inline Impl::NSStringMatchers::StartsWith
StartsWith(NSString * substr)4979             StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
4980 
4981         inline Impl::NSStringMatchers::EndsWith
EndsWith(NSString * substr)4982             EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
4983 
4984     } // namespace Matchers
4985 
4986     using namespace Matchers;
4987 
4988 #endif // CATCH_CONFIG_DISABLE_MATCHERS
4989 
4990 } // namespace Catch
4991 
4992 ///////////////////////////////////////////////////////////////////////////////
4993 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix
4994 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \
4995 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \
4996 { \
4997 return @ name; \
4998 } \
4999 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \
5000 { \
5001 return @ desc; \
5002 } \
5003 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )
5004 
5005 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )
5006 
5007 // end catch_objc.hpp
5008 #endif
5009 
5010 // Benchmarking needs the externally-facing parts of reporters to work
5011 #if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5012 // start catch_external_interfaces.h
5013 
5014 // start catch_reporter_bases.hpp
5015 
5016 // start catch_interfaces_reporter.h
5017 
5018 // start catch_config.hpp
5019 
5020 // start catch_test_spec_parser.h
5021 
5022 #ifdef __clang__
5023 #pragma clang diagnostic push
5024 #pragma clang diagnostic ignored "-Wpadded"
5025 #endif
5026 
5027 // start catch_test_spec.h
5028 
5029 #ifdef __clang__
5030 #pragma clang diagnostic push
5031 #pragma clang diagnostic ignored "-Wpadded"
5032 #endif
5033 
5034 // start catch_wildcard_pattern.h
5035 
5036 namespace Catch
5037 {
5038     class WildcardPattern {
5039         enum WildcardPosition {
5040             NoWildcard = 0,
5041             WildcardAtStart = 1,
5042             WildcardAtEnd = 2,
5043             WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
5044         };
5045 
5046     public:
5047 
5048         WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity );
5049         virtual ~WildcardPattern() = default;
5050         virtual bool matches( std::string const& str ) const;
5051 
5052     private:
5053         std::string normaliseString( std::string const& str ) const;
5054         CaseSensitive::Choice m_caseSensitivity;
5055         WildcardPosition m_wildcard = NoWildcard;
5056         std::string m_pattern;
5057     };
5058 }
5059 
5060 // end catch_wildcard_pattern.h
5061 #include <string>
5062 #include <vector>
5063 #include <memory>
5064 
5065 namespace Catch {
5066 
5067     struct IConfig;
5068 
5069     class TestSpec {
5070         class Pattern {
5071         public:
5072             explicit Pattern( std::string const& name );
5073             virtual ~Pattern();
5074             virtual bool matches( TestCaseInfo const& testCase ) const = 0;
5075             std::string const& name() const;
5076         private:
5077             std::string const m_name;
5078         };
5079         using PatternPtr = std::shared_ptr<Pattern>;
5080 
5081         class NamePattern : public Pattern {
5082         public:
5083             explicit NamePattern( std::string const& name, std::string const& filterString );
5084             bool matches( TestCaseInfo const& testCase ) const override;
5085         private:
5086             WildcardPattern m_wildcardPattern;
5087         };
5088 
5089         class TagPattern : public Pattern {
5090         public:
5091             explicit TagPattern( std::string const& tag, std::string const& filterString );
5092             bool matches( TestCaseInfo const& testCase ) const override;
5093         private:
5094             std::string m_tag;
5095         };
5096 
5097         class ExcludedPattern : public Pattern {
5098         public:
5099             explicit ExcludedPattern( PatternPtr const& underlyingPattern );
5100             bool matches( TestCaseInfo const& testCase ) const override;
5101         private:
5102             PatternPtr m_underlyingPattern;
5103         };
5104 
5105         struct Filter {
5106             std::vector<PatternPtr> m_patterns;
5107 
5108             bool matches( TestCaseInfo const& testCase ) const;
5109             std::string name() const;
5110         };
5111 
5112     public:
5113         struct FilterMatch {
5114             std::string name;
5115             std::vector<TestCase const*> tests;
5116         };
5117         using Matches = std::vector<FilterMatch>;
5118         using vectorStrings = std::vector<std::string>;
5119 
5120         bool hasFilters() const;
5121         bool matches( TestCaseInfo const& testCase ) const;
5122         Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const;
5123         const vectorStrings & getInvalidArgs() const;
5124 
5125     private:
5126         std::vector<Filter> m_filters;
5127         std::vector<std::string> m_invalidArgs;
5128         friend class TestSpecParser;
5129     };
5130 }
5131 
5132 #ifdef __clang__
5133 #pragma clang diagnostic pop
5134 #endif
5135 
5136 // end catch_test_spec.h
5137 // start catch_interfaces_tag_alias_registry.h
5138 
5139 #include <string>
5140 
5141 namespace Catch {
5142 
5143     struct TagAlias;
5144 
5145     struct ITagAliasRegistry {
5146         virtual ~ITagAliasRegistry();
5147         // Nullptr if not present
5148         virtual TagAlias const* find( std::string const& alias ) const = 0;
5149         virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
5150 
5151         static ITagAliasRegistry const& get();
5152     };
5153 
5154 } // end namespace Catch
5155 
5156 // end catch_interfaces_tag_alias_registry.h
5157 namespace Catch {
5158 
5159     class TestSpecParser {
5160         enum Mode{ None, Name, QuotedName, Tag, EscapedName };
5161         Mode m_mode = None;
5162         Mode lastMode = None;
5163         bool m_exclusion = false;
5164         std::size_t m_pos = 0;
5165         std::size_t m_realPatternPos = 0;
5166         std::string m_arg;
5167         std::string m_substring;
5168         std::string m_patternName;
5169         std::vector<std::size_t> m_escapeChars;
5170         TestSpec::Filter m_currentFilter;
5171         TestSpec m_testSpec;
5172         ITagAliasRegistry const* m_tagAliases = nullptr;
5173 
5174     public:
5175         TestSpecParser( ITagAliasRegistry const& tagAliases );
5176 
5177         TestSpecParser& parse( std::string const& arg );
5178         TestSpec testSpec();
5179 
5180     private:
5181         bool visitChar( char c );
5182         void startNewMode( Mode mode );
5183         bool processNoneChar( char c );
5184         void processNameChar( char c );
5185         bool processOtherChar( char c );
5186         void endMode();
5187         void escape();
5188         bool isControlChar( char c ) const;
5189         void saveLastMode();
5190         void revertBackToLastMode();
5191         void addFilter();
5192         bool separate();
5193 
5194         // Handles common preprocessing of the pattern for name/tag patterns
5195         std::string preprocessPattern();
5196         // Adds the current pattern as a test name
5197         void addNamePattern();
5198         // Adds the current pattern as a tag
5199         void addTagPattern();
5200 
addCharToPattern(char c)5201         inline void addCharToPattern(char c) {
5202             m_substring += c;
5203             m_patternName += c;
5204             m_realPatternPos++;
5205         }
5206 
5207     };
5208     TestSpec parseTestSpec( std::string const& arg );
5209 
5210 } // namespace Catch
5211 
5212 #ifdef __clang__
5213 #pragma clang diagnostic pop
5214 #endif
5215 
5216 // end catch_test_spec_parser.h
5217 // Libstdc++ doesn't like incomplete classes for unique_ptr
5218 
5219 #include <memory>
5220 #include <vector>
5221 #include <string>
5222 
5223 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
5224 #define CATCH_CONFIG_CONSOLE_WIDTH 80
5225 #endif
5226 
5227 namespace Catch {
5228 
5229     struct IStream;
5230 
5231     struct ConfigData {
5232         bool listTests = false;
5233         bool listTags = false;
5234         bool listReporters = false;
5235         bool listTestNamesOnly = false;
5236 
5237         bool showSuccessfulTests = false;
5238         bool shouldDebugBreak = false;
5239         bool noThrow = false;
5240         bool showHelp = false;
5241         bool showInvisibles = false;
5242         bool filenamesAsTags = false;
5243         bool libIdentify = false;
5244 
5245         int abortAfter = -1;
5246         unsigned int rngSeed = 0;
5247 
5248         bool benchmarkNoAnalysis = false;
5249         unsigned int benchmarkSamples = 100;
5250         double benchmarkConfidenceInterval = 0.95;
5251         unsigned int benchmarkResamples = 100000;
5252         std::chrono::milliseconds::rep benchmarkWarmupTime = 100;
5253 
5254         Verbosity verbosity = Verbosity::Normal;
5255         WarnAbout::What warnings = WarnAbout::Nothing;
5256         ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
5257         RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
5258         UseColour::YesOrNo useColour = UseColour::Auto;
5259         WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
5260 
5261         std::string outputFilename;
5262         std::string name;
5263         std::string processName;
5264 #ifndef CATCH_CONFIG_DEFAULT_REPORTER
5265 #define CATCH_CONFIG_DEFAULT_REPORTER "console"
5266 #endif
5267         std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
5268 #undef CATCH_CONFIG_DEFAULT_REPORTER
5269 
5270         std::vector<std::string> testsOrTags;
5271         std::vector<std::string> sectionsToRun;
5272     };
5273 
5274     class Config : public IConfig {
5275     public:
5276 
5277         Config() = default;
5278         Config( ConfigData const& data );
5279         virtual ~Config() = default;
5280 
5281         std::string const& getFilename() const;
5282 
5283         bool listTests() const;
5284         bool listTestNamesOnly() const;
5285         bool listTags() const;
5286         bool listReporters() const;
5287 
5288         std::string getProcessName() const;
5289         std::string const& getReporterName() const;
5290 
5291         std::vector<std::string> const& getTestsOrTags() const override;
5292         std::vector<std::string> const& getSectionsToRun() const override;
5293 
5294         TestSpec const& testSpec() const override;
5295         bool hasTestFilters() const override;
5296 
5297         bool showHelp() const;
5298 
5299         // IConfig interface
5300         bool allowThrows() const override;
5301         std::ostream& stream() const override;
5302         std::string name() const override;
5303         bool includeSuccessfulResults() const override;
5304         bool warnAboutMissingAssertions() const override;
5305         bool warnAboutNoTests() const override;
5306         ShowDurations::OrNot showDurations() const override;
5307         RunTests::InWhatOrder runOrder() const override;
5308         unsigned int rngSeed() const override;
5309         UseColour::YesOrNo useColour() const override;
5310         bool shouldDebugBreak() const override;
5311         int abortAfter() const override;
5312         bool showInvisibles() const override;
5313         Verbosity verbosity() const override;
5314         bool benchmarkNoAnalysis() const override;
5315         int benchmarkSamples() const override;
5316         double benchmarkConfidenceInterval() const override;
5317         unsigned int benchmarkResamples() const override;
5318         std::chrono::milliseconds benchmarkWarmupTime() const override;
5319 
5320     private:
5321 
5322         IStream const* openStream();
5323         ConfigData m_data;
5324 
5325         std::unique_ptr<IStream const> m_stream;
5326         TestSpec m_testSpec;
5327         bool m_hasTestFilters = false;
5328     };
5329 
5330 } // end namespace Catch
5331 
5332 // end catch_config.hpp
5333 // start catch_assertionresult.h
5334 
5335 #include <string>
5336 
5337 namespace Catch {
5338 
5339     struct AssertionResultData
5340     {
5341         AssertionResultData() = delete;
5342 
5343         AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
5344 
5345         std::string message;
5346         mutable std::string reconstructedExpression;
5347         LazyExpression lazyExpression;
5348         ResultWas::OfType resultType;
5349 
5350         std::string reconstructExpression() const;
5351     };
5352 
5353     class AssertionResult {
5354     public:
5355         AssertionResult() = delete;
5356         AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
5357 
5358         bool isOk() const;
5359         bool succeeded() const;
5360         ResultWas::OfType getResultType() const;
5361         bool hasExpression() const;
5362         bool hasMessage() const;
5363         std::string getExpression() const;
5364         std::string getExpressionInMacro() const;
5365         bool hasExpandedExpression() const;
5366         std::string getExpandedExpression() const;
5367         std::string getMessage() const;
5368         SourceLineInfo getSourceInfo() const;
5369         StringRef getTestMacroName() const;
5370 
5371     //protected:
5372         AssertionInfo m_info;
5373         AssertionResultData m_resultData;
5374     };
5375 
5376 } // end namespace Catch
5377 
5378 // end catch_assertionresult.h
5379 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5380 // start catch_estimate.hpp
5381 
5382  // Statistics estimates
5383 
5384 
5385 namespace Catch {
5386     namespace Benchmark {
5387         template <typename Duration>
5388         struct Estimate {
5389             Duration point;
5390             Duration lower_bound;
5391             Duration upper_bound;
5392             double confidence_interval;
5393 
5394             template <typename Duration2>
operator Estimate<Duration2>Catch::Benchmark::Estimate5395             operator Estimate<Duration2>() const {
5396                 return { point, lower_bound, upper_bound, confidence_interval };
5397             }
5398         };
5399     } // namespace Benchmark
5400 } // namespace Catch
5401 
5402 // end catch_estimate.hpp
5403 // start catch_outlier_classification.hpp
5404 
5405 // Outlier information
5406 
5407 namespace Catch {
5408     namespace Benchmark {
5409         struct OutlierClassification {
5410             int samples_seen = 0;
5411             int low_severe = 0;     // more than 3 times IQR below Q1
5412             int low_mild = 0;       // 1.5 to 3 times IQR below Q1
5413             int high_mild = 0;      // 1.5 to 3 times IQR above Q3
5414             int high_severe = 0;    // more than 3 times IQR above Q3
5415 
totalCatch::Benchmark::OutlierClassification5416             int total() const {
5417                 return low_severe + low_mild + high_mild + high_severe;
5418             }
5419         };
5420     } // namespace Benchmark
5421 } // namespace Catch
5422 
5423 // end catch_outlier_classification.hpp
5424 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
5425 
5426 #include <string>
5427 #include <iosfwd>
5428 #include <map>
5429 #include <set>
5430 #include <memory>
5431 #include <algorithm>
5432 
5433 namespace Catch {
5434 
5435     struct ReporterConfig {
5436         explicit ReporterConfig( IConfigPtr const& _fullConfig );
5437 
5438         ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream );
5439 
5440         std::ostream& stream() const;
5441         IConfigPtr fullConfig() const;
5442 
5443     private:
5444         std::ostream* m_stream;
5445         IConfigPtr m_fullConfig;
5446     };
5447 
5448     struct ReporterPreferences {
5449         bool shouldRedirectStdOut = false;
5450         bool shouldReportAllAssertions = false;
5451     };
5452 
5453     template<typename T>
5454     struct LazyStat : Option<T> {
operator =Catch::LazyStat5455         LazyStat& operator=( T const& _value ) {
5456             Option<T>::operator=( _value );
5457             used = false;
5458             return *this;
5459         }
resetCatch::LazyStat5460         void reset() {
5461             Option<T>::reset();
5462             used = false;
5463         }
5464         bool used = false;
5465     };
5466 
5467     struct TestRunInfo {
5468         TestRunInfo( std::string const& _name );
5469         std::string name;
5470     };
5471     struct GroupInfo {
5472         GroupInfo(  std::string const& _name,
5473                     std::size_t _groupIndex,
5474                     std::size_t _groupsCount );
5475 
5476         std::string name;
5477         std::size_t groupIndex;
5478         std::size_t groupsCounts;
5479     };
5480 
5481     struct AssertionStats {
5482         AssertionStats( AssertionResult const& _assertionResult,
5483                         std::vector<MessageInfo> const& _infoMessages,
5484                         Totals const& _totals );
5485 
5486         AssertionStats( AssertionStats const& )              = default;
5487         AssertionStats( AssertionStats && )                  = default;
5488         AssertionStats& operator = ( AssertionStats const& ) = delete;
5489         AssertionStats& operator = ( AssertionStats && )     = delete;
5490         virtual ~AssertionStats();
5491 
5492         AssertionResult assertionResult;
5493         std::vector<MessageInfo> infoMessages;
5494         Totals totals;
5495     };
5496 
5497     struct SectionStats {
5498         SectionStats(   SectionInfo const& _sectionInfo,
5499                         Counts const& _assertions,
5500                         double _durationInSeconds,
5501                         bool _missingAssertions );
5502         SectionStats( SectionStats const& )              = default;
5503         SectionStats( SectionStats && )                  = default;
5504         SectionStats& operator = ( SectionStats const& ) = default;
5505         SectionStats& operator = ( SectionStats && )     = default;
5506         virtual ~SectionStats();
5507 
5508         SectionInfo sectionInfo;
5509         Counts assertions;
5510         double durationInSeconds;
5511         bool missingAssertions;
5512     };
5513 
5514     struct TestCaseStats {
5515         TestCaseStats(  TestCaseInfo const& _testInfo,
5516                         Totals const& _totals,
5517                         std::string const& _stdOut,
5518                         std::string const& _stdErr,
5519                         bool _aborting );
5520 
5521         TestCaseStats( TestCaseStats const& )              = default;
5522         TestCaseStats( TestCaseStats && )                  = default;
5523         TestCaseStats& operator = ( TestCaseStats const& ) = default;
5524         TestCaseStats& operator = ( TestCaseStats && )     = default;
5525         virtual ~TestCaseStats();
5526 
5527         TestCaseInfo testInfo;
5528         Totals totals;
5529         std::string stdOut;
5530         std::string stdErr;
5531         bool aborting;
5532     };
5533 
5534     struct TestGroupStats {
5535         TestGroupStats( GroupInfo const& _groupInfo,
5536                         Totals const& _totals,
5537                         bool _aborting );
5538         TestGroupStats( GroupInfo const& _groupInfo );
5539 
5540         TestGroupStats( TestGroupStats const& )              = default;
5541         TestGroupStats( TestGroupStats && )                  = default;
5542         TestGroupStats& operator = ( TestGroupStats const& ) = default;
5543         TestGroupStats& operator = ( TestGroupStats && )     = default;
5544         virtual ~TestGroupStats();
5545 
5546         GroupInfo groupInfo;
5547         Totals totals;
5548         bool aborting;
5549     };
5550 
5551     struct TestRunStats {
5552         TestRunStats(   TestRunInfo const& _runInfo,
5553                         Totals const& _totals,
5554                         bool _aborting );
5555 
5556         TestRunStats( TestRunStats const& )              = default;
5557         TestRunStats( TestRunStats && )                  = default;
5558         TestRunStats& operator = ( TestRunStats const& ) = default;
5559         TestRunStats& operator = ( TestRunStats && )     = default;
5560         virtual ~TestRunStats();
5561 
5562         TestRunInfo runInfo;
5563         Totals totals;
5564         bool aborting;
5565     };
5566 
5567 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
5568     struct BenchmarkInfo {
5569         std::string name;
5570         double estimatedDuration;
5571         int iterations;
5572         int samples;
5573         unsigned int resamples;
5574         double clockResolution;
5575         double clockCost;
5576     };
5577 
5578     template <class Duration>
5579     struct BenchmarkStats {
5580         BenchmarkInfo info;
5581 
5582         std::vector<Duration> samples;
5583         Benchmark::Estimate<Duration> mean;
5584         Benchmark::Estimate<Duration> standardDeviation;
5585         Benchmark::OutlierClassification outliers;
5586         double outlierVariance;
5587 
5588         template <typename Duration2>
operator BenchmarkStats<Duration2>Catch::BenchmarkStats5589         operator BenchmarkStats<Duration2>() const {
5590             std::vector<Duration2> samples2;
5591             samples2.reserve(samples.size());
5592             std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); });
5593             return {
5594                 info,
5595                 std::move(samples2),
5596                 mean,
5597                 standardDeviation,
5598                 outliers,
5599                 outlierVariance,
5600             };
5601         }
5602     };
5603 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
5604 
5605     struct IStreamingReporter {
5606         virtual ~IStreamingReporter() = default;
5607 
5608         // Implementing class must also provide the following static methods:
5609         // static std::string getDescription();
5610         // static std::set<Verbosity> getSupportedVerbosities()
5611 
5612         virtual ReporterPreferences getPreferences() const = 0;
5613 
5614         virtual void noMatchingTestCases( std::string const& spec ) = 0;
5615 
reportInvalidArgumentsCatch::IStreamingReporter5616         virtual void reportInvalidArguments(std::string const&) {}
5617 
5618         virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5619         virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5620 
5621         virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5622         virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5623 
5624 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
benchmarkPreparingCatch::IStreamingReporter5625         virtual void benchmarkPreparing( std::string const& ) {}
benchmarkStartingCatch::IStreamingReporter5626         virtual void benchmarkStarting( BenchmarkInfo const& ) {}
benchmarkEndedCatch::IStreamingReporter5627         virtual void benchmarkEnded( BenchmarkStats<> const& ) {}
benchmarkFailedCatch::IStreamingReporter5628         virtual void benchmarkFailed( std::string const& ) {}
5629 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
5630 
5631         virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5632 
5633         // The return value indicates if the messages buffer should be cleared:
5634         virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
5635 
5636         virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5637         virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5638         virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5639         virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
5640 
5641         virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
5642 
5643         // Default empty implementation provided
5644         virtual void fatalErrorEncountered( StringRef name );
5645 
5646         virtual bool isMulti() const;
5647     };
5648     using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
5649 
5650     struct IReporterFactory {
5651         virtual ~IReporterFactory();
5652         virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0;
5653         virtual std::string getDescription() const = 0;
5654     };
5655     using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
5656 
5657     struct IReporterRegistry {
5658         using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
5659         using Listeners = std::vector<IReporterFactoryPtr>;
5660 
5661         virtual ~IReporterRegistry();
5662         virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0;
5663         virtual FactoryMap const& getFactories() const = 0;
5664         virtual Listeners const& getListeners() const = 0;
5665     };
5666 
5667 } // end namespace Catch
5668 
5669 // end catch_interfaces_reporter.h
5670 #include <algorithm>
5671 #include <cstring>
5672 #include <cfloat>
5673 #include <cstdio>
5674 #include <cassert>
5675 #include <memory>
5676 #include <ostream>
5677 
5678 namespace Catch {
5679     void prepareExpandedExpression(AssertionResult& result);
5680 
5681     // Returns double formatted as %.3f (format expected on output)
5682     std::string getFormattedDuration( double duration );
5683 
5684     std::string serializeFilters( std::vector<std::string> const& container );
5685 
5686     template<typename DerivedT>
5687     struct StreamingReporterBase : IStreamingReporter {
5688 
StreamingReporterBaseCatch::StreamingReporterBase5689         StreamingReporterBase( ReporterConfig const& _config )
5690         :   m_config( _config.fullConfig() ),
5691             stream( _config.stream() )
5692         {
5693             m_reporterPrefs.shouldRedirectStdOut = false;
5694             if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
5695                 CATCH_ERROR( "Verbosity level not supported by this reporter" );
5696         }
5697 
getPreferencesCatch::StreamingReporterBase5698         ReporterPreferences getPreferences() const override {
5699             return m_reporterPrefs;
5700         }
5701 
getSupportedVerbositiesCatch::StreamingReporterBase5702         static std::set<Verbosity> getSupportedVerbosities() {
5703             return { Verbosity::Normal };
5704         }
5705 
5706         ~StreamingReporterBase() override = default;
5707 
noMatchingTestCasesCatch::StreamingReporterBase5708         void noMatchingTestCases(std::string const&) override {}
5709 
reportInvalidArgumentsCatch::StreamingReporterBase5710         void reportInvalidArguments(std::string const&) override {}
5711 
testRunStartingCatch::StreamingReporterBase5712         void testRunStarting(TestRunInfo const& _testRunInfo) override {
5713             currentTestRunInfo = _testRunInfo;
5714         }
5715 
testGroupStartingCatch::StreamingReporterBase5716         void testGroupStarting(GroupInfo const& _groupInfo) override {
5717             currentGroupInfo = _groupInfo;
5718         }
5719 
testCaseStartingCatch::StreamingReporterBase5720         void testCaseStarting(TestCaseInfo const& _testInfo) override  {
5721             currentTestCaseInfo = _testInfo;
5722         }
sectionStartingCatch::StreamingReporterBase5723         void sectionStarting(SectionInfo const& _sectionInfo) override {
5724             m_sectionStack.push_back(_sectionInfo);
5725         }
5726 
sectionEndedCatch::StreamingReporterBase5727         void sectionEnded(SectionStats const& /* _sectionStats */) override {
5728             m_sectionStack.pop_back();
5729         }
testCaseEndedCatch::StreamingReporterBase5730         void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
5731             currentTestCaseInfo.reset();
5732         }
testGroupEndedCatch::StreamingReporterBase5733         void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override {
5734             currentGroupInfo.reset();
5735         }
testRunEndedCatch::StreamingReporterBase5736         void testRunEnded(TestRunStats const& /* _testRunStats */) override {
5737             currentTestCaseInfo.reset();
5738             currentGroupInfo.reset();
5739             currentTestRunInfo.reset();
5740         }
5741 
skipTestCatch::StreamingReporterBase5742         void skipTest(TestCaseInfo const&) override {
5743             // Don't do anything with this by default.
5744             // It can optionally be overridden in the derived class.
5745         }
5746 
5747         IConfigPtr m_config;
5748         std::ostream& stream;
5749 
5750         LazyStat<TestRunInfo> currentTestRunInfo;
5751         LazyStat<GroupInfo> currentGroupInfo;
5752         LazyStat<TestCaseInfo> currentTestCaseInfo;
5753 
5754         std::vector<SectionInfo> m_sectionStack;
5755         ReporterPreferences m_reporterPrefs;
5756     };
5757 
5758     template<typename DerivedT>
5759     struct CumulativeReporterBase : IStreamingReporter {
5760         template<typename T, typename ChildNodeT>
5761         struct Node {
NodeCatch::CumulativeReporterBase::Node5762             explicit Node( T const& _value ) : value( _value ) {}
~NodeCatch::CumulativeReporterBase::Node5763             virtual ~Node() {}
5764 
5765             using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
5766             T value;
5767             ChildNodes children;
5768         };
5769         struct SectionNode {
SectionNodeCatch::CumulativeReporterBase::SectionNode5770             explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
5771             virtual ~SectionNode() = default;
5772 
operator ==Catch::CumulativeReporterBase::SectionNode5773             bool operator == (SectionNode const& other) const {
5774                 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
5775             }
operator ==Catch::CumulativeReporterBase::SectionNode5776             bool operator == (std::shared_ptr<SectionNode> const& other) const {
5777                 return operator==(*other);
5778             }
5779 
5780             SectionStats stats;
5781             using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
5782             using Assertions = std::vector<AssertionStats>;
5783             ChildSections childSections;
5784             Assertions assertions;
5785             std::string stdOut;
5786             std::string stdErr;
5787         };
5788 
5789         struct BySectionInfo {
BySectionInfoCatch::CumulativeReporterBase::BySectionInfo5790             BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
BySectionInfoCatch::CumulativeReporterBase::BySectionInfo5791             BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
operator ()Catch::CumulativeReporterBase::BySectionInfo5792             bool operator() (std::shared_ptr<SectionNode> const& node) const {
5793                 return ((node->stats.sectionInfo.name == m_other.name) &&
5794                         (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
5795             }
5796             void operator=(BySectionInfo const&) = delete;
5797 
5798         private:
5799             SectionInfo const& m_other;
5800         };
5801 
5802         using TestCaseNode = Node<TestCaseStats, SectionNode>;
5803         using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
5804         using TestRunNode = Node<TestRunStats, TestGroupNode>;
5805 
CumulativeReporterBaseCatch::CumulativeReporterBase5806         CumulativeReporterBase( ReporterConfig const& _config )
5807         :   m_config( _config.fullConfig() ),
5808             stream( _config.stream() )
5809         {
5810             m_reporterPrefs.shouldRedirectStdOut = false;
5811             if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
5812                 CATCH_ERROR( "Verbosity level not supported by this reporter" );
5813         }
5814         ~CumulativeReporterBase() override = default;
5815 
getPreferencesCatch::CumulativeReporterBase5816         ReporterPreferences getPreferences() const override {
5817             return m_reporterPrefs;
5818         }
5819 
getSupportedVerbositiesCatch::CumulativeReporterBase5820         static std::set<Verbosity> getSupportedVerbosities() {
5821             return { Verbosity::Normal };
5822         }
5823 
testRunStartingCatch::CumulativeReporterBase5824         void testRunStarting( TestRunInfo const& ) override {}
testGroupStartingCatch::CumulativeReporterBase5825         void testGroupStarting( GroupInfo const& ) override {}
5826 
testCaseStartingCatch::CumulativeReporterBase5827         void testCaseStarting( TestCaseInfo const& ) override {}
5828 
sectionStartingCatch::CumulativeReporterBase5829         void sectionStarting( SectionInfo const& sectionInfo ) override {
5830             SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
5831             std::shared_ptr<SectionNode> node;
5832             if( m_sectionStack.empty() ) {
5833                 if( !m_rootSection )
5834                     m_rootSection = std::make_shared<SectionNode>( incompleteStats );
5835                 node = m_rootSection;
5836             }
5837             else {
5838                 SectionNode& parentNode = *m_sectionStack.back();
5839                 auto it =
5840                     std::find_if(   parentNode.childSections.begin(),
5841                                     parentNode.childSections.end(),
5842                                     BySectionInfo( sectionInfo ) );
5843                 if( it == parentNode.childSections.end() ) {
5844                     node = std::make_shared<SectionNode>( incompleteStats );
5845                     parentNode.childSections.push_back( node );
5846                 }
5847                 else
5848                     node = *it;
5849             }
5850             m_sectionStack.push_back( node );
5851             m_deepestSection = std::move(node);
5852         }
5853 
assertionStartingCatch::CumulativeReporterBase5854         void assertionStarting(AssertionInfo const&) override {}
5855 
assertionEndedCatch::CumulativeReporterBase5856         bool assertionEnded(AssertionStats const& assertionStats) override {
5857             assert(!m_sectionStack.empty());
5858             // AssertionResult holds a pointer to a temporary DecomposedExpression,
5859             // which getExpandedExpression() calls to build the expression string.
5860             // Our section stack copy of the assertionResult will likely outlive the
5861             // temporary, so it must be expanded or discarded now to avoid calling
5862             // a destroyed object later.
5863             prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );
5864             SectionNode& sectionNode = *m_sectionStack.back();
5865             sectionNode.assertions.push_back(assertionStats);
5866             return true;
5867         }
sectionEndedCatch::CumulativeReporterBase5868         void sectionEnded(SectionStats const& sectionStats) override {
5869             assert(!m_sectionStack.empty());
5870             SectionNode& node = *m_sectionStack.back();
5871             node.stats = sectionStats;
5872             m_sectionStack.pop_back();
5873         }
testCaseEndedCatch::CumulativeReporterBase5874         void testCaseEnded(TestCaseStats const& testCaseStats) override {
5875             auto node = std::make_shared<TestCaseNode>(testCaseStats);
5876             assert(m_sectionStack.size() == 0);
5877             node->children.push_back(m_rootSection);
5878             m_testCases.push_back(node);
5879             m_rootSection.reset();
5880 
5881             assert(m_deepestSection);
5882             m_deepestSection->stdOut = testCaseStats.stdOut;
5883             m_deepestSection->stdErr = testCaseStats.stdErr;
5884         }
testGroupEndedCatch::CumulativeReporterBase5885         void testGroupEnded(TestGroupStats const& testGroupStats) override {
5886             auto node = std::make_shared<TestGroupNode>(testGroupStats);
5887             node->children.swap(m_testCases);
5888             m_testGroups.push_back(node);
5889         }
testRunEndedCatch::CumulativeReporterBase5890         void testRunEnded(TestRunStats const& testRunStats) override {
5891             auto node = std::make_shared<TestRunNode>(testRunStats);
5892             node->children.swap(m_testGroups);
5893             m_testRuns.push_back(node);
5894             testRunEndedCumulative();
5895         }
5896         virtual void testRunEndedCumulative() = 0;
5897 
skipTestCatch::CumulativeReporterBase5898         void skipTest(TestCaseInfo const&) override {}
5899 
5900         IConfigPtr m_config;
5901         std::ostream& stream;
5902         std::vector<AssertionStats> m_assertions;
5903         std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
5904         std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
5905         std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
5906 
5907         std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
5908 
5909         std::shared_ptr<SectionNode> m_rootSection;
5910         std::shared_ptr<SectionNode> m_deepestSection;
5911         std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
5912         ReporterPreferences m_reporterPrefs;
5913     };
5914 
5915     template<char C>
getLineOfChars()5916     char const* getLineOfChars() {
5917         static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
5918         if( !*line ) {
5919             std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
5920             line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
5921         }
5922         return line;
5923     }
5924 
5925     struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
5926         TestEventListenerBase( ReporterConfig const& _config );
5927 
5928         static std::set<Verbosity> getSupportedVerbosities();
5929 
5930         void assertionStarting(AssertionInfo const&) override;
5931         bool assertionEnded(AssertionStats const&) override;
5932     };
5933 
5934 } // end namespace Catch
5935 
5936 // end catch_reporter_bases.hpp
5937 // start catch_console_colour.h
5938 
5939 namespace Catch {
5940 
5941     struct Colour {
5942         enum Code {
5943             None = 0,
5944 
5945             White,
5946             Red,
5947             Green,
5948             Blue,
5949             Cyan,
5950             Yellow,
5951             Grey,
5952 
5953             Bright = 0x10,
5954 
5955             BrightRed = Bright | Red,
5956             BrightGreen = Bright | Green,
5957             LightGrey = Bright | Grey,
5958             BrightWhite = Bright | White,
5959             BrightYellow = Bright | Yellow,
5960 
5961             // By intention
5962             FileName = LightGrey,
5963             Warning = BrightYellow,
5964             ResultError = BrightRed,
5965             ResultSuccess = BrightGreen,
5966             ResultExpectedFailure = Warning,
5967 
5968             Error = BrightRed,
5969             Success = Green,
5970 
5971             OriginalExpression = Cyan,
5972             ReconstructedExpression = BrightYellow,
5973 
5974             SecondaryText = LightGrey,
5975             Headers = White
5976         };
5977 
5978         // Use constructed object for RAII guard
5979         Colour( Code _colourCode );
5980         Colour( Colour&& other ) noexcept;
5981         Colour& operator=( Colour&& other ) noexcept;
5982         ~Colour();
5983 
5984         // Use static method for one-shot changes
5985         static void use( Code _colourCode );
5986 
5987     private:
5988         bool m_moved = false;
5989     };
5990 
5991     std::ostream& operator << ( std::ostream& os, Colour const& );
5992 
5993 } // end namespace Catch
5994 
5995 // end catch_console_colour.h
5996 // start catch_reporter_registrars.hpp
5997 
5998 
5999 namespace Catch {
6000 
6001     template<typename T>
6002     class ReporterRegistrar {
6003 
6004         class ReporterFactory : public IReporterFactory {
6005 
create(ReporterConfig const & config) const6006             IStreamingReporterPtr create( ReporterConfig const& config ) const override {
6007                 return std::unique_ptr<T>( new T( config ) );
6008             }
6009 
getDescription() const6010             std::string getDescription() const override {
6011                 return T::getDescription();
6012             }
6013         };
6014 
6015     public:
6016 
ReporterRegistrar(std::string const & name)6017         explicit ReporterRegistrar( std::string const& name ) {
6018             getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() );
6019         }
6020     };
6021 
6022     template<typename T>
6023     class ListenerRegistrar {
6024 
6025         class ListenerFactory : public IReporterFactory {
6026 
create(ReporterConfig const & config) const6027             IStreamingReporterPtr create( ReporterConfig const& config ) const override {
6028                 return std::unique_ptr<T>( new T( config ) );
6029             }
getDescription() const6030             std::string getDescription() const override {
6031                 return std::string();
6032             }
6033         };
6034 
6035     public:
6036 
ListenerRegistrar()6037         ListenerRegistrar() {
6038             getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() );
6039         }
6040     };
6041 }
6042 
6043 #if !defined(CATCH_CONFIG_DISABLE)
6044 
6045 #define CATCH_REGISTER_REPORTER( name, reporterType ) \
6046     CATCH_INTERNAL_START_WARNINGS_SUPPRESSION         \
6047     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS          \
6048     namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
6049     CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
6050 
6051 #define CATCH_REGISTER_LISTENER( listenerType ) \
6052     CATCH_INTERNAL_START_WARNINGS_SUPPRESSION   \
6053     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS    \
6054     namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
6055     CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
6056 #else // CATCH_CONFIG_DISABLE
6057 
6058 #define CATCH_REGISTER_REPORTER(name, reporterType)
6059 #define CATCH_REGISTER_LISTENER(listenerType)
6060 
6061 #endif // CATCH_CONFIG_DISABLE
6062 
6063 // end catch_reporter_registrars.hpp
6064 // Allow users to base their work off existing reporters
6065 // start catch_reporter_compact.h
6066 
6067 namespace Catch {
6068 
6069     struct CompactReporter : StreamingReporterBase<CompactReporter> {
6070 
6071         using StreamingReporterBase::StreamingReporterBase;
6072 
6073         ~CompactReporter() override;
6074 
6075         static std::string getDescription();
6076 
6077         ReporterPreferences getPreferences() const override;
6078 
6079         void noMatchingTestCases(std::string const& spec) override;
6080 
6081         void assertionStarting(AssertionInfo const&) override;
6082 
6083         bool assertionEnded(AssertionStats const& _assertionStats) override;
6084 
6085         void sectionEnded(SectionStats const& _sectionStats) override;
6086 
6087         void testRunEnded(TestRunStats const& _testRunStats) override;
6088 
6089     };
6090 
6091 } // end namespace Catch
6092 
6093 // end catch_reporter_compact.h
6094 // start catch_reporter_console.h
6095 
6096 #if defined(_MSC_VER)
6097 #pragma warning(push)
6098 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
6099                               // Note that 4062 (not all labels are handled
6100                               // and default is missing) is enabled
6101 #endif
6102 
6103 namespace Catch {
6104     // Fwd decls
6105     struct SummaryColumn;
6106     class TablePrinter;
6107 
6108     struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
6109         std::unique_ptr<TablePrinter> m_tablePrinter;
6110 
6111         ConsoleReporter(ReporterConfig const& config);
6112         ~ConsoleReporter() override;
6113         static std::string getDescription();
6114 
6115         void noMatchingTestCases(std::string const& spec) override;
6116 
6117         void reportInvalidArguments(std::string const&arg) override;
6118 
6119         void assertionStarting(AssertionInfo const&) override;
6120 
6121         bool assertionEnded(AssertionStats const& _assertionStats) override;
6122 
6123         void sectionStarting(SectionInfo const& _sectionInfo) override;
6124         void sectionEnded(SectionStats const& _sectionStats) override;
6125 
6126 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
6127         void benchmarkPreparing(std::string const& name) override;
6128         void benchmarkStarting(BenchmarkInfo const& info) override;
6129         void benchmarkEnded(BenchmarkStats<> const& stats) override;
6130         void benchmarkFailed(std::string const& error) override;
6131 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
6132 
6133         void testCaseEnded(TestCaseStats const& _testCaseStats) override;
6134         void testGroupEnded(TestGroupStats const& _testGroupStats) override;
6135         void testRunEnded(TestRunStats const& _testRunStats) override;
6136         void testRunStarting(TestRunInfo const& _testRunInfo) override;
6137     private:
6138 
6139         void lazyPrint();
6140 
6141         void lazyPrintWithoutClosingBenchmarkTable();
6142         void lazyPrintRunInfo();
6143         void lazyPrintGroupInfo();
6144         void printTestCaseAndSectionHeader();
6145 
6146         void printClosedHeader(std::string const& _name);
6147         void printOpenHeader(std::string const& _name);
6148 
6149         // if string has a : in first line will set indent to follow it on
6150         // subsequent lines
6151         void printHeaderString(std::string const& _string, std::size_t indent = 0);
6152 
6153         void printTotals(Totals const& totals);
6154         void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row);
6155 
6156         void printTotalsDivider(Totals const& totals);
6157         void printSummaryDivider();
6158         void printTestFilters();
6159 
6160     private:
6161         bool m_headerPrinted = false;
6162     };
6163 
6164 } // end namespace Catch
6165 
6166 #if defined(_MSC_VER)
6167 #pragma warning(pop)
6168 #endif
6169 
6170 // end catch_reporter_console.h
6171 // start catch_reporter_junit.h
6172 
6173 // start catch_xmlwriter.h
6174 
6175 #include <vector>
6176 
6177 namespace Catch {
6178     enum class XmlFormatting {
6179         None = 0x00,
6180         Indent = 0x01,
6181         Newline = 0x02,
6182     };
6183 
6184     XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs);
6185     XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs);
6186 
6187     class XmlEncode {
6188     public:
6189         enum ForWhat { ForTextNodes, ForAttributes };
6190 
6191         XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes );
6192 
6193         void encodeTo( std::ostream& os ) const;
6194 
6195         friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
6196 
6197     private:
6198         std::string m_str;
6199         ForWhat m_forWhat;
6200     };
6201 
6202     class XmlWriter {
6203     public:
6204 
6205         class ScopedElement {
6206         public:
6207             ScopedElement( XmlWriter* writer, XmlFormatting fmt );
6208 
6209             ScopedElement( ScopedElement&& other ) noexcept;
6210             ScopedElement& operator=( ScopedElement&& other ) noexcept;
6211 
6212             ~ScopedElement();
6213 
6214             ScopedElement& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent );
6215 
6216             template<typename T>
writeAttribute(std::string const & name,T const & attribute)6217             ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
6218                 m_writer->writeAttribute( name, attribute );
6219                 return *this;
6220             }
6221 
6222         private:
6223             mutable XmlWriter* m_writer = nullptr;
6224             XmlFormatting m_fmt;
6225         };
6226 
6227         XmlWriter( std::ostream& os = Catch::cout() );
6228         ~XmlWriter();
6229 
6230         XmlWriter( XmlWriter const& ) = delete;
6231         XmlWriter& operator=( XmlWriter const& ) = delete;
6232 
6233         XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6234 
6235         ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6236 
6237         XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6238 
6239         XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
6240 
6241         XmlWriter& writeAttribute( std::string const& name, bool attribute );
6242 
6243         template<typename T>
writeAttribute(std::string const & name,T const & attribute)6244         XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
6245             ReusableStringStream rss;
6246             rss << attribute;
6247             return writeAttribute( name, rss.str() );
6248         }
6249 
6250         XmlWriter& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6251 
6252         XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);
6253 
6254         void writeStylesheetRef( std::string const& url );
6255 
6256         XmlWriter& writeBlankLine();
6257 
6258         void ensureTagClosed();
6259 
6260     private:
6261 
6262         void applyFormatting(XmlFormatting fmt);
6263 
6264         void writeDeclaration();
6265 
6266         void newlineIfNecessary();
6267 
6268         bool m_tagIsOpen = false;
6269         bool m_needsNewline = false;
6270         std::vector<std::string> m_tags;
6271         std::string m_indent;
6272         std::ostream& m_os;
6273     };
6274 
6275 }
6276 
6277 // end catch_xmlwriter.h
6278 namespace Catch {
6279 
6280     class JunitReporter : public CumulativeReporterBase<JunitReporter> {
6281     public:
6282         JunitReporter(ReporterConfig const& _config);
6283 
6284         ~JunitReporter() override;
6285 
6286         static std::string getDescription();
6287 
6288         void noMatchingTestCases(std::string const& /*spec*/) override;
6289 
6290         void testRunStarting(TestRunInfo const& runInfo) override;
6291 
6292         void testGroupStarting(GroupInfo const& groupInfo) override;
6293 
6294         void testCaseStarting(TestCaseInfo const& testCaseInfo) override;
6295         bool assertionEnded(AssertionStats const& assertionStats) override;
6296 
6297         void testCaseEnded(TestCaseStats const& testCaseStats) override;
6298 
6299         void testGroupEnded(TestGroupStats const& testGroupStats) override;
6300 
6301         void testRunEndedCumulative() override;
6302 
6303         void writeGroup(TestGroupNode const& groupNode, double suiteTime);
6304 
6305         void writeTestCase(TestCaseNode const& testCaseNode);
6306 
6307         void writeSection(std::string const& className,
6308                           std::string const& rootName,
6309                           SectionNode const& sectionNode);
6310 
6311         void writeAssertions(SectionNode const& sectionNode);
6312         void writeAssertion(AssertionStats const& stats);
6313 
6314         XmlWriter xml;
6315         Timer suiteTimer;
6316         std::string stdOutForSuite;
6317         std::string stdErrForSuite;
6318         unsigned int unexpectedExceptions = 0;
6319         bool m_okToFail = false;
6320     };
6321 
6322 } // end namespace Catch
6323 
6324 // end catch_reporter_junit.h
6325 // start catch_reporter_xml.h
6326 
6327 namespace Catch {
6328     class XmlReporter : public StreamingReporterBase<XmlReporter> {
6329     public:
6330         XmlReporter(ReporterConfig const& _config);
6331 
6332         ~XmlReporter() override;
6333 
6334         static std::string getDescription();
6335 
6336         virtual std::string getStylesheetRef() const;
6337 
6338         void writeSourceInfo(SourceLineInfo const& sourceInfo);
6339 
6340     public: // StreamingReporterBase
6341 
6342         void noMatchingTestCases(std::string const& s) override;
6343 
6344         void testRunStarting(TestRunInfo const& testInfo) override;
6345 
6346         void testGroupStarting(GroupInfo const& groupInfo) override;
6347 
6348         void testCaseStarting(TestCaseInfo const& testInfo) override;
6349 
6350         void sectionStarting(SectionInfo const& sectionInfo) override;
6351 
6352         void assertionStarting(AssertionInfo const&) override;
6353 
6354         bool assertionEnded(AssertionStats const& assertionStats) override;
6355 
6356         void sectionEnded(SectionStats const& sectionStats) override;
6357 
6358         void testCaseEnded(TestCaseStats const& testCaseStats) override;
6359 
6360         void testGroupEnded(TestGroupStats const& testGroupStats) override;
6361 
6362         void testRunEnded(TestRunStats const& testRunStats) override;
6363 
6364 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
6365         void benchmarkPreparing(std::string const& name) override;
6366         void benchmarkStarting(BenchmarkInfo const&) override;
6367         void benchmarkEnded(BenchmarkStats<> const&) override;
6368         void benchmarkFailed(std::string const&) override;
6369 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
6370 
6371     private:
6372         Timer m_testCaseTimer;
6373         XmlWriter m_xml;
6374         int m_sectionDepth = 0;
6375     };
6376 
6377 } // end namespace Catch
6378 
6379 // end catch_reporter_xml.h
6380 
6381 // end catch_external_interfaces.h
6382 #endif
6383 
6384 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
6385 // start catch_benchmarking_all.hpp
6386 
6387 // A proxy header that includes all of the benchmarking headers to allow
6388 // concise include of the benchmarking features. You should prefer the
6389 // individual includes in standard use.
6390 
6391 // start catch_benchmark.hpp
6392 
6393  // Benchmark
6394 
6395 // start catch_chronometer.hpp
6396 
6397 // User-facing chronometer
6398 
6399 
6400 // start catch_clock.hpp
6401 
6402 // Clocks
6403 
6404 
6405 #include <chrono>
6406 #include <ratio>
6407 
6408 namespace Catch {
6409     namespace Benchmark {
6410         template <typename Clock>
6411         using ClockDuration = typename Clock::duration;
6412         template <typename Clock>
6413         using FloatDuration = std::chrono::duration<double, typename Clock::period>;
6414 
6415         template <typename Clock>
6416         using TimePoint = typename Clock::time_point;
6417 
6418         using default_clock = std::chrono::steady_clock;
6419 
6420         template <typename Clock>
6421         struct now {
operator ()Catch::Benchmark::now6422             TimePoint<Clock> operator()() const {
6423                 return Clock::now();
6424             }
6425         };
6426 
6427         using fp_seconds = std::chrono::duration<double, std::ratio<1>>;
6428     } // namespace Benchmark
6429 } // namespace Catch
6430 
6431 // end catch_clock.hpp
6432 // start catch_optimizer.hpp
6433 
6434  // Hinting the optimizer
6435 
6436 
6437 #if defined(_MSC_VER)
6438 #   include <atomic> // atomic_thread_fence
6439 #endif
6440 
6441 namespace Catch {
6442     namespace Benchmark {
6443 #if defined(__GNUC__) || defined(__clang__)
6444         template <typename T>
keep_memory(T * p)6445         inline void keep_memory(T* p) {
6446             asm volatile("" : : "g"(p) : "memory");
6447         }
keep_memory()6448         inline void keep_memory() {
6449             asm volatile("" : : : "memory");
6450         }
6451 
6452         namespace Detail {
optimizer_barrier()6453             inline void optimizer_barrier() { keep_memory(); }
6454         } // namespace Detail
6455 #elif defined(_MSC_VER)
6456 
6457 #pragma optimize("", off)
6458         template <typename T>
6459         inline void keep_memory(T* p) {
6460             // thanks @milleniumbug
6461             *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);
6462         }
6463         // TODO equivalent keep_memory()
6464 #pragma optimize("", on)
6465 
6466         namespace Detail {
6467             inline void optimizer_barrier() {
6468                 std::atomic_thread_fence(std::memory_order_seq_cst);
6469             }
6470         } // namespace Detail
6471 
6472 #endif
6473 
6474         template <typename T>
deoptimize_value(T && x)6475         inline void deoptimize_value(T&& x) {
6476             keep_memory(&x);
6477         }
6478 
6479         template <typename Fn, typename... Args>
invoke_deoptimized(Fn && fn,Args &&...args)6480         inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type {
6481             deoptimize_value(std::forward<Fn>(fn) (std::forward<Args...>(args...)));
6482         }
6483 
6484         template <typename Fn, typename... Args>
invoke_deoptimized(Fn && fn,Args &&...args)6485         inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type {
6486             std::forward<Fn>(fn) (std::forward<Args...>(args...));
6487         }
6488     } // namespace Benchmark
6489 } // namespace Catch
6490 
6491 // end catch_optimizer.hpp
6492 // start catch_complete_invoke.hpp
6493 
6494 // Invoke with a special case for void
6495 
6496 
6497 #include <type_traits>
6498 #include <utility>
6499 
6500 namespace Catch {
6501     namespace Benchmark {
6502         namespace Detail {
6503             template <typename T>
6504             struct CompleteType { using type = T; };
6505             template <>
6506             struct CompleteType<void> { struct type {}; };
6507 
6508             template <typename T>
6509             using CompleteType_t = typename CompleteType<T>::type;
6510 
6511             template <typename Result>
6512             struct CompleteInvoker {
6513                 template <typename Fun, typename... Args>
invokeCatch::Benchmark::Detail::CompleteInvoker6514                 static Result invoke(Fun&& fun, Args&&... args) {
6515                     return std::forward<Fun>(fun)(std::forward<Args>(args)...);
6516                 }
6517             };
6518             template <>
6519             struct CompleteInvoker<void> {
6520                 template <typename Fun, typename... Args>
invokeCatch::Benchmark::Detail::CompleteInvoker6521                 static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) {
6522                     std::forward<Fun>(fun)(std::forward<Args>(args)...);
6523                     return {};
6524                 }
6525             };
6526             template <typename Sig>
6527             using ResultOf_t = typename std::result_of<Sig>::type;
6528 
6529             // invoke and not return void :(
6530             template <typename Fun, typename... Args>
complete_invoke(Fun && fun,Args &&...args)6531             CompleteType_t<ResultOf_t<Fun(Args...)>> complete_invoke(Fun&& fun, Args&&... args) {
6532                 return CompleteInvoker<ResultOf_t<Fun(Args...)>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...);
6533             }
6534 
6535             const std::string benchmarkErrorMsg = "a benchmark failed to run successfully";
6536         } // namespace Detail
6537 
6538         template <typename Fun>
user_code(Fun && fun)6539         Detail::CompleteType_t<Detail::ResultOf_t<Fun()>> user_code(Fun&& fun) {
6540             CATCH_TRY{
6541                 return Detail::complete_invoke(std::forward<Fun>(fun));
6542             } CATCH_CATCH_ALL{
6543                 getResultCapture().benchmarkFailed(translateActiveException());
6544                 CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg);
6545             }
6546         }
6547     } // namespace Benchmark
6548 } // namespace Catch
6549 
6550 // end catch_complete_invoke.hpp
6551 namespace Catch {
6552     namespace Benchmark {
6553         namespace Detail {
6554             struct ChronometerConcept {
6555                 virtual void start() = 0;
6556                 virtual void finish() = 0;
6557                 virtual ~ChronometerConcept() = default;
6558             };
6559             template <typename Clock>
6560             struct ChronometerModel final : public ChronometerConcept {
startCatch::Benchmark::Detail::ChronometerModel6561                 void start() override { started = Clock::now(); }
finishCatch::Benchmark::Detail::ChronometerModel6562                 void finish() override { finished = Clock::now(); }
6563 
elapsedCatch::Benchmark::Detail::ChronometerModel6564                 ClockDuration<Clock> elapsed() const { return finished - started; }
6565 
6566                 TimePoint<Clock> started;
6567                 TimePoint<Clock> finished;
6568             };
6569         } // namespace Detail
6570 
6571         struct Chronometer {
6572         public:
6573             template <typename Fun>
measureCatch::Benchmark::Chronometer6574             void measure(Fun&& fun) { measure(std::forward<Fun>(fun), is_callable<Fun(int)>()); }
6575 
runsCatch::Benchmark::Chronometer6576             int runs() const { return k; }
6577 
ChronometerCatch::Benchmark::Chronometer6578             Chronometer(Detail::ChronometerConcept& meter, int k)
6579                 : impl(&meter)
6580                 , k(k) {}
6581 
6582         private:
6583             template <typename Fun>
measureCatch::Benchmark::Chronometer6584             void measure(Fun&& fun, std::false_type) {
6585                 measure([&fun](int) { return fun(); }, std::true_type());
6586             }
6587 
6588             template <typename Fun>
measureCatch::Benchmark::Chronometer6589             void measure(Fun&& fun, std::true_type) {
6590                 Detail::optimizer_barrier();
6591                 impl->start();
6592                 for (int i = 0; i < k; ++i) invoke_deoptimized(fun, i);
6593                 impl->finish();
6594                 Detail::optimizer_barrier();
6595             }
6596 
6597             Detail::ChronometerConcept* impl;
6598             int k;
6599         };
6600     } // namespace Benchmark
6601 } // namespace Catch
6602 
6603 // end catch_chronometer.hpp
6604 // start catch_environment.hpp
6605 
6606 // Environment information
6607 
6608 
6609 namespace Catch {
6610     namespace Benchmark {
6611         template <typename Duration>
6612         struct EnvironmentEstimate {
6613             Duration mean;
6614             OutlierClassification outliers;
6615 
6616             template <typename Duration2>
operator EnvironmentEstimate<Duration2>Catch::Benchmark::EnvironmentEstimate6617             operator EnvironmentEstimate<Duration2>() const {
6618                 return { mean, outliers };
6619             }
6620         };
6621         template <typename Clock>
6622         struct Environment {
6623             using clock_type = Clock;
6624             EnvironmentEstimate<FloatDuration<Clock>> clock_resolution;
6625             EnvironmentEstimate<FloatDuration<Clock>> clock_cost;
6626         };
6627     } // namespace Benchmark
6628 } // namespace Catch
6629 
6630 // end catch_environment.hpp
6631 // start catch_execution_plan.hpp
6632 
6633  // Execution plan
6634 
6635 
6636 // start catch_benchmark_function.hpp
6637 
6638  // Dumb std::function implementation for consistent call overhead
6639 
6640 
6641 #include <cassert>
6642 #include <type_traits>
6643 #include <utility>
6644 #include <memory>
6645 
6646 namespace Catch {
6647     namespace Benchmark {
6648         namespace Detail {
6649             template <typename T>
6650             using Decay = typename std::decay<T>::type;
6651             template <typename T, typename U>
6652             struct is_related
6653                 : std::is_same<Decay<T>, Decay<U>> {};
6654 
6655             /// We need to reinvent std::function because every piece of code that might add overhead
6656             /// in a measurement context needs to have consistent performance characteristics so that we
6657             /// can account for it in the measurement.
6658             /// Implementations of std::function with optimizations that aren't always applicable, like
6659             /// small buffer optimizations, are not uncommon.
6660             /// This is effectively an implementation of std::function without any such optimizations;
6661             /// it may be slow, but it is consistently slow.
6662             struct BenchmarkFunction {
6663             private:
6664                 struct callable {
6665                     virtual void call(Chronometer meter) const = 0;
6666                     virtual callable* clone() const = 0;
6667                     virtual ~callable() = default;
6668                 };
6669                 template <typename Fun>
6670                 struct model : public callable {
modelCatch::Benchmark::Detail::BenchmarkFunction::model6671                     model(Fun&& fun) : fun(std::move(fun)) {}
modelCatch::Benchmark::Detail::BenchmarkFunction::model6672                     model(Fun const& fun) : fun(fun) {}
6673 
cloneCatch::Benchmark::Detail::BenchmarkFunction::model6674                     model<Fun>* clone() const override { return new model<Fun>(*this); }
6675 
callCatch::Benchmark::Detail::BenchmarkFunction::model6676                     void call(Chronometer meter) const override {
6677                         call(meter, is_callable<Fun(Chronometer)>());
6678                     }
callCatch::Benchmark::Detail::BenchmarkFunction::model6679                     void call(Chronometer meter, std::true_type) const {
6680                         fun(meter);
6681                     }
callCatch::Benchmark::Detail::BenchmarkFunction::model6682                     void call(Chronometer meter, std::false_type) const {
6683                         meter.measure(fun);
6684                     }
6685 
6686                     Fun fun;
6687                 };
6688 
operator ()Catch::Benchmark::Detail::BenchmarkFunction::do_nothing6689                 struct do_nothing { void operator()() const {} };
6690 
6691                 template <typename T>
BenchmarkFunctionCatch::Benchmark::Detail::BenchmarkFunction6692                 BenchmarkFunction(model<T>* c) : f(c) {}
6693 
6694             public:
BenchmarkFunctionCatch::Benchmark::Detail::BenchmarkFunction6695                 BenchmarkFunction()
6696                     : f(new model<do_nothing>{ {} }) {}
6697 
6698                 template <typename Fun,
6699                     typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0>
BenchmarkFunctionCatch::Benchmark::Detail::BenchmarkFunction6700                     BenchmarkFunction(Fun&& fun)
6701                     : f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun))) {}
6702 
BenchmarkFunctionCatch::Benchmark::Detail::BenchmarkFunction6703                 BenchmarkFunction(BenchmarkFunction&& that)
6704                     : f(std::move(that.f)) {}
6705 
BenchmarkFunctionCatch::Benchmark::Detail::BenchmarkFunction6706                 BenchmarkFunction(BenchmarkFunction const& that)
6707                     : f(that.f->clone()) {}
6708 
operator =Catch::Benchmark::Detail::BenchmarkFunction6709                 BenchmarkFunction& operator=(BenchmarkFunction&& that) {
6710                     f = std::move(that.f);
6711                     return *this;
6712                 }
6713 
operator =Catch::Benchmark::Detail::BenchmarkFunction6714                 BenchmarkFunction& operator=(BenchmarkFunction const& that) {
6715                     f.reset(that.f->clone());
6716                     return *this;
6717                 }
6718 
operator ()Catch::Benchmark::Detail::BenchmarkFunction6719                 void operator()(Chronometer meter) const { f->call(meter); }
6720 
6721             private:
6722                 std::unique_ptr<callable> f;
6723             };
6724         } // namespace Detail
6725     } // namespace Benchmark
6726 } // namespace Catch
6727 
6728 // end catch_benchmark_function.hpp
6729 // start catch_repeat.hpp
6730 
6731 // repeat algorithm
6732 
6733 
6734 #include <type_traits>
6735 #include <utility>
6736 
6737 namespace Catch {
6738     namespace Benchmark {
6739         namespace Detail {
6740             template <typename Fun>
6741             struct repeater {
operator ()Catch::Benchmark::Detail::repeater6742                 void operator()(int k) const {
6743                     for (int i = 0; i < k; ++i) {
6744                         fun();
6745                     }
6746                 }
6747                 Fun fun;
6748             };
6749             template <typename Fun>
repeat(Fun && fun)6750             repeater<typename std::decay<Fun>::type> repeat(Fun&& fun) {
6751                 return { std::forward<Fun>(fun) };
6752             }
6753         } // namespace Detail
6754     } // namespace Benchmark
6755 } // namespace Catch
6756 
6757 // end catch_repeat.hpp
6758 // start catch_run_for_at_least.hpp
6759 
6760 // Run a function for a minimum amount of time
6761 
6762 
6763 // start catch_measure.hpp
6764 
6765 // Measure
6766 
6767 
6768 // start catch_timing.hpp
6769 
6770 // Timing
6771 
6772 
6773 #include <tuple>
6774 #include <type_traits>
6775 
6776 namespace Catch {
6777     namespace Benchmark {
6778         template <typename Duration, typename Result>
6779         struct Timing {
6780             Duration elapsed;
6781             Result result;
6782             int iterations;
6783         };
6784         template <typename Clock, typename Sig>
6785         using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<Detail::ResultOf_t<Sig>>>;
6786     } // namespace Benchmark
6787 } // namespace Catch
6788 
6789 // end catch_timing.hpp
6790 #include <utility>
6791 
6792 namespace Catch {
6793     namespace Benchmark {
6794         namespace Detail {
6795             template <typename Clock, typename Fun, typename... Args>
measure(Fun && fun,Args &&...args)6796             TimingOf<Clock, Fun(Args...)> measure(Fun&& fun, Args&&... args) {
6797                 auto start = Clock::now();
6798                 auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...);
6799                 auto end = Clock::now();
6800                 auto delta = end - start;
6801                 return { delta, std::forward<decltype(r)>(r), 1 };
6802             }
6803         } // namespace Detail
6804     } // namespace Benchmark
6805 } // namespace Catch
6806 
6807 // end catch_measure.hpp
6808 #include <utility>
6809 #include <type_traits>
6810 
6811 namespace Catch {
6812     namespace Benchmark {
6813         namespace Detail {
6814             template <typename Clock, typename Fun>
measure_one(Fun && fun,int iters,std::false_type)6815             TimingOf<Clock, Fun(int)> measure_one(Fun&& fun, int iters, std::false_type) {
6816                 return Detail::measure<Clock>(fun, iters);
6817             }
6818             template <typename Clock, typename Fun>
measure_one(Fun && fun,int iters,std::true_type)6819             TimingOf<Clock, Fun(Chronometer)> measure_one(Fun&& fun, int iters, std::true_type) {
6820                 Detail::ChronometerModel<Clock> meter;
6821                 auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));
6822 
6823                 return { meter.elapsed(), std::move(result), iters };
6824             }
6825 
6826             template <typename Clock, typename Fun>
6827             using run_for_at_least_argument_t = typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type;
6828 
6829             struct optimized_away_error : std::exception {
whatCatch::Benchmark::Detail::optimized_away_error6830                 const char* what() const noexcept override {
6831                     return "could not measure benchmark, maybe it was optimized away";
6832                 }
6833             };
6834 
6835             template <typename Clock, typename Fun>
run_for_at_least(ClockDuration<Clock> how_long,int seed,Fun && fun)6836             TimingOf<Clock, Fun(run_for_at_least_argument_t<Clock, Fun>)> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) {
6837                 auto iters = seed;
6838                 while (iters < (1 << 30)) {
6839                     auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());
6840 
6841                     if (Timing.elapsed >= how_long) {
6842                         return { Timing.elapsed, std::move(Timing.result), iters };
6843                     }
6844                     iters *= 2;
6845                 }
6846                 throw optimized_away_error{};
6847             }
6848         } // namespace Detail
6849     } // namespace Benchmark
6850 } // namespace Catch
6851 
6852 // end catch_run_for_at_least.hpp
6853 #include <algorithm>
6854 
6855 namespace Catch {
6856     namespace Benchmark {
6857         template <typename Duration>
6858         struct ExecutionPlan {
6859             int iterations_per_sample;
6860             Duration estimated_duration;
6861             Detail::BenchmarkFunction benchmark;
6862             Duration warmup_time;
6863             int warmup_iterations;
6864 
6865             template <typename Duration2>
operator ExecutionPlan<Duration2>Catch::Benchmark::ExecutionPlan6866             operator ExecutionPlan<Duration2>() const {
6867                 return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations };
6868             }
6869 
6870             template <typename Clock>
runCatch::Benchmark::ExecutionPlan6871             std::vector<FloatDuration<Clock>> run(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
6872                 // warmup a bit
6873                 Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{}));
6874 
6875                 std::vector<FloatDuration<Clock>> times;
6876                 times.reserve(cfg.benchmarkSamples());
6877                 std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] {
6878                     Detail::ChronometerModel<Clock> model;
6879                     this->benchmark(Chronometer(model, iterations_per_sample));
6880                     auto sample_time = model.elapsed() - env.clock_cost.mean;
6881                     if (sample_time < FloatDuration<Clock>::zero()) sample_time = FloatDuration<Clock>::zero();
6882                     return sample_time / iterations_per_sample;
6883                 });
6884                 return times;
6885             }
6886         };
6887     } // namespace Benchmark
6888 } // namespace Catch
6889 
6890 // end catch_execution_plan.hpp
6891 // start catch_estimate_clock.hpp
6892 
6893  // Environment measurement
6894 
6895 
6896 // start catch_stats.hpp
6897 
6898 // Statistical analysis tools
6899 
6900 
6901 #include <algorithm>
6902 #include <functional>
6903 #include <vector>
6904 #include <iterator>
6905 #include <numeric>
6906 #include <tuple>
6907 #include <cmath>
6908 #include <utility>
6909 #include <cstddef>
6910 #include <random>
6911 
6912 namespace Catch {
6913     namespace Benchmark {
6914         namespace Detail {
6915             using sample = std::vector<double>;
6916 
6917             double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last);
6918 
6919             template <typename Iterator>
classify_outliers(Iterator first,Iterator last)6920             OutlierClassification classify_outliers(Iterator first, Iterator last) {
6921                 std::vector<double> copy(first, last);
6922 
6923                 auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end());
6924                 auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end());
6925                 auto iqr = q3 - q1;
6926                 auto los = q1 - (iqr * 3.);
6927                 auto lom = q1 - (iqr * 1.5);
6928                 auto him = q3 + (iqr * 1.5);
6929                 auto his = q3 + (iqr * 3.);
6930 
6931                 OutlierClassification o;
6932                 for (; first != last; ++first) {
6933                     auto&& t = *first;
6934                     if (t < los) ++o.low_severe;
6935                     else if (t < lom) ++o.low_mild;
6936                     else if (t > his) ++o.high_severe;
6937                     else if (t > him) ++o.high_mild;
6938                     ++o.samples_seen;
6939                 }
6940                 return o;
6941             }
6942 
6943             template <typename Iterator>
mean(Iterator first,Iterator last)6944             double mean(Iterator first, Iterator last) {
6945                 auto count = last - first;
6946                 double sum = std::accumulate(first, last, 0.);
6947                 return sum / count;
6948             }
6949 
6950             template <typename URng, typename Iterator, typename Estimator>
resample(URng & rng,int resamples,Iterator first,Iterator last,Estimator & estimator)6951             sample resample(URng& rng, int resamples, Iterator first, Iterator last, Estimator& estimator) {
6952                 auto n = last - first;
6953                 std::uniform_int_distribution<decltype(n)> dist(0, n - 1);
6954 
6955                 sample out;
6956                 out.reserve(resamples);
6957                 std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] {
6958                     std::vector<double> resampled;
6959                     resampled.reserve(n);
6960                     std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[dist(rng)]; });
6961                     return estimator(resampled.begin(), resampled.end());
6962                 });
6963                 std::sort(out.begin(), out.end());
6964                 return out;
6965             }
6966 
6967             template <typename Estimator, typename Iterator>
jackknife(Estimator && estimator,Iterator first,Iterator last)6968             sample jackknife(Estimator&& estimator, Iterator first, Iterator last) {
6969                 auto n = last - first;
6970                 auto second = std::next(first);
6971                 sample results;
6972                 results.reserve(n);
6973 
6974                 for (auto it = first; it != last; ++it) {
6975                     std::iter_swap(it, first);
6976                     results.push_back(estimator(second, last));
6977                 }
6978 
6979                 return results;
6980             }
6981 
normal_cdf(double x)6982             inline double normal_cdf(double x) {
6983                 return std::erfc(-x / std::sqrt(2.0)) / 2.0;
6984             }
6985 
6986             double erfc_inv(double x);
6987 
6988             double normal_quantile(double p);
6989 
6990             template <typename Iterator, typename Estimator>
bootstrap(double confidence_level,Iterator first,Iterator last,sample const & resample,Estimator && estimator)6991             Estimate<double> bootstrap(double confidence_level, Iterator first, Iterator last, sample const& resample, Estimator&& estimator) {
6992                 auto n_samples = last - first;
6993 
6994                 double point = estimator(first, last);
6995                 // Degenerate case with a single sample
6996                 if (n_samples == 1) return { point, point, point, confidence_level };
6997 
6998                 sample jack = jackknife(estimator, first, last);
6999                 double jack_mean = mean(jack.begin(), jack.end());
7000                 double sum_squares, sum_cubes;
7001                 std::tie(sum_squares, sum_cubes) = std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.), [jack_mean](std::pair<double, double> sqcb, double x) -> std::pair<double, double> {
7002                     auto d = jack_mean - x;
7003                     auto d2 = d * d;
7004                     auto d3 = d2 * d;
7005                     return { sqcb.first + d2, sqcb.second + d3 };
7006                 });
7007 
7008                 double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));
7009                 int n = static_cast<int>(resample.size());
7010                 double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / (double)n;
7011                 // degenerate case with uniform samples
7012                 if (prob_n == 0) return { point, point, point, confidence_level };
7013 
7014                 double bias = normal_quantile(prob_n);
7015                 double z1 = normal_quantile((1. - confidence_level) / 2.);
7016 
7017                 auto cumn = [n](double x) -> int {
7018                     return std::lround(normal_cdf(x) * n); };
7019                 auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); };
7020                 double b1 = bias + z1;
7021                 double b2 = bias - z1;
7022                 double a1 = a(b1);
7023                 double a2 = a(b2);
7024                 auto lo = std::max(cumn(a1), 0);
7025                 auto hi = std::min(cumn(a2), n - 1);
7026 
7027                 return { point, resample[lo], resample[hi], confidence_level };
7028             }
7029 
7030             double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n);
7031 
7032             struct bootstrap_analysis {
7033                 Estimate<double> mean;
7034                 Estimate<double> standard_deviation;
7035                 double outlier_variance;
7036             };
7037 
7038             bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last);
7039         } // namespace Detail
7040     } // namespace Benchmark
7041 } // namespace Catch
7042 
7043 // end catch_stats.hpp
7044 #include <algorithm>
7045 #include <iterator>
7046 #include <tuple>
7047 #include <vector>
7048 #include <cmath>
7049 
7050 namespace Catch {
7051     namespace Benchmark {
7052         namespace Detail {
7053             template <typename Clock>
resolution(int k)7054             std::vector<double> resolution(int k) {
7055                 std::vector<TimePoint<Clock>> times;
7056                 times.reserve(k + 1);
7057                 std::generate_n(std::back_inserter(times), k + 1, now<Clock>{});
7058 
7059                 std::vector<double> deltas;
7060                 deltas.reserve(k);
7061                 std::transform(std::next(times.begin()), times.end(), times.begin(),
7062                     std::back_inserter(deltas),
7063                     [](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); });
7064 
7065                 return deltas;
7066             }
7067 
7068             const auto warmup_iterations = 10000;
7069             const auto warmup_time = std::chrono::milliseconds(100);
7070             const auto minimum_ticks = 1000;
7071             const auto warmup_seed = 10000;
7072             const auto clock_resolution_estimation_time = std::chrono::milliseconds(500);
7073             const auto clock_cost_estimation_time_limit = std::chrono::seconds(1);
7074             const auto clock_cost_estimation_tick_limit = 100000;
7075             const auto clock_cost_estimation_time = std::chrono::milliseconds(10);
7076             const auto clock_cost_estimation_iterations = 10000;
7077 
7078             template <typename Clock>
warmup()7079             int warmup() {
7080                 return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>)
7081                     .iterations;
7082             }
7083             template <typename Clock>
estimate_clock_resolution(int iterations)7084             EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations) {
7085                 auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time), iterations, &resolution<Clock>)
7086                     .result;
7087                 return {
7088                     FloatDuration<Clock>(mean(r.begin(), r.end())),
7089                     classify_outliers(r.begin(), r.end()),
7090                 };
7091             }
7092             template <typename Clock>
estimate_clock_cost(FloatDuration<Clock> resolution)7093             EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {
7094                 auto time_limit = std::min(resolution * clock_cost_estimation_tick_limit, FloatDuration<Clock>(clock_cost_estimation_time_limit));
7095                 auto time_clock = [](int k) {
7096                     return Detail::measure<Clock>([k] {
7097                         for (int i = 0; i < k; ++i) {
7098                             volatile auto ignored = Clock::now();
7099                             (void)ignored;
7100                         }
7101                     }).elapsed;
7102                 };
7103                 time_clock(1);
7104                 int iters = clock_cost_estimation_iterations;
7105                 auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock);
7106                 std::vector<double> times;
7107                 int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));
7108                 times.reserve(nsamples);
7109                 std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] {
7110                     return static_cast<double>((time_clock(r.iterations) / r.iterations).count());
7111                 });
7112                 return {
7113                     FloatDuration<Clock>(mean(times.begin(), times.end())),
7114                     classify_outliers(times.begin(), times.end()),
7115                 };
7116             }
7117 
7118             template <typename Clock>
measure_environment()7119             Environment<FloatDuration<Clock>> measure_environment() {
7120                 static Environment<FloatDuration<Clock>>* env = nullptr;
7121                 if (env) {
7122                     return *env;
7123                 }
7124 
7125                 auto iters = Detail::warmup<Clock>();
7126                 auto resolution = Detail::estimate_clock_resolution<Clock>(iters);
7127                 auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);
7128 
7129                 env = new Environment<FloatDuration<Clock>>{ resolution, cost };
7130                 return *env;
7131             }
7132         } // namespace Detail
7133     } // namespace Benchmark
7134 } // namespace Catch
7135 
7136 // end catch_estimate_clock.hpp
7137 // start catch_analyse.hpp
7138 
7139  // Run and analyse one benchmark
7140 
7141 
7142 // start catch_sample_analysis.hpp
7143 
7144 // Benchmark results
7145 
7146 
7147 #include <algorithm>
7148 #include <vector>
7149 #include <string>
7150 #include <iterator>
7151 
7152 namespace Catch {
7153     namespace Benchmark {
7154         template <typename Duration>
7155         struct SampleAnalysis {
7156             std::vector<Duration> samples;
7157             Estimate<Duration> mean;
7158             Estimate<Duration> standard_deviation;
7159             OutlierClassification outliers;
7160             double outlier_variance;
7161 
7162             template <typename Duration2>
operator SampleAnalysis<Duration2>Catch::Benchmark::SampleAnalysis7163             operator SampleAnalysis<Duration2>() const {
7164                 std::vector<Duration2> samples2;
7165                 samples2.reserve(samples.size());
7166                 std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); });
7167                 return {
7168                     std::move(samples2),
7169                     mean,
7170                     standard_deviation,
7171                     outliers,
7172                     outlier_variance,
7173                 };
7174             }
7175         };
7176     } // namespace Benchmark
7177 } // namespace Catch
7178 
7179 // end catch_sample_analysis.hpp
7180 #include <algorithm>
7181 #include <iterator>
7182 #include <vector>
7183 
7184 namespace Catch {
7185     namespace Benchmark {
7186         namespace Detail {
7187             template <typename Duration, typename Iterator>
analyse(const IConfig & cfg,Environment<Duration>,Iterator first,Iterator last)7188             SampleAnalysis<Duration> analyse(const IConfig &cfg, Environment<Duration>, Iterator first, Iterator last) {
7189                 if (!cfg.benchmarkNoAnalysis()) {
7190                     std::vector<double> samples;
7191                     samples.reserve(last - first);
7192                     std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); });
7193 
7194                     auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end());
7195                     auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end());
7196 
7197                     auto wrap_estimate = [](Estimate<double> e) {
7198                         return Estimate<Duration> {
7199                             Duration(e.point),
7200                                 Duration(e.lower_bound),
7201                                 Duration(e.upper_bound),
7202                                 e.confidence_interval,
7203                         };
7204                     };
7205                     std::vector<Duration> samples2;
7206                     samples2.reserve(samples.size());
7207                     std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); });
7208                     return {
7209                         std::move(samples2),
7210                         wrap_estimate(analysis.mean),
7211                         wrap_estimate(analysis.standard_deviation),
7212                         outliers,
7213                         analysis.outlier_variance,
7214                     };
7215                 } else {
7216                     std::vector<Duration> samples;
7217                     samples.reserve(last - first);
7218 
7219                     Duration mean = Duration(0);
7220                     int i = 0;
7221                     for (auto it = first; it < last; ++it, ++i) {
7222                         samples.push_back(Duration(*it));
7223                         mean += Duration(*it);
7224                     }
7225                     mean /= i;
7226 
7227                     return {
7228                         std::move(samples),
7229                         Estimate<Duration>{mean, mean, mean, 0.0},
7230                         Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0},
7231                         OutlierClassification{},
7232                         0.0
7233                     };
7234                 }
7235             }
7236         } // namespace Detail
7237     } // namespace Benchmark
7238 } // namespace Catch
7239 
7240 // end catch_analyse.hpp
7241 #include <algorithm>
7242 #include <functional>
7243 #include <string>
7244 #include <vector>
7245 #include <cmath>
7246 
7247 namespace Catch {
7248     namespace Benchmark {
7249         struct Benchmark {
BenchmarkCatch::Benchmark::Benchmark7250             Benchmark(std::string &&name)
7251                 : name(std::move(name)) {}
7252 
7253             template <class FUN>
BenchmarkCatch::Benchmark::Benchmark7254             Benchmark(std::string &&name, FUN &&func)
7255                 : fun(std::move(func)), name(std::move(name)) {}
7256 
7257             template <typename Clock>
prepareCatch::Benchmark::Benchmark7258             ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {
7259                 auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;
7260                 auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));
7261                 auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun);
7262                 int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));
7263                 return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };
7264             }
7265 
7266             template <typename Clock = default_clock>
runCatch::Benchmark::Benchmark7267             void run() {
7268                 IConfigPtr cfg = getCurrentContext().getConfig();
7269 
7270                 auto env = Detail::measure_environment<Clock>();
7271 
7272                 getResultCapture().benchmarkPreparing(name);
7273                 CATCH_TRY{
7274                     auto plan = user_code([&] {
7275                         return prepare<Clock>(*cfg, env);
7276                     });
7277 
7278                     BenchmarkInfo info {
7279                         name,
7280                         plan.estimated_duration.count(),
7281                         plan.iterations_per_sample,
7282                         cfg->benchmarkSamples(),
7283                         cfg->benchmarkResamples(),
7284                         env.clock_resolution.mean.count(),
7285                         env.clock_cost.mean.count()
7286                     };
7287 
7288                     getResultCapture().benchmarkStarting(info);
7289 
7290                     auto samples = user_code([&] {
7291                         return plan.template run<Clock>(*cfg, env);
7292                     });
7293 
7294                     auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());
7295                     BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };
7296                     getResultCapture().benchmarkEnded(stats);
7297 
7298                 } CATCH_CATCH_ALL{
7299                     if (translateActiveException() != Detail::benchmarkErrorMsg) // benchmark errors have been reported, otherwise rethrow.
7300                         std::rethrow_exception(std::current_exception());
7301                 }
7302             }
7303 
7304             // sets lambda to be used in fun *and* executes benchmark!
7305             template <typename Fun,
7306                 typename std::enable_if<!Detail::is_related<Fun, Benchmark>::value, int>::type = 0>
operator =Catch::Benchmark::Benchmark7307                 Benchmark & operator=(Fun func) {
7308                 fun = Detail::BenchmarkFunction(func);
7309                 run();
7310                 return *this;
7311             }
7312 
operator boolCatch::Benchmark::Benchmark7313             explicit operator bool() {
7314                 return true;
7315             }
7316 
7317         private:
7318             Detail::BenchmarkFunction fun;
7319             std::string name;
7320         };
7321     }
7322 } // namespace Catch
7323 
7324 #define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1
7325 #define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2
7326 
7327 #define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\
7328     if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
7329         BenchmarkName = [&](int benchmarkIndex)
7330 
7331 #define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\
7332     if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \
7333         BenchmarkName = [&]
7334 
7335 // end catch_benchmark.hpp
7336 // start catch_constructor.hpp
7337 
7338 // Constructor and destructor helpers
7339 
7340 
7341 #include <type_traits>
7342 
7343 namespace Catch {
7344     namespace Benchmark {
7345         namespace Detail {
7346             template <typename T, bool Destruct>
7347             struct ObjectStorage
7348             {
7349                 using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;
7350 
ObjectStorageCatch::Benchmark::Detail::ObjectStorage7351                 ObjectStorage() : data() {}
7352 
ObjectStorageCatch::Benchmark::Detail::ObjectStorage7353                 ObjectStorage(const ObjectStorage& other)
7354                 {
7355                     new(&data) T(other.stored_object());
7356                 }
7357 
ObjectStorageCatch::Benchmark::Detail::ObjectStorage7358                 ObjectStorage(ObjectStorage&& other)
7359                 {
7360                     new(&data) T(std::move(other.stored_object()));
7361                 }
7362 
~ObjectStorageCatch::Benchmark::Detail::ObjectStorage7363                 ~ObjectStorage() { destruct_on_exit<T>(); }
7364 
7365                 template <typename... Args>
constructCatch::Benchmark::Detail::ObjectStorage7366                 void construct(Args&&... args)
7367                 {
7368                     new (&data) T(std::forward<Args>(args)...);
7369                 }
7370 
7371                 template <bool AllowManualDestruction = !Destruct>
destructCatch::Benchmark::Detail::ObjectStorage7372                 typename std::enable_if<AllowManualDestruction>::type destruct()
7373                 {
7374                     stored_object().~T();
7375                 }
7376 
7377             private:
7378                 // If this is a constructor benchmark, destruct the underlying object
7379                 template <typename U>
destruct_on_exitCatch::Benchmark::Detail::ObjectStorage7380                 void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }
7381                 // Otherwise, don't
7382                 template <typename U>
destruct_on_exitCatch::Benchmark::Detail::ObjectStorage7383                 void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }
7384 
stored_objectCatch::Benchmark::Detail::ObjectStorage7385                 T& stored_object() {
7386                     return *static_cast<T*>(static_cast<void*>(&data));
7387                 }
7388 
stored_objectCatch::Benchmark::Detail::ObjectStorage7389                 T const& stored_object() const {
7390                     return *static_cast<T*>(static_cast<void*>(&data));
7391                 }
7392 
7393                 TStorage data;
7394             };
7395         }
7396 
7397         template <typename T>
7398         using storage_for = Detail::ObjectStorage<T, true>;
7399 
7400         template <typename T>
7401         using destructable_object = Detail::ObjectStorage<T, false>;
7402     }
7403 }
7404 
7405 // end catch_constructor.hpp
7406 // end catch_benchmarking_all.hpp
7407 #endif
7408 
7409 #endif // ! CATCH_CONFIG_IMPL_ONLY
7410 
7411 #ifdef CATCH_IMPL
7412 // start catch_impl.hpp
7413 
7414 #ifdef __clang__
7415 #pragma clang diagnostic push
7416 #pragma clang diagnostic ignored "-Wweak-vtables"
7417 #endif
7418 
7419 // Keep these here for external reporters
7420 // start catch_test_case_tracker.h
7421 
7422 #include <string>
7423 #include <vector>
7424 #include <memory>
7425 
7426 namespace Catch {
7427 namespace TestCaseTracking {
7428 
7429     struct NameAndLocation {
7430         std::string name;
7431         SourceLineInfo location;
7432 
7433         NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
7434     };
7435 
7436     struct ITracker;
7437 
7438     using ITrackerPtr = std::shared_ptr<ITracker>;
7439 
7440     struct ITracker {
7441         virtual ~ITracker();
7442 
7443         // static queries
7444         virtual NameAndLocation const& nameAndLocation() const = 0;
7445 
7446         // dynamic queries
7447         virtual bool isComplete() const = 0; // Successfully completed or failed
7448         virtual bool isSuccessfullyCompleted() const = 0;
7449         virtual bool isOpen() const = 0; // Started but not complete
7450         virtual bool hasChildren() const = 0;
7451 
7452         virtual ITracker& parent() = 0;
7453 
7454         // actions
7455         virtual void close() = 0; // Successfully complete
7456         virtual void fail() = 0;
7457         virtual void markAsNeedingAnotherRun() = 0;
7458 
7459         virtual void addChild( ITrackerPtr const& child ) = 0;
7460         virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0;
7461         virtual void openChild() = 0;
7462 
7463         // Debug/ checking
7464         virtual bool isSectionTracker() const = 0;
7465         virtual bool isGeneratorTracker() const = 0;
7466     };
7467 
7468     class TrackerContext {
7469 
7470         enum RunState {
7471             NotStarted,
7472             Executing,
7473             CompletedCycle
7474         };
7475 
7476         ITrackerPtr m_rootTracker;
7477         ITracker* m_currentTracker = nullptr;
7478         RunState m_runState = NotStarted;
7479 
7480     public:
7481 
7482         ITracker& startRun();
7483         void endRun();
7484 
7485         void startCycle();
7486         void completeCycle();
7487 
7488         bool completedCycle() const;
7489         ITracker& currentTracker();
7490         void setCurrentTracker( ITracker* tracker );
7491     };
7492 
7493     class TrackerBase : public ITracker {
7494     protected:
7495         enum CycleState {
7496             NotStarted,
7497             Executing,
7498             ExecutingChildren,
7499             NeedsAnotherRun,
7500             CompletedSuccessfully,
7501             Failed
7502         };
7503 
7504         using Children = std::vector<ITrackerPtr>;
7505         NameAndLocation m_nameAndLocation;
7506         TrackerContext& m_ctx;
7507         ITracker* m_parent;
7508         Children m_children;
7509         CycleState m_runState = NotStarted;
7510 
7511     public:
7512         TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
7513 
7514         NameAndLocation const& nameAndLocation() const override;
7515         bool isComplete() const override;
7516         bool isSuccessfullyCompleted() const override;
7517         bool isOpen() const override;
7518         bool hasChildren() const override;
7519 
7520         void addChild( ITrackerPtr const& child ) override;
7521 
7522         ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override;
7523         ITracker& parent() override;
7524 
7525         void openChild() override;
7526 
7527         bool isSectionTracker() const override;
7528         bool isGeneratorTracker() const override;
7529 
7530         void open();
7531 
7532         void close() override;
7533         void fail() override;
7534         void markAsNeedingAnotherRun() override;
7535 
7536     private:
7537         void moveToParent();
7538         void moveToThis();
7539     };
7540 
7541     class SectionTracker : public TrackerBase {
7542         std::vector<std::string> m_filters;
7543         std::string m_trimmed_name;
7544     public:
7545         SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
7546 
7547         bool isSectionTracker() const override;
7548 
7549         bool isComplete() const override;
7550 
7551         static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
7552 
7553         void tryOpen();
7554 
7555         void addInitialFilters( std::vector<std::string> const& filters );
7556         void addNextFilters( std::vector<std::string> const& filters );
7557     };
7558 
7559 } // namespace TestCaseTracking
7560 
7561 using TestCaseTracking::ITracker;
7562 using TestCaseTracking::TrackerContext;
7563 using TestCaseTracking::SectionTracker;
7564 
7565 } // namespace Catch
7566 
7567 // end catch_test_case_tracker.h
7568 
7569 // start catch_leak_detector.h
7570 
7571 namespace Catch {
7572 
7573     struct LeakDetector {
7574         LeakDetector();
7575         ~LeakDetector();
7576     };
7577 
7578 }
7579 // end catch_leak_detector.h
7580 // Cpp files will be included in the single-header file here
7581 // start catch_stats.cpp
7582 
7583 // Statistical analysis tools
7584 
7585 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
7586 
7587 #include <cassert>
7588 #include <random>
7589 
7590 #if defined(CATCH_CONFIG_USE_ASYNC)
7591 #include <future>
7592 #endif
7593 
7594 namespace {
erf_inv(double x)7595     double erf_inv(double x) {
7596         // Code accompanying the article "Approximating the erfinv function" in GPU Computing Gems, Volume 2
7597         double w, p;
7598 
7599         w = -log((1.0 - x) * (1.0 + x));
7600 
7601         if (w < 6.250000) {
7602             w = w - 3.125000;
7603             p = -3.6444120640178196996e-21;
7604             p = -1.685059138182016589e-19 + p * w;
7605             p = 1.2858480715256400167e-18 + p * w;
7606             p = 1.115787767802518096e-17 + p * w;
7607             p = -1.333171662854620906e-16 + p * w;
7608             p = 2.0972767875968561637e-17 + p * w;
7609             p = 6.6376381343583238325e-15 + p * w;
7610             p = -4.0545662729752068639e-14 + p * w;
7611             p = -8.1519341976054721522e-14 + p * w;
7612             p = 2.6335093153082322977e-12 + p * w;
7613             p = -1.2975133253453532498e-11 + p * w;
7614             p = -5.4154120542946279317e-11 + p * w;
7615             p = 1.051212273321532285e-09 + p * w;
7616             p = -4.1126339803469836976e-09 + p * w;
7617             p = -2.9070369957882005086e-08 + p * w;
7618             p = 4.2347877827932403518e-07 + p * w;
7619             p = -1.3654692000834678645e-06 + p * w;
7620             p = -1.3882523362786468719e-05 + p * w;
7621             p = 0.0001867342080340571352 + p * w;
7622             p = -0.00074070253416626697512 + p * w;
7623             p = -0.0060336708714301490533 + p * w;
7624             p = 0.24015818242558961693 + p * w;
7625             p = 1.6536545626831027356 + p * w;
7626         } else if (w < 16.000000) {
7627             w = sqrt(w) - 3.250000;
7628             p = 2.2137376921775787049e-09;
7629             p = 9.0756561938885390979e-08 + p * w;
7630             p = -2.7517406297064545428e-07 + p * w;
7631             p = 1.8239629214389227755e-08 + p * w;
7632             p = 1.5027403968909827627e-06 + p * w;
7633             p = -4.013867526981545969e-06 + p * w;
7634             p = 2.9234449089955446044e-06 + p * w;
7635             p = 1.2475304481671778723e-05 + p * w;
7636             p = -4.7318229009055733981e-05 + p * w;
7637             p = 6.8284851459573175448e-05 + p * w;
7638             p = 2.4031110387097893999e-05 + p * w;
7639             p = -0.0003550375203628474796 + p * w;
7640             p = 0.00095328937973738049703 + p * w;
7641             p = -0.0016882755560235047313 + p * w;
7642             p = 0.0024914420961078508066 + p * w;
7643             p = -0.0037512085075692412107 + p * w;
7644             p = 0.005370914553590063617 + p * w;
7645             p = 1.0052589676941592334 + p * w;
7646             p = 3.0838856104922207635 + p * w;
7647         } else {
7648             w = sqrt(w) - 5.000000;
7649             p = -2.7109920616438573243e-11;
7650             p = -2.5556418169965252055e-10 + p * w;
7651             p = 1.5076572693500548083e-09 + p * w;
7652             p = -3.7894654401267369937e-09 + p * w;
7653             p = 7.6157012080783393804e-09 + p * w;
7654             p = -1.4960026627149240478e-08 + p * w;
7655             p = 2.9147953450901080826e-08 + p * w;
7656             p = -6.7711997758452339498e-08 + p * w;
7657             p = 2.2900482228026654717e-07 + p * w;
7658             p = -9.9298272942317002539e-07 + p * w;
7659             p = 4.5260625972231537039e-06 + p * w;
7660             p = -1.9681778105531670567e-05 + p * w;
7661             p = 7.5995277030017761139e-05 + p * w;
7662             p = -0.00021503011930044477347 + p * w;
7663             p = -0.00013871931833623122026 + p * w;
7664             p = 1.0103004648645343977 + p * w;
7665             p = 4.8499064014085844221 + p * w;
7666         }
7667         return p * x;
7668     }
7669 
standard_deviation(std::vector<double>::iterator first,std::vector<double>::iterator last)7670     double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last) {
7671         auto m = Catch::Benchmark::Detail::mean(first, last);
7672         double variance = std::accumulate(first, last, 0., [m](double a, double b) {
7673             double diff = b - m;
7674             return a + diff * diff;
7675             }) / (last - first);
7676             return std::sqrt(variance);
7677     }
7678 
7679 }
7680 
7681 namespace Catch {
7682     namespace Benchmark {
7683         namespace Detail {
7684 
weighted_average_quantile(int k,int q,std::vector<double>::iterator first,std::vector<double>::iterator last)7685             double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) {
7686                 auto count = last - first;
7687                 double idx = (count - 1) * k / static_cast<double>(q);
7688                 int j = static_cast<int>(idx);
7689                 double g = idx - j;
7690                 std::nth_element(first, first + j, last);
7691                 auto xj = first[j];
7692                 if (g == 0) return xj;
7693 
7694                 auto xj1 = *std::min_element(first + (j + 1), last);
7695                 return xj + g * (xj1 - xj);
7696             }
7697 
erfc_inv(double x)7698             double erfc_inv(double x) {
7699                 return erf_inv(1.0 - x);
7700             }
7701 
normal_quantile(double p)7702             double normal_quantile(double p) {
7703                 static const double ROOT_TWO = std::sqrt(2.0);
7704 
7705                 double result = 0.0;
7706                 assert(p >= 0 && p <= 1);
7707                 if (p < 0 || p > 1) {
7708                     return result;
7709                 }
7710 
7711                 result = -erfc_inv(2.0 * p);
7712                 // result *= normal distribution standard deviation (1.0) * sqrt(2)
7713                 result *= /*sd * */ ROOT_TWO;
7714                 // result += normal disttribution mean (0)
7715                 return result;
7716             }
7717 
outlier_variance(Estimate<double> mean,Estimate<double> stddev,int n)7718             double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n) {
7719                 double sb = stddev.point;
7720                 double mn = mean.point / n;
7721                 double mg_min = mn / 2.;
7722                 double sg = std::min(mg_min / 4., sb / std::sqrt(n));
7723                 double sg2 = sg * sg;
7724                 double sb2 = sb * sb;
7725 
7726                 auto c_max = [n, mn, sb2, sg2](double x) -> double {
7727                     double k = mn - x;
7728                     double d = k * k;
7729                     double nd = n * d;
7730                     double k0 = -n * nd;
7731                     double k1 = sb2 - n * sg2 + nd;
7732                     double det = k1 * k1 - 4 * sg2 * k0;
7733                     return (int)(-2. * k0 / (k1 + std::sqrt(det)));
7734                 };
7735 
7736                 auto var_out = [n, sb2, sg2](double c) {
7737                     double nc = n - c;
7738                     return (nc / n) * (sb2 - nc * sg2);
7739                 };
7740 
7741                 return std::min(var_out(1), var_out(std::min(c_max(0.), c_max(mg_min)))) / sb2;
7742             }
7743 
analyse_samples(double confidence_level,int n_resamples,std::vector<double>::iterator first,std::vector<double>::iterator last)7744             bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) {
7745                 CATCH_INTERNAL_START_WARNINGS_SUPPRESSION
7746                 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
7747                 static std::random_device entropy;
7748                 CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION
7749 
7750                 auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++
7751 
7752                 auto mean = &Detail::mean<std::vector<double>::iterator>;
7753                 auto stddev = &standard_deviation;
7754 
7755 #if defined(CATCH_CONFIG_USE_ASYNC)
7756                 auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) {
7757                     auto seed = entropy();
7758                     return std::async(std::launch::async, [=] {
7759                         std::mt19937 rng(seed);
7760                         auto resampled = resample(rng, n_resamples, first, last, f);
7761                         return bootstrap(confidence_level, first, last, resampled, f);
7762                     });
7763                 };
7764 
7765                 auto mean_future = Estimate(mean);
7766                 auto stddev_future = Estimate(stddev);
7767 
7768                 auto mean_estimate = mean_future.get();
7769                 auto stddev_estimate = stddev_future.get();
7770 #else
7771                 auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) {
7772                     auto seed = entropy();
7773                     std::mt19937 rng(seed);
7774                     auto resampled = resample(rng, n_resamples, first, last, f);
7775                     return bootstrap(confidence_level, first, last, resampled, f);
7776                 };
7777 
7778                 auto mean_estimate = Estimate(mean);
7779                 auto stddev_estimate = Estimate(stddev);
7780 #endif // CATCH_USE_ASYNC
7781 
7782                 double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n);
7783 
7784                 return { mean_estimate, stddev_estimate, outlier_variance };
7785             }
7786         } // namespace Detail
7787     } // namespace Benchmark
7788 } // namespace Catch
7789 
7790 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
7791 // end catch_stats.cpp
7792 // start catch_approx.cpp
7793 
7794 #include <cmath>
7795 #include <limits>
7796 
7797 namespace {
7798 
7799 // Performs equivalent check of std::fabs(lhs - rhs) <= margin
7800 // But without the subtraction to allow for INFINITY in comparison
marginComparison(double lhs,double rhs,double margin)7801 bool marginComparison(double lhs, double rhs, double margin) {
7802     return (lhs + margin >= rhs) && (rhs + margin >= lhs);
7803 }
7804 
7805 }
7806 
7807 namespace Catch {
7808 namespace Detail {
7809 
Approx(double value)7810     Approx::Approx ( double value )
7811     :   m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
7812         m_margin( 0.0 ),
7813         m_scale( 0.0 ),
7814         m_value( value )
7815     {}
7816 
custom()7817     Approx Approx::custom() {
7818         return Approx( 0 );
7819     }
7820 
operator -() const7821     Approx Approx::operator-() const {
7822         auto temp(*this);
7823         temp.m_value = -temp.m_value;
7824         return temp;
7825     }
7826 
toString() const7827     std::string Approx::toString() const {
7828         ReusableStringStream rss;
7829         rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
7830         return rss.str();
7831     }
7832 
equalityComparisonImpl(const double other) const7833     bool Approx::equalityComparisonImpl(const double other) const {
7834         // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
7835         // Thanks to Richard Harris for his help refining the scaled margin value
7836         return marginComparison(m_value, other, m_margin)
7837             || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value)));
7838     }
7839 
setMargin(double newMargin)7840     void Approx::setMargin(double newMargin) {
7841         CATCH_ENFORCE(newMargin >= 0,
7842             "Invalid Approx::margin: " << newMargin << '.'
7843             << " Approx::Margin has to be non-negative.");
7844         m_margin = newMargin;
7845     }
7846 
setEpsilon(double newEpsilon)7847     void Approx::setEpsilon(double newEpsilon) {
7848         CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
7849             "Invalid Approx::epsilon: " << newEpsilon << '.'
7850             << " Approx::epsilon has to be in [0, 1]");
7851         m_epsilon = newEpsilon;
7852     }
7853 
7854 } // end namespace Detail
7855 
7856 namespace literals {
operator ""_a(long double val)7857     Detail::Approx operator "" _a(long double val) {
7858         return Detail::Approx(val);
7859     }
operator ""_a(unsigned long long val)7860     Detail::Approx operator "" _a(unsigned long long val) {
7861         return Detail::Approx(val);
7862     }
7863 } // end namespace literals
7864 
convert(Catch::Detail::Approx const & value)7865 std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
7866     return value.toString();
7867 }
7868 
7869 } // end namespace Catch
7870 // end catch_approx.cpp
7871 // start catch_assertionhandler.cpp
7872 
7873 // start catch_debugger.h
7874 
7875 namespace Catch {
7876     bool isDebuggerActive();
7877 }
7878 
7879 #ifdef CATCH_PLATFORM_MAC
7880 
7881     #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
7882 
7883 #elif defined(CATCH_PLATFORM_IPHONE)
7884 
7885     // use inline assembler
7886     #if defined(__i386__) || defined(__x86_64__)
7887         #define CATCH_TRAP()  __asm__("int $3")
7888     #elif defined(__aarch64__)
7889         #define CATCH_TRAP()  __asm__(".inst 0xd4200000")
7890     #elif defined(__arm__) && !defined(__thumb__)
7891         #define CATCH_TRAP()  __asm__(".inst 0xe7f001f0")
7892     #elif defined(__arm__) &&  defined(__thumb__)
7893         #define CATCH_TRAP()  __asm__(".inst 0xde01")
7894     #endif
7895 
7896 #elif defined(CATCH_PLATFORM_LINUX)
7897     // If we can use inline assembler, do it because this allows us to break
7898     // directly at the location of the failing check instead of breaking inside
7899     // raise() called from it, i.e. one stack frame below.
7900     #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
7901         #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */
7902     #else // Fall back to the generic way.
7903         #include <signal.h>
7904 
7905         #define CATCH_TRAP() raise(SIGTRAP)
7906     #endif
7907 #elif defined(_MSC_VER)
7908     #define CATCH_TRAP() __debugbreak()
7909 #elif defined(__MINGW32__)
7910     extern "C" __declspec(dllimport) void __stdcall DebugBreak();
7911     #define CATCH_TRAP() DebugBreak()
7912 #endif
7913 
7914 #ifndef CATCH_BREAK_INTO_DEBUGGER
7915     #ifdef CATCH_TRAP
7916         #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
7917     #else
7918         #define CATCH_BREAK_INTO_DEBUGGER() []{}()
7919     #endif
7920 #endif
7921 
7922 // end catch_debugger.h
7923 // start catch_run_context.h
7924 
7925 // start catch_fatal_condition.h
7926 
7927 // start catch_windows_h_proxy.h
7928 
7929 
7930 #if defined(CATCH_PLATFORM_WINDOWS)
7931 
7932 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
7933 #  define CATCH_DEFINED_NOMINMAX
7934 #  define NOMINMAX
7935 #endif
7936 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
7937 #  define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
7938 #  define WIN32_LEAN_AND_MEAN
7939 #endif
7940 
7941 #ifdef __AFXDLL
7942 #include <AfxWin.h>
7943 #else
7944 #include <windows.h>
7945 #endif
7946 
7947 #ifdef CATCH_DEFINED_NOMINMAX
7948 #  undef NOMINMAX
7949 #endif
7950 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
7951 #  undef WIN32_LEAN_AND_MEAN
7952 #endif
7953 
7954 #endif // defined(CATCH_PLATFORM_WINDOWS)
7955 
7956 // end catch_windows_h_proxy.h
7957 #if defined( CATCH_CONFIG_WINDOWS_SEH )
7958 
7959 namespace Catch {
7960 
7961     struct FatalConditionHandler {
7962 
7963         static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
7964         FatalConditionHandler();
7965         static void reset();
7966         ~FatalConditionHandler();
7967 
7968     private:
7969         static bool isSet;
7970         static ULONG guaranteeSize;
7971         static PVOID exceptionHandlerHandle;
7972     };
7973 
7974 } // namespace Catch
7975 
7976 #elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
7977 
7978 #include <signal.h>
7979 
7980 namespace Catch {
7981 
7982     struct FatalConditionHandler {
7983 
7984         static bool isSet;
7985         static struct sigaction oldSigActions[];
7986         static stack_t oldSigStack;
7987         static char altStackMem[];
7988 
7989         static void handleSignal( int sig );
7990 
7991         FatalConditionHandler();
7992         ~FatalConditionHandler();
7993         static void reset();
7994     };
7995 
7996 } // namespace Catch
7997 
7998 #else
7999 
8000 namespace Catch {
8001     struct FatalConditionHandler {
8002         void reset();
8003     };
8004 }
8005 
8006 #endif
8007 
8008 // end catch_fatal_condition.h
8009 #include <string>
8010 
8011 namespace Catch {
8012 
8013     struct IMutableContext;
8014 
8015     ///////////////////////////////////////////////////////////////////////////
8016 
8017     class RunContext : public IResultCapture, public IRunner {
8018 
8019     public:
8020         RunContext( RunContext const& ) = delete;
8021         RunContext& operator =( RunContext const& ) = delete;
8022 
8023         explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter );
8024 
8025         ~RunContext() override;
8026 
8027         void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
8028         void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );
8029 
8030         Totals runTest(TestCase const& testCase);
8031 
8032         IConfigPtr config() const;
8033         IStreamingReporter& reporter() const;
8034 
8035     public: // IResultCapture
8036 
8037         // Assertion handlers
8038         void handleExpr
8039                 (   AssertionInfo const& info,
8040                     ITransientExpression const& expr,
8041                     AssertionReaction& reaction ) override;
8042         void handleMessage
8043                 (   AssertionInfo const& info,
8044                     ResultWas::OfType resultType,
8045                     StringRef const& message,
8046                     AssertionReaction& reaction ) override;
8047         void handleUnexpectedExceptionNotThrown
8048                 (   AssertionInfo const& info,
8049                     AssertionReaction& reaction ) override;
8050         void handleUnexpectedInflightException
8051                 (   AssertionInfo const& info,
8052                     std::string const& message,
8053                     AssertionReaction& reaction ) override;
8054         void handleIncomplete
8055                 (   AssertionInfo const& info ) override;
8056         void handleNonExpr
8057                 (   AssertionInfo const &info,
8058                     ResultWas::OfType resultType,
8059                     AssertionReaction &reaction ) override;
8060 
8061         bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;
8062 
8063         void sectionEnded( SectionEndInfo const& endInfo ) override;
8064         void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
8065 
8066         auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;
8067 
8068 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
8069         void benchmarkPreparing( std::string const& name ) override;
8070         void benchmarkStarting( BenchmarkInfo const& info ) override;
8071         void benchmarkEnded( BenchmarkStats<> const& stats ) override;
8072         void benchmarkFailed( std::string const& error ) override;
8073 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
8074 
8075         void pushScopedMessage( MessageInfo const& message ) override;
8076         void popScopedMessage( MessageInfo const& message ) override;
8077 
8078         void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
8079 
8080         std::string getCurrentTestName() const override;
8081 
8082         const AssertionResult* getLastResult() const override;
8083 
8084         void exceptionEarlyReported() override;
8085 
8086         void handleFatalErrorCondition( StringRef message ) override;
8087 
8088         bool lastAssertionPassed() override;
8089 
8090         void assertionPassed() override;
8091 
8092     public:
8093         // !TBD We need to do this another way!
8094         bool aborting() const final;
8095 
8096     private:
8097 
8098         void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );
8099         void invokeActiveTestCase();
8100 
8101         void resetAssertionInfo();
8102         bool testForMissingAssertions( Counts& assertions );
8103 
8104         void assertionEnded( AssertionResult const& result );
8105         void reportExpr
8106                 (   AssertionInfo const &info,
8107                     ResultWas::OfType resultType,
8108                     ITransientExpression const *expr,
8109                     bool negated );
8110 
8111         void populateReaction( AssertionReaction& reaction );
8112 
8113     private:
8114 
8115         void handleUnfinishedSections();
8116 
8117         TestRunInfo m_runInfo;
8118         IMutableContext& m_context;
8119         TestCase const* m_activeTestCase = nullptr;
8120         ITracker* m_testCaseTracker = nullptr;
8121         Option<AssertionResult> m_lastResult;
8122 
8123         IConfigPtr m_config;
8124         Totals m_totals;
8125         IStreamingReporterPtr m_reporter;
8126         std::vector<MessageInfo> m_messages;
8127         std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
8128         AssertionInfo m_lastAssertionInfo;
8129         std::vector<SectionEndInfo> m_unfinishedSections;
8130         std::vector<ITracker*> m_activeSections;
8131         TrackerContext m_trackerContext;
8132         bool m_lastAssertionPassed = false;
8133         bool m_shouldReportUnexpected = true;
8134         bool m_includeSuccessfulResults;
8135     };
8136 
8137     void seedRng(IConfig const& config);
8138     unsigned int rngSeed();
8139 } // end namespace Catch
8140 
8141 // end catch_run_context.h
8142 namespace Catch {
8143 
8144     namespace {
operator <<(std::ostream & os,ITransientExpression const & expr)8145         auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
8146             expr.streamReconstructedExpression( os );
8147             return os;
8148         }
8149     }
8150 
LazyExpression(bool isNegated)8151     LazyExpression::LazyExpression( bool isNegated )
8152     :   m_isNegated( isNegated )
8153     {}
8154 
LazyExpression(LazyExpression const & other)8155     LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {}
8156 
operator bool() const8157     LazyExpression::operator bool() const {
8158         return m_transientExpression != nullptr;
8159     }
8160 
operator <<(std::ostream & os,LazyExpression const & lazyExpr)8161     auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& {
8162         if( lazyExpr.m_isNegated )
8163             os << "!";
8164 
8165         if( lazyExpr ) {
8166             if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
8167                 os << "(" << *lazyExpr.m_transientExpression << ")";
8168             else
8169                 os << *lazyExpr.m_transientExpression;
8170         }
8171         else {
8172             os << "{** error - unchecked empty expression requested **}";
8173         }
8174         return os;
8175     }
8176 
AssertionHandler(StringRef const & macroName,SourceLineInfo const & lineInfo,StringRef capturedExpression,ResultDisposition::Flags resultDisposition)8177     AssertionHandler::AssertionHandler
8178         (   StringRef const& macroName,
8179             SourceLineInfo const& lineInfo,
8180             StringRef capturedExpression,
8181             ResultDisposition::Flags resultDisposition )
8182     :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
8183         m_resultCapture( getResultCapture() )
8184     {}
8185 
handleExpr(ITransientExpression const & expr)8186     void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
8187         m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
8188     }
handleMessage(ResultWas::OfType resultType,StringRef const & message)8189     void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) {
8190         m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
8191     }
8192 
allowThrows() const8193     auto AssertionHandler::allowThrows() const -> bool {
8194         return getCurrentContext().getConfig()->allowThrows();
8195     }
8196 
complete()8197     void AssertionHandler::complete() {
8198         setCompleted();
8199         if( m_reaction.shouldDebugBreak ) {
8200 
8201             // If you find your debugger stopping you here then go one level up on the
8202             // call-stack for the code that caused it (typically a failed assertion)
8203 
8204             // (To go back to the test and change execution, jump over the throw, next)
8205             CATCH_BREAK_INTO_DEBUGGER();
8206         }
8207         if (m_reaction.shouldThrow) {
8208 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
8209             throw Catch::TestFailureException();
8210 #else
8211             CATCH_ERROR( "Test failure requires aborting test!" );
8212 #endif
8213         }
8214     }
setCompleted()8215     void AssertionHandler::setCompleted() {
8216         m_completed = true;
8217     }
8218 
handleUnexpectedInflightException()8219     void AssertionHandler::handleUnexpectedInflightException() {
8220         m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
8221     }
8222 
handleExceptionThrownAsExpected()8223     void AssertionHandler::handleExceptionThrownAsExpected() {
8224         m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
8225     }
handleExceptionNotThrownAsExpected()8226     void AssertionHandler::handleExceptionNotThrownAsExpected() {
8227         m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
8228     }
8229 
handleUnexpectedExceptionNotThrown()8230     void AssertionHandler::handleUnexpectedExceptionNotThrown() {
8231         m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
8232     }
8233 
handleThrowingCallSkipped()8234     void AssertionHandler::handleThrowingCallSkipped() {
8235         m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
8236     }
8237 
8238     // This is the overload that takes a string and infers the Equals matcher from it
8239     // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
handleExceptionMatchExpr(AssertionHandler & handler,std::string const & str,StringRef const & matcherString)8240     void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString  ) {
8241         handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
8242     }
8243 
8244 } // namespace Catch
8245 // end catch_assertionhandler.cpp
8246 // start catch_assertionresult.cpp
8247 
8248 namespace Catch {
AssertionResultData(ResultWas::OfType _resultType,LazyExpression const & _lazyExpression)8249     AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):
8250         lazyExpression(_lazyExpression),
8251         resultType(_resultType) {}
8252 
reconstructExpression() const8253     std::string AssertionResultData::reconstructExpression() const {
8254 
8255         if( reconstructedExpression.empty() ) {
8256             if( lazyExpression ) {
8257                 ReusableStringStream rss;
8258                 rss << lazyExpression;
8259                 reconstructedExpression = rss.str();
8260             }
8261         }
8262         return reconstructedExpression;
8263     }
8264 
AssertionResult(AssertionInfo const & info,AssertionResultData const & data)8265     AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
8266     :   m_info( info ),
8267         m_resultData( data )
8268     {}
8269 
8270     // Result was a success
succeeded() const8271     bool AssertionResult::succeeded() const {
8272         return Catch::isOk( m_resultData.resultType );
8273     }
8274 
8275     // Result was a success, or failure is suppressed
isOk() const8276     bool AssertionResult::isOk() const {
8277         return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
8278     }
8279 
getResultType() const8280     ResultWas::OfType AssertionResult::getResultType() const {
8281         return m_resultData.resultType;
8282     }
8283 
hasExpression() const8284     bool AssertionResult::hasExpression() const {
8285         return !m_info.capturedExpression.empty();
8286     }
8287 
hasMessage() const8288     bool AssertionResult::hasMessage() const {
8289         return !m_resultData.message.empty();
8290     }
8291 
getExpression() const8292     std::string AssertionResult::getExpression() const {
8293         // Possibly overallocating by 3 characters should be basically free
8294         std::string expr; expr.reserve(m_info.capturedExpression.size() + 3);
8295         if (isFalseTest(m_info.resultDisposition)) {
8296             expr += "!(";
8297         }
8298         expr += m_info.capturedExpression;
8299         if (isFalseTest(m_info.resultDisposition)) {
8300             expr += ')';
8301         }
8302         return expr;
8303     }
8304 
getExpressionInMacro() const8305     std::string AssertionResult::getExpressionInMacro() const {
8306         std::string expr;
8307         if( m_info.macroName.empty() )
8308             expr = static_cast<std::string>(m_info.capturedExpression);
8309         else {
8310             expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
8311             expr += m_info.macroName;
8312             expr += "( ";
8313             expr += m_info.capturedExpression;
8314             expr += " )";
8315         }
8316         return expr;
8317     }
8318 
hasExpandedExpression() const8319     bool AssertionResult::hasExpandedExpression() const {
8320         return hasExpression() && getExpandedExpression() != getExpression();
8321     }
8322 
getExpandedExpression() const8323     std::string AssertionResult::getExpandedExpression() const {
8324         std::string expr = m_resultData.reconstructExpression();
8325         return expr.empty()
8326                 ? getExpression()
8327                 : expr;
8328     }
8329 
getMessage() const8330     std::string AssertionResult::getMessage() const {
8331         return m_resultData.message;
8332     }
getSourceInfo() const8333     SourceLineInfo AssertionResult::getSourceInfo() const {
8334         return m_info.lineInfo;
8335     }
8336 
getTestMacroName() const8337     StringRef AssertionResult::getTestMacroName() const {
8338         return m_info.macroName;
8339     }
8340 
8341 } // end namespace Catch
8342 // end catch_assertionresult.cpp
8343 // start catch_capture_matchers.cpp
8344 
8345 namespace Catch {
8346 
8347     using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
8348 
8349     // This is the general overload that takes a any string matcher
8350     // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
8351     // the Equals matcher (so the header does not mention matchers)
handleExceptionMatchExpr(AssertionHandler & handler,StringMatcher const & matcher,StringRef const & matcherString)8352     void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  ) {
8353         std::string exceptionMessage = Catch::translateActiveException();
8354         MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
8355         handler.handleExpr( expr );
8356     }
8357 
8358 } // namespace Catch
8359 // end catch_capture_matchers.cpp
8360 // start catch_commandline.cpp
8361 
8362 // start catch_commandline.h
8363 
8364 // start catch_clara.h
8365 
8366 // Use Catch's value for console width (store Clara's off to the side, if present)
8367 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
8368 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8369 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8370 #endif
8371 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
8372 
8373 #ifdef __clang__
8374 #pragma clang diagnostic push
8375 #pragma clang diagnostic ignored "-Wweak-vtables"
8376 #pragma clang diagnostic ignored "-Wexit-time-destructors"
8377 #pragma clang diagnostic ignored "-Wshadow"
8378 #endif
8379 
8380 // start clara.hpp
8381 // Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
8382 //
8383 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8384 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8385 //
8386 // See https://github.com/philsquared/Clara for more details
8387 
8388 // Clara v1.1.5
8389 
8390 
8391 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
8392 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
8393 #endif
8394 
8395 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8396 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
8397 #endif
8398 
8399 #ifndef CLARA_CONFIG_OPTIONAL_TYPE
8400 #ifdef __has_include
8401 #if __has_include(<optional>) && __cplusplus >= 201703L
8402 #include <optional>
8403 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional
8404 #endif
8405 #endif
8406 #endif
8407 
8408 // ----------- #included from clara_textflow.hpp -----------
8409 
8410 // TextFlowCpp
8411 //
8412 // A single-header library for wrapping and laying out basic text, by Phil Nash
8413 //
8414 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8415 // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8416 //
8417 // This project is hosted at https://github.com/philsquared/textflowcpp
8418 
8419 
8420 #include <cassert>
8421 #include <ostream>
8422 #include <sstream>
8423 #include <vector>
8424 
8425 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
8426 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
8427 #endif
8428 
8429 namespace Catch {
8430 namespace clara {
8431 namespace TextFlow {
8432 
isWhitespace(char c)8433 inline auto isWhitespace(char c) -> bool {
8434 	static std::string chars = " \t\n\r";
8435 	return chars.find(c) != std::string::npos;
8436 }
isBreakableBefore(char c)8437 inline auto isBreakableBefore(char c) -> bool {
8438 	static std::string chars = "[({<|";
8439 	return chars.find(c) != std::string::npos;
8440 }
isBreakableAfter(char c)8441 inline auto isBreakableAfter(char c) -> bool {
8442 	static std::string chars = "])}>.,:;*+-=&/\\";
8443 	return chars.find(c) != std::string::npos;
8444 }
8445 
8446 class Columns;
8447 
8448 class Column {
8449 	std::vector<std::string> m_strings;
8450 	size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
8451 	size_t m_indent = 0;
8452 	size_t m_initialIndent = std::string::npos;
8453 
8454 public:
8455 	class iterator {
8456 		friend Column;
8457 
8458 		Column const& m_column;
8459 		size_t m_stringIndex = 0;
8460 		size_t m_pos = 0;
8461 
8462 		size_t m_len = 0;
8463 		size_t m_end = 0;
8464 		bool m_suffix = false;
8465 
iterator(Column const & column,size_t stringIndex)8466 		iterator(Column const& column, size_t stringIndex)
8467 			: m_column(column),
8468 			m_stringIndex(stringIndex) {}
8469 
line() const8470 		auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
8471 
isBoundary(size_t at) const8472 		auto isBoundary(size_t at) const -> bool {
8473 			assert(at > 0);
8474 			assert(at <= line().size());
8475 
8476 			return at == line().size() ||
8477 				(isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
8478 				isBreakableBefore(line()[at]) ||
8479 				isBreakableAfter(line()[at - 1]);
8480 		}
8481 
calcLength()8482 		void calcLength() {
8483 			assert(m_stringIndex < m_column.m_strings.size());
8484 
8485 			m_suffix = false;
8486 			auto width = m_column.m_width - indent();
8487 			m_end = m_pos;
8488 			if (line()[m_pos] == '\n') {
8489 				++m_end;
8490 			}
8491 			while (m_end < line().size() && line()[m_end] != '\n')
8492 				++m_end;
8493 
8494 			if (m_end < m_pos + width) {
8495 				m_len = m_end - m_pos;
8496 			} else {
8497 				size_t len = width;
8498 				while (len > 0 && !isBoundary(m_pos + len))
8499 					--len;
8500 				while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
8501 					--len;
8502 
8503 				if (len > 0) {
8504 					m_len = len;
8505 				} else {
8506 					m_suffix = true;
8507 					m_len = width - 1;
8508 				}
8509 			}
8510 		}
8511 
indent() const8512 		auto indent() const -> size_t {
8513 			auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
8514 			return initial == std::string::npos ? m_column.m_indent : initial;
8515 		}
8516 
addIndentAndSuffix(std::string const & plain) const8517 		auto addIndentAndSuffix(std::string const &plain) const -> std::string {
8518 			return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);
8519 		}
8520 
8521 	public:
8522 		using difference_type = std::ptrdiff_t;
8523 		using value_type = std::string;
8524 		using pointer = value_type * ;
8525 		using reference = value_type & ;
8526 		using iterator_category = std::forward_iterator_tag;
8527 
iterator(Column const & column)8528 		explicit iterator(Column const& column) : m_column(column) {
8529 			assert(m_column.m_width > m_column.m_indent);
8530 			assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
8531 			calcLength();
8532 			if (m_len == 0)
8533 				m_stringIndex++; // Empty string
8534 		}
8535 
operator *() const8536 		auto operator *() const -> std::string {
8537 			assert(m_stringIndex < m_column.m_strings.size());
8538 			assert(m_pos <= m_end);
8539 			return addIndentAndSuffix(line().substr(m_pos, m_len));
8540 		}
8541 
operator ++()8542 		auto operator ++() -> iterator& {
8543 			m_pos += m_len;
8544 			if (m_pos < line().size() && line()[m_pos] == '\n')
8545 				m_pos += 1;
8546 			else
8547 				while (m_pos < line().size() && isWhitespace(line()[m_pos]))
8548 					++m_pos;
8549 
8550 			if (m_pos == line().size()) {
8551 				m_pos = 0;
8552 				++m_stringIndex;
8553 			}
8554 			if (m_stringIndex < m_column.m_strings.size())
8555 				calcLength();
8556 			return *this;
8557 		}
operator ++(int)8558 		auto operator ++(int) -> iterator {
8559 			iterator prev(*this);
8560 			operator++();
8561 			return prev;
8562 		}
8563 
operator ==(iterator const & other) const8564 		auto operator ==(iterator const& other) const -> bool {
8565 			return
8566 				m_pos == other.m_pos &&
8567 				m_stringIndex == other.m_stringIndex &&
8568 				&m_column == &other.m_column;
8569 		}
operator !=(iterator const & other) const8570 		auto operator !=(iterator const& other) const -> bool {
8571 			return !operator==(other);
8572 		}
8573 	};
8574 	using const_iterator = iterator;
8575 
Column(std::string const & text)8576 	explicit Column(std::string const& text) { m_strings.push_back(text); }
8577 
width(size_t newWidth)8578 	auto width(size_t newWidth) -> Column& {
8579 		assert(newWidth > 0);
8580 		m_width = newWidth;
8581 		return *this;
8582 	}
indent(size_t newIndent)8583 	auto indent(size_t newIndent) -> Column& {
8584 		m_indent = newIndent;
8585 		return *this;
8586 	}
initialIndent(size_t newIndent)8587 	auto initialIndent(size_t newIndent) -> Column& {
8588 		m_initialIndent = newIndent;
8589 		return *this;
8590 	}
8591 
width() const8592 	auto width() const -> size_t { return m_width; }
begin() const8593 	auto begin() const -> iterator { return iterator(*this); }
end() const8594 	auto end() const -> iterator { return { *this, m_strings.size() }; }
8595 
operator <<(std::ostream & os,Column const & col)8596 	inline friend std::ostream& operator << (std::ostream& os, Column const& col) {
8597 		bool first = true;
8598 		for (auto line : col) {
8599 			if (first)
8600 				first = false;
8601 			else
8602 				os << "\n";
8603 			os << line;
8604 		}
8605 		return os;
8606 	}
8607 
8608 	auto operator + (Column const& other)->Columns;
8609 
toString() const8610 	auto toString() const -> std::string {
8611 		std::ostringstream oss;
8612 		oss << *this;
8613 		return oss.str();
8614 	}
8615 };
8616 
8617 class Spacer : public Column {
8618 
8619 public:
Spacer(size_t spaceWidth)8620 	explicit Spacer(size_t spaceWidth) : Column("") {
8621 		width(spaceWidth);
8622 	}
8623 };
8624 
8625 class Columns {
8626 	std::vector<Column> m_columns;
8627 
8628 public:
8629 
8630 	class iterator {
8631 		friend Columns;
8632 		struct EndTag {};
8633 
8634 		std::vector<Column> const& m_columns;
8635 		std::vector<Column::iterator> m_iterators;
8636 		size_t m_activeIterators;
8637 
iterator(Columns const & columns,EndTag)8638 		iterator(Columns const& columns, EndTag)
8639 			: m_columns(columns.m_columns),
8640 			m_activeIterators(0) {
8641 			m_iterators.reserve(m_columns.size());
8642 
8643 			for (auto const& col : m_columns)
8644 				m_iterators.push_back(col.end());
8645 		}
8646 
8647 	public:
8648 		using difference_type = std::ptrdiff_t;
8649 		using value_type = std::string;
8650 		using pointer = value_type * ;
8651 		using reference = value_type & ;
8652 		using iterator_category = std::forward_iterator_tag;
8653 
iterator(Columns const & columns)8654 		explicit iterator(Columns const& columns)
8655 			: m_columns(columns.m_columns),
8656 			m_activeIterators(m_columns.size()) {
8657 			m_iterators.reserve(m_columns.size());
8658 
8659 			for (auto const& col : m_columns)
8660 				m_iterators.push_back(col.begin());
8661 		}
8662 
operator ==(iterator const & other) const8663 		auto operator ==(iterator const& other) const -> bool {
8664 			return m_iterators == other.m_iterators;
8665 		}
operator !=(iterator const & other) const8666 		auto operator !=(iterator const& other) const -> bool {
8667 			return m_iterators != other.m_iterators;
8668 		}
operator *() const8669 		auto operator *() const -> std::string {
8670 			std::string row, padding;
8671 
8672 			for (size_t i = 0; i < m_columns.size(); ++i) {
8673 				auto width = m_columns[i].width();
8674 				if (m_iterators[i] != m_columns[i].end()) {
8675 					std::string col = *m_iterators[i];
8676 					row += padding + col;
8677 					if (col.size() < width)
8678 						padding = std::string(width - col.size(), ' ');
8679 					else
8680 						padding = "";
8681 				} else {
8682 					padding += std::string(width, ' ');
8683 				}
8684 			}
8685 			return row;
8686 		}
operator ++()8687 		auto operator ++() -> iterator& {
8688 			for (size_t i = 0; i < m_columns.size(); ++i) {
8689 				if (m_iterators[i] != m_columns[i].end())
8690 					++m_iterators[i];
8691 			}
8692 			return *this;
8693 		}
operator ++(int)8694 		auto operator ++(int) -> iterator {
8695 			iterator prev(*this);
8696 			operator++();
8697 			return prev;
8698 		}
8699 	};
8700 	using const_iterator = iterator;
8701 
begin() const8702 	auto begin() const -> iterator { return iterator(*this); }
end() const8703 	auto end() const -> iterator { return { *this, iterator::EndTag() }; }
8704 
operator +=(Column const & col)8705 	auto operator += (Column const& col) -> Columns& {
8706 		m_columns.push_back(col);
8707 		return *this;
8708 	}
operator +(Column const & col)8709 	auto operator + (Column const& col) -> Columns {
8710 		Columns combined = *this;
8711 		combined += col;
8712 		return combined;
8713 	}
8714 
operator <<(std::ostream & os,Columns const & cols)8715 	inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) {
8716 
8717 		bool first = true;
8718 		for (auto line : cols) {
8719 			if (first)
8720 				first = false;
8721 			else
8722 				os << "\n";
8723 			os << line;
8724 		}
8725 		return os;
8726 	}
8727 
toString() const8728 	auto toString() const -> std::string {
8729 		std::ostringstream oss;
8730 		oss << *this;
8731 		return oss.str();
8732 	}
8733 };
8734 
operator +(Column const & other)8735 inline auto Column::operator + (Column const& other) -> Columns {
8736 	Columns cols;
8737 	cols += *this;
8738 	cols += other;
8739 	return cols;
8740 }
8741 }
8742 
8743 }
8744 }
8745 
8746 // ----------- end of #include from clara_textflow.hpp -----------
8747 // ........... back in clara.hpp
8748 
8749 #include <cctype>
8750 #include <string>
8751 #include <memory>
8752 #include <set>
8753 #include <algorithm>
8754 
8755 #if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
8756 #define CATCH_PLATFORM_WINDOWS
8757 #endif
8758 
8759 namespace Catch { namespace clara {
8760 namespace detail {
8761 
8762     // Traits for extracting arg and return type of lambdas (for single argument lambdas)
8763     template<typename L>
8764     struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
8765 
8766     template<typename ClassT, typename ReturnT, typename... Args>
8767     struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
8768         static const bool isValid = false;
8769     };
8770 
8771     template<typename ClassT, typename ReturnT, typename ArgT>
8772     struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
8773         static const bool isValid = true;
8774         using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
8775         using ReturnType = ReturnT;
8776     };
8777 
8778     class TokenStream;
8779 
8780     // Transport for raw args (copied from main args, or supplied via init list for testing)
8781     class Args {
8782         friend TokenStream;
8783         std::string m_exeName;
8784         std::vector<std::string> m_args;
8785 
8786     public:
Args(int argc,char const * const * argv)8787         Args( int argc, char const* const* argv )
8788             : m_exeName(argv[0]),
8789               m_args(argv + 1, argv + argc) {}
8790 
Args(std::initializer_list<std::string> args)8791         Args( std::initializer_list<std::string> args )
8792         :   m_exeName( *args.begin() ),
8793             m_args( args.begin()+1, args.end() )
8794         {}
8795 
exeName() const8796         auto exeName() const -> std::string {
8797             return m_exeName;
8798         }
8799     };
8800 
8801     // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string
8802     // may encode an option + its argument if the : or = form is used
8803     enum class TokenType {
8804         Option, Argument
8805     };
8806     struct Token {
8807         TokenType type;
8808         std::string token;
8809     };
8810 
isOptPrefix(char c)8811     inline auto isOptPrefix( char c ) -> bool {
8812         return c == '-'
8813 #ifdef CATCH_PLATFORM_WINDOWS
8814             || c == '/'
8815 #endif
8816         ;
8817     }
8818 
8819     // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled
8820     class TokenStream {
8821         using Iterator = std::vector<std::string>::const_iterator;
8822         Iterator it;
8823         Iterator itEnd;
8824         std::vector<Token> m_tokenBuffer;
8825 
loadBuffer()8826         void loadBuffer() {
8827             m_tokenBuffer.resize( 0 );
8828 
8829             // Skip any empty strings
8830             while( it != itEnd && it->empty() )
8831                 ++it;
8832 
8833             if( it != itEnd ) {
8834                 auto const &next = *it;
8835                 if( isOptPrefix( next[0] ) ) {
8836                     auto delimiterPos = next.find_first_of( " :=" );
8837                     if( delimiterPos != std::string::npos ) {
8838                         m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
8839                         m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
8840                     } else {
8841                         if( next[1] != '-' && next.size() > 2 ) {
8842                             std::string opt = "- ";
8843                             for( size_t i = 1; i < next.size(); ++i ) {
8844                                 opt[1] = next[i];
8845                                 m_tokenBuffer.push_back( { TokenType::Option, opt } );
8846                             }
8847                         } else {
8848                             m_tokenBuffer.push_back( { TokenType::Option, next } );
8849                         }
8850                     }
8851                 } else {
8852                     m_tokenBuffer.push_back( { TokenType::Argument, next } );
8853                 }
8854             }
8855         }
8856 
8857     public:
TokenStream(Args const & args)8858         explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
8859 
TokenStream(Iterator it,Iterator itEnd)8860         TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
8861             loadBuffer();
8862         }
8863 
operator bool() const8864         explicit operator bool() const {
8865             return !m_tokenBuffer.empty() || it != itEnd;
8866         }
8867 
count() const8868         auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
8869 
operator *() const8870         auto operator*() const -> Token {
8871             assert( !m_tokenBuffer.empty() );
8872             return m_tokenBuffer.front();
8873         }
8874 
operator ->() const8875         auto operator->() const -> Token const * {
8876             assert( !m_tokenBuffer.empty() );
8877             return &m_tokenBuffer.front();
8878         }
8879 
operator ++()8880         auto operator++() -> TokenStream & {
8881             if( m_tokenBuffer.size() >= 2 ) {
8882                 m_tokenBuffer.erase( m_tokenBuffer.begin() );
8883             } else {
8884                 if( it != itEnd )
8885                     ++it;
8886                 loadBuffer();
8887             }
8888             return *this;
8889         }
8890     };
8891 
8892     class ResultBase {
8893     public:
8894         enum Type {
8895             Ok, LogicError, RuntimeError
8896         };
8897 
8898     protected:
ResultBase(Type type)8899         ResultBase( Type type ) : m_type( type ) {}
8900         virtual ~ResultBase() = default;
8901 
8902         virtual void enforceOk() const = 0;
8903 
8904         Type m_type;
8905     };
8906 
8907     template<typename T>
8908     class ResultValueBase : public ResultBase {
8909     public:
value() const8910         auto value() const -> T const & {
8911             enforceOk();
8912             return m_value;
8913         }
8914 
8915     protected:
ResultValueBase(Type type)8916         ResultValueBase( Type type ) : ResultBase( type ) {}
8917 
ResultValueBase(ResultValueBase const & other)8918         ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) {
8919             if( m_type == ResultBase::Ok )
8920                 new( &m_value ) T( other.m_value );
8921         }
8922 
ResultValueBase(Type,T const & value)8923         ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {
8924             new( &m_value ) T( value );
8925         }
8926 
operator =(ResultValueBase const & other)8927         auto operator=( ResultValueBase const &other ) -> ResultValueBase & {
8928             if( m_type == ResultBase::Ok )
8929                 m_value.~T();
8930             ResultBase::operator=(other);
8931             if( m_type == ResultBase::Ok )
8932                 new( &m_value ) T( other.m_value );
8933             return *this;
8934         }
8935 
~ResultValueBase()8936         ~ResultValueBase() override {
8937             if( m_type == Ok )
8938                 m_value.~T();
8939         }
8940 
8941         union {
8942             T m_value;
8943         };
8944     };
8945 
8946     template<>
8947     class ResultValueBase<void> : public ResultBase {
8948     protected:
8949         using ResultBase::ResultBase;
8950     };
8951 
8952     template<typename T = void>
8953     class BasicResult : public ResultValueBase<T> {
8954     public:
8955         template<typename U>
BasicResult(BasicResult<U> const & other)8956         explicit BasicResult( BasicResult<U> const &other )
8957         :   ResultValueBase<T>( other.type() ),
8958             m_errorMessage( other.errorMessage() )
8959         {
8960             assert( type() != ResultBase::Ok );
8961         }
8962 
8963         template<typename U>
ok(U const & value)8964         static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; }
ok()8965         static auto ok() -> BasicResult { return { ResultBase::Ok }; }
logicError(std::string const & message)8966         static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; }
runtimeError(std::string const & message)8967         static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; }
8968 
operator bool() const8969         explicit operator bool() const { return m_type == ResultBase::Ok; }
type() const8970         auto type() const -> ResultBase::Type { return m_type; }
errorMessage() const8971         auto errorMessage() const -> std::string { return m_errorMessage; }
8972 
8973     protected:
enforceOk() const8974         void enforceOk() const override {
8975 
8976             // Errors shouldn't reach this point, but if they do
8977             // the actual error message will be in m_errorMessage
8978             assert( m_type != ResultBase::LogicError );
8979             assert( m_type != ResultBase::RuntimeError );
8980             if( m_type != ResultBase::Ok )
8981                 std::abort();
8982         }
8983 
8984         std::string m_errorMessage; // Only populated if resultType is an error
8985 
BasicResult(ResultBase::Type type,std::string const & message)8986         BasicResult( ResultBase::Type type, std::string const &message )
8987         :   ResultValueBase<T>(type),
8988             m_errorMessage(message)
8989         {
8990             assert( m_type != ResultBase::Ok );
8991         }
8992 
8993         using ResultValueBase<T>::ResultValueBase;
8994         using ResultBase::m_type;
8995     };
8996 
8997     enum class ParseResultType {
8998         Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
8999     };
9000 
9001     class ParseState {
9002     public:
9003 
ParseState(ParseResultType type,TokenStream const & remainingTokens)9004         ParseState( ParseResultType type, TokenStream const &remainingTokens )
9005         : m_type(type),
9006           m_remainingTokens( remainingTokens )
9007         {}
9008 
type() const9009         auto type() const -> ParseResultType { return m_type; }
remainingTokens() const9010         auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
9011 
9012     private:
9013         ParseResultType m_type;
9014         TokenStream m_remainingTokens;
9015     };
9016 
9017     using Result = BasicResult<void>;
9018     using ParserResult = BasicResult<ParseResultType>;
9019     using InternalParseResult = BasicResult<ParseState>;
9020 
9021     struct HelpColumns {
9022         std::string left;
9023         std::string right;
9024     };
9025 
9026     template<typename T>
convertInto(std::string const & source,T & target)9027     inline auto convertInto( std::string const &source, T& target ) -> ParserResult {
9028         std::stringstream ss;
9029         ss << source;
9030         ss >> target;
9031         if( ss.fail() )
9032             return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" );
9033         else
9034             return ParserResult::ok( ParseResultType::Matched );
9035     }
convertInto(std::string const & source,std::string & target)9036     inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult {
9037         target = source;
9038         return ParserResult::ok( ParseResultType::Matched );
9039     }
convertInto(std::string const & source,bool & target)9040     inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
9041         std::string srcLC = source;
9042         std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } );
9043         if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
9044             target = true;
9045         else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
9046             target = false;
9047         else
9048             return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
9049         return ParserResult::ok( ParseResultType::Matched );
9050     }
9051 #ifdef CLARA_CONFIG_OPTIONAL_TYPE
9052     template<typename T>
convertInto(std::string const & source,CLARA_CONFIG_OPTIONAL_TYPE<T> & target)9053     inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
9054         T temp;
9055         auto result = convertInto( source, temp );
9056         if( result )
9057             target = std::move(temp);
9058         return result;
9059     }
9060 #endif // CLARA_CONFIG_OPTIONAL_TYPE
9061 
9062     struct NonCopyable {
9063         NonCopyable() = default;
9064         NonCopyable( NonCopyable const & ) = delete;
9065         NonCopyable( NonCopyable && ) = delete;
9066         NonCopyable &operator=( NonCopyable const & ) = delete;
9067         NonCopyable &operator=( NonCopyable && ) = delete;
9068     };
9069 
9070     struct BoundRef : NonCopyable {
9071         virtual ~BoundRef() = default;
isContainerCatch::clara::detail::BoundRef9072         virtual auto isContainer() const -> bool { return false; }
isFlagCatch::clara::detail::BoundRef9073         virtual auto isFlag() const -> bool { return false; }
9074     };
9075     struct BoundValueRefBase : BoundRef {
9076         virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
9077     };
9078     struct BoundFlagRefBase : BoundRef {
9079         virtual auto setFlag( bool flag ) -> ParserResult = 0;
isFlagCatch::clara::detail::BoundFlagRefBase9080         virtual auto isFlag() const -> bool { return true; }
9081     };
9082 
9083     template<typename T>
9084     struct BoundValueRef : BoundValueRefBase {
9085         T &m_ref;
9086 
BoundValueRefCatch::clara::detail::BoundValueRef9087         explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
9088 
setValueCatch::clara::detail::BoundValueRef9089         auto setValue( std::string const &arg ) -> ParserResult override {
9090             return convertInto( arg, m_ref );
9091         }
9092     };
9093 
9094     template<typename T>
9095     struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
9096         std::vector<T> &m_ref;
9097 
BoundValueRefCatch::clara::detail::BoundValueRef9098         explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
9099 
isContainerCatch::clara::detail::BoundValueRef9100         auto isContainer() const -> bool override { return true; }
9101 
setValueCatch::clara::detail::BoundValueRef9102         auto setValue( std::string const &arg ) -> ParserResult override {
9103             T temp;
9104             auto result = convertInto( arg, temp );
9105             if( result )
9106                 m_ref.push_back( temp );
9107             return result;
9108         }
9109     };
9110 
9111     struct BoundFlagRef : BoundFlagRefBase {
9112         bool &m_ref;
9113 
BoundFlagRefCatch::clara::detail::BoundFlagRef9114         explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}
9115 
setFlagCatch::clara::detail::BoundFlagRef9116         auto setFlag( bool flag ) -> ParserResult override {
9117             m_ref = flag;
9118             return ParserResult::ok( ParseResultType::Matched );
9119         }
9120     };
9121 
9122     template<typename ReturnType>
9123     struct LambdaInvoker {
9124         static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" );
9125 
9126         template<typename L, typename ArgType>
invokeCatch::clara::detail::LambdaInvoker9127         static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
9128             return lambda( arg );
9129         }
9130     };
9131 
9132     template<>
9133     struct LambdaInvoker<void> {
9134         template<typename L, typename ArgType>
invokeCatch::clara::detail::LambdaInvoker9135         static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
9136             lambda( arg );
9137             return ParserResult::ok( ParseResultType::Matched );
9138         }
9139     };
9140 
9141     template<typename ArgType, typename L>
invokeLambda(L const & lambda,std::string const & arg)9142     inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
9143         ArgType temp{};
9144         auto result = convertInto( arg, temp );
9145         return !result
9146            ? result
9147            : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
9148     }
9149 
9150     template<typename L>
9151     struct BoundLambda : BoundValueRefBase {
9152         L m_lambda;
9153 
9154         static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
BoundLambdaCatch::clara::detail::BoundLambda9155         explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}
9156 
setValueCatch::clara::detail::BoundLambda9157         auto setValue( std::string const &arg ) -> ParserResult override {
9158             return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
9159         }
9160     };
9161 
9162     template<typename L>
9163     struct BoundFlagLambda : BoundFlagRefBase {
9164         L m_lambda;
9165 
9166         static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
9167         static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" );
9168 
BoundFlagLambdaCatch::clara::detail::BoundFlagLambda9169         explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}
9170 
setFlagCatch::clara::detail::BoundFlagLambda9171         auto setFlag( bool flag ) -> ParserResult override {
9172             return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
9173         }
9174     };
9175 
9176     enum class Optionality { Optional, Required };
9177 
9178     struct Parser;
9179 
9180     class ParserBase {
9181     public:
9182         virtual ~ParserBase() = default;
validate() const9183         virtual auto validate() const -> Result { return Result::ok(); }
9184         virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult  = 0;
cardinality() const9185         virtual auto cardinality() const -> size_t { return 1; }
9186 
parse(Args const & args) const9187         auto parse( Args const &args ) const -> InternalParseResult {
9188             return parse( args.exeName(), TokenStream( args ) );
9189         }
9190     };
9191 
9192     template<typename DerivedT>
9193     class ComposableParserImpl : public ParserBase {
9194     public:
9195         template<typename T>
9196         auto operator|( T const &other ) const -> Parser;
9197 
9198 		template<typename T>
9199         auto operator+( T const &other ) const -> Parser;
9200     };
9201 
9202     // Common code and state for Args and Opts
9203     template<typename DerivedT>
9204     class ParserRefImpl : public ComposableParserImpl<DerivedT> {
9205     protected:
9206         Optionality m_optionality = Optionality::Optional;
9207         std::shared_ptr<BoundRef> m_ref;
9208         std::string m_hint;
9209         std::string m_description;
9210 
ParserRefImpl(std::shared_ptr<BoundRef> const & ref)9211         explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
9212 
9213     public:
9214         template<typename T>
ParserRefImpl(T & ref,std::string const & hint)9215         ParserRefImpl( T &ref, std::string const &hint )
9216         :   m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
9217             m_hint( hint )
9218         {}
9219 
9220         template<typename LambdaT>
ParserRefImpl(LambdaT const & ref,std::string const & hint)9221         ParserRefImpl( LambdaT const &ref, std::string const &hint )
9222         :   m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
9223             m_hint(hint)
9224         {}
9225 
operator ()(std::string const & description)9226         auto operator()( std::string const &description ) -> DerivedT & {
9227             m_description = description;
9228             return static_cast<DerivedT &>( *this );
9229         }
9230 
optional()9231         auto optional() -> DerivedT & {
9232             m_optionality = Optionality::Optional;
9233             return static_cast<DerivedT &>( *this );
9234         };
9235 
required()9236         auto required() -> DerivedT & {
9237             m_optionality = Optionality::Required;
9238             return static_cast<DerivedT &>( *this );
9239         };
9240 
isOptional() const9241         auto isOptional() const -> bool {
9242             return m_optionality == Optionality::Optional;
9243         }
9244 
cardinality() const9245         auto cardinality() const -> size_t override {
9246             if( m_ref->isContainer() )
9247                 return 0;
9248             else
9249                 return 1;
9250         }
9251 
hint() const9252         auto hint() const -> std::string { return m_hint; }
9253     };
9254 
9255     class ExeName : public ComposableParserImpl<ExeName> {
9256         std::shared_ptr<std::string> m_name;
9257         std::shared_ptr<BoundValueRefBase> m_ref;
9258 
9259         template<typename LambdaT>
makeRef(LambdaT const & lambda)9260         static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
9261             return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
9262         }
9263 
9264     public:
ExeName()9265         ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
9266 
ExeName(std::string & ref)9267         explicit ExeName( std::string &ref ) : ExeName() {
9268             m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
9269         }
9270 
9271         template<typename LambdaT>
ExeName(LambdaT const & lambda)9272         explicit ExeName( LambdaT const& lambda ) : ExeName() {
9273             m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );
9274         }
9275 
9276         // The exe name is not parsed out of the normal tokens, but is handled specially
parse(std::string const &,TokenStream const & tokens) const9277         auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
9278             return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
9279         }
9280 
name() const9281         auto name() const -> std::string { return *m_name; }
set(std::string const & newName)9282         auto set( std::string const& newName ) -> ParserResult {
9283 
9284             auto lastSlash = newName.find_last_of( "\\/" );
9285             auto filename = ( lastSlash == std::string::npos )
9286                     ? newName
9287                     : newName.substr( lastSlash+1 );
9288 
9289             *m_name = filename;
9290             if( m_ref )
9291                 return m_ref->setValue( filename );
9292             else
9293                 return ParserResult::ok( ParseResultType::Matched );
9294         }
9295     };
9296 
9297     class Arg : public ParserRefImpl<Arg> {
9298     public:
9299         using ParserRefImpl::ParserRefImpl;
9300 
parse(std::string const &,TokenStream const & tokens) const9301         auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override {
9302             auto validationResult = validate();
9303             if( !validationResult )
9304                 return InternalParseResult( validationResult );
9305 
9306             auto remainingTokens = tokens;
9307             auto const &token = *remainingTokens;
9308             if( token.type != TokenType::Argument )
9309                 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
9310 
9311             assert( !m_ref->isFlag() );
9312             auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
9313 
9314             auto result = valueRef->setValue( remainingTokens->token );
9315             if( !result )
9316                 return InternalParseResult( result );
9317             else
9318                 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
9319         }
9320     };
9321 
normaliseOpt(std::string const & optName)9322     inline auto normaliseOpt( std::string const &optName ) -> std::string {
9323 #ifdef CATCH_PLATFORM_WINDOWS
9324         if( optName[0] == '/' )
9325             return "-" + optName.substr( 1 );
9326         else
9327 #endif
9328             return optName;
9329     }
9330 
9331     class Opt : public ParserRefImpl<Opt> {
9332     protected:
9333         std::vector<std::string> m_optNames;
9334 
9335     public:
9336         template<typename LambdaT>
Opt(LambdaT const & ref)9337         explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
9338 
Opt(bool & ref)9339         explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}
9340 
9341         template<typename LambdaT>
Opt(LambdaT const & ref,std::string const & hint)9342         Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
9343 
9344         template<typename T>
Opt(T & ref,std::string const & hint)9345         Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
9346 
operator [](std::string const & optName)9347         auto operator[]( std::string const &optName ) -> Opt & {
9348             m_optNames.push_back( optName );
9349             return *this;
9350         }
9351 
getHelpColumns() const9352         auto getHelpColumns() const -> std::vector<HelpColumns> {
9353             std::ostringstream oss;
9354             bool first = true;
9355             for( auto const &opt : m_optNames ) {
9356                 if (first)
9357                     first = false;
9358                 else
9359                     oss << ", ";
9360                 oss << opt;
9361             }
9362             if( !m_hint.empty() )
9363                 oss << " <" << m_hint << ">";
9364             return { { oss.str(), m_description } };
9365         }
9366 
isMatch(std::string const & optToken) const9367         auto isMatch( std::string const &optToken ) const -> bool {
9368             auto normalisedToken = normaliseOpt( optToken );
9369             for( auto const &name : m_optNames ) {
9370                 if( normaliseOpt( name ) == normalisedToken )
9371                     return true;
9372             }
9373             return false;
9374         }
9375 
9376         using ParserBase::parse;
9377 
parse(std::string const &,TokenStream const & tokens) const9378         auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
9379             auto validationResult = validate();
9380             if( !validationResult )
9381                 return InternalParseResult( validationResult );
9382 
9383             auto remainingTokens = tokens;
9384             if( remainingTokens && remainingTokens->type == TokenType::Option ) {
9385                 auto const &token = *remainingTokens;
9386                 if( isMatch(token.token ) ) {
9387                     if( m_ref->isFlag() ) {
9388                         auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
9389                         auto result = flagRef->setFlag( true );
9390                         if( !result )
9391                             return InternalParseResult( result );
9392                         if( result.value() == ParseResultType::ShortCircuitAll )
9393                             return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
9394                     } else {
9395                         auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
9396                         ++remainingTokens;
9397                         if( !remainingTokens )
9398                             return InternalParseResult::runtimeError( "Expected argument following " + token.token );
9399                         auto const &argToken = *remainingTokens;
9400                         if( argToken.type != TokenType::Argument )
9401                             return InternalParseResult::runtimeError( "Expected argument following " + token.token );
9402                         auto result = valueRef->setValue( argToken.token );
9403                         if( !result )
9404                             return InternalParseResult( result );
9405                         if( result.value() == ParseResultType::ShortCircuitAll )
9406                             return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
9407                     }
9408                     return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
9409                 }
9410             }
9411             return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
9412         }
9413 
validate() const9414         auto validate() const -> Result override {
9415             if( m_optNames.empty() )
9416                 return Result::logicError( "No options supplied to Opt" );
9417             for( auto const &name : m_optNames ) {
9418                 if( name.empty() )
9419                     return Result::logicError( "Option name cannot be empty" );
9420 #ifdef CATCH_PLATFORM_WINDOWS
9421                 if( name[0] != '-' && name[0] != '/' )
9422                     return Result::logicError( "Option name must begin with '-' or '/'" );
9423 #else
9424                 if( name[0] != '-' )
9425                     return Result::logicError( "Option name must begin with '-'" );
9426 #endif
9427             }
9428             return ParserRefImpl::validate();
9429         }
9430     };
9431 
9432     struct Help : Opt {
HelpCatch::clara::detail::Help9433         Help( bool &showHelpFlag )
9434         :   Opt([&]( bool flag ) {
9435                 showHelpFlag = flag;
9436                 return ParserResult::ok( ParseResultType::ShortCircuitAll );
9437             })
9438         {
9439             static_cast<Opt &>( *this )
9440                     ("display usage information")
9441                     ["-?"]["-h"]["--help"]
9442                     .optional();
9443         }
9444     };
9445 
9446     struct Parser : ParserBase {
9447 
9448         mutable ExeName m_exeName;
9449         std::vector<Opt> m_options;
9450         std::vector<Arg> m_args;
9451 
operator |=Catch::clara::detail::Parser9452         auto operator|=( ExeName const &exeName ) -> Parser & {
9453             m_exeName = exeName;
9454             return *this;
9455         }
9456 
operator |=Catch::clara::detail::Parser9457         auto operator|=( Arg const &arg ) -> Parser & {
9458             m_args.push_back(arg);
9459             return *this;
9460         }
9461 
operator |=Catch::clara::detail::Parser9462         auto operator|=( Opt const &opt ) -> Parser & {
9463             m_options.push_back(opt);
9464             return *this;
9465         }
9466 
operator |=Catch::clara::detail::Parser9467         auto operator|=( Parser const &other ) -> Parser & {
9468             m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
9469             m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
9470             return *this;
9471         }
9472 
9473         template<typename T>
operator |Catch::clara::detail::Parser9474         auto operator|( T const &other ) const -> Parser {
9475             return Parser( *this ) |= other;
9476         }
9477 
9478         // Forward deprecated interface with '+' instead of '|'
9479         template<typename T>
operator +=Catch::clara::detail::Parser9480         auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
9481         template<typename T>
operator +Catch::clara::detail::Parser9482         auto operator+( T const &other ) const -> Parser { return operator|( other ); }
9483 
getHelpColumnsCatch::clara::detail::Parser9484         auto getHelpColumns() const -> std::vector<HelpColumns> {
9485             std::vector<HelpColumns> cols;
9486             for (auto const &o : m_options) {
9487                 auto childCols = o.getHelpColumns();
9488                 cols.insert( cols.end(), childCols.begin(), childCols.end() );
9489             }
9490             return cols;
9491         }
9492 
writeToStreamCatch::clara::detail::Parser9493         void writeToStream( std::ostream &os ) const {
9494             if (!m_exeName.name().empty()) {
9495                 os << "usage:\n" << "  " << m_exeName.name() << " ";
9496                 bool required = true, first = true;
9497                 for( auto const &arg : m_args ) {
9498                     if (first)
9499                         first = false;
9500                     else
9501                         os << " ";
9502                     if( arg.isOptional() && required ) {
9503                         os << "[";
9504                         required = false;
9505                     }
9506                     os << "<" << arg.hint() << ">";
9507                     if( arg.cardinality() == 0 )
9508                         os << " ... ";
9509                 }
9510                 if( !required )
9511                     os << "]";
9512                 if( !m_options.empty() )
9513                     os << " options";
9514                 os << "\n\nwhere options are:" << std::endl;
9515             }
9516 
9517             auto rows = getHelpColumns();
9518             size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
9519             size_t optWidth = 0;
9520             for( auto const &cols : rows )
9521                 optWidth = (std::max)(optWidth, cols.left.size() + 2);
9522 
9523             optWidth = (std::min)(optWidth, consoleWidth/2);
9524 
9525             for( auto const &cols : rows ) {
9526                 auto row =
9527                         TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
9528                         TextFlow::Spacer(4) +
9529                         TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
9530                 os << row << std::endl;
9531             }
9532         }
9533 
operator <<(std::ostream & os,Parser const & parser)9534         friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& {
9535             parser.writeToStream( os );
9536             return os;
9537         }
9538 
validateCatch::clara::detail::Parser9539         auto validate() const -> Result override {
9540             for( auto const &opt : m_options ) {
9541                 auto result = opt.validate();
9542                 if( !result )
9543                     return result;
9544             }
9545             for( auto const &arg : m_args ) {
9546                 auto result = arg.validate();
9547                 if( !result )
9548                     return result;
9549             }
9550             return Result::ok();
9551         }
9552 
9553         using ParserBase::parse;
9554 
parseCatch::clara::detail::Parser9555         auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override {
9556 
9557             struct ParserInfo {
9558                 ParserBase const* parser = nullptr;
9559                 size_t count = 0;
9560             };
9561             const size_t totalParsers = m_options.size() + m_args.size();
9562             assert( totalParsers < 512 );
9563             // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do
9564             ParserInfo parseInfos[512];
9565 
9566             {
9567                 size_t i = 0;
9568                 for (auto const &opt : m_options) parseInfos[i++].parser = &opt;
9569                 for (auto const &arg : m_args) parseInfos[i++].parser = &arg;
9570             }
9571 
9572             m_exeName.set( exeName );
9573 
9574             auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
9575             while( result.value().remainingTokens() ) {
9576                 bool tokenParsed = false;
9577 
9578                 for( size_t i = 0; i < totalParsers; ++i ) {
9579                     auto&  parseInfo = parseInfos[i];
9580                     if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
9581                         result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
9582                         if (!result)
9583                             return result;
9584                         if (result.value().type() != ParseResultType::NoMatch) {
9585                             tokenParsed = true;
9586                             ++parseInfo.count;
9587                             break;
9588                         }
9589                     }
9590                 }
9591 
9592                 if( result.value().type() == ParseResultType::ShortCircuitAll )
9593                     return result;
9594                 if( !tokenParsed )
9595                     return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token );
9596             }
9597             // !TBD Check missing required options
9598             return result;
9599         }
9600     };
9601 
9602     template<typename DerivedT>
9603     template<typename T>
operator |(T const & other) const9604     auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser {
9605         return Parser() | static_cast<DerivedT const &>( *this ) | other;
9606     }
9607 } // namespace detail
9608 
9609 // A Combined parser
9610 using detail::Parser;
9611 
9612 // A parser for options
9613 using detail::Opt;
9614 
9615 // A parser for arguments
9616 using detail::Arg;
9617 
9618 // Wrapper for argc, argv from main()
9619 using detail::Args;
9620 
9621 // Specifies the name of the executable
9622 using detail::ExeName;
9623 
9624 // Convenience wrapper for option parser that specifies the help option
9625 using detail::Help;
9626 
9627 // enum of result types from a parse
9628 using detail::ParseResultType;
9629 
9630 // Result type for parser operation
9631 using detail::ParserResult;
9632 
9633 }} // namespace Catch::clara
9634 
9635 // end clara.hpp
9636 #ifdef __clang__
9637 #pragma clang diagnostic pop
9638 #endif
9639 
9640 // Restore Clara's value for console width, if present
9641 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
9642 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
9643 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
9644 #endif
9645 
9646 // end catch_clara.h
9647 namespace Catch {
9648 
9649     clara::Parser makeCommandLineParser( ConfigData& config );
9650 
9651 } // end namespace Catch
9652 
9653 // end catch_commandline.h
9654 #include <fstream>
9655 #include <ctime>
9656 
9657 namespace Catch {
9658 
makeCommandLineParser(ConfigData & config)9659     clara::Parser makeCommandLineParser( ConfigData& config ) {
9660 
9661         using namespace clara;
9662 
9663         auto const setWarning = [&]( std::string const& warning ) {
9664                 auto warningSet = [&]() {
9665                     if( warning == "NoAssertions" )
9666                         return WarnAbout::NoAssertions;
9667 
9668                     if ( warning == "NoTests" )
9669                         return WarnAbout::NoTests;
9670 
9671                     return WarnAbout::Nothing;
9672                 }();
9673 
9674                 if (warningSet == WarnAbout::Nothing)
9675                     return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );
9676                 config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );
9677                 return ParserResult::ok( ParseResultType::Matched );
9678             };
9679         auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
9680                 std::ifstream f( filename.c_str() );
9681                 if( !f.is_open() )
9682                     return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" );
9683 
9684                 std::string line;
9685                 while( std::getline( f, line ) ) {
9686                     line = trim(line);
9687                     if( !line.empty() && !startsWith( line, '#' ) ) {
9688                         if( !startsWith( line, '"' ) )
9689                             line = '"' + line + '"';
9690                         config.testsOrTags.push_back( line );
9691                         config.testsOrTags.emplace_back( "," );
9692                     }
9693                 }
9694                 //Remove comma in the end
9695                 if(!config.testsOrTags.empty())
9696                     config.testsOrTags.erase( config.testsOrTags.end()-1 );
9697 
9698                 return ParserResult::ok( ParseResultType::Matched );
9699             };
9700         auto const setTestOrder = [&]( std::string const& order ) {
9701                 if( startsWith( "declared", order ) )
9702                     config.runOrder = RunTests::InDeclarationOrder;
9703                 else if( startsWith( "lexical", order ) )
9704                     config.runOrder = RunTests::InLexicographicalOrder;
9705                 else if( startsWith( "random", order ) )
9706                     config.runOrder = RunTests::InRandomOrder;
9707                 else
9708                     return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" );
9709                 return ParserResult::ok( ParseResultType::Matched );
9710             };
9711         auto const setRngSeed = [&]( std::string const& seed ) {
9712                 if( seed != "time" )
9713                     return clara::detail::convertInto( seed, config.rngSeed );
9714                 config.rngSeed = static_cast<unsigned int>( std::time(nullptr) );
9715                 return ParserResult::ok( ParseResultType::Matched );
9716             };
9717         auto const setColourUsage = [&]( std::string const& useColour ) {
9718                     auto mode = toLower( useColour );
9719 
9720                     if( mode == "yes" )
9721                         config.useColour = UseColour::Yes;
9722                     else if( mode == "no" )
9723                         config.useColour = UseColour::No;
9724                     else if( mode == "auto" )
9725                         config.useColour = UseColour::Auto;
9726                     else
9727                         return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" );
9728                 return ParserResult::ok( ParseResultType::Matched );
9729             };
9730         auto const setWaitForKeypress = [&]( std::string const& keypress ) {
9731                 auto keypressLc = toLower( keypress );
9732                 if (keypressLc == "never")
9733                     config.waitForKeypress = WaitForKeypress::Never;
9734                 else if( keypressLc == "start" )
9735                     config.waitForKeypress = WaitForKeypress::BeforeStart;
9736                 else if( keypressLc == "exit" )
9737                     config.waitForKeypress = WaitForKeypress::BeforeExit;
9738                 else if( keypressLc == "both" )
9739                     config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
9740                 else
9741                     return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" );
9742             return ParserResult::ok( ParseResultType::Matched );
9743             };
9744         auto const setVerbosity = [&]( std::string const& verbosity ) {
9745             auto lcVerbosity = toLower( verbosity );
9746             if( lcVerbosity == "quiet" )
9747                 config.verbosity = Verbosity::Quiet;
9748             else if( lcVerbosity == "normal" )
9749                 config.verbosity = Verbosity::Normal;
9750             else if( lcVerbosity == "high" )
9751                 config.verbosity = Verbosity::High;
9752             else
9753                 return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" );
9754             return ParserResult::ok( ParseResultType::Matched );
9755         };
9756         auto const setReporter = [&]( std::string const& reporter ) {
9757             IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
9758 
9759             auto lcReporter = toLower( reporter );
9760             auto result = factories.find( lcReporter );
9761 
9762             if( factories.end() != result )
9763                 config.reporterName = lcReporter;
9764             else
9765                 return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" );
9766             return ParserResult::ok( ParseResultType::Matched );
9767         };
9768 
9769         auto cli
9770             = ExeName( config.processName )
9771             | Help( config.showHelp )
9772             | Opt( config.listTests )
9773                 ["-l"]["--list-tests"]
9774                 ( "list all/matching test cases" )
9775             | Opt( config.listTags )
9776                 ["-t"]["--list-tags"]
9777                 ( "list all/matching tags" )
9778             | Opt( config.showSuccessfulTests )
9779                 ["-s"]["--success"]
9780                 ( "include successful tests in output" )
9781             | Opt( config.shouldDebugBreak )
9782                 ["-b"]["--break"]
9783                 ( "break into debugger on failure" )
9784             | Opt( config.noThrow )
9785                 ["-e"]["--nothrow"]
9786                 ( "skip exception tests" )
9787             | Opt( config.showInvisibles )
9788                 ["-i"]["--invisibles"]
9789                 ( "show invisibles (tabs, newlines)" )
9790             | Opt( config.outputFilename, "filename" )
9791                 ["-o"]["--out"]
9792                 ( "output filename" )
9793             | Opt( setReporter, "name" )
9794                 ["-r"]["--reporter"]
9795                 ( "reporter to use (defaults to console)" )
9796             | Opt( config.name, "name" )
9797                 ["-n"]["--name"]
9798                 ( "suite name" )
9799             | Opt( [&]( bool ){ config.abortAfter = 1; } )
9800                 ["-a"]["--abort"]
9801                 ( "abort at first failure" )
9802             | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
9803                 ["-x"]["--abortx"]
9804                 ( "abort after x failures" )
9805             | Opt( setWarning, "warning name" )
9806                 ["-w"]["--warn"]
9807                 ( "enable warnings" )
9808             | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
9809                 ["-d"]["--durations"]
9810                 ( "show test durations" )
9811             | Opt( loadTestNamesFromFile, "filename" )
9812                 ["-f"]["--input-file"]
9813                 ( "load test names to run from a file" )
9814             | Opt( config.filenamesAsTags )
9815                 ["-#"]["--filenames-as-tags"]
9816                 ( "adds a tag for the filename" )
9817             | Opt( config.sectionsToRun, "section name" )
9818                 ["-c"]["--section"]
9819                 ( "specify section to run" )
9820             | Opt( setVerbosity, "quiet|normal|high" )
9821                 ["-v"]["--verbosity"]
9822                 ( "set output verbosity" )
9823             | Opt( config.listTestNamesOnly )
9824                 ["--list-test-names-only"]
9825                 ( "list all/matching test cases names only" )
9826             | Opt( config.listReporters )
9827                 ["--list-reporters"]
9828                 ( "list all reporters" )
9829             | Opt( setTestOrder, "decl|lex|rand" )
9830                 ["--order"]
9831                 ( "test case order (defaults to decl)" )
9832             | Opt( setRngSeed, "'time'|number" )
9833                 ["--rng-seed"]
9834                 ( "set a specific seed for random numbers" )
9835             | Opt( setColourUsage, "yes|no" )
9836                 ["--use-colour"]
9837                 ( "should output be colourised" )
9838             | Opt( config.libIdentify )
9839                 ["--libidentify"]
9840                 ( "report name and version according to libidentify standard" )
9841             | Opt( setWaitForKeypress, "never|start|exit|both" )
9842                 ["--wait-for-keypress"]
9843                 ( "waits for a keypress before exiting" )
9844             | Opt( config.benchmarkSamples, "samples" )
9845                 ["--benchmark-samples"]
9846                 ( "number of samples to collect (default: 100)" )
9847             | Opt( config.benchmarkResamples, "resamples" )
9848                 ["--benchmark-resamples"]
9849                 ( "number of resamples for the bootstrap (default: 100000)" )
9850             | Opt( config.benchmarkConfidenceInterval, "confidence interval" )
9851                 ["--benchmark-confidence-interval"]
9852                 ( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" )
9853             | Opt( config.benchmarkNoAnalysis )
9854                 ["--benchmark-no-analysis"]
9855                 ( "perform only measurements; do not perform any analysis" )
9856             | Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" )
9857                 ["--benchmark-warmup-time"]
9858                 ( "amount of time in milliseconds spent on warming up each test (default: 100)" )
9859             | Arg( config.testsOrTags, "test name|pattern|tags" )
9860                 ( "which test or tests to use" );
9861 
9862         return cli;
9863     }
9864 
9865 } // end namespace Catch
9866 // end catch_commandline.cpp
9867 // start catch_common.cpp
9868 
9869 #include <cstring>
9870 #include <ostream>
9871 
9872 namespace Catch {
9873 
operator ==(SourceLineInfo const & other) const9874     bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
9875         return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
9876     }
operator <(SourceLineInfo const & other) const9877     bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
9878         // We can assume that the same file will usually have the same pointer.
9879         // Thus, if the pointers are the same, there is no point in calling the strcmp
9880         return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));
9881     }
9882 
operator <<(std::ostream & os,SourceLineInfo const & info)9883     std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
9884 #ifndef __GNUG__
9885         os << info.file << '(' << info.line << ')';
9886 #else
9887         os << info.file << ':' << info.line;
9888 #endif
9889         return os;
9890     }
9891 
operator +() const9892     std::string StreamEndStop::operator+() const {
9893         return std::string();
9894     }
9895 
9896     NonCopyable::NonCopyable() = default;
9897     NonCopyable::~NonCopyable() = default;
9898 
9899 }
9900 // end catch_common.cpp
9901 // start catch_config.cpp
9902 
9903 namespace Catch {
9904 
Config(ConfigData const & data)9905     Config::Config( ConfigData const& data )
9906     :   m_data( data ),
9907         m_stream( openStream() )
9908     {
9909         // We need to trim filter specs to avoid trouble with superfluous
9910         // whitespace (esp. important for bdd macros, as those are manually
9911         // aligned with whitespace).
9912 
9913         for (auto& elem : m_data.testsOrTags) {
9914             elem = trim(elem);
9915         }
9916         for (auto& elem : m_data.sectionsToRun) {
9917             elem = trim(elem);
9918         }
9919 
9920         TestSpecParser parser(ITagAliasRegistry::get());
9921         if (!m_data.testsOrTags.empty()) {
9922             m_hasTestFilters = true;
9923             for (auto const& testOrTags : m_data.testsOrTags) {
9924                 parser.parse(testOrTags);
9925             }
9926         }
9927         m_testSpec = parser.testSpec();
9928     }
9929 
getFilename() const9930     std::string const& Config::getFilename() const {
9931         return m_data.outputFilename ;
9932     }
9933 
listTests() const9934     bool Config::listTests() const          { return m_data.listTests; }
listTestNamesOnly() const9935     bool Config::listTestNamesOnly() const  { return m_data.listTestNamesOnly; }
listTags() const9936     bool Config::listTags() const           { return m_data.listTags; }
listReporters() const9937     bool Config::listReporters() const      { return m_data.listReporters; }
9938 
getProcessName() const9939     std::string Config::getProcessName() const { return m_data.processName; }
getReporterName() const9940     std::string const& Config::getReporterName() const { return m_data.reporterName; }
9941 
getTestsOrTags() const9942     std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
getSectionsToRun() const9943     std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
9944 
testSpec() const9945     TestSpec const& Config::testSpec() const { return m_testSpec; }
hasTestFilters() const9946     bool Config::hasTestFilters() const { return m_hasTestFilters; }
9947 
showHelp() const9948     bool Config::showHelp() const { return m_data.showHelp; }
9949 
9950     // IConfig interface
allowThrows() const9951     bool Config::allowThrows() const                   { return !m_data.noThrow; }
stream() const9952     std::ostream& Config::stream() const               { return m_stream->stream(); }
name() const9953     std::string Config::name() const                   { return m_data.name.empty() ? m_data.processName : m_data.name; }
includeSuccessfulResults() const9954     bool Config::includeSuccessfulResults() const      { return m_data.showSuccessfulTests; }
warnAboutMissingAssertions() const9955     bool Config::warnAboutMissingAssertions() const    { return !!(m_data.warnings & WarnAbout::NoAssertions); }
warnAboutNoTests() const9956     bool Config::warnAboutNoTests() const              { return !!(m_data.warnings & WarnAbout::NoTests); }
showDurations() const9957     ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
runOrder() const9958     RunTests::InWhatOrder Config::runOrder() const     { return m_data.runOrder; }
rngSeed() const9959     unsigned int Config::rngSeed() const               { return m_data.rngSeed; }
useColour() const9960     UseColour::YesOrNo Config::useColour() const       { return m_data.useColour; }
shouldDebugBreak() const9961     bool Config::shouldDebugBreak() const              { return m_data.shouldDebugBreak; }
abortAfter() const9962     int Config::abortAfter() const                     { return m_data.abortAfter; }
showInvisibles() const9963     bool Config::showInvisibles() const                { return m_data.showInvisibles; }
verbosity() const9964     Verbosity Config::verbosity() const                { return m_data.verbosity; }
9965 
benchmarkNoAnalysis() const9966     bool Config::benchmarkNoAnalysis() const                      { return m_data.benchmarkNoAnalysis; }
benchmarkSamples() const9967     int Config::benchmarkSamples() const                          { return m_data.benchmarkSamples; }
benchmarkConfidenceInterval() const9968     double Config::benchmarkConfidenceInterval() const            { return m_data.benchmarkConfidenceInterval; }
benchmarkResamples() const9969     unsigned int Config::benchmarkResamples() const               { return m_data.benchmarkResamples; }
benchmarkWarmupTime() const9970     std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }
9971 
openStream()9972     IStream const* Config::openStream() {
9973         return Catch::makeStream(m_data.outputFilename);
9974     }
9975 
9976 } // end namespace Catch
9977 // end catch_config.cpp
9978 // start catch_console_colour.cpp
9979 
9980 #if defined(__clang__)
9981 #    pragma clang diagnostic push
9982 #    pragma clang diagnostic ignored "-Wexit-time-destructors"
9983 #endif
9984 
9985 // start catch_errno_guard.h
9986 
9987 namespace Catch {
9988 
9989     class ErrnoGuard {
9990     public:
9991         ErrnoGuard();
9992         ~ErrnoGuard();
9993     private:
9994         int m_oldErrno;
9995     };
9996 
9997 }
9998 
9999 // end catch_errno_guard.h
10000 #include <sstream>
10001 
10002 namespace Catch {
10003     namespace {
10004 
10005         struct IColourImpl {
10006             virtual ~IColourImpl() = default;
10007             virtual void use( Colour::Code _colourCode ) = 0;
10008         };
10009 
10010         struct NoColourImpl : IColourImpl {
useCatch::__anon6f5048d92d11::NoColourImpl10011             void use( Colour::Code ) override {}
10012 
instanceCatch::__anon6f5048d92d11::NoColourImpl10013             static IColourImpl* instance() {
10014                 static NoColourImpl s_instance;
10015                 return &s_instance;
10016             }
10017         };
10018 
10019     } // anon namespace
10020 } // namespace Catch
10021 
10022 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
10023 #   ifdef CATCH_PLATFORM_WINDOWS
10024 #       define CATCH_CONFIG_COLOUR_WINDOWS
10025 #   else
10026 #       define CATCH_CONFIG_COLOUR_ANSI
10027 #   endif
10028 #endif
10029 
10030 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
10031 
10032 namespace Catch {
10033 namespace {
10034 
10035     class Win32ColourImpl : public IColourImpl {
10036     public:
Win32ColourImpl()10037         Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
10038         {
10039             CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
10040             GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
10041             originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
10042             originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
10043         }
10044 
use(Colour::Code _colourCode)10045         void use( Colour::Code _colourCode ) override {
10046             switch( _colourCode ) {
10047                 case Colour::None:      return setTextAttribute( originalForegroundAttributes );
10048                 case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
10049                 case Colour::Red:       return setTextAttribute( FOREGROUND_RED );
10050                 case Colour::Green:     return setTextAttribute( FOREGROUND_GREEN );
10051                 case Colour::Blue:      return setTextAttribute( FOREGROUND_BLUE );
10052                 case Colour::Cyan:      return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
10053                 case Colour::Yellow:    return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
10054                 case Colour::Grey:      return setTextAttribute( 0 );
10055 
10056                 case Colour::LightGrey:     return setTextAttribute( FOREGROUND_INTENSITY );
10057                 case Colour::BrightRed:     return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
10058                 case Colour::BrightGreen:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
10059                 case Colour::BrightWhite:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
10060                 case Colour::BrightYellow:  return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
10061 
10062                 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
10063 
10064                 default:
10065                     CATCH_ERROR( "Unknown colour requested" );
10066             }
10067         }
10068 
10069     private:
setTextAttribute(WORD _textAttribute)10070         void setTextAttribute( WORD _textAttribute ) {
10071             SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
10072         }
10073         HANDLE stdoutHandle;
10074         WORD originalForegroundAttributes;
10075         WORD originalBackgroundAttributes;
10076     };
10077 
platformColourInstance()10078     IColourImpl* platformColourInstance() {
10079         static Win32ColourImpl s_instance;
10080 
10081         IConfigPtr config = getCurrentContext().getConfig();
10082         UseColour::YesOrNo colourMode = config
10083             ? config->useColour()
10084             : UseColour::Auto;
10085         if( colourMode == UseColour::Auto )
10086             colourMode = UseColour::Yes;
10087         return colourMode == UseColour::Yes
10088             ? &s_instance
10089             : NoColourImpl::instance();
10090     }
10091 
10092 } // end anon namespace
10093 } // end namespace Catch
10094 
10095 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
10096 
10097 #include <unistd.h>
10098 
10099 namespace Catch {
10100 namespace {
10101 
10102     // use POSIX/ ANSI console terminal codes
10103     // Thanks to Adam Strzelecki for original contribution
10104     // (http://github.com/nanoant)
10105     // https://github.com/philsquared/Catch/pull/131
10106     class PosixColourImpl : public IColourImpl {
10107     public:
use(Colour::Code _colourCode)10108         void use( Colour::Code _colourCode ) override {
10109             switch( _colourCode ) {
10110                 case Colour::None:
10111                 case Colour::White:     return setColour( "[0m" );
10112                 case Colour::Red:       return setColour( "[0;31m" );
10113                 case Colour::Green:     return setColour( "[0;32m" );
10114                 case Colour::Blue:      return setColour( "[0;34m" );
10115                 case Colour::Cyan:      return setColour( "[0;36m" );
10116                 case Colour::Yellow:    return setColour( "[0;33m" );
10117                 case Colour::Grey:      return setColour( "[1;30m" );
10118 
10119                 case Colour::LightGrey:     return setColour( "[0;37m" );
10120                 case Colour::BrightRed:     return setColour( "[1;31m" );
10121                 case Colour::BrightGreen:   return setColour( "[1;32m" );
10122                 case Colour::BrightWhite:   return setColour( "[1;37m" );
10123                 case Colour::BrightYellow:  return setColour( "[1;33m" );
10124 
10125                 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
10126                 default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
10127             }
10128         }
instance()10129         static IColourImpl* instance() {
10130             static PosixColourImpl s_instance;
10131             return &s_instance;
10132         }
10133 
10134     private:
setColour(const char * _escapeCode)10135         void setColour( const char* _escapeCode ) {
10136             getCurrentContext().getConfig()->stream()
10137                 << '\033' << _escapeCode;
10138         }
10139     };
10140 
useColourOnPlatform()10141     bool useColourOnPlatform() {
10142         return
10143 #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
10144             !isDebuggerActive() &&
10145 #endif
10146 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
10147             isatty(STDOUT_FILENO)
10148 #else
10149             false
10150 #endif
10151             ;
10152     }
platformColourInstance()10153     IColourImpl* platformColourInstance() {
10154         ErrnoGuard guard;
10155         IConfigPtr config = getCurrentContext().getConfig();
10156         UseColour::YesOrNo colourMode = config
10157             ? config->useColour()
10158             : UseColour::Auto;
10159         if( colourMode == UseColour::Auto )
10160             colourMode = useColourOnPlatform()
10161                 ? UseColour::Yes
10162                 : UseColour::No;
10163         return colourMode == UseColour::Yes
10164             ? PosixColourImpl::instance()
10165             : NoColourImpl::instance();
10166     }
10167 
10168 } // end anon namespace
10169 } // end namespace Catch
10170 
10171 #else  // not Windows or ANSI ///////////////////////////////////////////////
10172 
10173 namespace Catch {
10174 
platformColourInstance()10175     static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
10176 
10177 } // end namespace Catch
10178 
10179 #endif // Windows/ ANSI/ None
10180 
10181 namespace Catch {
10182 
Colour(Code _colourCode)10183     Colour::Colour( Code _colourCode ) { use( _colourCode ); }
Colour(Colour && other)10184     Colour::Colour( Colour&& other ) noexcept {
10185         m_moved = other.m_moved;
10186         other.m_moved = true;
10187     }
operator =(Colour && other)10188     Colour& Colour::operator=( Colour&& other ) noexcept {
10189         m_moved = other.m_moved;
10190         other.m_moved  = true;
10191         return *this;
10192     }
10193 
~Colour()10194     Colour::~Colour(){ if( !m_moved ) use( None ); }
10195 
use(Code _colourCode)10196     void Colour::use( Code _colourCode ) {
10197         static IColourImpl* impl = platformColourInstance();
10198         // Strictly speaking, this cannot possibly happen.
10199         // However, under some conditions it does happen (see #1626),
10200         // and this change is small enough that we can let practicality
10201         // triumph over purity in this case.
10202         if (impl != nullptr) {
10203             impl->use( _colourCode );
10204         }
10205     }
10206 
operator <<(std::ostream & os,Colour const &)10207     std::ostream& operator << ( std::ostream& os, Colour const& ) {
10208         return os;
10209     }
10210 
10211 } // end namespace Catch
10212 
10213 #if defined(__clang__)
10214 #    pragma clang diagnostic pop
10215 #endif
10216 
10217 // end catch_console_colour.cpp
10218 // start catch_context.cpp
10219 
10220 namespace Catch {
10221 
10222     class Context : public IMutableContext, NonCopyable {
10223 
10224     public: // IContext
getResultCapture()10225         IResultCapture* getResultCapture() override {
10226             return m_resultCapture;
10227         }
getRunner()10228         IRunner* getRunner() override {
10229             return m_runner;
10230         }
10231 
getConfig() const10232         IConfigPtr const& getConfig() const override {
10233             return m_config;
10234         }
10235 
10236         ~Context() override;
10237 
10238     public: // IMutableContext
setResultCapture(IResultCapture * resultCapture)10239         void setResultCapture( IResultCapture* resultCapture ) override {
10240             m_resultCapture = resultCapture;
10241         }
setRunner(IRunner * runner)10242         void setRunner( IRunner* runner ) override {
10243             m_runner = runner;
10244         }
setConfig(IConfigPtr const & config)10245         void setConfig( IConfigPtr const& config ) override {
10246             m_config = config;
10247         }
10248 
10249         friend IMutableContext& getCurrentMutableContext();
10250 
10251     private:
10252         IConfigPtr m_config;
10253         IRunner* m_runner = nullptr;
10254         IResultCapture* m_resultCapture = nullptr;
10255     };
10256 
10257     IMutableContext *IMutableContext::currentContext = nullptr;
10258 
createContext()10259     void IMutableContext::createContext()
10260     {
10261         currentContext = new Context();
10262     }
10263 
cleanUpContext()10264     void cleanUpContext() {
10265         delete IMutableContext::currentContext;
10266         IMutableContext::currentContext = nullptr;
10267     }
10268     IContext::~IContext() = default;
10269     IMutableContext::~IMutableContext() = default;
10270     Context::~Context() = default;
10271 
rng()10272     SimplePcg32& rng() {
10273         static SimplePcg32 s_rng;
10274         return s_rng;
10275     }
10276 
10277 }
10278 // end catch_context.cpp
10279 // start catch_debug_console.cpp
10280 
10281 // start catch_debug_console.h
10282 
10283 #include <string>
10284 
10285 namespace Catch {
10286     void writeToDebugConsole( std::string const& text );
10287 }
10288 
10289 // end catch_debug_console.h
10290 #if defined(CATCH_CONFIG_ANDROID_LOGWRITE)
10291 #include <android/log.h>
10292 
10293     namespace Catch {
writeToDebugConsole(std::string const & text)10294         void writeToDebugConsole( std::string const& text ) {
10295             __android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() );
10296         }
10297     }
10298 
10299 #elif defined(CATCH_PLATFORM_WINDOWS)
10300 
10301     namespace Catch {
writeToDebugConsole(std::string const & text)10302         void writeToDebugConsole( std::string const& text ) {
10303             ::OutputDebugStringA( text.c_str() );
10304         }
10305     }
10306 
10307 #else
10308 
10309     namespace Catch {
writeToDebugConsole(std::string const & text)10310         void writeToDebugConsole( std::string const& text ) {
10311             // !TBD: Need a version for Mac/ XCode and other IDEs
10312             Catch::cout() << text;
10313         }
10314     }
10315 
10316 #endif // Platform
10317 // end catch_debug_console.cpp
10318 // start catch_debugger.cpp
10319 
10320 #if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)
10321 
10322 #  include <assert.h>
10323 #  include <stdbool.h>
10324 #  include <sys/types.h>
10325 #  include <unistd.h>
10326 #  include <cstddef>
10327 #  include <ostream>
10328 
10329 #ifdef __apple_build_version__
10330     // These headers will only compile with AppleClang (XCode)
10331     // For other compilers (Clang, GCC, ... ) we need to exclude them
10332 #  include <sys/sysctl.h>
10333 #endif
10334 
10335     namespace Catch {
10336         #ifdef __apple_build_version__
10337         // The following function is taken directly from the following technical note:
10338         // https://developer.apple.com/library/archive/qa/qa1361/_index.html
10339 
10340         // Returns true if the current process is being debugged (either
10341         // running under the debugger or has a debugger attached post facto).
isDebuggerActive()10342         bool isDebuggerActive(){
10343             int                 mib[4];
10344             struct kinfo_proc   info;
10345             std::size_t         size;
10346 
10347             // Initialize the flags so that, if sysctl fails for some bizarre
10348             // reason, we get a predictable result.
10349 
10350             info.kp_proc.p_flag = 0;
10351 
10352             // Initialize mib, which tells sysctl the info we want, in this case
10353             // we're looking for information about a specific process ID.
10354 
10355             mib[0] = CTL_KERN;
10356             mib[1] = KERN_PROC;
10357             mib[2] = KERN_PROC_PID;
10358             mib[3] = getpid();
10359 
10360             // Call sysctl.
10361 
10362             size = sizeof(info);
10363             if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {
10364                 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
10365                 return false;
10366             }
10367 
10368             // We're being debugged if the P_TRACED flag is set.
10369 
10370             return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
10371         }
10372         #else
10373         bool isDebuggerActive() {
10374             // We need to find another way to determine this for non-appleclang compilers on macOS
10375             return false;
10376         }
10377         #endif
10378     } // namespace Catch
10379 
10380 #elif defined(CATCH_PLATFORM_LINUX)
10381     #include <fstream>
10382     #include <string>
10383 
10384     namespace Catch{
10385         // The standard POSIX way of detecting a debugger is to attempt to
10386         // ptrace() the process, but this needs to be done from a child and not
10387         // this process itself to still allow attaching to this process later
10388         // if wanted, so is rather heavy. Under Linux we have the PID of the
10389         // "debugger" (which doesn't need to be gdb, of course, it could also
10390         // be strace, for example) in /proc/$PID/status, so just get it from
10391         // there instead.
isDebuggerActive()10392         bool isDebuggerActive(){
10393             // Libstdc++ has a bug, where std::ifstream sets errno to 0
10394             // This way our users can properly assert over errno values
10395             ErrnoGuard guard;
10396             std::ifstream in("/proc/self/status");
10397             for( std::string line; std::getline(in, line); ) {
10398                 static const int PREFIX_LEN = 11;
10399                 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
10400                     // We're traced if the PID is not 0 and no other PID starts
10401                     // with 0 digit, so it's enough to check for just a single
10402                     // character.
10403                     return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
10404                 }
10405             }
10406 
10407             return false;
10408         }
10409     } // namespace Catch
10410 #elif defined(_MSC_VER)
10411     extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
10412     namespace Catch {
isDebuggerActive()10413         bool isDebuggerActive() {
10414             return IsDebuggerPresent() != 0;
10415         }
10416     }
10417 #elif defined(__MINGW32__)
10418     extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
10419     namespace Catch {
isDebuggerActive()10420         bool isDebuggerActive() {
10421             return IsDebuggerPresent() != 0;
10422         }
10423     }
10424 #else
10425     namespace Catch {
isDebuggerActive()10426        bool isDebuggerActive() { return false; }
10427     }
10428 #endif // Platform
10429 // end catch_debugger.cpp
10430 // start catch_decomposer.cpp
10431 
10432 namespace Catch {
10433 
10434     ITransientExpression::~ITransientExpression() = default;
10435 
formatReconstructedExpression(std::ostream & os,std::string const & lhs,StringRef op,std::string const & rhs)10436     void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
10437         if( lhs.size() + rhs.size() < 40 &&
10438                 lhs.find('\n') == std::string::npos &&
10439                 rhs.find('\n') == std::string::npos )
10440             os << lhs << " " << op << " " << rhs;
10441         else
10442             os << lhs << "\n" << op << "\n" << rhs;
10443     }
10444 }
10445 // end catch_decomposer.cpp
10446 // start catch_enforce.cpp
10447 
10448 #include <stdexcept>
10449 
10450 namespace Catch {
10451 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
10452     [[noreturn]]
throw_exception(std::exception const & e)10453     void throw_exception(std::exception const& e) {
10454         Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"
10455                       << "The message was: " << e.what() << '\n';
10456         std::terminate();
10457     }
10458 #endif
10459 
10460     [[noreturn]]
throw_logic_error(std::string const & msg)10461     void throw_logic_error(std::string const& msg) {
10462         throw_exception(std::logic_error(msg));
10463     }
10464 
10465     [[noreturn]]
throw_domain_error(std::string const & msg)10466     void throw_domain_error(std::string const& msg) {
10467         throw_exception(std::domain_error(msg));
10468     }
10469 
10470     [[noreturn]]
throw_runtime_error(std::string const & msg)10471     void throw_runtime_error(std::string const& msg) {
10472         throw_exception(std::runtime_error(msg));
10473     }
10474 
10475 } // namespace Catch;
10476 // end catch_enforce.cpp
10477 // start catch_enum_values_registry.cpp
10478 // start catch_enum_values_registry.h
10479 
10480 #include <vector>
10481 #include <memory>
10482 
10483 namespace Catch {
10484 
10485     namespace Detail {
10486 
10487         std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );
10488 
10489         class EnumValuesRegistry : public IMutableEnumValuesRegistry {
10490 
10491             std::vector<std::unique_ptr<EnumInfo>> m_enumInfos;
10492 
10493             EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override;
10494         };
10495 
10496         std::vector<StringRef> parseEnums( StringRef enums );
10497 
10498     } // Detail
10499 
10500 } // Catch
10501 
10502 // end catch_enum_values_registry.h
10503 
10504 #include <map>
10505 #include <cassert>
10506 
10507 namespace Catch {
10508 
~IMutableEnumValuesRegistry()10509     IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {}
10510 
10511     namespace Detail {
10512 
10513         namespace {
10514             // Extracts the actual name part of an enum instance
10515             // In other words, it returns the Blue part of Bikeshed::Colour::Blue
extractInstanceName(StringRef enumInstance)10516             StringRef extractInstanceName(StringRef enumInstance) {
10517                 // Find last occurence of ":"
10518                 size_t name_start = enumInstance.size();
10519                 while (name_start > 0 && enumInstance[name_start - 1] != ':') {
10520                     --name_start;
10521                 }
10522                 return enumInstance.substr(name_start, enumInstance.size() - name_start);
10523             }
10524         }
10525 
parseEnums(StringRef enums)10526         std::vector<StringRef> parseEnums( StringRef enums ) {
10527             auto enumValues = splitStringRef( enums, ',' );
10528             std::vector<StringRef> parsed;
10529             parsed.reserve( enumValues.size() );
10530             for( auto const& enumValue : enumValues ) {
10531                 parsed.push_back(trim(extractInstanceName(enumValue)));
10532             }
10533             return parsed;
10534         }
10535 
~EnumInfo()10536         EnumInfo::~EnumInfo() {}
10537 
lookup(int value) const10538         StringRef EnumInfo::lookup( int value ) const {
10539             for( auto const& valueToName : m_values ) {
10540                 if( valueToName.first == value )
10541                     return valueToName.second;
10542             }
10543             return "{** unexpected enum value **}"_sr;
10544         }
10545 
makeEnumInfo(StringRef enumName,StringRef allValueNames,std::vector<int> const & values)10546         std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
10547             std::unique_ptr<EnumInfo> enumInfo( new EnumInfo );
10548             enumInfo->m_name = enumName;
10549             enumInfo->m_values.reserve( values.size() );
10550 
10551             const auto valueNames = Catch::Detail::parseEnums( allValueNames );
10552             assert( valueNames.size() == values.size() );
10553             std::size_t i = 0;
10554             for( auto value : values )
10555                 enumInfo->m_values.emplace_back(value, valueNames[i++]);
10556 
10557             return enumInfo;
10558         }
10559 
registerEnum(StringRef enumName,StringRef allValueNames,std::vector<int> const & values)10560         EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {
10561             m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));
10562             return *m_enumInfos.back();
10563         }
10564 
10565     } // Detail
10566 } // Catch
10567 
10568 // end catch_enum_values_registry.cpp
10569 // start catch_errno_guard.cpp
10570 
10571 #include <cerrno>
10572 
10573 namespace Catch {
ErrnoGuard()10574         ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
~ErrnoGuard()10575         ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
10576 }
10577 // end catch_errno_guard.cpp
10578 // start catch_exception_translator_registry.cpp
10579 
10580 // start catch_exception_translator_registry.h
10581 
10582 #include <vector>
10583 #include <string>
10584 #include <memory>
10585 
10586 namespace Catch {
10587 
10588     class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
10589     public:
10590         ~ExceptionTranslatorRegistry();
10591         virtual void registerTranslator( const IExceptionTranslator* translator );
10592         std::string translateActiveException() const override;
10593         std::string tryTranslators() const;
10594 
10595     private:
10596         std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
10597     };
10598 }
10599 
10600 // end catch_exception_translator_registry.h
10601 #ifdef __OBJC__
10602 #import "Foundation/Foundation.h"
10603 #endif
10604 
10605 namespace Catch {
10606 
~ExceptionTranslatorRegistry()10607     ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
10608     }
10609 
registerTranslator(const IExceptionTranslator * translator)10610     void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) {
10611         m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
10612     }
10613 
10614 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
translateActiveException() const10615     std::string ExceptionTranslatorRegistry::translateActiveException() const {
10616         try {
10617 #ifdef __OBJC__
10618             // In Objective-C try objective-c exceptions first
10619             @try {
10620                 return tryTranslators();
10621             }
10622             @catch (NSException *exception) {
10623                 return Catch::Detail::stringify( [exception description] );
10624             }
10625 #else
10626             // Compiling a mixed mode project with MSVC means that CLR
10627             // exceptions will be caught in (...) as well. However, these
10628             // do not fill-in std::current_exception and thus lead to crash
10629             // when attempting rethrow.
10630             // /EHa switch also causes structured exceptions to be caught
10631             // here, but they fill-in current_exception properly, so
10632             // at worst the output should be a little weird, instead of
10633             // causing a crash.
10634             if (std::current_exception() == nullptr) {
10635                 return "Non C++ exception. Possibly a CLR exception.";
10636             }
10637             return tryTranslators();
10638 #endif
10639         }
10640         catch( TestFailureException& ) {
10641             std::rethrow_exception(std::current_exception());
10642         }
10643         catch( std::exception& ex ) {
10644             return ex.what();
10645         }
10646         catch( std::string& msg ) {
10647             return msg;
10648         }
10649         catch( const char* msg ) {
10650             return msg;
10651         }
10652         catch(...) {
10653             return "Unknown exception";
10654         }
10655     }
10656 
tryTranslators() const10657     std::string ExceptionTranslatorRegistry::tryTranslators() const {
10658         if (m_translators.empty()) {
10659             std::rethrow_exception(std::current_exception());
10660         } else {
10661             return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
10662         }
10663     }
10664 
10665 #else // ^^ Exceptions are enabled // Exceptions are disabled vv
translateActiveException() const10666     std::string ExceptionTranslatorRegistry::translateActiveException() const {
10667         CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
10668     }
10669 
tryTranslators() const10670     std::string ExceptionTranslatorRegistry::tryTranslators() const {
10671         CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
10672     }
10673 #endif
10674 
10675 }
10676 // end catch_exception_translator_registry.cpp
10677 // start catch_fatal_condition.cpp
10678 
10679 #if defined(__GNUC__)
10680 #    pragma GCC diagnostic push
10681 #    pragma GCC diagnostic ignored "-Wmissing-field-initializers"
10682 #endif
10683 
10684 #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
10685 
10686 namespace {
10687     // Report the error condition
reportFatal(char const * const message)10688     void reportFatal( char const * const message ) {
10689         Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
10690     }
10691 }
10692 
10693 #endif // signals/SEH handling
10694 
10695 #if defined( CATCH_CONFIG_WINDOWS_SEH )
10696 
10697 namespace Catch {
10698     struct SignalDefs { DWORD id; const char* name; };
10699 
10700     // There is no 1-1 mapping between signals and windows exceptions.
10701     // Windows can easily distinguish between SO and SigSegV,
10702     // but SigInt, SigTerm, etc are handled differently.
10703     static SignalDefs signalDefs[] = {
10704         { static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION),  "SIGILL - Illegal instruction signal" },
10705         { static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" },
10706         { static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" },
10707         { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
10708     };
10709 
handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo)10710     LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
10711         for (auto const& def : signalDefs) {
10712             if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
10713                 reportFatal(def.name);
10714             }
10715         }
10716         // If its not an exception we care about, pass it along.
10717         // This stops us from eating debugger breaks etc.
10718         return EXCEPTION_CONTINUE_SEARCH;
10719     }
10720 
FatalConditionHandler()10721     FatalConditionHandler::FatalConditionHandler() {
10722         isSet = true;
10723         // 32k seems enough for Catch to handle stack overflow,
10724         // but the value was found experimentally, so there is no strong guarantee
10725         guaranteeSize = 32 * 1024;
10726         exceptionHandlerHandle = nullptr;
10727         // Register as first handler in current chain
10728         exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
10729         // Pass in guarantee size to be filled
10730         SetThreadStackGuarantee(&guaranteeSize);
10731     }
10732 
reset()10733     void FatalConditionHandler::reset() {
10734         if (isSet) {
10735             RemoveVectoredExceptionHandler(exceptionHandlerHandle);
10736             SetThreadStackGuarantee(&guaranteeSize);
10737             exceptionHandlerHandle = nullptr;
10738             isSet = false;
10739         }
10740     }
10741 
~FatalConditionHandler()10742     FatalConditionHandler::~FatalConditionHandler() {
10743         reset();
10744     }
10745 
10746 bool FatalConditionHandler::isSet = false;
10747 ULONG FatalConditionHandler::guaranteeSize = 0;
10748 PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
10749 
10750 } // namespace Catch
10751 
10752 #elif defined( CATCH_CONFIG_POSIX_SIGNALS )
10753 
10754 namespace Catch {
10755 
10756     struct SignalDefs {
10757         int id;
10758         const char* name;
10759     };
10760 
10761     // 32kb for the alternate stack seems to be sufficient. However, this value
10762     // is experimentally determined, so that's not guaranteed.
10763     static constexpr std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
10764 
10765     static SignalDefs signalDefs[] = {
10766         { SIGINT,  "SIGINT - Terminal interrupt signal" },
10767         { SIGILL,  "SIGILL - Illegal instruction signal" },
10768         { SIGFPE,  "SIGFPE - Floating point error signal" },
10769         { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
10770         { SIGTERM, "SIGTERM - Termination request signal" },
10771         { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
10772     };
10773 
handleSignal(int sig)10774     void FatalConditionHandler::handleSignal( int sig ) {
10775         char const * name = "<unknown signal>";
10776         for (auto const& def : signalDefs) {
10777             if (sig == def.id) {
10778                 name = def.name;
10779                 break;
10780             }
10781         }
10782         reset();
10783         reportFatal(name);
10784         raise( sig );
10785     }
10786 
FatalConditionHandler()10787     FatalConditionHandler::FatalConditionHandler() {
10788         isSet = true;
10789         stack_t sigStack;
10790         sigStack.ss_sp = altStackMem;
10791         sigStack.ss_size = sigStackSize;
10792         sigStack.ss_flags = 0;
10793         sigaltstack(&sigStack, &oldSigStack);
10794         struct sigaction sa = { };
10795 
10796         sa.sa_handler = handleSignal;
10797         sa.sa_flags = SA_ONSTACK;
10798         for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
10799             sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
10800         }
10801     }
10802 
~FatalConditionHandler()10803     FatalConditionHandler::~FatalConditionHandler() {
10804         reset();
10805     }
10806 
reset()10807     void FatalConditionHandler::reset() {
10808         if( isSet ) {
10809             // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
10810             for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
10811                 sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
10812             }
10813             // Return the old stack
10814             sigaltstack(&oldSigStack, nullptr);
10815             isSet = false;
10816         }
10817     }
10818 
10819     bool FatalConditionHandler::isSet = false;
10820     struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
10821     stack_t FatalConditionHandler::oldSigStack = {};
10822     char FatalConditionHandler::altStackMem[sigStackSize] = {};
10823 
10824 } // namespace Catch
10825 
10826 #else
10827 
10828 namespace Catch {
reset()10829     void FatalConditionHandler::reset() {}
10830 }
10831 
10832 #endif // signals/SEH handling
10833 
10834 #if defined(__GNUC__)
10835 #    pragma GCC diagnostic pop
10836 #endif
10837 // end catch_fatal_condition.cpp
10838 // start catch_generators.cpp
10839 
10840 #include <limits>
10841 #include <set>
10842 
10843 namespace Catch {
10844 
~IGeneratorTracker()10845 IGeneratorTracker::~IGeneratorTracker() {}
10846 
what() const10847 const char* GeneratorException::what() const noexcept {
10848     return m_msg;
10849 }
10850 
10851 namespace Generators {
10852 
~GeneratorUntypedBase()10853     GeneratorUntypedBase::~GeneratorUntypedBase() {}
10854 
acquireGeneratorTracker(SourceLineInfo const & lineInfo)10855     auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
10856         return getResultCapture().acquireGeneratorTracker( lineInfo );
10857     }
10858 
10859 } // namespace Generators
10860 } // namespace Catch
10861 // end catch_generators.cpp
10862 // start catch_interfaces_capture.cpp
10863 
10864 namespace Catch {
10865     IResultCapture::~IResultCapture() = default;
10866 }
10867 // end catch_interfaces_capture.cpp
10868 // start catch_interfaces_config.cpp
10869 
10870 namespace Catch {
10871     IConfig::~IConfig() = default;
10872 }
10873 // end catch_interfaces_config.cpp
10874 // start catch_interfaces_exception.cpp
10875 
10876 namespace Catch {
10877     IExceptionTranslator::~IExceptionTranslator() = default;
10878     IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;
10879 }
10880 // end catch_interfaces_exception.cpp
10881 // start catch_interfaces_registry_hub.cpp
10882 
10883 namespace Catch {
10884     IRegistryHub::~IRegistryHub() = default;
10885     IMutableRegistryHub::~IMutableRegistryHub() = default;
10886 }
10887 // end catch_interfaces_registry_hub.cpp
10888 // start catch_interfaces_reporter.cpp
10889 
10890 // start catch_reporter_listening.h
10891 
10892 namespace Catch {
10893 
10894     class ListeningReporter : public IStreamingReporter {
10895         using Reporters = std::vector<IStreamingReporterPtr>;
10896         Reporters m_listeners;
10897         IStreamingReporterPtr m_reporter = nullptr;
10898         ReporterPreferences m_preferences;
10899 
10900     public:
10901         ListeningReporter();
10902 
10903         void addListener( IStreamingReporterPtr&& listener );
10904         void addReporter( IStreamingReporterPtr&& reporter );
10905 
10906     public: // IStreamingReporter
10907 
10908         ReporterPreferences getPreferences() const override;
10909 
10910         void noMatchingTestCases( std::string const& spec ) override;
10911 
10912         void reportInvalidArguments(std::string const&arg) override;
10913 
10914         static std::set<Verbosity> getSupportedVerbosities();
10915 
10916 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
10917         void benchmarkPreparing(std::string const& name) override;
10918         void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
10919         void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;
10920         void benchmarkFailed(std::string const&) override;
10921 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
10922 
10923         void testRunStarting( TestRunInfo const& testRunInfo ) override;
10924         void testGroupStarting( GroupInfo const& groupInfo ) override;
10925         void testCaseStarting( TestCaseInfo const& testInfo ) override;
10926         void sectionStarting( SectionInfo const& sectionInfo ) override;
10927         void assertionStarting( AssertionInfo const& assertionInfo ) override;
10928 
10929         // The return value indicates if the messages buffer should be cleared:
10930         bool assertionEnded( AssertionStats const& assertionStats ) override;
10931         void sectionEnded( SectionStats const& sectionStats ) override;
10932         void testCaseEnded( TestCaseStats const& testCaseStats ) override;
10933         void testGroupEnded( TestGroupStats const& testGroupStats ) override;
10934         void testRunEnded( TestRunStats const& testRunStats ) override;
10935 
10936         void skipTest( TestCaseInfo const& testInfo ) override;
10937         bool isMulti() const override;
10938 
10939     };
10940 
10941 } // end namespace Catch
10942 
10943 // end catch_reporter_listening.h
10944 namespace Catch {
10945 
ReporterConfig(IConfigPtr const & _fullConfig)10946     ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig )
10947     :   m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
10948 
ReporterConfig(IConfigPtr const & _fullConfig,std::ostream & _stream)10949     ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream )
10950     :   m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
10951 
stream() const10952     std::ostream& ReporterConfig::stream() const { return *m_stream; }
fullConfig() const10953     IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; }
10954 
TestRunInfo(std::string const & _name)10955     TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {}
10956 
GroupInfo(std::string const & _name,std::size_t _groupIndex,std::size_t _groupsCount)10957     GroupInfo::GroupInfo(  std::string const& _name,
10958                            std::size_t _groupIndex,
10959                            std::size_t _groupsCount )
10960     :   name( _name ),
10961         groupIndex( _groupIndex ),
10962         groupsCounts( _groupsCount )
10963     {}
10964 
AssertionStats(AssertionResult const & _assertionResult,std::vector<MessageInfo> const & _infoMessages,Totals const & _totals)10965      AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
10966                                      std::vector<MessageInfo> const& _infoMessages,
10967                                      Totals const& _totals )
10968     :   assertionResult( _assertionResult ),
10969         infoMessages( _infoMessages ),
10970         totals( _totals )
10971     {
10972         assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
10973 
10974         if( assertionResult.hasMessage() ) {
10975             // Copy message into messages list.
10976             // !TBD This should have been done earlier, somewhere
10977             MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
10978             builder << assertionResult.getMessage();
10979             builder.m_info.message = builder.m_stream.str();
10980 
10981             infoMessages.push_back( builder.m_info );
10982         }
10983     }
10984 
10985      AssertionStats::~AssertionStats() = default;
10986 
SectionStats(SectionInfo const & _sectionInfo,Counts const & _assertions,double _durationInSeconds,bool _missingAssertions)10987     SectionStats::SectionStats(  SectionInfo const& _sectionInfo,
10988                                  Counts const& _assertions,
10989                                  double _durationInSeconds,
10990                                  bool _missingAssertions )
10991     :   sectionInfo( _sectionInfo ),
10992         assertions( _assertions ),
10993         durationInSeconds( _durationInSeconds ),
10994         missingAssertions( _missingAssertions )
10995     {}
10996 
10997     SectionStats::~SectionStats() = default;
10998 
TestCaseStats(TestCaseInfo const & _testInfo,Totals const & _totals,std::string const & _stdOut,std::string const & _stdErr,bool _aborting)10999     TestCaseStats::TestCaseStats(  TestCaseInfo const& _testInfo,
11000                                    Totals const& _totals,
11001                                    std::string const& _stdOut,
11002                                    std::string const& _stdErr,
11003                                    bool _aborting )
11004     : testInfo( _testInfo ),
11005         totals( _totals ),
11006         stdOut( _stdOut ),
11007         stdErr( _stdErr ),
11008         aborting( _aborting )
11009     {}
11010 
11011     TestCaseStats::~TestCaseStats() = default;
11012 
TestGroupStats(GroupInfo const & _groupInfo,Totals const & _totals,bool _aborting)11013     TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo,
11014                                     Totals const& _totals,
11015                                     bool _aborting )
11016     :   groupInfo( _groupInfo ),
11017         totals( _totals ),
11018         aborting( _aborting )
11019     {}
11020 
TestGroupStats(GroupInfo const & _groupInfo)11021     TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo )
11022     :   groupInfo( _groupInfo ),
11023         aborting( false )
11024     {}
11025 
11026     TestGroupStats::~TestGroupStats() = default;
11027 
TestRunStats(TestRunInfo const & _runInfo,Totals const & _totals,bool _aborting)11028     TestRunStats::TestRunStats(   TestRunInfo const& _runInfo,
11029                     Totals const& _totals,
11030                     bool _aborting )
11031     :   runInfo( _runInfo ),
11032         totals( _totals ),
11033         aborting( _aborting )
11034     {}
11035 
11036     TestRunStats::~TestRunStats() = default;
11037 
fatalErrorEncountered(StringRef)11038     void IStreamingReporter::fatalErrorEncountered( StringRef ) {}
isMulti() const11039     bool IStreamingReporter::isMulti() const { return false; }
11040 
11041     IReporterFactory::~IReporterFactory() = default;
11042     IReporterRegistry::~IReporterRegistry() = default;
11043 
11044 } // end namespace Catch
11045 // end catch_interfaces_reporter.cpp
11046 // start catch_interfaces_runner.cpp
11047 
11048 namespace Catch {
11049     IRunner::~IRunner() = default;
11050 }
11051 // end catch_interfaces_runner.cpp
11052 // start catch_interfaces_testcase.cpp
11053 
11054 namespace Catch {
11055     ITestInvoker::~ITestInvoker() = default;
11056     ITestCaseRegistry::~ITestCaseRegistry() = default;
11057 }
11058 // end catch_interfaces_testcase.cpp
11059 // start catch_leak_detector.cpp
11060 
11061 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG
11062 #include <crtdbg.h>
11063 
11064 namespace Catch {
11065 
LeakDetector()11066     LeakDetector::LeakDetector() {
11067         int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
11068         flag |= _CRTDBG_LEAK_CHECK_DF;
11069         flag |= _CRTDBG_ALLOC_MEM_DF;
11070         _CrtSetDbgFlag(flag);
11071         _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
11072         _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
11073         // Change this to leaking allocation's number to break there
11074         _CrtSetBreakAlloc(-1);
11075     }
11076 }
11077 
11078 #else
11079 
LeakDetector()11080     Catch::LeakDetector::LeakDetector() {}
11081 
11082 #endif
11083 
~LeakDetector()11084 Catch::LeakDetector::~LeakDetector() {
11085     Catch::cleanUp();
11086 }
11087 // end catch_leak_detector.cpp
11088 // start catch_list.cpp
11089 
11090 // start catch_list.h
11091 
11092 #include <set>
11093 
11094 namespace Catch {
11095 
11096     std::size_t listTests( Config const& config );
11097 
11098     std::size_t listTestsNamesOnly( Config const& config );
11099 
11100     struct TagInfo {
11101         void add( std::string const& spelling );
11102         std::string all() const;
11103 
11104         std::set<std::string> spellings;
11105         std::size_t count = 0;
11106     };
11107 
11108     std::size_t listTags( Config const& config );
11109 
11110     std::size_t listReporters();
11111 
11112     Option<std::size_t> list( std::shared_ptr<Config> const& config );
11113 
11114 } // end namespace Catch
11115 
11116 // end catch_list.h
11117 // start catch_text.h
11118 
11119 namespace Catch {
11120     using namespace clara::TextFlow;
11121 }
11122 
11123 // end catch_text.h
11124 #include <limits>
11125 #include <algorithm>
11126 #include <iomanip>
11127 
11128 namespace Catch {
11129 
listTests(Config const & config)11130     std::size_t listTests( Config const& config ) {
11131         TestSpec const& testSpec = config.testSpec();
11132         if( config.hasTestFilters() )
11133             Catch::cout() << "Matching test cases:\n";
11134         else {
11135             Catch::cout() << "All available test cases:\n";
11136         }
11137 
11138         auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
11139         for( auto const& testCaseInfo : matchedTestCases ) {
11140             Colour::Code colour = testCaseInfo.isHidden()
11141                 ? Colour::SecondaryText
11142                 : Colour::None;
11143             Colour colourGuard( colour );
11144 
11145             Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n";
11146             if( config.verbosity() >= Verbosity::High ) {
11147                 Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl;
11148                 std::string description = testCaseInfo.description;
11149                 if( description.empty() )
11150                     description = "(NO DESCRIPTION)";
11151                 Catch::cout() << Column( description ).indent(4) << std::endl;
11152             }
11153             if( !testCaseInfo.tags.empty() )
11154                 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";
11155         }
11156 
11157         if( !config.hasTestFilters() )
11158             Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl;
11159         else
11160             Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;
11161         return matchedTestCases.size();
11162     }
11163 
listTestsNamesOnly(Config const & config)11164     std::size_t listTestsNamesOnly( Config const& config ) {
11165         TestSpec const& testSpec = config.testSpec();
11166         std::size_t matchedTests = 0;
11167         std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
11168         for( auto const& testCaseInfo : matchedTestCases ) {
11169             matchedTests++;
11170             if( startsWith( testCaseInfo.name, '#' ) )
11171                Catch::cout() << '"' << testCaseInfo.name << '"';
11172             else
11173                Catch::cout() << testCaseInfo.name;
11174             if ( config.verbosity() >= Verbosity::High )
11175                 Catch::cout() << "\t@" << testCaseInfo.lineInfo;
11176             Catch::cout() << std::endl;
11177         }
11178         return matchedTests;
11179     }
11180 
add(std::string const & spelling)11181     void TagInfo::add( std::string const& spelling ) {
11182         ++count;
11183         spellings.insert( spelling );
11184     }
11185 
all() const11186     std::string TagInfo::all() const {
11187         size_t size = 0;
11188         for (auto const& spelling : spellings) {
11189             // Add 2 for the brackes
11190             size += spelling.size() + 2;
11191         }
11192 
11193         std::string out; out.reserve(size);
11194         for (auto const& spelling : spellings) {
11195             out += '[';
11196             out += spelling;
11197             out += ']';
11198         }
11199         return out;
11200     }
11201 
listTags(Config const & config)11202     std::size_t listTags( Config const& config ) {
11203         TestSpec const& testSpec = config.testSpec();
11204         if( config.hasTestFilters() )
11205             Catch::cout() << "Tags for matching test cases:\n";
11206         else {
11207             Catch::cout() << "All available tags:\n";
11208         }
11209 
11210         std::map<std::string, TagInfo> tagCounts;
11211 
11212         std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
11213         for( auto const& testCase : matchedTestCases ) {
11214             for( auto const& tagName : testCase.getTestCaseInfo().tags ) {
11215                 std::string lcaseTagName = toLower( tagName );
11216                 auto countIt = tagCounts.find( lcaseTagName );
11217                 if( countIt == tagCounts.end() )
11218                     countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
11219                 countIt->second.add( tagName );
11220             }
11221         }
11222 
11223         for( auto const& tagCount : tagCounts ) {
11224             ReusableStringStream rss;
11225             rss << "  " << std::setw(2) << tagCount.second.count << "  ";
11226             auto str = rss.str();
11227             auto wrapper = Column( tagCount.second.all() )
11228                                                     .initialIndent( 0 )
11229                                                     .indent( str.size() )
11230                                                     .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
11231             Catch::cout() << str << wrapper << '\n';
11232         }
11233         Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
11234         return tagCounts.size();
11235     }
11236 
listReporters()11237     std::size_t listReporters() {
11238         Catch::cout() << "Available reporters:\n";
11239         IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
11240         std::size_t maxNameLen = 0;
11241         for( auto const& factoryKvp : factories )
11242             maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );
11243 
11244         for( auto const& factoryKvp : factories ) {
11245             Catch::cout()
11246                     << Column( factoryKvp.first + ":" )
11247                             .indent(2)
11248                             .width( 5+maxNameLen )
11249                     +  Column( factoryKvp.second->getDescription() )
11250                             .initialIndent(0)
11251                             .indent(2)
11252                             .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
11253                     << "\n";
11254         }
11255         Catch::cout() << std::endl;
11256         return factories.size();
11257     }
11258 
list(std::shared_ptr<Config> const & config)11259     Option<std::size_t> list( std::shared_ptr<Config> const& config ) {
11260         Option<std::size_t> listedCount;
11261         getCurrentMutableContext().setConfig( config );
11262         if( config->listTests() )
11263             listedCount = listedCount.valueOr(0) + listTests( *config );
11264         if( config->listTestNamesOnly() )
11265             listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config );
11266         if( config->listTags() )
11267             listedCount = listedCount.valueOr(0) + listTags( *config );
11268         if( config->listReporters() )
11269             listedCount = listedCount.valueOr(0) + listReporters();
11270         return listedCount;
11271     }
11272 
11273 } // end namespace Catch
11274 // end catch_list.cpp
11275 // start catch_matchers.cpp
11276 
11277 namespace Catch {
11278 namespace Matchers {
11279     namespace Impl {
11280 
toString() const11281         std::string MatcherUntypedBase::toString() const {
11282             if( m_cachedToString.empty() )
11283                 m_cachedToString = describe();
11284             return m_cachedToString;
11285         }
11286 
11287         MatcherUntypedBase::~MatcherUntypedBase() = default;
11288 
11289     } // namespace Impl
11290 } // namespace Matchers
11291 
11292 using namespace Matchers;
11293 using Matchers::Impl::MatcherBase;
11294 
11295 } // namespace Catch
11296 // end catch_matchers.cpp
11297 // start catch_matchers_exception.cpp
11298 
11299 namespace Catch {
11300 namespace Matchers {
11301 namespace Exception {
11302 
match(std::exception const & ex) const11303 bool ExceptionMessageMatcher::match(std::exception const& ex) const {
11304     return ex.what() == m_message;
11305 }
11306 
describe() const11307 std::string ExceptionMessageMatcher::describe() const {
11308     return "exception message matches \"" + m_message + "\"";
11309 }
11310 
11311 }
Message(std::string const & message)11312 Exception::ExceptionMessageMatcher Message(std::string const& message) {
11313     return Exception::ExceptionMessageMatcher(message);
11314 }
11315 
11316 // namespace Exception
11317 } // namespace Matchers
11318 } // namespace Catch
11319 // end catch_matchers_exception.cpp
11320 // start catch_matchers_floating.cpp
11321 
11322 // start catch_polyfills.hpp
11323 
11324 namespace Catch {
11325     bool isnan(float f);
11326     bool isnan(double d);
11327 }
11328 
11329 // end catch_polyfills.hpp
11330 // start catch_to_string.hpp
11331 
11332 #include <string>
11333 
11334 namespace Catch {
11335     template <typename T>
to_string(T const & t)11336     std::string to_string(T const& t) {
11337 #if defined(CATCH_CONFIG_CPP11_TO_STRING)
11338         return std::to_string(t);
11339 #else
11340         ReusableStringStream rss;
11341         rss << t;
11342         return rss.str();
11343 #endif
11344     }
11345 } // end namespace Catch
11346 
11347 // end catch_to_string.hpp
11348 #include <algorithm>
11349 #include <cmath>
11350 #include <cstdlib>
11351 #include <cstdint>
11352 #include <cstring>
11353 #include <sstream>
11354 #include <type_traits>
11355 #include <iomanip>
11356 #include <limits>
11357 
11358 namespace Catch {
11359 namespace {
11360 
convert(float f)11361     int32_t convert(float f) {
11362         static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
11363         int32_t i;
11364         std::memcpy(&i, &f, sizeof(f));
11365         return i;
11366     }
11367 
convert(double d)11368     int64_t convert(double d) {
11369         static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");
11370         int64_t i;
11371         std::memcpy(&i, &d, sizeof(d));
11372         return i;
11373     }
11374 
11375     template <typename FP>
almostEqualUlps(FP lhs,FP rhs,uint64_t maxUlpDiff)11376     bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) {
11377         // Comparison with NaN should always be false.
11378         // This way we can rule it out before getting into the ugly details
11379         if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
11380             return false;
11381         }
11382 
11383         auto lc = convert(lhs);
11384         auto rc = convert(rhs);
11385 
11386         if ((lc < 0) != (rc < 0)) {
11387             // Potentially we can have +0 and -0
11388             return lhs == rhs;
11389         }
11390 
11391         auto ulpDiff = std::abs(lc - rc);
11392         return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;
11393     }
11394 
11395 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
11396 
nextafter(float x,float y)11397     float nextafter(float x, float y) {
11398         return ::nextafterf(x, y);
11399     }
11400 
nextafter(double x,double y)11401     double nextafter(double x, double y) {
11402         return ::nextafter(x, y);
11403     }
11404 
11405 #endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^
11406 
11407 template <typename FP>
step(FP start,FP direction,uint64_t steps)11408 FP step(FP start, FP direction, uint64_t steps) {
11409     for (uint64_t i = 0; i < steps; ++i) {
11410 #if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)
11411         start = Catch::nextafter(start, direction);
11412 #else
11413         start = std::nextafter(start, direction);
11414 #endif
11415     }
11416     return start;
11417 }
11418 
11419 // Performs equivalent check of std::fabs(lhs - rhs) <= margin
11420 // But without the subtraction to allow for INFINITY in comparison
marginComparison(double lhs,double rhs,double margin)11421 bool marginComparison(double lhs, double rhs, double margin) {
11422     return (lhs + margin >= rhs) && (rhs + margin >= lhs);
11423 }
11424 
11425 template <typename FloatingPoint>
write(std::ostream & out,FloatingPoint num)11426 void write(std::ostream& out, FloatingPoint num) {
11427     out << std::scientific
11428         << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1)
11429         << num;
11430 }
11431 
11432 } // end anonymous namespace
11433 
11434 namespace Matchers {
11435 namespace Floating {
11436 
11437     enum class FloatingPointKind : uint8_t {
11438         Float,
11439         Double
11440     };
11441 
WithinAbsMatcher(double target,double margin)11442     WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
11443         :m_target{ target }, m_margin{ margin } {
11444         CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'
11445             << " Margin has to be non-negative.");
11446     }
11447 
11448     // Performs equivalent check of std::fabs(lhs - rhs) <= margin
11449     // But without the subtraction to allow for INFINITY in comparison
match(double const & matchee) const11450     bool WithinAbsMatcher::match(double const& matchee) const {
11451         return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
11452     }
11453 
describe() const11454     std::string WithinAbsMatcher::describe() const {
11455         return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
11456     }
11457 
WithinUlpsMatcher(double target,uint64_t ulps,FloatingPointKind baseType)11458     WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)
11459         :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
11460         CATCH_ENFORCE(m_type == FloatingPointKind::Double
11461                    || m_ulps < (std::numeric_limits<uint32_t>::max)(),
11462             "Provided ULP is impossibly large for a float comparison.");
11463     }
11464 
11465 #if defined(__clang__)
11466 #pragma clang diagnostic push
11467 // Clang <3.5 reports on the default branch in the switch below
11468 #pragma clang diagnostic ignored "-Wunreachable-code"
11469 #endif
11470 
match(double const & matchee) const11471     bool WithinUlpsMatcher::match(double const& matchee) const {
11472         switch (m_type) {
11473         case FloatingPointKind::Float:
11474             return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
11475         case FloatingPointKind::Double:
11476             return almostEqualUlps<double>(matchee, m_target, m_ulps);
11477         default:
11478             CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" );
11479         }
11480     }
11481 
11482 #if defined(__clang__)
11483 #pragma clang diagnostic pop
11484 #endif
11485 
describe() const11486     std::string WithinUlpsMatcher::describe() const {
11487         std::stringstream ret;
11488 
11489         ret << "is within " << m_ulps << " ULPs of ";
11490 
11491         if (m_type == FloatingPointKind::Float) {
11492             write(ret, static_cast<float>(m_target));
11493             ret << 'f';
11494         } else {
11495             write(ret, m_target);
11496         }
11497 
11498         ret << " ([";
11499         if (m_type == FloatingPointKind::Double) {
11500             write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps));
11501             ret << ", ";
11502             write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps));
11503         } else {
11504             // We have to cast INFINITY to float because of MinGW, see #1782
11505             write(ret, step(static_cast<float>(m_target), static_cast<float>(-INFINITY), m_ulps));
11506             ret << ", ";
11507             write(ret, step(static_cast<float>(m_target), static_cast<float>( INFINITY), m_ulps));
11508         }
11509         ret << "])";
11510 
11511         return ret.str();
11512     }
11513 
WithinRelMatcher(double target,double epsilon)11514     WithinRelMatcher::WithinRelMatcher(double target, double epsilon):
11515         m_target(target),
11516         m_epsilon(epsilon){
11517         CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon <  0 does not make sense.");
11518         CATCH_ENFORCE(m_epsilon  < 1., "Relative comparison with epsilon >= 1 does not make sense.");
11519     }
11520 
match(double const & matchee) const11521     bool WithinRelMatcher::match(double const& matchee) const {
11522         const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));
11523         return marginComparison(matchee, m_target,
11524                                 std::isinf(relMargin)? 0 : relMargin);
11525     }
11526 
describe() const11527     std::string WithinRelMatcher::describe() const {
11528         Catch::ReusableStringStream sstr;
11529         sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other";
11530         return sstr.str();
11531     }
11532 
11533 }// namespace Floating
11534 
WithinULP(double target,uint64_t maxUlpDiff)11535 Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {
11536     return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
11537 }
11538 
WithinULP(float target,uint64_t maxUlpDiff)11539 Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {
11540     return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
11541 }
11542 
WithinAbs(double target,double margin)11543 Floating::WithinAbsMatcher WithinAbs(double target, double margin) {
11544     return Floating::WithinAbsMatcher(target, margin);
11545 }
11546 
WithinRel(double target,double eps)11547 Floating::WithinRelMatcher WithinRel(double target, double eps) {
11548     return Floating::WithinRelMatcher(target, eps);
11549 }
11550 
WithinRel(double target)11551 Floating::WithinRelMatcher WithinRel(double target) {
11552     return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);
11553 }
11554 
WithinRel(float target,float eps)11555 Floating::WithinRelMatcher WithinRel(float target, float eps) {
11556     return Floating::WithinRelMatcher(target, eps);
11557 }
11558 
WithinRel(float target)11559 Floating::WithinRelMatcher WithinRel(float target) {
11560     return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);
11561 }
11562 
11563 } // namespace Matchers
11564 } // namespace Catch
11565 
11566 // end catch_matchers_floating.cpp
11567 // start catch_matchers_generic.cpp
11568 
finalizeDescription(const std::string & desc)11569 std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {
11570     if (desc.empty()) {
11571         return "matches undescribed predicate";
11572     } else {
11573         return "matches predicate: \"" + desc + '"';
11574     }
11575 }
11576 // end catch_matchers_generic.cpp
11577 // start catch_matchers_string.cpp
11578 
11579 #include <regex>
11580 
11581 namespace Catch {
11582 namespace Matchers {
11583 
11584     namespace StdString {
11585 
CasedString(std::string const & str,CaseSensitive::Choice caseSensitivity)11586         CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
11587         :   m_caseSensitivity( caseSensitivity ),
11588             m_str( adjustString( str ) )
11589         {}
adjustString(std::string const & str) const11590         std::string CasedString::adjustString( std::string const& str ) const {
11591             return m_caseSensitivity == CaseSensitive::No
11592                    ? toLower( str )
11593                    : str;
11594         }
caseSensitivitySuffix() const11595         std::string CasedString::caseSensitivitySuffix() const {
11596             return m_caseSensitivity == CaseSensitive::No
11597                    ? " (case insensitive)"
11598                    : std::string();
11599         }
11600 
StringMatcherBase(std::string const & operation,CasedString const & comparator)11601         StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
11602         : m_comparator( comparator ),
11603           m_operation( operation ) {
11604         }
11605 
describe() const11606         std::string StringMatcherBase::describe() const {
11607             std::string description;
11608             description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
11609                                         m_comparator.caseSensitivitySuffix().size());
11610             description += m_operation;
11611             description += ": \"";
11612             description += m_comparator.m_str;
11613             description += "\"";
11614             description += m_comparator.caseSensitivitySuffix();
11615             return description;
11616         }
11617 
EqualsMatcher(CasedString const & comparator)11618         EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
11619 
match(std::string const & source) const11620         bool EqualsMatcher::match( std::string const& source ) const {
11621             return m_comparator.adjustString( source ) == m_comparator.m_str;
11622         }
11623 
ContainsMatcher(CasedString const & comparator)11624         ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
11625 
match(std::string const & source) const11626         bool ContainsMatcher::match( std::string const& source ) const {
11627             return contains( m_comparator.adjustString( source ), m_comparator.m_str );
11628         }
11629 
StartsWithMatcher(CasedString const & comparator)11630         StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
11631 
match(std::string const & source) const11632         bool StartsWithMatcher::match( std::string const& source ) const {
11633             return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
11634         }
11635 
EndsWithMatcher(CasedString const & comparator)11636         EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
11637 
match(std::string const & source) const11638         bool EndsWithMatcher::match( std::string const& source ) const {
11639             return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
11640         }
11641 
RegexMatcher(std::string regex,CaseSensitive::Choice caseSensitivity)11642         RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}
11643 
match(std::string const & matchee) const11644         bool RegexMatcher::match(std::string const& matchee) const {
11645             auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway
11646             if (m_caseSensitivity == CaseSensitive::Choice::No) {
11647                 flags |= std::regex::icase;
11648             }
11649             auto reg = std::regex(m_regex, flags);
11650             return std::regex_match(matchee, reg);
11651         }
11652 
describe() const11653         std::string RegexMatcher::describe() const {
11654             return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");
11655         }
11656 
11657     } // namespace StdString
11658 
Equals(std::string const & str,CaseSensitive::Choice caseSensitivity)11659     StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
11660         return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
11661     }
Contains(std::string const & str,CaseSensitive::Choice caseSensitivity)11662     StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
11663         return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
11664     }
EndsWith(std::string const & str,CaseSensitive::Choice caseSensitivity)11665     StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
11666         return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
11667     }
StartsWith(std::string const & str,CaseSensitive::Choice caseSensitivity)11668     StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
11669         return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
11670     }
11671 
Matches(std::string const & regex,CaseSensitive::Choice caseSensitivity)11672     StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) {
11673         return StdString::RegexMatcher(regex, caseSensitivity);
11674     }
11675 
11676 } // namespace Matchers
11677 } // namespace Catch
11678 // end catch_matchers_string.cpp
11679 // start catch_message.cpp
11680 
11681 // start catch_uncaught_exceptions.h
11682 
11683 namespace Catch {
11684     bool uncaught_exceptions();
11685 } // end namespace Catch
11686 
11687 // end catch_uncaught_exceptions.h
11688 #include <cassert>
11689 #include <stack>
11690 
11691 namespace Catch {
11692 
MessageInfo(StringRef const & _macroName,SourceLineInfo const & _lineInfo,ResultWas::OfType _type)11693     MessageInfo::MessageInfo(   StringRef const& _macroName,
11694                                 SourceLineInfo const& _lineInfo,
11695                                 ResultWas::OfType _type )
11696     :   macroName( _macroName ),
11697         lineInfo( _lineInfo ),
11698         type( _type ),
11699         sequence( ++globalCount )
11700     {}
11701 
operator ==(MessageInfo const & other) const11702     bool MessageInfo::operator==( MessageInfo const& other ) const {
11703         return sequence == other.sequence;
11704     }
11705 
operator <(MessageInfo const & other) const11706     bool MessageInfo::operator<( MessageInfo const& other ) const {
11707         return sequence < other.sequence;
11708     }
11709 
11710     // This may need protecting if threading support is added
11711     unsigned int MessageInfo::globalCount = 0;
11712 
11713     ////////////////////////////////////////////////////////////////////////////
11714 
MessageBuilder(StringRef const & macroName,SourceLineInfo const & lineInfo,ResultWas::OfType type)11715     Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,
11716                                            SourceLineInfo const& lineInfo,
11717                                            ResultWas::OfType type )
11718         :m_info(macroName, lineInfo, type) {}
11719 
11720     ////////////////////////////////////////////////////////////////////////////
11721 
ScopedMessage(MessageBuilder const & builder)11722     ScopedMessage::ScopedMessage( MessageBuilder const& builder )
11723     : m_info( builder.m_info ), m_moved()
11724     {
11725         m_info.message = builder.m_stream.str();
11726         getResultCapture().pushScopedMessage( m_info );
11727     }
11728 
ScopedMessage(ScopedMessage && old)11729     ScopedMessage::ScopedMessage( ScopedMessage&& old )
11730     : m_info( old.m_info ), m_moved()
11731     {
11732         old.m_moved = true;
11733     }
11734 
~ScopedMessage()11735     ScopedMessage::~ScopedMessage() {
11736         if ( !uncaught_exceptions() && !m_moved ){
11737             getResultCapture().popScopedMessage(m_info);
11738         }
11739     }
11740 
Capturer(StringRef macroName,SourceLineInfo const & lineInfo,ResultWas::OfType resultType,StringRef names)11741     Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
11742         auto trimmed = [&] (size_t start, size_t end) {
11743             while (names[start] == ',' || isspace(names[start])) {
11744                 ++start;
11745             }
11746             while (names[end] == ',' || isspace(names[end])) {
11747                 --end;
11748             }
11749             return names.substr(start, end - start + 1);
11750         };
11751         auto skipq = [&] (size_t start, char quote) {
11752             for (auto i = start + 1; i < names.size() ; ++i) {
11753                 if (names[i] == quote)
11754                     return i;
11755                 if (names[i] == '\\')
11756                     ++i;
11757             }
11758             CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote");
11759         };
11760 
11761         size_t start = 0;
11762         std::stack<char> openings;
11763         for (size_t pos = 0; pos < names.size(); ++pos) {
11764             char c = names[pos];
11765             switch (c) {
11766             case '[':
11767             case '{':
11768             case '(':
11769             // It is basically impossible to disambiguate between
11770             // comparison and start of template args in this context
11771 //            case '<':
11772                 openings.push(c);
11773                 break;
11774             case ']':
11775             case '}':
11776             case ')':
11777 //           case '>':
11778                 openings.pop();
11779                 break;
11780             case '"':
11781             case '\'':
11782                 pos = skipq(pos, c);
11783                 break;
11784             case ',':
11785                 if (start != pos && openings.empty()) {
11786                     m_messages.emplace_back(macroName, lineInfo, resultType);
11787                     m_messages.back().message = static_cast<std::string>(trimmed(start, pos));
11788                     m_messages.back().message += " := ";
11789                     start = pos;
11790                 }
11791             }
11792         }
11793         assert(openings.empty() && "Mismatched openings");
11794         m_messages.emplace_back(macroName, lineInfo, resultType);
11795         m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));
11796         m_messages.back().message += " := ";
11797     }
~Capturer()11798     Capturer::~Capturer() {
11799         if ( !uncaught_exceptions() ){
11800             assert( m_captured == m_messages.size() );
11801             for( size_t i = 0; i < m_captured; ++i  )
11802                 m_resultCapture.popScopedMessage( m_messages[i] );
11803         }
11804     }
11805 
captureValue(size_t index,std::string const & value)11806     void Capturer::captureValue( size_t index, std::string const& value ) {
11807         assert( index < m_messages.size() );
11808         m_messages[index].message += value;
11809         m_resultCapture.pushScopedMessage( m_messages[index] );
11810         m_captured++;
11811     }
11812 
11813 } // end namespace Catch
11814 // end catch_message.cpp
11815 // start catch_output_redirect.cpp
11816 
11817 // start catch_output_redirect.h
11818 #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
11819 #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
11820 
11821 #include <cstdio>
11822 #include <iosfwd>
11823 #include <string>
11824 
11825 namespace Catch {
11826 
11827     class RedirectedStream {
11828         std::ostream& m_originalStream;
11829         std::ostream& m_redirectionStream;
11830         std::streambuf* m_prevBuf;
11831 
11832     public:
11833         RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
11834         ~RedirectedStream();
11835     };
11836 
11837     class RedirectedStdOut {
11838         ReusableStringStream m_rss;
11839         RedirectedStream m_cout;
11840     public:
11841         RedirectedStdOut();
11842         auto str() const -> std::string;
11843     };
11844 
11845     // StdErr has two constituent streams in C++, std::cerr and std::clog
11846     // This means that we need to redirect 2 streams into 1 to keep proper
11847     // order of writes
11848     class RedirectedStdErr {
11849         ReusableStringStream m_rss;
11850         RedirectedStream m_cerr;
11851         RedirectedStream m_clog;
11852     public:
11853         RedirectedStdErr();
11854         auto str() const -> std::string;
11855     };
11856 
11857     class RedirectedStreams {
11858     public:
11859         RedirectedStreams(RedirectedStreams const&) = delete;
11860         RedirectedStreams& operator=(RedirectedStreams const&) = delete;
11861         RedirectedStreams(RedirectedStreams&&) = delete;
11862         RedirectedStreams& operator=(RedirectedStreams&&) = delete;
11863 
11864         RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
11865         ~RedirectedStreams();
11866     private:
11867         std::string& m_redirectedCout;
11868         std::string& m_redirectedCerr;
11869         RedirectedStdOut m_redirectedStdOut;
11870         RedirectedStdErr m_redirectedStdErr;
11871     };
11872 
11873 #if defined(CATCH_CONFIG_NEW_CAPTURE)
11874 
11875     // Windows's implementation of std::tmpfile is terrible (it tries
11876     // to create a file inside system folder, thus requiring elevated
11877     // privileges for the binary), so we have to use tmpnam(_s) and
11878     // create the file ourselves there.
11879     class TempFile {
11880     public:
11881         TempFile(TempFile const&) = delete;
11882         TempFile& operator=(TempFile const&) = delete;
11883         TempFile(TempFile&&) = delete;
11884         TempFile& operator=(TempFile&&) = delete;
11885 
11886         TempFile();
11887         ~TempFile();
11888 
11889         std::FILE* getFile();
11890         std::string getContents();
11891 
11892     private:
11893         std::FILE* m_file = nullptr;
11894     #if defined(_MSC_VER)
11895         char m_buffer[L_tmpnam] = { 0 };
11896     #endif
11897     };
11898 
11899     class OutputRedirect {
11900     public:
11901         OutputRedirect(OutputRedirect const&) = delete;
11902         OutputRedirect& operator=(OutputRedirect const&) = delete;
11903         OutputRedirect(OutputRedirect&&) = delete;
11904         OutputRedirect& operator=(OutputRedirect&&) = delete;
11905 
11906         OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
11907         ~OutputRedirect();
11908 
11909     private:
11910         int m_originalStdout = -1;
11911         int m_originalStderr = -1;
11912         TempFile m_stdoutFile;
11913         TempFile m_stderrFile;
11914         std::string& m_stdoutDest;
11915         std::string& m_stderrDest;
11916     };
11917 
11918 #endif
11919 
11920 } // end namespace Catch
11921 
11922 #endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
11923 // end catch_output_redirect.h
11924 #include <cstdio>
11925 #include <cstring>
11926 #include <fstream>
11927 #include <sstream>
11928 #include <stdexcept>
11929 
11930 #if defined(CATCH_CONFIG_NEW_CAPTURE)
11931     #if defined(_MSC_VER)
11932     #include <io.h>      //_dup and _dup2
11933     #define dup _dup
11934     #define dup2 _dup2
11935     #define fileno _fileno
11936     #else
11937     #include <unistd.h>  // dup and dup2
11938     #endif
11939 #endif
11940 
11941 namespace Catch {
11942 
RedirectedStream(std::ostream & originalStream,std::ostream & redirectionStream)11943     RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
11944     :   m_originalStream( originalStream ),
11945         m_redirectionStream( redirectionStream ),
11946         m_prevBuf( m_originalStream.rdbuf() )
11947     {
11948         m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
11949     }
11950 
~RedirectedStream()11951     RedirectedStream::~RedirectedStream() {
11952         m_originalStream.rdbuf( m_prevBuf );
11953     }
11954 
RedirectedStdOut()11955     RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
str() const11956     auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }
11957 
RedirectedStdErr()11958     RedirectedStdErr::RedirectedStdErr()
11959     :   m_cerr( Catch::cerr(), m_rss.get() ),
11960         m_clog( Catch::clog(), m_rss.get() )
11961     {}
str() const11962     auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
11963 
RedirectedStreams(std::string & redirectedCout,std::string & redirectedCerr)11964     RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
11965     :   m_redirectedCout(redirectedCout),
11966         m_redirectedCerr(redirectedCerr)
11967     {}
11968 
~RedirectedStreams()11969     RedirectedStreams::~RedirectedStreams() {
11970         m_redirectedCout += m_redirectedStdOut.str();
11971         m_redirectedCerr += m_redirectedStdErr.str();
11972     }
11973 
11974 #if defined(CATCH_CONFIG_NEW_CAPTURE)
11975 
11976 #if defined(_MSC_VER)
TempFile()11977     TempFile::TempFile() {
11978         if (tmpnam_s(m_buffer)) {
11979             CATCH_RUNTIME_ERROR("Could not get a temp filename");
11980         }
11981         if (fopen_s(&m_file, m_buffer, "w")) {
11982             char buffer[100];
11983             if (strerror_s(buffer, errno)) {
11984                 CATCH_RUNTIME_ERROR("Could not translate errno to a string");
11985             }
11986             CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer);
11987         }
11988     }
11989 #else
TempFile()11990     TempFile::TempFile() {
11991         m_file = std::tmpfile();
11992         if (!m_file) {
11993             CATCH_RUNTIME_ERROR("Could not create a temp file.");
11994         }
11995     }
11996 
11997 #endif
11998 
~TempFile()11999     TempFile::~TempFile() {
12000          // TBD: What to do about errors here?
12001          std::fclose(m_file);
12002          // We manually create the file on Windows only, on Linux
12003          // it will be autodeleted
12004 #if defined(_MSC_VER)
12005          std::remove(m_buffer);
12006 #endif
12007     }
12008 
getFile()12009     FILE* TempFile::getFile() {
12010         return m_file;
12011     }
12012 
getContents()12013     std::string TempFile::getContents() {
12014         std::stringstream sstr;
12015         char buffer[100] = {};
12016         std::rewind(m_file);
12017         while (std::fgets(buffer, sizeof(buffer), m_file)) {
12018             sstr << buffer;
12019         }
12020         return sstr.str();
12021     }
12022 
OutputRedirect(std::string & stdout_dest,std::string & stderr_dest)12023     OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
12024         m_originalStdout(dup(1)),
12025         m_originalStderr(dup(2)),
12026         m_stdoutDest(stdout_dest),
12027         m_stderrDest(stderr_dest) {
12028         dup2(fileno(m_stdoutFile.getFile()), 1);
12029         dup2(fileno(m_stderrFile.getFile()), 2);
12030     }
12031 
~OutputRedirect()12032     OutputRedirect::~OutputRedirect() {
12033         Catch::cout() << std::flush;
12034         fflush(stdout);
12035         // Since we support overriding these streams, we flush cerr
12036         // even though std::cerr is unbuffered
12037         Catch::cerr() << std::flush;
12038         Catch::clog() << std::flush;
12039         fflush(stderr);
12040 
12041         dup2(m_originalStdout, 1);
12042         dup2(m_originalStderr, 2);
12043 
12044         m_stdoutDest += m_stdoutFile.getContents();
12045         m_stderrDest += m_stderrFile.getContents();
12046     }
12047 
12048 #endif // CATCH_CONFIG_NEW_CAPTURE
12049 
12050 } // namespace Catch
12051 
12052 #if defined(CATCH_CONFIG_NEW_CAPTURE)
12053     #if defined(_MSC_VER)
12054     #undef dup
12055     #undef dup2
12056     #undef fileno
12057     #endif
12058 #endif
12059 // end catch_output_redirect.cpp
12060 // start catch_polyfills.cpp
12061 
12062 #include <cmath>
12063 
12064 namespace Catch {
12065 
12066 #if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
isnan(float f)12067     bool isnan(float f) {
12068         return std::isnan(f);
12069     }
isnan(double d)12070     bool isnan(double d) {
12071         return std::isnan(d);
12072     }
12073 #else
12074     // For now we only use this for embarcadero
12075     bool isnan(float f) {
12076         return std::_isnan(f);
12077     }
12078     bool isnan(double d) {
12079         return std::_isnan(d);
12080     }
12081 #endif
12082 
12083 } // end namespace Catch
12084 // end catch_polyfills.cpp
12085 // start catch_random_number_generator.cpp
12086 
12087 namespace Catch {
12088 
12089 namespace {
12090 
12091 #if defined(_MSC_VER)
12092 #pragma warning(push)
12093 #pragma warning(disable:4146) // we negate uint32 during the rotate
12094 #endif
12095         // Safe rotr implementation thanks to John Regehr
rotate_right(uint32_t val,uint32_t count)12096         uint32_t rotate_right(uint32_t val, uint32_t count) {
12097             const uint32_t mask = 31;
12098             count &= mask;
12099             return (val >> count) | (val << (-count & mask));
12100         }
12101 
12102 #if defined(_MSC_VER)
12103 #pragma warning(pop)
12104 #endif
12105 
12106 }
12107 
SimplePcg32(result_type seed_)12108     SimplePcg32::SimplePcg32(result_type seed_) {
12109         seed(seed_);
12110     }
12111 
seed(result_type seed_)12112     void SimplePcg32::seed(result_type seed_) {
12113         m_state = 0;
12114         (*this)();
12115         m_state += seed_;
12116         (*this)();
12117     }
12118 
discard(uint64_t skip)12119     void SimplePcg32::discard(uint64_t skip) {
12120         // We could implement this to run in O(log n) steps, but this
12121         // should suffice for our use case.
12122         for (uint64_t s = 0; s < skip; ++s) {
12123             static_cast<void>((*this)());
12124         }
12125     }
12126 
operator ()()12127     SimplePcg32::result_type SimplePcg32::operator()() {
12128         // prepare the output value
12129         const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);
12130         const auto output = rotate_right(xorshifted, m_state >> 59u);
12131 
12132         // advance state
12133         m_state = m_state * 6364136223846793005ULL + s_inc;
12134 
12135         return output;
12136     }
12137 
operator ==(SimplePcg32 const & lhs,SimplePcg32 const & rhs)12138     bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
12139         return lhs.m_state == rhs.m_state;
12140     }
12141 
operator !=(SimplePcg32 const & lhs,SimplePcg32 const & rhs)12142     bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {
12143         return lhs.m_state != rhs.m_state;
12144     }
12145 }
12146 // end catch_random_number_generator.cpp
12147 // start catch_registry_hub.cpp
12148 
12149 // start catch_test_case_registry_impl.h
12150 
12151 #include <vector>
12152 #include <set>
12153 #include <algorithm>
12154 #include <ios>
12155 
12156 namespace Catch {
12157 
12158     class TestCase;
12159     struct IConfig;
12160 
12161     std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
12162 
12163     bool isThrowSafe( TestCase const& testCase, IConfig const& config );
12164     bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
12165 
12166     void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
12167 
12168     std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
12169     std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
12170 
12171     class TestRegistry : public ITestCaseRegistry {
12172     public:
12173         virtual ~TestRegistry() = default;
12174 
12175         virtual void registerTest( TestCase const& testCase );
12176 
12177         std::vector<TestCase> const& getAllTests() const override;
12178         std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override;
12179 
12180     private:
12181         std::vector<TestCase> m_functions;
12182         mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
12183         mutable std::vector<TestCase> m_sortedFunctions;
12184         std::size_t m_unnamedCount = 0;
12185         std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
12186     };
12187 
12188     ///////////////////////////////////////////////////////////////////////////
12189 
12190     class TestInvokerAsFunction : public ITestInvoker {
12191         void(*m_testAsFunction)();
12192     public:
12193         TestInvokerAsFunction( void(*testAsFunction)() ) noexcept;
12194 
12195         void invoke() const override;
12196     };
12197 
12198     std::string extractClassName( StringRef const& classOrQualifiedMethodName );
12199 
12200     ///////////////////////////////////////////////////////////////////////////
12201 
12202 } // end namespace Catch
12203 
12204 // end catch_test_case_registry_impl.h
12205 // start catch_reporter_registry.h
12206 
12207 #include <map>
12208 
12209 namespace Catch {
12210 
12211     class ReporterRegistry : public IReporterRegistry {
12212 
12213     public:
12214 
12215         ~ReporterRegistry() override;
12216 
12217         IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override;
12218 
12219         void registerReporter( std::string const& name, IReporterFactoryPtr const& factory );
12220         void registerListener( IReporterFactoryPtr const& factory );
12221 
12222         FactoryMap const& getFactories() const override;
12223         Listeners const& getListeners() const override;
12224 
12225     private:
12226         FactoryMap m_factories;
12227         Listeners m_listeners;
12228     };
12229 }
12230 
12231 // end catch_reporter_registry.h
12232 // start catch_tag_alias_registry.h
12233 
12234 // start catch_tag_alias.h
12235 
12236 #include <string>
12237 
12238 namespace Catch {
12239 
12240     struct TagAlias {
12241         TagAlias(std::string const& _tag, SourceLineInfo _lineInfo);
12242 
12243         std::string tag;
12244         SourceLineInfo lineInfo;
12245     };
12246 
12247 } // end namespace Catch
12248 
12249 // end catch_tag_alias.h
12250 #include <map>
12251 
12252 namespace Catch {
12253 
12254     class TagAliasRegistry : public ITagAliasRegistry {
12255     public:
12256         ~TagAliasRegistry() override;
12257         TagAlias const* find( std::string const& alias ) const override;
12258         std::string expandAliases( std::string const& unexpandedTestSpec ) const override;
12259         void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
12260 
12261     private:
12262         std::map<std::string, TagAlias> m_registry;
12263     };
12264 
12265 } // end namespace Catch
12266 
12267 // end catch_tag_alias_registry.h
12268 // start catch_startup_exception_registry.h
12269 
12270 #include <vector>
12271 #include <exception>
12272 
12273 namespace Catch {
12274 
12275     class StartupExceptionRegistry {
12276     public:
12277         void add(std::exception_ptr const& exception) noexcept;
12278         std::vector<std::exception_ptr> const& getExceptions() const noexcept;
12279     private:
12280         std::vector<std::exception_ptr> m_exceptions;
12281     };
12282 
12283 } // end namespace Catch
12284 
12285 // end catch_startup_exception_registry.h
12286 // start catch_singletons.hpp
12287 
12288 namespace Catch {
12289 
12290     struct ISingleton {
12291         virtual ~ISingleton();
12292     };
12293 
12294     void addSingleton( ISingleton* singleton );
12295     void cleanupSingletons();
12296 
12297     template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
12298     class Singleton : SingletonImplT, public ISingleton {
12299 
getInternal()12300         static auto getInternal() -> Singleton* {
12301             static Singleton* s_instance = nullptr;
12302             if( !s_instance ) {
12303                 s_instance = new Singleton;
12304                 addSingleton( s_instance );
12305             }
12306             return s_instance;
12307         }
12308 
12309     public:
get()12310         static auto get() -> InterfaceT const& {
12311             return *getInternal();
12312         }
getMutable()12313         static auto getMutable() -> MutableInterfaceT& {
12314             return *getInternal();
12315         }
12316     };
12317 
12318 } // namespace Catch
12319 
12320 // end catch_singletons.hpp
12321 namespace Catch {
12322 
12323     namespace {
12324 
12325         class RegistryHub : public IRegistryHub, public IMutableRegistryHub,
12326                             private NonCopyable {
12327 
12328         public: // IRegistryHub
12329             RegistryHub() = default;
getReporterRegistry() const12330             IReporterRegistry const& getReporterRegistry() const override {
12331                 return m_reporterRegistry;
12332             }
getTestCaseRegistry() const12333             ITestCaseRegistry const& getTestCaseRegistry() const override {
12334                 return m_testCaseRegistry;
12335             }
getExceptionTranslatorRegistry() const12336             IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {
12337                 return m_exceptionTranslatorRegistry;
12338             }
getTagAliasRegistry() const12339             ITagAliasRegistry const& getTagAliasRegistry() const override {
12340                 return m_tagAliasRegistry;
12341             }
getStartupExceptionRegistry() const12342             StartupExceptionRegistry const& getStartupExceptionRegistry() const override {
12343                 return m_exceptionRegistry;
12344             }
12345 
12346         public: // IMutableRegistryHub
registerReporter(std::string const & name,IReporterFactoryPtr const & factory)12347             void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override {
12348                 m_reporterRegistry.registerReporter( name, factory );
12349             }
registerListener(IReporterFactoryPtr const & factory)12350             void registerListener( IReporterFactoryPtr const& factory ) override {
12351                 m_reporterRegistry.registerListener( factory );
12352             }
registerTest(TestCase const & testInfo)12353             void registerTest( TestCase const& testInfo ) override {
12354                 m_testCaseRegistry.registerTest( testInfo );
12355             }
registerTranslator(const IExceptionTranslator * translator)12356             void registerTranslator( const IExceptionTranslator* translator ) override {
12357                 m_exceptionTranslatorRegistry.registerTranslator( translator );
12358             }
registerTagAlias(std::string const & alias,std::string const & tag,SourceLineInfo const & lineInfo)12359             void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {
12360                 m_tagAliasRegistry.add( alias, tag, lineInfo );
12361             }
registerStartupException()12362             void registerStartupException() noexcept override {
12363                 m_exceptionRegistry.add(std::current_exception());
12364             }
getMutableEnumValuesRegistry()12365             IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {
12366                 return m_enumValuesRegistry;
12367             }
12368 
12369         private:
12370             TestRegistry m_testCaseRegistry;
12371             ReporterRegistry m_reporterRegistry;
12372             ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
12373             TagAliasRegistry m_tagAliasRegistry;
12374             StartupExceptionRegistry m_exceptionRegistry;
12375             Detail::EnumValuesRegistry m_enumValuesRegistry;
12376         };
12377     }
12378 
12379     using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
12380 
getRegistryHub()12381     IRegistryHub const& getRegistryHub() {
12382         return RegistryHubSingleton::get();
12383     }
getMutableRegistryHub()12384     IMutableRegistryHub& getMutableRegistryHub() {
12385         return RegistryHubSingleton::getMutable();
12386     }
cleanUp()12387     void cleanUp() {
12388         cleanupSingletons();
12389         cleanUpContext();
12390     }
translateActiveException()12391     std::string translateActiveException() {
12392         return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
12393     }
12394 
12395 } // end namespace Catch
12396 // end catch_registry_hub.cpp
12397 // start catch_reporter_registry.cpp
12398 
12399 namespace Catch {
12400 
12401     ReporterRegistry::~ReporterRegistry() = default;
12402 
create(std::string const & name,IConfigPtr const & config) const12403     IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const {
12404         auto it =  m_factories.find( name );
12405         if( it == m_factories.end() )
12406             return nullptr;
12407         return it->second->create( ReporterConfig( config ) );
12408     }
12409 
registerReporter(std::string const & name,IReporterFactoryPtr const & factory)12410     void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) {
12411         m_factories.emplace(name, factory);
12412     }
registerListener(IReporterFactoryPtr const & factory)12413     void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) {
12414         m_listeners.push_back( factory );
12415     }
12416 
getFactories() const12417     IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const {
12418         return m_factories;
12419     }
getListeners() const12420     IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const {
12421         return m_listeners;
12422     }
12423 
12424 }
12425 // end catch_reporter_registry.cpp
12426 // start catch_result_type.cpp
12427 
12428 namespace Catch {
12429 
isOk(ResultWas::OfType resultType)12430     bool isOk( ResultWas::OfType resultType ) {
12431         return ( resultType & ResultWas::FailureBit ) == 0;
12432     }
isJustInfo(int flags)12433     bool isJustInfo( int flags ) {
12434         return flags == ResultWas::Info;
12435     }
12436 
operator |(ResultDisposition::Flags lhs,ResultDisposition::Flags rhs)12437     ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
12438         return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
12439     }
12440 
shouldContinueOnFailure(int flags)12441     bool shouldContinueOnFailure( int flags )    { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
shouldSuppressFailure(int flags)12442     bool shouldSuppressFailure( int flags )      { return ( flags & ResultDisposition::SuppressFail ) != 0; }
12443 
12444 } // end namespace Catch
12445 // end catch_result_type.cpp
12446 // start catch_run_context.cpp
12447 
12448 #include <cassert>
12449 #include <algorithm>
12450 #include <sstream>
12451 
12452 namespace Catch {
12453 
12454     namespace Generators {
12455         struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
12456             GeneratorBasePtr m_generator;
12457 
GeneratorTrackerCatch::Generators::GeneratorTracker12458             GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
12459             :   TrackerBase( nameAndLocation, ctx, parent )
12460             {}
12461             ~GeneratorTracker();
12462 
acquireCatch::Generators::GeneratorTracker12463             static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
12464                 std::shared_ptr<GeneratorTracker> tracker;
12465 
12466                 ITracker& currentTracker = ctx.currentTracker();
12467                 if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
12468                     assert( childTracker );
12469                     assert( childTracker->isGeneratorTracker() );
12470                     tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
12471                 }
12472                 else {
12473                     tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );
12474                     currentTracker.addChild( tracker );
12475                 }
12476 
12477                 if( !ctx.completedCycle() && !tracker->isComplete() ) {
12478                     tracker->open();
12479                 }
12480 
12481                 return *tracker;
12482             }
12483 
12484             // TrackerBase interface
isGeneratorTrackerCatch::Generators::GeneratorTracker12485             bool isGeneratorTracker() const override { return true; }
hasGeneratorCatch::Generators::GeneratorTracker12486             auto hasGenerator() const -> bool override {
12487                 return !!m_generator;
12488             }
closeCatch::Generators::GeneratorTracker12489             void close() override {
12490                 TrackerBase::close();
12491                 // Generator interface only finds out if it has another item on atual move
12492                 if (m_runState == CompletedSuccessfully && m_generator->next()) {
12493                     m_children.clear();
12494                     m_runState = Executing;
12495                 }
12496             }
12497 
12498             // IGeneratorTracker interface
getGeneratorCatch::Generators::GeneratorTracker12499             auto getGenerator() const -> GeneratorBasePtr const& override {
12500                 return m_generator;
12501             }
setGeneratorCatch::Generators::GeneratorTracker12502             void setGenerator( GeneratorBasePtr&& generator ) override {
12503                 m_generator = std::move( generator );
12504             }
12505         };
~GeneratorTracker()12506         GeneratorTracker::~GeneratorTracker() {}
12507     }
12508 
RunContext(IConfigPtr const & _config,IStreamingReporterPtr && reporter)12509     RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
12510     :   m_runInfo(_config->name()),
12511         m_context(getCurrentMutableContext()),
12512         m_config(_config),
12513         m_reporter(std::move(reporter)),
12514         m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
12515         m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
12516     {
12517         m_context.setRunner(this);
12518         m_context.setConfig(m_config);
12519         m_context.setResultCapture(this);
12520         m_reporter->testRunStarting(m_runInfo);
12521     }
12522 
~RunContext()12523     RunContext::~RunContext() {
12524         m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
12525     }
12526 
testGroupStarting(std::string const & testSpec,std::size_t groupIndex,std::size_t groupsCount)12527     void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
12528         m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
12529     }
12530 
testGroupEnded(std::string const & testSpec,Totals const & totals,std::size_t groupIndex,std::size_t groupsCount)12531     void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {
12532         m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
12533     }
12534 
runTest(TestCase const & testCase)12535     Totals RunContext::runTest(TestCase const& testCase) {
12536         Totals prevTotals = m_totals;
12537 
12538         std::string redirectedCout;
12539         std::string redirectedCerr;
12540 
12541         auto const& testInfo = testCase.getTestCaseInfo();
12542 
12543         m_reporter->testCaseStarting(testInfo);
12544 
12545         m_activeTestCase = &testCase;
12546 
12547         ITracker& rootTracker = m_trackerContext.startRun();
12548         assert(rootTracker.isSectionTracker());
12549         static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
12550         do {
12551             m_trackerContext.startCycle();
12552             m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
12553             runCurrentTest(redirectedCout, redirectedCerr);
12554         } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
12555 
12556         Totals deltaTotals = m_totals.delta(prevTotals);
12557         if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
12558             deltaTotals.assertions.failed++;
12559             deltaTotals.testCases.passed--;
12560             deltaTotals.testCases.failed++;
12561         }
12562         m_totals.testCases += deltaTotals.testCases;
12563         m_reporter->testCaseEnded(TestCaseStats(testInfo,
12564                                   deltaTotals,
12565                                   redirectedCout,
12566                                   redirectedCerr,
12567                                   aborting()));
12568 
12569         m_activeTestCase = nullptr;
12570         m_testCaseTracker = nullptr;
12571 
12572         return deltaTotals;
12573     }
12574 
config() const12575     IConfigPtr RunContext::config() const {
12576         return m_config;
12577     }
12578 
reporter() const12579     IStreamingReporter& RunContext::reporter() const {
12580         return *m_reporter;
12581     }
12582 
assertionEnded(AssertionResult const & result)12583     void RunContext::assertionEnded(AssertionResult const & result) {
12584         if (result.getResultType() == ResultWas::Ok) {
12585             m_totals.assertions.passed++;
12586             m_lastAssertionPassed = true;
12587         } else if (!result.isOk()) {
12588             m_lastAssertionPassed = false;
12589             if( m_activeTestCase->getTestCaseInfo().okToFail() )
12590                 m_totals.assertions.failedButOk++;
12591             else
12592                 m_totals.assertions.failed++;
12593         }
12594         else {
12595             m_lastAssertionPassed = true;
12596         }
12597 
12598         // We have no use for the return value (whether messages should be cleared), because messages were made scoped
12599         // and should be let to clear themselves out.
12600         static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
12601 
12602         if (result.getResultType() != ResultWas::Warning)
12603             m_messageScopes.clear();
12604 
12605         // Reset working state
12606         resetAssertionInfo();
12607         m_lastResult = result;
12608     }
resetAssertionInfo()12609     void RunContext::resetAssertionInfo() {
12610         m_lastAssertionInfo.macroName = StringRef();
12611         m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
12612     }
12613 
sectionStarted(SectionInfo const & sectionInfo,Counts & assertions)12614     bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {
12615         ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
12616         if (!sectionTracker.isOpen())
12617             return false;
12618         m_activeSections.push_back(&sectionTracker);
12619 
12620         m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
12621 
12622         m_reporter->sectionStarting(sectionInfo);
12623 
12624         assertions = m_totals.assertions;
12625 
12626         return true;
12627     }
acquireGeneratorTracker(SourceLineInfo const & lineInfo)12628     auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
12629         using namespace Generators;
12630         GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) );
12631         assert( tracker.isOpen() );
12632         m_lastAssertionInfo.lineInfo = lineInfo;
12633         return tracker;
12634     }
12635 
testForMissingAssertions(Counts & assertions)12636     bool RunContext::testForMissingAssertions(Counts& assertions) {
12637         if (assertions.total() != 0)
12638             return false;
12639         if (!m_config->warnAboutMissingAssertions())
12640             return false;
12641         if (m_trackerContext.currentTracker().hasChildren())
12642             return false;
12643         m_totals.assertions.failed++;
12644         assertions.failed++;
12645         return true;
12646     }
12647 
sectionEnded(SectionEndInfo const & endInfo)12648     void RunContext::sectionEnded(SectionEndInfo const & endInfo) {
12649         Counts assertions = m_totals.assertions - endInfo.prevAssertions;
12650         bool missingAssertions = testForMissingAssertions(assertions);
12651 
12652         if (!m_activeSections.empty()) {
12653             m_activeSections.back()->close();
12654             m_activeSections.pop_back();
12655         }
12656 
12657         m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
12658         m_messages.clear();
12659         m_messageScopes.clear();
12660     }
12661 
sectionEndedEarly(SectionEndInfo const & endInfo)12662     void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
12663         if (m_unfinishedSections.empty())
12664             m_activeSections.back()->fail();
12665         else
12666             m_activeSections.back()->close();
12667         m_activeSections.pop_back();
12668 
12669         m_unfinishedSections.push_back(endInfo);
12670     }
12671 
12672 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
benchmarkPreparing(std::string const & name)12673     void RunContext::benchmarkPreparing(std::string const& name) {
12674 		m_reporter->benchmarkPreparing(name);
12675 	}
benchmarkStarting(BenchmarkInfo const & info)12676     void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
12677         m_reporter->benchmarkStarting( info );
12678     }
benchmarkEnded(BenchmarkStats<> const & stats)12679     void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
12680         m_reporter->benchmarkEnded( stats );
12681     }
benchmarkFailed(std::string const & error)12682 	void RunContext::benchmarkFailed(std::string const & error) {
12683 		m_reporter->benchmarkFailed(error);
12684 	}
12685 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
12686 
pushScopedMessage(MessageInfo const & message)12687     void RunContext::pushScopedMessage(MessageInfo const & message) {
12688         m_messages.push_back(message);
12689     }
12690 
popScopedMessage(MessageInfo const & message)12691     void RunContext::popScopedMessage(MessageInfo const & message) {
12692         m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
12693     }
12694 
emplaceUnscopedMessage(MessageBuilder const & builder)12695     void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
12696         m_messageScopes.emplace_back( builder );
12697     }
12698 
getCurrentTestName() const12699     std::string RunContext::getCurrentTestName() const {
12700         return m_activeTestCase
12701             ? m_activeTestCase->getTestCaseInfo().name
12702             : std::string();
12703     }
12704 
getLastResult() const12705     const AssertionResult * RunContext::getLastResult() const {
12706         return &(*m_lastResult);
12707     }
12708 
exceptionEarlyReported()12709     void RunContext::exceptionEarlyReported() {
12710         m_shouldReportUnexpected = false;
12711     }
12712 
handleFatalErrorCondition(StringRef message)12713     void RunContext::handleFatalErrorCondition( StringRef message ) {
12714         // First notify reporter that bad things happened
12715         m_reporter->fatalErrorEncountered(message);
12716 
12717         // Don't rebuild the result -- the stringification itself can cause more fatal errors
12718         // Instead, fake a result data.
12719         AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
12720         tempResult.message = static_cast<std::string>(message);
12721         AssertionResult result(m_lastAssertionInfo, tempResult);
12722 
12723         assertionEnded(result);
12724 
12725         handleUnfinishedSections();
12726 
12727         // Recreate section for test case (as we will lose the one that was in scope)
12728         auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
12729         SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
12730 
12731         Counts assertions;
12732         assertions.failed = 1;
12733         SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
12734         m_reporter->sectionEnded(testCaseSectionStats);
12735 
12736         auto const& testInfo = m_activeTestCase->getTestCaseInfo();
12737 
12738         Totals deltaTotals;
12739         deltaTotals.testCases.failed = 1;
12740         deltaTotals.assertions.failed = 1;
12741         m_reporter->testCaseEnded(TestCaseStats(testInfo,
12742                                   deltaTotals,
12743                                   std::string(),
12744                                   std::string(),
12745                                   false));
12746         m_totals.testCases.failed++;
12747         testGroupEnded(std::string(), m_totals, 1, 1);
12748         m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
12749     }
12750 
lastAssertionPassed()12751     bool RunContext::lastAssertionPassed() {
12752          return m_lastAssertionPassed;
12753     }
12754 
assertionPassed()12755     void RunContext::assertionPassed() {
12756         m_lastAssertionPassed = true;
12757         ++m_totals.assertions.passed;
12758         resetAssertionInfo();
12759         m_messageScopes.clear();
12760     }
12761 
aborting() const12762     bool RunContext::aborting() const {
12763         return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());
12764     }
12765 
runCurrentTest(std::string & redirectedCout,std::string & redirectedCerr)12766     void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
12767         auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
12768         SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
12769         m_reporter->sectionStarting(testCaseSection);
12770         Counts prevAssertions = m_totals.assertions;
12771         double duration = 0;
12772         m_shouldReportUnexpected = true;
12773         m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
12774 
12775         seedRng(*m_config);
12776 
12777         Timer timer;
12778         CATCH_TRY {
12779             if (m_reporter->getPreferences().shouldRedirectStdOut) {
12780 #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
12781                 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
12782 
12783                 timer.start();
12784                 invokeActiveTestCase();
12785 #else
12786                 OutputRedirect r(redirectedCout, redirectedCerr);
12787                 timer.start();
12788                 invokeActiveTestCase();
12789 #endif
12790             } else {
12791                 timer.start();
12792                 invokeActiveTestCase();
12793             }
12794             duration = timer.getElapsedSeconds();
12795         } CATCH_CATCH_ANON (TestFailureException&) {
12796             // This just means the test was aborted due to failure
12797         } CATCH_CATCH_ALL {
12798             // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
12799             // are reported without translation at the point of origin.
12800             if( m_shouldReportUnexpected ) {
12801                 AssertionReaction dummyReaction;
12802                 handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
12803             }
12804         }
12805         Counts assertions = m_totals.assertions - prevAssertions;
12806         bool missingAssertions = testForMissingAssertions(assertions);
12807 
12808         m_testCaseTracker->close();
12809         handleUnfinishedSections();
12810         m_messages.clear();
12811         m_messageScopes.clear();
12812 
12813         SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
12814         m_reporter->sectionEnded(testCaseSectionStats);
12815     }
12816 
invokeActiveTestCase()12817     void RunContext::invokeActiveTestCase() {
12818         FatalConditionHandler fatalConditionHandler; // Handle signals
12819         m_activeTestCase->invoke();
12820         fatalConditionHandler.reset();
12821     }
12822 
handleUnfinishedSections()12823     void RunContext::handleUnfinishedSections() {
12824         // If sections ended prematurely due to an exception we stored their
12825         // infos here so we can tear them down outside the unwind process.
12826         for (auto it = m_unfinishedSections.rbegin(),
12827              itEnd = m_unfinishedSections.rend();
12828              it != itEnd;
12829              ++it)
12830             sectionEnded(*it);
12831         m_unfinishedSections.clear();
12832     }
12833 
handleExpr(AssertionInfo const & info,ITransientExpression const & expr,AssertionReaction & reaction)12834     void RunContext::handleExpr(
12835         AssertionInfo const& info,
12836         ITransientExpression const& expr,
12837         AssertionReaction& reaction
12838     ) {
12839         m_reporter->assertionStarting( info );
12840 
12841         bool negated = isFalseTest( info.resultDisposition );
12842         bool result = expr.getResult() != negated;
12843 
12844         if( result ) {
12845             if (!m_includeSuccessfulResults) {
12846                 assertionPassed();
12847             }
12848             else {
12849                 reportExpr(info, ResultWas::Ok, &expr, negated);
12850             }
12851         }
12852         else {
12853             reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
12854             populateReaction( reaction );
12855         }
12856     }
reportExpr(AssertionInfo const & info,ResultWas::OfType resultType,ITransientExpression const * expr,bool negated)12857     void RunContext::reportExpr(
12858             AssertionInfo const &info,
12859             ResultWas::OfType resultType,
12860             ITransientExpression const *expr,
12861             bool negated ) {
12862 
12863         m_lastAssertionInfo = info;
12864         AssertionResultData data( resultType, LazyExpression( negated ) );
12865 
12866         AssertionResult assertionResult{ info, data };
12867         assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
12868 
12869         assertionEnded( assertionResult );
12870     }
12871 
handleMessage(AssertionInfo const & info,ResultWas::OfType resultType,StringRef const & message,AssertionReaction & reaction)12872     void RunContext::handleMessage(
12873             AssertionInfo const& info,
12874             ResultWas::OfType resultType,
12875             StringRef const& message,
12876             AssertionReaction& reaction
12877     ) {
12878         m_reporter->assertionStarting( info );
12879 
12880         m_lastAssertionInfo = info;
12881 
12882         AssertionResultData data( resultType, LazyExpression( false ) );
12883         data.message = static_cast<std::string>(message);
12884         AssertionResult assertionResult{ m_lastAssertionInfo, data };
12885         assertionEnded( assertionResult );
12886         if( !assertionResult.isOk() )
12887             populateReaction( reaction );
12888     }
handleUnexpectedExceptionNotThrown(AssertionInfo const & info,AssertionReaction & reaction)12889     void RunContext::handleUnexpectedExceptionNotThrown(
12890             AssertionInfo const& info,
12891             AssertionReaction& reaction
12892     ) {
12893         handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
12894     }
12895 
handleUnexpectedInflightException(AssertionInfo const & info,std::string const & message,AssertionReaction & reaction)12896     void RunContext::handleUnexpectedInflightException(
12897             AssertionInfo const& info,
12898             std::string const& message,
12899             AssertionReaction& reaction
12900     ) {
12901         m_lastAssertionInfo = info;
12902 
12903         AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
12904         data.message = message;
12905         AssertionResult assertionResult{ info, data };
12906         assertionEnded( assertionResult );
12907         populateReaction( reaction );
12908     }
12909 
populateReaction(AssertionReaction & reaction)12910     void RunContext::populateReaction( AssertionReaction& reaction ) {
12911         reaction.shouldDebugBreak = m_config->shouldDebugBreak();
12912         reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
12913     }
12914 
handleIncomplete(AssertionInfo const & info)12915     void RunContext::handleIncomplete(
12916             AssertionInfo const& info
12917     ) {
12918         m_lastAssertionInfo = info;
12919 
12920         AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
12921         data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
12922         AssertionResult assertionResult{ info, data };
12923         assertionEnded( assertionResult );
12924     }
handleNonExpr(AssertionInfo const & info,ResultWas::OfType resultType,AssertionReaction & reaction)12925     void RunContext::handleNonExpr(
12926             AssertionInfo const &info,
12927             ResultWas::OfType resultType,
12928             AssertionReaction &reaction
12929     ) {
12930         m_lastAssertionInfo = info;
12931 
12932         AssertionResultData data( resultType, LazyExpression( false ) );
12933         AssertionResult assertionResult{ info, data };
12934         assertionEnded( assertionResult );
12935 
12936         if( !assertionResult.isOk() )
12937             populateReaction( reaction );
12938     }
12939 
getResultCapture()12940     IResultCapture& getResultCapture() {
12941         if (auto* capture = getCurrentContext().getResultCapture())
12942             return *capture;
12943         else
12944             CATCH_INTERNAL_ERROR("No result capture instance");
12945     }
12946 
seedRng(IConfig const & config)12947     void seedRng(IConfig const& config) {
12948         if (config.rngSeed() != 0) {
12949             std::srand(config.rngSeed());
12950             rng().seed(config.rngSeed());
12951         }
12952     }
12953 
rngSeed()12954     unsigned int rngSeed() {
12955         return getCurrentContext().getConfig()->rngSeed();
12956     }
12957 
12958 }
12959 // end catch_run_context.cpp
12960 // start catch_section.cpp
12961 
12962 namespace Catch {
12963 
Section(SectionInfo const & info)12964     Section::Section( SectionInfo const& info )
12965     :   m_info( info ),
12966         m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
12967     {
12968         m_timer.start();
12969     }
12970 
~Section()12971     Section::~Section() {
12972         if( m_sectionIncluded ) {
12973             SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
12974             if( uncaught_exceptions() )
12975                 getResultCapture().sectionEndedEarly( endInfo );
12976             else
12977                 getResultCapture().sectionEnded( endInfo );
12978         }
12979     }
12980 
12981     // This indicates whether the section should be executed or not
operator bool() const12982     Section::operator bool() const {
12983         return m_sectionIncluded;
12984     }
12985 
12986 } // end namespace Catch
12987 // end catch_section.cpp
12988 // start catch_section_info.cpp
12989 
12990 namespace Catch {
12991 
SectionInfo(SourceLineInfo const & _lineInfo,std::string const & _name)12992     SectionInfo::SectionInfo
12993         (   SourceLineInfo const& _lineInfo,
12994             std::string const& _name )
12995     :   name( _name ),
12996         lineInfo( _lineInfo )
12997     {}
12998 
12999 } // end namespace Catch
13000 // end catch_section_info.cpp
13001 // start catch_session.cpp
13002 
13003 // start catch_session.h
13004 
13005 #include <memory>
13006 
13007 namespace Catch {
13008 
13009     class Session : NonCopyable {
13010     public:
13011 
13012         Session();
13013         ~Session() override;
13014 
13015         void showHelp() const;
13016         void libIdentify();
13017 
13018         int applyCommandLine( int argc, char const * const * argv );
13019     #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
13020         int applyCommandLine( int argc, wchar_t const * const * argv );
13021     #endif
13022 
13023         void useConfigData( ConfigData const& configData );
13024 
13025         template<typename CharT>
run(int argc,CharT const * const argv[])13026         int run(int argc, CharT const * const argv[]) {
13027             if (m_startupExceptions)
13028                 return 1;
13029             int returnCode = applyCommandLine(argc, argv);
13030             if (returnCode == 0)
13031                 returnCode = run();
13032             return returnCode;
13033         }
13034 
13035         int run();
13036 
13037         clara::Parser const& cli() const;
13038         void cli( clara::Parser const& newParser );
13039         ConfigData& configData();
13040         Config& config();
13041     private:
13042         int runInternal();
13043 
13044         clara::Parser m_cli;
13045         ConfigData m_configData;
13046         std::shared_ptr<Config> m_config;
13047         bool m_startupExceptions = false;
13048     };
13049 
13050 } // end namespace Catch
13051 
13052 // end catch_session.h
13053 // start catch_version.h
13054 
13055 #include <iosfwd>
13056 
13057 namespace Catch {
13058 
13059     // Versioning information
13060     struct Version {
13061         Version( Version const& ) = delete;
13062         Version& operator=( Version const& ) = delete;
13063         Version(    unsigned int _majorVersion,
13064                     unsigned int _minorVersion,
13065                     unsigned int _patchNumber,
13066                     char const * const _branchName,
13067                     unsigned int _buildNumber );
13068 
13069         unsigned int const majorVersion;
13070         unsigned int const minorVersion;
13071         unsigned int const patchNumber;
13072 
13073         // buildNumber is only used if branchName is not null
13074         char const * const branchName;
13075         unsigned int const buildNumber;
13076 
13077         friend std::ostream& operator << ( std::ostream& os, Version const& version );
13078     };
13079 
13080     Version const& libraryVersion();
13081 }
13082 
13083 // end catch_version.h
13084 #include <cstdlib>
13085 #include <iomanip>
13086 #include <set>
13087 #include <iterator>
13088 
13089 namespace Catch {
13090 
13091     namespace {
13092         const int MaxExitCode = 255;
13093 
createReporter(std::string const & reporterName,IConfigPtr const & config)13094         IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) {
13095             auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);
13096             CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'");
13097 
13098             return reporter;
13099         }
13100 
makeReporter(std::shared_ptr<Config> const & config)13101         IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
13102             if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
13103                 return createReporter(config->getReporterName(), config);
13104             }
13105 
13106             // On older platforms, returning std::unique_ptr<ListeningReporter>
13107             // when the return type is std::unique_ptr<IStreamingReporter>
13108             // doesn't compile without a std::move call. However, this causes
13109             // a warning on newer platforms. Thus, we have to work around
13110             // it a bit and downcast the pointer manually.
13111             auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter);
13112             auto& multi = static_cast<ListeningReporter&>(*ret);
13113             auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
13114             for (auto const& listener : listeners) {
13115                 multi.addListener(listener->create(Catch::ReporterConfig(config)));
13116             }
13117             multi.addReporter(createReporter(config->getReporterName(), config));
13118             return ret;
13119         }
13120 
13121         class TestGroup {
13122         public:
TestGroup(std::shared_ptr<Config> const & config)13123             explicit TestGroup(std::shared_ptr<Config> const& config)
13124             : m_config{config}
13125             , m_context{config, makeReporter(config)}
13126             {
13127                 auto const& allTestCases = getAllTestCasesSorted(*m_config);
13128                 m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);
13129                 auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
13130 
13131                 if (m_matches.empty() && invalidArgs.empty()) {
13132                     for (auto const& test : allTestCases)
13133                         if (!test.isHidden())
13134                             m_tests.emplace(&test);
13135                 } else {
13136                     for (auto const& match : m_matches)
13137                         m_tests.insert(match.tests.begin(), match.tests.end());
13138                 }
13139             }
13140 
execute()13141             Totals execute() {
13142                 auto const& invalidArgs = m_config->testSpec().getInvalidArgs();
13143                 Totals totals;
13144                 m_context.testGroupStarting(m_config->name(), 1, 1);
13145                 for (auto const& testCase : m_tests) {
13146                     if (!m_context.aborting())
13147                         totals += m_context.runTest(*testCase);
13148                     else
13149                         m_context.reporter().skipTest(*testCase);
13150                 }
13151 
13152                 for (auto const& match : m_matches) {
13153                     if (match.tests.empty()) {
13154                         m_context.reporter().noMatchingTestCases(match.name);
13155                         totals.error = -1;
13156                     }
13157                 }
13158 
13159                 if (!invalidArgs.empty()) {
13160                     for (auto const& invalidArg: invalidArgs)
13161                          m_context.reporter().reportInvalidArguments(invalidArg);
13162                 }
13163 
13164                 m_context.testGroupEnded(m_config->name(), totals, 1, 1);
13165                 return totals;
13166             }
13167 
13168         private:
13169             using Tests = std::set<TestCase const*>;
13170 
13171             std::shared_ptr<Config> m_config;
13172             RunContext m_context;
13173             Tests m_tests;
13174             TestSpec::Matches m_matches;
13175         };
13176 
applyFilenamesAsTags(Catch::IConfig const & config)13177         void applyFilenamesAsTags(Catch::IConfig const& config) {
13178             auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
13179             for (auto& testCase : tests) {
13180                 auto tags = testCase.tags;
13181 
13182                 std::string filename = testCase.lineInfo.file;
13183                 auto lastSlash = filename.find_last_of("\\/");
13184                 if (lastSlash != std::string::npos) {
13185                     filename.erase(0, lastSlash);
13186                     filename[0] = '#';
13187                 }
13188 
13189                 auto lastDot = filename.find_last_of('.');
13190                 if (lastDot != std::string::npos) {
13191                     filename.erase(lastDot);
13192                 }
13193 
13194                 tags.push_back(std::move(filename));
13195                 setTags(testCase, tags);
13196             }
13197         }
13198 
13199     } // anon namespace
13200 
Session()13201     Session::Session() {
13202         static bool alreadyInstantiated = false;
13203         if( alreadyInstantiated ) {
13204             CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
13205             CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }
13206         }
13207 
13208         // There cannot be exceptions at startup in no-exception mode.
13209 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
13210         const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
13211         if ( !exceptions.empty() ) {
13212             config();
13213             getCurrentMutableContext().setConfig(m_config);
13214 
13215             m_startupExceptions = true;
13216             Colour colourGuard( Colour::Red );
13217             Catch::cerr() << "Errors occurred during startup!" << '\n';
13218             // iterate over all exceptions and notify user
13219             for ( const auto& ex_ptr : exceptions ) {
13220                 try {
13221                     std::rethrow_exception(ex_ptr);
13222                 } catch ( std::exception const& ex ) {
13223                     Catch::cerr() << Column( ex.what() ).indent(2) << '\n';
13224                 }
13225             }
13226         }
13227 #endif
13228 
13229         alreadyInstantiated = true;
13230         m_cli = makeCommandLineParser( m_configData );
13231     }
~Session()13232     Session::~Session() {
13233         Catch::cleanUp();
13234     }
13235 
showHelp() const13236     void Session::showHelp() const {
13237         Catch::cout()
13238                 << "\nCatch v" << libraryVersion() << "\n"
13239                 << m_cli << std::endl
13240                 << "For more detailed usage please see the project docs\n" << std::endl;
13241     }
libIdentify()13242     void Session::libIdentify() {
13243         Catch::cout()
13244                 << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n"
13245                 << std::left << std::setw(16) << "category: " << "testframework\n"
13246                 << std::left << std::setw(16) << "framework: " << "Catch Test\n"
13247                 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
13248     }
13249 
applyCommandLine(int argc,char const * const * argv)13250     int Session::applyCommandLine( int argc, char const * const * argv ) {
13251         if( m_startupExceptions )
13252             return 1;
13253 
13254         auto result = m_cli.parse( clara::Args( argc, argv ) );
13255         if( !result ) {
13256             config();
13257             getCurrentMutableContext().setConfig(m_config);
13258             Catch::cerr()
13259                 << Colour( Colour::Red )
13260                 << "\nError(s) in input:\n"
13261                 << Column( result.errorMessage() ).indent( 2 )
13262                 << "\n\n";
13263             Catch::cerr() << "Run with -? for usage\n" << std::endl;
13264             return MaxExitCode;
13265         }
13266 
13267         if( m_configData.showHelp )
13268             showHelp();
13269         if( m_configData.libIdentify )
13270             libIdentify();
13271         m_config.reset();
13272         return 0;
13273     }
13274 
13275 #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)
applyCommandLine(int argc,wchar_t const * const * argv)13276     int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
13277 
13278         char **utf8Argv = new char *[ argc ];
13279 
13280         for ( int i = 0; i < argc; ++i ) {
13281             int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr );
13282 
13283             utf8Argv[ i ] = new char[ bufSize ];
13284 
13285             WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr );
13286         }
13287 
13288         int returnCode = applyCommandLine( argc, utf8Argv );
13289 
13290         for ( int i = 0; i < argc; ++i )
13291             delete [] utf8Argv[ i ];
13292 
13293         delete [] utf8Argv;
13294 
13295         return returnCode;
13296     }
13297 #endif
13298 
useConfigData(ConfigData const & configData)13299     void Session::useConfigData( ConfigData const& configData ) {
13300         m_configData = configData;
13301         m_config.reset();
13302     }
13303 
run()13304     int Session::run() {
13305         if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
13306             Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
13307             static_cast<void>(std::getchar());
13308         }
13309         int exitCode = runInternal();
13310         if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
13311             Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
13312             static_cast<void>(std::getchar());
13313         }
13314         return exitCode;
13315     }
13316 
cli() const13317     clara::Parser const& Session::cli() const {
13318         return m_cli;
13319     }
cli(clara::Parser const & newParser)13320     void Session::cli( clara::Parser const& newParser ) {
13321         m_cli = newParser;
13322     }
configData()13323     ConfigData& Session::configData() {
13324         return m_configData;
13325     }
config()13326     Config& Session::config() {
13327         if( !m_config )
13328             m_config = std::make_shared<Config>( m_configData );
13329         return *m_config;
13330     }
13331 
runInternal()13332     int Session::runInternal() {
13333         if( m_startupExceptions )
13334             return 1;
13335 
13336         if (m_configData.showHelp || m_configData.libIdentify) {
13337             return 0;
13338         }
13339 
13340         CATCH_TRY {
13341             config(); // Force config to be constructed
13342 
13343             seedRng( *m_config );
13344 
13345             if( m_configData.filenamesAsTags )
13346                 applyFilenamesAsTags( *m_config );
13347 
13348             // Handle list request
13349             if( Option<std::size_t> listed = list( m_config ) )
13350                 return static_cast<int>( *listed );
13351 
13352             TestGroup tests { m_config };
13353             auto const totals = tests.execute();
13354 
13355             if( m_config->warnAboutNoTests() && totals.error == -1 )
13356                 return 2;
13357 
13358             // Note that on unices only the lower 8 bits are usually used, clamping
13359             // the return value to 255 prevents false negative when some multiple
13360             // of 256 tests has failed
13361             return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
13362         }
13363 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
13364         catch( std::exception& ex ) {
13365             Catch::cerr() << ex.what() << std::endl;
13366             return MaxExitCode;
13367         }
13368 #endif
13369     }
13370 
13371 } // end namespace Catch
13372 // end catch_session.cpp
13373 // start catch_singletons.cpp
13374 
13375 #include <vector>
13376 
13377 namespace Catch {
13378 
13379     namespace {
getSingletons()13380         static auto getSingletons() -> std::vector<ISingleton*>*& {
13381             static std::vector<ISingleton*>* g_singletons = nullptr;
13382             if( !g_singletons )
13383                 g_singletons = new std::vector<ISingleton*>();
13384             return g_singletons;
13385         }
13386     }
13387 
~ISingleton()13388     ISingleton::~ISingleton() {}
13389 
addSingleton(ISingleton * singleton)13390     void addSingleton(ISingleton* singleton ) {
13391         getSingletons()->push_back( singleton );
13392     }
cleanupSingletons()13393     void cleanupSingletons() {
13394         auto& singletons = getSingletons();
13395         for( auto singleton : *singletons )
13396             delete singleton;
13397         delete singletons;
13398         singletons = nullptr;
13399     }
13400 
13401 } // namespace Catch
13402 // end catch_singletons.cpp
13403 // start catch_startup_exception_registry.cpp
13404 
13405 namespace Catch {
add(std::exception_ptr const & exception)13406 void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
13407         CATCH_TRY {
13408             m_exceptions.push_back(exception);
13409         } CATCH_CATCH_ALL {
13410             // If we run out of memory during start-up there's really not a lot more we can do about it
13411             std::terminate();
13412         }
13413     }
13414 
getExceptions() const13415     std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept {
13416         return m_exceptions;
13417     }
13418 
13419 } // end namespace Catch
13420 // end catch_startup_exception_registry.cpp
13421 // start catch_stream.cpp
13422 
13423 #include <cstdio>
13424 #include <iostream>
13425 #include <fstream>
13426 #include <sstream>
13427 #include <vector>
13428 #include <memory>
13429 
13430 namespace Catch {
13431 
13432     Catch::IStream::~IStream() = default;
13433 
13434     namespace Detail { namespace {
13435         template<typename WriterF, std::size_t bufferSize=256>
13436         class StreamBufImpl : public std::streambuf {
13437             char data[bufferSize];
13438             WriterF m_writer;
13439 
13440         public:
StreamBufImpl()13441             StreamBufImpl() {
13442                 setp( data, data + sizeof(data) );
13443             }
13444 
~StreamBufImpl()13445             ~StreamBufImpl() noexcept {
13446                 StreamBufImpl::sync();
13447             }
13448 
13449         private:
overflow(int c)13450             int overflow( int c ) override {
13451                 sync();
13452 
13453                 if( c != EOF ) {
13454                     if( pbase() == epptr() )
13455                         m_writer( std::string( 1, static_cast<char>( c ) ) );
13456                     else
13457                         sputc( static_cast<char>( c ) );
13458                 }
13459                 return 0;
13460             }
13461 
sync()13462             int sync() override {
13463                 if( pbase() != pptr() ) {
13464                     m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
13465                     setp( pbase(), epptr() );
13466                 }
13467                 return 0;
13468             }
13469         };
13470 
13471         ///////////////////////////////////////////////////////////////////////////
13472 
13473         struct OutputDebugWriter {
13474 
operator ()Catch::Detail::__anon6f5048d93911::OutputDebugWriter13475             void operator()( std::string const&str ) {
13476                 writeToDebugConsole( str );
13477             }
13478         };
13479 
13480         ///////////////////////////////////////////////////////////////////////////
13481 
13482         class FileStream : public IStream {
13483             mutable std::ofstream m_ofs;
13484         public:
FileStream(StringRef filename)13485             FileStream( StringRef filename ) {
13486                 m_ofs.open( filename.c_str() );
13487                 CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" );
13488             }
13489             ~FileStream() override = default;
13490         public: // IStream
stream() const13491             std::ostream& stream() const override {
13492                 return m_ofs;
13493             }
13494         };
13495 
13496         ///////////////////////////////////////////////////////////////////////////
13497 
13498         class CoutStream : public IStream {
13499             mutable std::ostream m_os;
13500         public:
13501             // Store the streambuf from cout up-front because
13502             // cout may get redirected when running tests
CoutStream()13503             CoutStream() : m_os( Catch::cout().rdbuf() ) {}
13504             ~CoutStream() override = default;
13505 
13506         public: // IStream
stream() const13507             std::ostream& stream() const override { return m_os; }
13508         };
13509 
13510         ///////////////////////////////////////////////////////////////////////////
13511 
13512         class DebugOutStream : public IStream {
13513             std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
13514             mutable std::ostream m_os;
13515         public:
DebugOutStream()13516             DebugOutStream()
13517             :   m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
13518                 m_os( m_streamBuf.get() )
13519             {}
13520 
13521             ~DebugOutStream() override = default;
13522 
13523         public: // IStream
stream() const13524             std::ostream& stream() const override { return m_os; }
13525         };
13526 
13527     }} // namespace anon::detail
13528 
13529     ///////////////////////////////////////////////////////////////////////////
13530 
makeStream(StringRef const & filename)13531     auto makeStream( StringRef const &filename ) -> IStream const* {
13532         if( filename.empty() )
13533             return new Detail::CoutStream();
13534         else if( filename[0] == '%' ) {
13535             if( filename == "%debug" )
13536                 return new Detail::DebugOutStream();
13537             else
13538                 CATCH_ERROR( "Unrecognised stream: '" << filename << "'" );
13539         }
13540         else
13541             return new Detail::FileStream( filename );
13542     }
13543 
13544     // This class encapsulates the idea of a pool of ostringstreams that can be reused.
13545     struct StringStreams {
13546         std::vector<std::unique_ptr<std::ostringstream>> m_streams;
13547         std::vector<std::size_t> m_unused;
13548         std::ostringstream m_referenceStream; // Used for copy state/ flags from
13549 
addCatch::StringStreams13550         auto add() -> std::size_t {
13551             if( m_unused.empty() ) {
13552                 m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) );
13553                 return m_streams.size()-1;
13554             }
13555             else {
13556                 auto index = m_unused.back();
13557                 m_unused.pop_back();
13558                 return index;
13559             }
13560         }
13561 
releaseCatch::StringStreams13562         void release( std::size_t index ) {
13563             m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
13564             m_unused.push_back(index);
13565         }
13566     };
13567 
ReusableStringStream()13568     ReusableStringStream::ReusableStringStream()
13569     :   m_index( Singleton<StringStreams>::getMutable().add() ),
13570         m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
13571     {}
13572 
~ReusableStringStream()13573     ReusableStringStream::~ReusableStringStream() {
13574         static_cast<std::ostringstream*>( m_oss )->str("");
13575         m_oss->clear();
13576         Singleton<StringStreams>::getMutable().release( m_index );
13577     }
13578 
str() const13579     auto ReusableStringStream::str() const -> std::string {
13580         return static_cast<std::ostringstream*>( m_oss )->str();
13581     }
13582 
13583     ///////////////////////////////////////////////////////////////////////////
13584 
13585 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
cout()13586     std::ostream& cout() { return std::cout; }
cerr()13587     std::ostream& cerr() { return std::cerr; }
clog()13588     std::ostream& clog() { return std::clog; }
13589 #endif
13590 }
13591 // end catch_stream.cpp
13592 // start catch_string_manip.cpp
13593 
13594 #include <algorithm>
13595 #include <ostream>
13596 #include <cstring>
13597 #include <cctype>
13598 #include <vector>
13599 
13600 namespace Catch {
13601 
13602     namespace {
toLowerCh(char c)13603         char toLowerCh(char c) {
13604             return static_cast<char>( std::tolower( c ) );
13605         }
13606     }
13607 
startsWith(std::string const & s,std::string const & prefix)13608     bool startsWith( std::string const& s, std::string const& prefix ) {
13609         return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
13610     }
startsWith(std::string const & s,char prefix)13611     bool startsWith( std::string const& s, char prefix ) {
13612         return !s.empty() && s[0] == prefix;
13613     }
endsWith(std::string const & s,std::string const & suffix)13614     bool endsWith( std::string const& s, std::string const& suffix ) {
13615         return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
13616     }
endsWith(std::string const & s,char suffix)13617     bool endsWith( std::string const& s, char suffix ) {
13618         return !s.empty() && s[s.size()-1] == suffix;
13619     }
contains(std::string const & s,std::string const & infix)13620     bool contains( std::string const& s, std::string const& infix ) {
13621         return s.find( infix ) != std::string::npos;
13622     }
toLowerInPlace(std::string & s)13623     void toLowerInPlace( std::string& s ) {
13624         std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
13625     }
toLower(std::string const & s)13626     std::string toLower( std::string const& s ) {
13627         std::string lc = s;
13628         toLowerInPlace( lc );
13629         return lc;
13630     }
trim(std::string const & str)13631     std::string trim( std::string const& str ) {
13632         static char const* whitespaceChars = "\n\r\t ";
13633         std::string::size_type start = str.find_first_not_of( whitespaceChars );
13634         std::string::size_type end = str.find_last_not_of( whitespaceChars );
13635 
13636         return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
13637     }
13638 
trim(StringRef ref)13639     StringRef trim(StringRef ref) {
13640         const auto is_ws = [](char c) {
13641             return c == ' ' || c == '\t' || c == '\n' || c == '\r';
13642         };
13643         size_t real_begin = 0;
13644         while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; }
13645         size_t real_end = ref.size();
13646         while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; }
13647 
13648         return ref.substr(real_begin, real_end - real_begin);
13649     }
13650 
replaceInPlace(std::string & str,std::string const & replaceThis,std::string const & withThis)13651     bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
13652         bool replaced = false;
13653         std::size_t i = str.find( replaceThis );
13654         while( i != std::string::npos ) {
13655             replaced = true;
13656             str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
13657             if( i < str.size()-withThis.size() )
13658                 i = str.find( replaceThis, i+withThis.size() );
13659             else
13660                 i = std::string::npos;
13661         }
13662         return replaced;
13663     }
13664 
splitStringRef(StringRef str,char delimiter)13665     std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) {
13666         std::vector<StringRef> subStrings;
13667         std::size_t start = 0;
13668         for(std::size_t pos = 0; pos < str.size(); ++pos ) {
13669             if( str[pos] == delimiter ) {
13670                 if( pos - start > 1 )
13671                     subStrings.push_back( str.substr( start, pos-start ) );
13672                 start = pos+1;
13673             }
13674         }
13675         if( start < str.size() )
13676             subStrings.push_back( str.substr( start, str.size()-start ) );
13677         return subStrings;
13678     }
13679 
pluralise(std::size_t count,std::string const & label)13680     pluralise::pluralise( std::size_t count, std::string const& label )
13681     :   m_count( count ),
13682         m_label( label )
13683     {}
13684 
operator <<(std::ostream & os,pluralise const & pluraliser)13685     std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
13686         os << pluraliser.m_count << ' ' << pluraliser.m_label;
13687         if( pluraliser.m_count != 1 )
13688             os << 's';
13689         return os;
13690     }
13691 
13692 }
13693 // end catch_string_manip.cpp
13694 // start catch_stringref.cpp
13695 
13696 #include <algorithm>
13697 #include <ostream>
13698 #include <cstring>
13699 #include <cstdint>
13700 
13701 namespace Catch {
StringRef(char const * rawChars)13702     StringRef::StringRef( char const* rawChars ) noexcept
13703     : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
13704     {}
13705 
c_str() const13706     auto StringRef::c_str() const -> char const* {
13707         CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance");
13708         return m_start;
13709     }
data() const13710     auto StringRef::data() const noexcept -> char const* {
13711         return m_start;
13712     }
13713 
substr(size_type start,size_type size) const13714     auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {
13715         if (start < m_size) {
13716             return StringRef(m_start + start, (std::min)(m_size - start, size));
13717         } else {
13718             return StringRef();
13719         }
13720     }
operator ==(StringRef const & other) const13721     auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {
13722         return m_size == other.m_size
13723             && (std::memcmp( m_start, other.m_start, m_size ) == 0);
13724     }
13725 
operator <<(std::ostream & os,StringRef const & str)13726     auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
13727         return os.write(str.data(), str.size());
13728     }
13729 
operator +=(std::string & lhs,StringRef const & rhs)13730     auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
13731         lhs.append(rhs.data(), rhs.size());
13732         return lhs;
13733     }
13734 
13735 } // namespace Catch
13736 // end catch_stringref.cpp
13737 // start catch_tag_alias.cpp
13738 
13739 namespace Catch {
TagAlias(std::string const & _tag,SourceLineInfo _lineInfo)13740     TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
13741 }
13742 // end catch_tag_alias.cpp
13743 // start catch_tag_alias_autoregistrar.cpp
13744 
13745 namespace Catch {
13746 
RegistrarForTagAliases(char const * alias,char const * tag,SourceLineInfo const & lineInfo)13747     RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
13748         CATCH_TRY {
13749             getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
13750         } CATCH_CATCH_ALL {
13751             // Do not throw when constructing global objects, instead register the exception to be processed later
13752             getMutableRegistryHub().registerStartupException();
13753         }
13754     }
13755 
13756 }
13757 // end catch_tag_alias_autoregistrar.cpp
13758 // start catch_tag_alias_registry.cpp
13759 
13760 #include <sstream>
13761 
13762 namespace Catch {
13763 
~TagAliasRegistry()13764     TagAliasRegistry::~TagAliasRegistry() {}
13765 
find(std::string const & alias) const13766     TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {
13767         auto it = m_registry.find( alias );
13768         if( it != m_registry.end() )
13769             return &(it->second);
13770         else
13771             return nullptr;
13772     }
13773 
expandAliases(std::string const & unexpandedTestSpec) const13774     std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
13775         std::string expandedTestSpec = unexpandedTestSpec;
13776         for( auto const& registryKvp : m_registry ) {
13777             std::size_t pos = expandedTestSpec.find( registryKvp.first );
13778             if( pos != std::string::npos ) {
13779                 expandedTestSpec =  expandedTestSpec.substr( 0, pos ) +
13780                                     registryKvp.second.tag +
13781                                     expandedTestSpec.substr( pos + registryKvp.first.size() );
13782             }
13783         }
13784         return expandedTestSpec;
13785     }
13786 
add(std::string const & alias,std::string const & tag,SourceLineInfo const & lineInfo)13787     void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
13788         CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'),
13789                       "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo );
13790 
13791         CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
13792                       "error: tag alias, '" << alias << "' already registered.\n"
13793                       << "\tFirst seen at: " << find(alias)->lineInfo << "\n"
13794                       << "\tRedefined at: " << lineInfo );
13795     }
13796 
~ITagAliasRegistry()13797     ITagAliasRegistry::~ITagAliasRegistry() {}
13798 
get()13799     ITagAliasRegistry const& ITagAliasRegistry::get() {
13800         return getRegistryHub().getTagAliasRegistry();
13801     }
13802 
13803 } // end namespace Catch
13804 // end catch_tag_alias_registry.cpp
13805 // start catch_test_case_info.cpp
13806 
13807 #include <cctype>
13808 #include <exception>
13809 #include <algorithm>
13810 #include <sstream>
13811 
13812 namespace Catch {
13813 
13814     namespace {
parseSpecialTag(std::string const & tag)13815         TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
13816             if( startsWith( tag, '.' ) ||
13817                 tag == "!hide" )
13818                 return TestCaseInfo::IsHidden;
13819             else if( tag == "!throws" )
13820                 return TestCaseInfo::Throws;
13821             else if( tag == "!shouldfail" )
13822                 return TestCaseInfo::ShouldFail;
13823             else if( tag == "!mayfail" )
13824                 return TestCaseInfo::MayFail;
13825             else if( tag == "!nonportable" )
13826                 return TestCaseInfo::NonPortable;
13827             else if( tag == "!benchmark" )
13828                 return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
13829             else
13830                 return TestCaseInfo::None;
13831         }
isReservedTag(std::string const & tag)13832         bool isReservedTag( std::string const& tag ) {
13833             return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
13834         }
enforceNotReservedTag(std::string const & tag,SourceLineInfo const & _lineInfo)13835         void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
13836             CATCH_ENFORCE( !isReservedTag(tag),
13837                           "Tag name: [" << tag << "] is not allowed.\n"
13838                           << "Tag names starting with non alphanumeric characters are reserved\n"
13839                           << _lineInfo );
13840         }
13841     }
13842 
makeTestCase(ITestInvoker * _testCase,std::string const & _className,NameAndTags const & nameAndTags,SourceLineInfo const & _lineInfo)13843     TestCase makeTestCase(  ITestInvoker* _testCase,
13844                             std::string const& _className,
13845                             NameAndTags const& nameAndTags,
13846                             SourceLineInfo const& _lineInfo )
13847     {
13848         bool isHidden = false;
13849 
13850         // Parse out tags
13851         std::vector<std::string> tags;
13852         std::string desc, tag;
13853         bool inTag = false;
13854         for (char c : nameAndTags.tags) {
13855             if( !inTag ) {
13856                 if( c == '[' )
13857                     inTag = true;
13858                 else
13859                     desc += c;
13860             }
13861             else {
13862                 if( c == ']' ) {
13863                     TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
13864                     if( ( prop & TestCaseInfo::IsHidden ) != 0 )
13865                         isHidden = true;
13866                     else if( prop == TestCaseInfo::None )
13867                         enforceNotReservedTag( tag, _lineInfo );
13868 
13869                     // Merged hide tags like `[.approvals]` should be added as
13870                     // `[.][approvals]`. The `[.]` is added at later point, so
13871                     // we only strip the prefix
13872                     if (startsWith(tag, '.') && tag.size() > 1) {
13873                         tag.erase(0, 1);
13874                     }
13875                     tags.push_back( tag );
13876                     tag.clear();
13877                     inTag = false;
13878                 }
13879                 else
13880                     tag += c;
13881             }
13882         }
13883         if( isHidden ) {
13884             // Add all "hidden" tags to make them behave identically
13885             tags.insert( tags.end(), { ".", "!hide" } );
13886         }
13887 
13888         TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo );
13889         return TestCase( _testCase, std::move(info) );
13890     }
13891 
setTags(TestCaseInfo & testCaseInfo,std::vector<std::string> tags)13892     void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
13893         std::sort(begin(tags), end(tags));
13894         tags.erase(std::unique(begin(tags), end(tags)), end(tags));
13895         testCaseInfo.lcaseTags.clear();
13896 
13897         for( auto const& tag : tags ) {
13898             std::string lcaseTag = toLower( tag );
13899             testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
13900             testCaseInfo.lcaseTags.push_back( lcaseTag );
13901         }
13902         testCaseInfo.tags = std::move(tags);
13903     }
13904 
TestCaseInfo(std::string const & _name,std::string const & _className,std::string const & _description,std::vector<std::string> const & _tags,SourceLineInfo const & _lineInfo)13905     TestCaseInfo::TestCaseInfo( std::string const& _name,
13906                                 std::string const& _className,
13907                                 std::string const& _description,
13908                                 std::vector<std::string> const& _tags,
13909                                 SourceLineInfo const& _lineInfo )
13910     :   name( _name ),
13911         className( _className ),
13912         description( _description ),
13913         lineInfo( _lineInfo ),
13914         properties( None )
13915     {
13916         setTags( *this, _tags );
13917     }
13918 
isHidden() const13919     bool TestCaseInfo::isHidden() const {
13920         return ( properties & IsHidden ) != 0;
13921     }
throws() const13922     bool TestCaseInfo::throws() const {
13923         return ( properties & Throws ) != 0;
13924     }
okToFail() const13925     bool TestCaseInfo::okToFail() const {
13926         return ( properties & (ShouldFail | MayFail ) ) != 0;
13927     }
expectedToFail() const13928     bool TestCaseInfo::expectedToFail() const {
13929         return ( properties & (ShouldFail ) ) != 0;
13930     }
13931 
tagsAsString() const13932     std::string TestCaseInfo::tagsAsString() const {
13933         std::string ret;
13934         // '[' and ']' per tag
13935         std::size_t full_size = 2 * tags.size();
13936         for (const auto& tag : tags) {
13937             full_size += tag.size();
13938         }
13939         ret.reserve(full_size);
13940         for (const auto& tag : tags) {
13941             ret.push_back('[');
13942             ret.append(tag);
13943             ret.push_back(']');
13944         }
13945 
13946         return ret;
13947     }
13948 
TestCase(ITestInvoker * testCase,TestCaseInfo && info)13949     TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}
13950 
withName(std::string const & _newName) const13951     TestCase TestCase::withName( std::string const& _newName ) const {
13952         TestCase other( *this );
13953         other.name = _newName;
13954         return other;
13955     }
13956 
invoke() const13957     void TestCase::invoke() const {
13958         test->invoke();
13959     }
13960 
operator ==(TestCase const & other) const13961     bool TestCase::operator == ( TestCase const& other ) const {
13962         return  test.get() == other.test.get() &&
13963                 name == other.name &&
13964                 className == other.className;
13965     }
13966 
operator <(TestCase const & other) const13967     bool TestCase::operator < ( TestCase const& other ) const {
13968         return name < other.name;
13969     }
13970 
getTestCaseInfo() const13971     TestCaseInfo const& TestCase::getTestCaseInfo() const
13972     {
13973         return *this;
13974     }
13975 
13976 } // end namespace Catch
13977 // end catch_test_case_info.cpp
13978 // start catch_test_case_registry_impl.cpp
13979 
13980 #include <sstream>
13981 
13982 namespace Catch {
13983 
sortTests(IConfig const & config,std::vector<TestCase> const & unsortedTestCases)13984     std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
13985 
13986         std::vector<TestCase> sorted = unsortedTestCases;
13987 
13988         switch( config.runOrder() ) {
13989             case RunTests::InLexicographicalOrder:
13990                 std::sort( sorted.begin(), sorted.end() );
13991                 break;
13992             case RunTests::InRandomOrder:
13993                 seedRng( config );
13994                 std::shuffle( sorted.begin(), sorted.end(), rng() );
13995                 break;
13996             case RunTests::InDeclarationOrder:
13997                 // already in declaration order
13998                 break;
13999         }
14000         return sorted;
14001     }
14002 
isThrowSafe(TestCase const & testCase,IConfig const & config)14003     bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {
14004         return !testCase.throws() || config.allowThrows();
14005     }
14006 
matchTest(TestCase const & testCase,TestSpec const & testSpec,IConfig const & config)14007     bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
14008         return testSpec.matches( testCase ) && isThrowSafe( testCase, config );
14009     }
14010 
enforceNoDuplicateTestCases(std::vector<TestCase> const & functions)14011     void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
14012         std::set<TestCase> seenFunctions;
14013         for( auto const& function : functions ) {
14014             auto prev = seenFunctions.insert( function );
14015             CATCH_ENFORCE( prev.second,
14016                     "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n"
14017                     << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
14018                     << "\tRedefined at " << function.getTestCaseInfo().lineInfo );
14019         }
14020     }
14021 
filterTests(std::vector<TestCase> const & testCases,TestSpec const & testSpec,IConfig const & config)14022     std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
14023         std::vector<TestCase> filtered;
14024         filtered.reserve( testCases.size() );
14025         for (auto const& testCase : testCases) {
14026             if ((!testSpec.hasFilters() && !testCase.isHidden()) ||
14027                 (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
14028                 filtered.push_back(testCase);
14029             }
14030         }
14031         return filtered;
14032     }
getAllTestCasesSorted(IConfig const & config)14033     std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
14034         return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
14035     }
14036 
registerTest(TestCase const & testCase)14037     void TestRegistry::registerTest( TestCase const& testCase ) {
14038         std::string name = testCase.getTestCaseInfo().name;
14039         if( name.empty() ) {
14040             ReusableStringStream rss;
14041             rss << "Anonymous test case " << ++m_unnamedCount;
14042             return registerTest( testCase.withName( rss.str() ) );
14043         }
14044         m_functions.push_back( testCase );
14045     }
14046 
getAllTests() const14047     std::vector<TestCase> const& TestRegistry::getAllTests() const {
14048         return m_functions;
14049     }
getAllTestsSorted(IConfig const & config) const14050     std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
14051         if( m_sortedFunctions.empty() )
14052             enforceNoDuplicateTestCases( m_functions );
14053 
14054         if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
14055             m_sortedFunctions = sortTests( config, m_functions );
14056             m_currentSortOrder = config.runOrder();
14057         }
14058         return m_sortedFunctions;
14059     }
14060 
14061     ///////////////////////////////////////////////////////////////////////////
TestInvokerAsFunction(void (* testAsFunction)())14062     TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
14063 
invoke() const14064     void TestInvokerAsFunction::invoke() const {
14065         m_testAsFunction();
14066     }
14067 
extractClassName(StringRef const & classOrQualifiedMethodName)14068     std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
14069         std::string className(classOrQualifiedMethodName);
14070         if( startsWith( className, '&' ) )
14071         {
14072             std::size_t lastColons = className.rfind( "::" );
14073             std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
14074             if( penultimateColons == std::string::npos )
14075                 penultimateColons = 1;
14076             className = className.substr( penultimateColons, lastColons-penultimateColons );
14077         }
14078         return className;
14079     }
14080 
14081 } // end namespace Catch
14082 // end catch_test_case_registry_impl.cpp
14083 // start catch_test_case_tracker.cpp
14084 
14085 #include <algorithm>
14086 #include <cassert>
14087 #include <stdexcept>
14088 #include <memory>
14089 #include <sstream>
14090 
14091 #if defined(__clang__)
14092 #    pragma clang diagnostic push
14093 #    pragma clang diagnostic ignored "-Wexit-time-destructors"
14094 #endif
14095 
14096 namespace Catch {
14097 namespace TestCaseTracking {
14098 
NameAndLocation(std::string const & _name,SourceLineInfo const & _location)14099     NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
14100     :   name( _name ),
14101         location( _location )
14102     {}
14103 
14104     ITracker::~ITracker() = default;
14105 
startRun()14106     ITracker& TrackerContext::startRun() {
14107         m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr );
14108         m_currentTracker = nullptr;
14109         m_runState = Executing;
14110         return *m_rootTracker;
14111     }
14112 
endRun()14113     void TrackerContext::endRun() {
14114         m_rootTracker.reset();
14115         m_currentTracker = nullptr;
14116         m_runState = NotStarted;
14117     }
14118 
startCycle()14119     void TrackerContext::startCycle() {
14120         m_currentTracker = m_rootTracker.get();
14121         m_runState = Executing;
14122     }
completeCycle()14123     void TrackerContext::completeCycle() {
14124         m_runState = CompletedCycle;
14125     }
14126 
completedCycle() const14127     bool TrackerContext::completedCycle() const {
14128         return m_runState == CompletedCycle;
14129     }
currentTracker()14130     ITracker& TrackerContext::currentTracker() {
14131         return *m_currentTracker;
14132     }
setCurrentTracker(ITracker * tracker)14133     void TrackerContext::setCurrentTracker( ITracker* tracker ) {
14134         m_currentTracker = tracker;
14135     }
14136 
TrackerBase(NameAndLocation const & nameAndLocation,TrackerContext & ctx,ITracker * parent)14137     TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
14138     :   m_nameAndLocation( nameAndLocation ),
14139         m_ctx( ctx ),
14140         m_parent( parent )
14141     {}
14142 
nameAndLocation() const14143     NameAndLocation const& TrackerBase::nameAndLocation() const {
14144         return m_nameAndLocation;
14145     }
isComplete() const14146     bool TrackerBase::isComplete() const {
14147         return m_runState == CompletedSuccessfully || m_runState == Failed;
14148     }
isSuccessfullyCompleted() const14149     bool TrackerBase::isSuccessfullyCompleted() const {
14150         return m_runState == CompletedSuccessfully;
14151     }
isOpen() const14152     bool TrackerBase::isOpen() const {
14153         return m_runState != NotStarted && !isComplete();
14154     }
hasChildren() const14155     bool TrackerBase::hasChildren() const {
14156         return !m_children.empty();
14157     }
14158 
addChild(ITrackerPtr const & child)14159     void TrackerBase::addChild( ITrackerPtr const& child ) {
14160         m_children.push_back( child );
14161     }
14162 
findChild(NameAndLocation const & nameAndLocation)14163     ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) {
14164         auto it = std::find_if( m_children.begin(), m_children.end(),
14165             [&nameAndLocation]( ITrackerPtr const& tracker ){
14166                 return
14167                     tracker->nameAndLocation().location == nameAndLocation.location &&
14168                     tracker->nameAndLocation().name == nameAndLocation.name;
14169             } );
14170         return( it != m_children.end() )
14171             ? *it
14172             : nullptr;
14173     }
parent()14174     ITracker& TrackerBase::parent() {
14175         assert( m_parent ); // Should always be non-null except for root
14176         return *m_parent;
14177     }
14178 
openChild()14179     void TrackerBase::openChild() {
14180         if( m_runState != ExecutingChildren ) {
14181             m_runState = ExecutingChildren;
14182             if( m_parent )
14183                 m_parent->openChild();
14184         }
14185     }
14186 
isSectionTracker() const14187     bool TrackerBase::isSectionTracker() const { return false; }
isGeneratorTracker() const14188     bool TrackerBase::isGeneratorTracker() const { return false; }
14189 
open()14190     void TrackerBase::open() {
14191         m_runState = Executing;
14192         moveToThis();
14193         if( m_parent )
14194             m_parent->openChild();
14195     }
14196 
close()14197     void TrackerBase::close() {
14198 
14199         // Close any still open children (e.g. generators)
14200         while( &m_ctx.currentTracker() != this )
14201             m_ctx.currentTracker().close();
14202 
14203         switch( m_runState ) {
14204             case NeedsAnotherRun:
14205                 break;
14206 
14207             case Executing:
14208                 m_runState = CompletedSuccessfully;
14209                 break;
14210             case ExecutingChildren:
14211                 if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) )
14212                     m_runState = CompletedSuccessfully;
14213                 break;
14214 
14215             case NotStarted:
14216             case CompletedSuccessfully:
14217             case Failed:
14218                 CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState );
14219 
14220             default:
14221                 CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState );
14222         }
14223         moveToParent();
14224         m_ctx.completeCycle();
14225     }
fail()14226     void TrackerBase::fail() {
14227         m_runState = Failed;
14228         if( m_parent )
14229             m_parent->markAsNeedingAnotherRun();
14230         moveToParent();
14231         m_ctx.completeCycle();
14232     }
markAsNeedingAnotherRun()14233     void TrackerBase::markAsNeedingAnotherRun() {
14234         m_runState = NeedsAnotherRun;
14235     }
14236 
moveToParent()14237     void TrackerBase::moveToParent() {
14238         assert( m_parent );
14239         m_ctx.setCurrentTracker( m_parent );
14240     }
moveToThis()14241     void TrackerBase::moveToThis() {
14242         m_ctx.setCurrentTracker( this );
14243     }
14244 
SectionTracker(NameAndLocation const & nameAndLocation,TrackerContext & ctx,ITracker * parent)14245     SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
14246     :   TrackerBase( nameAndLocation, ctx, parent ),
14247         m_trimmed_name(trim(nameAndLocation.name))
14248     {
14249         if( parent ) {
14250             while( !parent->isSectionTracker() )
14251                 parent = &parent->parent();
14252 
14253             SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
14254             addNextFilters( parentSection.m_filters );
14255         }
14256     }
14257 
isComplete() const14258     bool SectionTracker::isComplete() const {
14259         bool complete = true;
14260 
14261         if ((m_filters.empty() || m_filters[0] == "")
14262             || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {
14263             complete = TrackerBase::isComplete();
14264         }
14265         return complete;
14266     }
14267 
isSectionTracker() const14268     bool SectionTracker::isSectionTracker() const { return true; }
14269 
acquire(TrackerContext & ctx,NameAndLocation const & nameAndLocation)14270     SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
14271         std::shared_ptr<SectionTracker> section;
14272 
14273         ITracker& currentTracker = ctx.currentTracker();
14274         if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
14275             assert( childTracker );
14276             assert( childTracker->isSectionTracker() );
14277             section = std::static_pointer_cast<SectionTracker>( childTracker );
14278         }
14279         else {
14280             section = std::make_shared<SectionTracker>( nameAndLocation, ctx, &currentTracker );
14281             currentTracker.addChild( section );
14282         }
14283         if( !ctx.completedCycle() )
14284             section->tryOpen();
14285         return *section;
14286     }
14287 
tryOpen()14288     void SectionTracker::tryOpen() {
14289         if( !isComplete() )
14290             open();
14291     }
14292 
addInitialFilters(std::vector<std::string> const & filters)14293     void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
14294         if( !filters.empty() ) {
14295             m_filters.reserve( m_filters.size() + filters.size() + 2 );
14296             m_filters.emplace_back(""); // Root - should never be consulted
14297             m_filters.emplace_back(""); // Test Case - not a section filter
14298             m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
14299         }
14300     }
addNextFilters(std::vector<std::string> const & filters)14301     void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) {
14302         if( filters.size() > 1 )
14303             m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );
14304     }
14305 
14306 } // namespace TestCaseTracking
14307 
14308 using TestCaseTracking::ITracker;
14309 using TestCaseTracking::TrackerContext;
14310 using TestCaseTracking::SectionTracker;
14311 
14312 } // namespace Catch
14313 
14314 #if defined(__clang__)
14315 #    pragma clang diagnostic pop
14316 #endif
14317 // end catch_test_case_tracker.cpp
14318 // start catch_test_registry.cpp
14319 
14320 namespace Catch {
14321 
makeTestInvoker(void (* testAsFunction)())14322     auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* {
14323         return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
14324     }
14325 
NameAndTags(StringRef const & name_,StringRef const & tags_)14326     NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
14327 
AutoReg(ITestInvoker * invoker,SourceLineInfo const & lineInfo,StringRef const & classOrMethod,NameAndTags const & nameAndTags)14328     AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
14329         CATCH_TRY {
14330             getMutableRegistryHub()
14331                     .registerTest(
14332                         makeTestCase(
14333                             invoker,
14334                             extractClassName( classOrMethod ),
14335                             nameAndTags,
14336                             lineInfo));
14337         } CATCH_CATCH_ALL {
14338             // Do not throw when constructing global objects, instead register the exception to be processed later
14339             getMutableRegistryHub().registerStartupException();
14340         }
14341     }
14342 
14343     AutoReg::~AutoReg() = default;
14344 }
14345 // end catch_test_registry.cpp
14346 // start catch_test_spec.cpp
14347 
14348 #include <algorithm>
14349 #include <string>
14350 #include <vector>
14351 #include <memory>
14352 
14353 namespace Catch {
14354 
Pattern(std::string const & name)14355     TestSpec::Pattern::Pattern( std::string const& name )
14356     : m_name( name )
14357     {}
14358 
14359     TestSpec::Pattern::~Pattern() = default;
14360 
name() const14361     std::string const& TestSpec::Pattern::name() const {
14362         return m_name;
14363     }
14364 
NamePattern(std::string const & name,std::string const & filterString)14365     TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString )
14366     : Pattern( filterString )
14367     , m_wildcardPattern( toLower( name ), CaseSensitive::No )
14368     {}
14369 
matches(TestCaseInfo const & testCase) const14370     bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
14371         return m_wildcardPattern.matches( testCase.name );
14372     }
14373 
TagPattern(std::string const & tag,std::string const & filterString)14374     TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString )
14375     : Pattern( filterString )
14376     , m_tag( toLower( tag ) )
14377     {}
14378 
matches(TestCaseInfo const & testCase) const14379     bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
14380         return std::find(begin(testCase.lcaseTags),
14381                          end(testCase.lcaseTags),
14382                          m_tag) != end(testCase.lcaseTags);
14383     }
14384 
ExcludedPattern(PatternPtr const & underlyingPattern)14385     TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern )
14386     : Pattern( underlyingPattern->name() )
14387     , m_underlyingPattern( underlyingPattern )
14388     {}
14389 
matches(TestCaseInfo const & testCase) const14390     bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const {
14391         return !m_underlyingPattern->matches( testCase );
14392     }
14393 
matches(TestCaseInfo const & testCase) const14394     bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
14395         return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } );
14396     }
14397 
name() const14398     std::string TestSpec::Filter::name() const {
14399         std::string name;
14400         for( auto const& p : m_patterns )
14401             name += p->name();
14402         return name;
14403     }
14404 
hasFilters() const14405     bool TestSpec::hasFilters() const {
14406         return !m_filters.empty();
14407     }
14408 
matches(TestCaseInfo const & testCase) const14409     bool TestSpec::matches( TestCaseInfo const& testCase ) const {
14410         return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );
14411     }
14412 
matchesByFilter(std::vector<TestCase> const & testCases,IConfig const & config) const14413     TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const
14414     {
14415         Matches matches( m_filters.size() );
14416         std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){
14417             std::vector<TestCase const*> currentMatches;
14418             for( auto const& test : testCases )
14419                 if( isThrowSafe( test, config ) && filter.matches( test ) )
14420                     currentMatches.emplace_back( &test );
14421             return FilterMatch{ filter.name(), currentMatches };
14422         } );
14423         return matches;
14424     }
14425 
getInvalidArgs() const14426     const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{
14427         return  (m_invalidArgs);
14428     }
14429 
14430 }
14431 // end catch_test_spec.cpp
14432 // start catch_test_spec_parser.cpp
14433 
14434 namespace Catch {
14435 
TestSpecParser(ITagAliasRegistry const & tagAliases)14436     TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
14437 
parse(std::string const & arg)14438     TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
14439         m_mode = None;
14440         m_exclusion = false;
14441         m_arg = m_tagAliases->expandAliases( arg );
14442         m_escapeChars.clear();
14443         m_substring.reserve(m_arg.size());
14444         m_patternName.reserve(m_arg.size());
14445         m_realPatternPos = 0;
14446 
14447         for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
14448           //if visitChar fails
14449            if( !visitChar( m_arg[m_pos] ) ){
14450                m_testSpec.m_invalidArgs.push_back(arg);
14451                break;
14452            }
14453         endMode();
14454         return *this;
14455     }
testSpec()14456     TestSpec TestSpecParser::testSpec() {
14457         addFilter();
14458         return m_testSpec;
14459     }
visitChar(char c)14460     bool TestSpecParser::visitChar( char c ) {
14461         if( (m_mode != EscapedName) && (c == '\\') ) {
14462             escape();
14463             addCharToPattern(c);
14464             return true;
14465         }else if((m_mode != EscapedName) && (c == ',') )  {
14466             return separate();
14467         }
14468 
14469         switch( m_mode ) {
14470         case None:
14471             if( processNoneChar( c ) )
14472                 return true;
14473             break;
14474         case Name:
14475             processNameChar( c );
14476             break;
14477         case EscapedName:
14478             endMode();
14479             addCharToPattern(c);
14480             return true;
14481         default:
14482         case Tag:
14483         case QuotedName:
14484             if( processOtherChar( c ) )
14485                 return true;
14486             break;
14487         }
14488 
14489         m_substring += c;
14490         if( !isControlChar( c ) ) {
14491             m_patternName += c;
14492             m_realPatternPos++;
14493         }
14494         return true;
14495     }
14496     // Two of the processing methods return true to signal the caller to return
14497     // without adding the given character to the current pattern strings
processNoneChar(char c)14498     bool TestSpecParser::processNoneChar( char c ) {
14499         switch( c ) {
14500         case ' ':
14501             return true;
14502         case '~':
14503             m_exclusion = true;
14504             return false;
14505         case '[':
14506             startNewMode( Tag );
14507             return false;
14508         case '"':
14509             startNewMode( QuotedName );
14510             return false;
14511         default:
14512             startNewMode( Name );
14513             return false;
14514         }
14515     }
processNameChar(char c)14516     void TestSpecParser::processNameChar( char c ) {
14517         if( c == '[' ) {
14518             if( m_substring == "exclude:" )
14519                 m_exclusion = true;
14520             else
14521                 endMode();
14522             startNewMode( Tag );
14523         }
14524     }
processOtherChar(char c)14525     bool TestSpecParser::processOtherChar( char c ) {
14526         if( !isControlChar( c ) )
14527             return false;
14528         m_substring += c;
14529         endMode();
14530         return true;
14531     }
startNewMode(Mode mode)14532     void TestSpecParser::startNewMode( Mode mode ) {
14533         m_mode = mode;
14534     }
endMode()14535     void TestSpecParser::endMode() {
14536         switch( m_mode ) {
14537         case Name:
14538         case QuotedName:
14539             return addNamePattern();
14540         case Tag:
14541             return addTagPattern();
14542         case EscapedName:
14543             revertBackToLastMode();
14544             return;
14545         case None:
14546         default:
14547             return startNewMode( None );
14548         }
14549     }
escape()14550     void TestSpecParser::escape() {
14551         saveLastMode();
14552         m_mode = EscapedName;
14553         m_escapeChars.push_back(m_realPatternPos);
14554     }
isControlChar(char c) const14555     bool TestSpecParser::isControlChar( char c ) const {
14556         switch( m_mode ) {
14557             default:
14558                 return false;
14559             case None:
14560                 return c == '~';
14561             case Name:
14562                 return c == '[';
14563             case EscapedName:
14564                 return true;
14565             case QuotedName:
14566                 return c == '"';
14567             case Tag:
14568                 return c == '[' || c == ']';
14569         }
14570     }
14571 
addFilter()14572     void TestSpecParser::addFilter() {
14573         if( !m_currentFilter.m_patterns.empty() ) {
14574             m_testSpec.m_filters.push_back( m_currentFilter );
14575             m_currentFilter = TestSpec::Filter();
14576         }
14577     }
14578 
saveLastMode()14579     void TestSpecParser::saveLastMode() {
14580       lastMode = m_mode;
14581     }
14582 
revertBackToLastMode()14583     void TestSpecParser::revertBackToLastMode() {
14584       m_mode = lastMode;
14585     }
14586 
separate()14587     bool TestSpecParser::separate() {
14588       if( (m_mode==QuotedName) || (m_mode==Tag) ){
14589          //invalid argument, signal failure to previous scope.
14590          m_mode = None;
14591          m_pos = m_arg.size();
14592          m_substring.clear();
14593          m_patternName.clear();
14594          return false;
14595       }
14596       endMode();
14597       addFilter();
14598       return true; //success
14599     }
14600 
preprocessPattern()14601     std::string TestSpecParser::preprocessPattern() {
14602         std::string token = m_patternName;
14603         for (std::size_t i = 0; i < m_escapeChars.size(); ++i)
14604             token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);
14605         m_escapeChars.clear();
14606         if (startsWith(token, "exclude:")) {
14607             m_exclusion = true;
14608             token = token.substr(8);
14609         }
14610 
14611         m_patternName.clear();
14612 
14613         return token;
14614     }
14615 
addNamePattern()14616     void TestSpecParser::addNamePattern() {
14617         auto token = preprocessPattern();
14618 
14619         if (!token.empty()) {
14620             TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring);
14621             if (m_exclusion)
14622                 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
14623             m_currentFilter.m_patterns.push_back(pattern);
14624         }
14625         m_substring.clear();
14626         m_exclusion = false;
14627         m_mode = None;
14628     }
14629 
addTagPattern()14630     void TestSpecParser::addTagPattern() {
14631         auto token = preprocessPattern();
14632 
14633         if (!token.empty()) {
14634             // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])
14635             // we have to create a separate hide tag and shorten the real one
14636             if (token.size() > 1 && token[0] == '.') {
14637                 token.erase(token.begin());
14638                 TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring);
14639                 if (m_exclusion) {
14640                     pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
14641                 }
14642                 m_currentFilter.m_patterns.push_back(pattern);
14643             }
14644 
14645             TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring);
14646 
14647             if (m_exclusion) {
14648                 pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);
14649             }
14650             m_currentFilter.m_patterns.push_back(pattern);
14651         }
14652         m_substring.clear();
14653         m_exclusion = false;
14654         m_mode = None;
14655     }
14656 
parseTestSpec(std::string const & arg)14657     TestSpec parseTestSpec( std::string const& arg ) {
14658         return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
14659     }
14660 
14661 } // namespace Catch
14662 // end catch_test_spec_parser.cpp
14663 // start catch_timer.cpp
14664 
14665 #include <chrono>
14666 
14667 static const uint64_t nanosecondsInSecond = 1000000000;
14668 
14669 namespace Catch {
14670 
getCurrentNanosecondsSinceEpoch()14671     auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
14672         return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
14673     }
14674 
14675     namespace {
estimateClockResolution()14676         auto estimateClockResolution() -> uint64_t {
14677             uint64_t sum = 0;
14678             static const uint64_t iterations = 1000000;
14679 
14680             auto startTime = getCurrentNanosecondsSinceEpoch();
14681 
14682             for( std::size_t i = 0; i < iterations; ++i ) {
14683 
14684                 uint64_t ticks;
14685                 uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
14686                 do {
14687                     ticks = getCurrentNanosecondsSinceEpoch();
14688                 } while( ticks == baseTicks );
14689 
14690                 auto delta = ticks - baseTicks;
14691                 sum += delta;
14692 
14693                 // If we have been calibrating for over 3 seconds -- the clock
14694                 // is terrible and we should move on.
14695                 // TBD: How to signal that the measured resolution is probably wrong?
14696                 if (ticks > startTime + 3 * nanosecondsInSecond) {
14697                     return sum / ( i + 1u );
14698                 }
14699             }
14700 
14701             // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers
14702             // - and potentially do more iterations if there's a high variance.
14703             return sum/iterations;
14704         }
14705     }
getEstimatedClockResolution()14706     auto getEstimatedClockResolution() -> uint64_t {
14707         static auto s_resolution = estimateClockResolution();
14708         return s_resolution;
14709     }
14710 
start()14711     void Timer::start() {
14712        m_nanoseconds = getCurrentNanosecondsSinceEpoch();
14713     }
getElapsedNanoseconds() const14714     auto Timer::getElapsedNanoseconds() const -> uint64_t {
14715         return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;
14716     }
getElapsedMicroseconds() const14717     auto Timer::getElapsedMicroseconds() const -> uint64_t {
14718         return getElapsedNanoseconds()/1000;
14719     }
getElapsedMilliseconds() const14720     auto Timer::getElapsedMilliseconds() const -> unsigned int {
14721         return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
14722     }
getElapsedSeconds() const14723     auto Timer::getElapsedSeconds() const -> double {
14724         return getElapsedMicroseconds()/1000000.0;
14725     }
14726 
14727 } // namespace Catch
14728 // end catch_timer.cpp
14729 // start catch_tostring.cpp
14730 
14731 #if defined(__clang__)
14732 #    pragma clang diagnostic push
14733 #    pragma clang diagnostic ignored "-Wexit-time-destructors"
14734 #    pragma clang diagnostic ignored "-Wglobal-constructors"
14735 #endif
14736 
14737 // Enable specific decls locally
14738 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
14739 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
14740 #endif
14741 
14742 #include <cmath>
14743 #include <iomanip>
14744 
14745 namespace Catch {
14746 
14747 namespace Detail {
14748 
14749     const std::string unprintableString = "{?}";
14750 
14751     namespace {
14752         const int hexThreshold = 255;
14753 
14754         struct Endianness {
14755             enum Arch { Big, Little };
14756 
whichCatch::Detail::__anon6f5048d94311::Endianness14757             static Arch which() {
14758                 int one = 1;
14759                 // If the lowest byte we read is non-zero, we can assume
14760                 // that little endian format is used.
14761                 auto value = *reinterpret_cast<char*>(&one);
14762                 return value ? Little : Big;
14763             }
14764         };
14765     }
14766 
rawMemoryToString(const void * object,std::size_t size)14767     std::string rawMemoryToString( const void *object, std::size_t size ) {
14768         // Reverse order for little endian architectures
14769         int i = 0, end = static_cast<int>( size ), inc = 1;
14770         if( Endianness::which() == Endianness::Little ) {
14771             i = end-1;
14772             end = inc = -1;
14773         }
14774 
14775         unsigned char const *bytes = static_cast<unsigned char const *>(object);
14776         ReusableStringStream rss;
14777         rss << "0x" << std::setfill('0') << std::hex;
14778         for( ; i != end; i += inc )
14779              rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
14780        return rss.str();
14781     }
14782 }
14783 
14784 template<typename T>
fpToString(T value,int precision)14785 std::string fpToString( T value, int precision ) {
14786     if (Catch::isnan(value)) {
14787         return "nan";
14788     }
14789 
14790     ReusableStringStream rss;
14791     rss << std::setprecision( precision )
14792         << std::fixed
14793         << value;
14794     std::string d = rss.str();
14795     std::size_t i = d.find_last_not_of( '0' );
14796     if( i != std::string::npos && i != d.size()-1 ) {
14797         if( d[i] == '.' )
14798             i++;
14799         d = d.substr( 0, i+1 );
14800     }
14801     return d;
14802 }
14803 
14804 //// ======================================================= ////
14805 //
14806 //   Out-of-line defs for full specialization of StringMaker
14807 //
14808 //// ======================================================= ////
14809 
convert(const std::string & str)14810 std::string StringMaker<std::string>::convert(const std::string& str) {
14811     if (!getCurrentContext().getConfig()->showInvisibles()) {
14812         return '"' + str + '"';
14813     }
14814 
14815     std::string s("\"");
14816     for (char c : str) {
14817         switch (c) {
14818         case '\n':
14819             s.append("\\n");
14820             break;
14821         case '\t':
14822             s.append("\\t");
14823             break;
14824         default:
14825             s.push_back(c);
14826             break;
14827         }
14828     }
14829     s.append("\"");
14830     return s;
14831 }
14832 
14833 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
convert(std::string_view str)14834 std::string StringMaker<std::string_view>::convert(std::string_view str) {
14835     return ::Catch::Detail::stringify(std::string{ str });
14836 }
14837 #endif
14838 
convert(char const * str)14839 std::string StringMaker<char const*>::convert(char const* str) {
14840     if (str) {
14841         return ::Catch::Detail::stringify(std::string{ str });
14842     } else {
14843         return{ "{null string}" };
14844     }
14845 }
convert(char * str)14846 std::string StringMaker<char*>::convert(char* str) {
14847     if (str) {
14848         return ::Catch::Detail::stringify(std::string{ str });
14849     } else {
14850         return{ "{null string}" };
14851     }
14852 }
14853 
14854 #ifdef CATCH_CONFIG_WCHAR
convert(const std::wstring & wstr)14855 std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
14856     std::string s;
14857     s.reserve(wstr.size());
14858     for (auto c : wstr) {
14859         s += (c <= 0xff) ? static_cast<char>(c) : '?';
14860     }
14861     return ::Catch::Detail::stringify(s);
14862 }
14863 
14864 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW
convert(std::wstring_view str)14865 std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {
14866     return StringMaker<std::wstring>::convert(std::wstring(str));
14867 }
14868 # endif
14869 
convert(wchar_t const * str)14870 std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
14871     if (str) {
14872         return ::Catch::Detail::stringify(std::wstring{ str });
14873     } else {
14874         return{ "{null string}" };
14875     }
14876 }
convert(wchar_t * str)14877 std::string StringMaker<wchar_t *>::convert(wchar_t * str) {
14878     if (str) {
14879         return ::Catch::Detail::stringify(std::wstring{ str });
14880     } else {
14881         return{ "{null string}" };
14882     }
14883 }
14884 #endif
14885 
14886 #if defined(CATCH_CONFIG_CPP17_BYTE)
14887 #include <cstddef>
convert(std::byte value)14888 std::string StringMaker<std::byte>::convert(std::byte value) {
14889     return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value));
14890 }
14891 #endif // defined(CATCH_CONFIG_CPP17_BYTE)
14892 
convert(int value)14893 std::string StringMaker<int>::convert(int value) {
14894     return ::Catch::Detail::stringify(static_cast<long long>(value));
14895 }
convert(long value)14896 std::string StringMaker<long>::convert(long value) {
14897     return ::Catch::Detail::stringify(static_cast<long long>(value));
14898 }
convert(long long value)14899 std::string StringMaker<long long>::convert(long long value) {
14900     ReusableStringStream rss;
14901     rss << value;
14902     if (value > Detail::hexThreshold) {
14903         rss << " (0x" << std::hex << value << ')';
14904     }
14905     return rss.str();
14906 }
14907 
convert(unsigned int value)14908 std::string StringMaker<unsigned int>::convert(unsigned int value) {
14909     return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
14910 }
convert(unsigned long value)14911 std::string StringMaker<unsigned long>::convert(unsigned long value) {
14912     return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
14913 }
convert(unsigned long long value)14914 std::string StringMaker<unsigned long long>::convert(unsigned long long value) {
14915     ReusableStringStream rss;
14916     rss << value;
14917     if (value > Detail::hexThreshold) {
14918         rss << " (0x" << std::hex << value << ')';
14919     }
14920     return rss.str();
14921 }
14922 
convert(bool b)14923 std::string StringMaker<bool>::convert(bool b) {
14924     return b ? "true" : "false";
14925 }
14926 
convert(signed char value)14927 std::string StringMaker<signed char>::convert(signed char value) {
14928     if (value == '\r') {
14929         return "'\\r'";
14930     } else if (value == '\f') {
14931         return "'\\f'";
14932     } else if (value == '\n') {
14933         return "'\\n'";
14934     } else if (value == '\t') {
14935         return "'\\t'";
14936     } else if ('\0' <= value && value < ' ') {
14937         return ::Catch::Detail::stringify(static_cast<unsigned int>(value));
14938     } else {
14939         char chstr[] = "' '";
14940         chstr[1] = value;
14941         return chstr;
14942     }
14943 }
convert(char c)14944 std::string StringMaker<char>::convert(char c) {
14945     return ::Catch::Detail::stringify(static_cast<signed char>(c));
14946 }
convert(unsigned char c)14947 std::string StringMaker<unsigned char>::convert(unsigned char c) {
14948     return ::Catch::Detail::stringify(static_cast<char>(c));
14949 }
14950 
convert(std::nullptr_t)14951 std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) {
14952     return "nullptr";
14953 }
14954 
14955 int StringMaker<float>::precision = 5;
14956 
convert(float value)14957 std::string StringMaker<float>::convert(float value) {
14958     return fpToString(value, precision) + 'f';
14959 }
14960 
14961 int StringMaker<double>::precision = 10;
14962 
convert(double value)14963 std::string StringMaker<double>::convert(double value) {
14964     return fpToString(value, precision);
14965 }
14966 
symbol()14967 std::string ratio_string<std::atto>::symbol() { return "a"; }
symbol()14968 std::string ratio_string<std::femto>::symbol() { return "f"; }
symbol()14969 std::string ratio_string<std::pico>::symbol() { return "p"; }
symbol()14970 std::string ratio_string<std::nano>::symbol() { return "n"; }
symbol()14971 std::string ratio_string<std::micro>::symbol() { return "u"; }
symbol()14972 std::string ratio_string<std::milli>::symbol() { return "m"; }
14973 
14974 } // end namespace Catch
14975 
14976 #if defined(__clang__)
14977 #    pragma clang diagnostic pop
14978 #endif
14979 
14980 // end catch_tostring.cpp
14981 // start catch_totals.cpp
14982 
14983 namespace Catch {
14984 
operator -(Counts const & other) const14985     Counts Counts::operator - ( Counts const& other ) const {
14986         Counts diff;
14987         diff.passed = passed - other.passed;
14988         diff.failed = failed - other.failed;
14989         diff.failedButOk = failedButOk - other.failedButOk;
14990         return diff;
14991     }
14992 
operator +=(Counts const & other)14993     Counts& Counts::operator += ( Counts const& other ) {
14994         passed += other.passed;
14995         failed += other.failed;
14996         failedButOk += other.failedButOk;
14997         return *this;
14998     }
14999 
total() const15000     std::size_t Counts::total() const {
15001         return passed + failed + failedButOk;
15002     }
allPassed() const15003     bool Counts::allPassed() const {
15004         return failed == 0 && failedButOk == 0;
15005     }
allOk() const15006     bool Counts::allOk() const {
15007         return failed == 0;
15008     }
15009 
operator -(Totals const & other) const15010     Totals Totals::operator - ( Totals const& other ) const {
15011         Totals diff;
15012         diff.assertions = assertions - other.assertions;
15013         diff.testCases = testCases - other.testCases;
15014         return diff;
15015     }
15016 
operator +=(Totals const & other)15017     Totals& Totals::operator += ( Totals const& other ) {
15018         assertions += other.assertions;
15019         testCases += other.testCases;
15020         return *this;
15021     }
15022 
delta(Totals const & prevTotals) const15023     Totals Totals::delta( Totals const& prevTotals ) const {
15024         Totals diff = *this - prevTotals;
15025         if( diff.assertions.failed > 0 )
15026             ++diff.testCases.failed;
15027         else if( diff.assertions.failedButOk > 0 )
15028             ++diff.testCases.failedButOk;
15029         else
15030             ++diff.testCases.passed;
15031         return diff;
15032     }
15033 
15034 }
15035 // end catch_totals.cpp
15036 // start catch_uncaught_exceptions.cpp
15037 
15038 #include <exception>
15039 
15040 namespace Catch {
uncaught_exceptions()15041     bool uncaught_exceptions() {
15042 #if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
15043         return std::uncaught_exceptions() > 0;
15044 #else
15045         return std::uncaught_exception();
15046 #endif
15047   }
15048 } // end namespace Catch
15049 // end catch_uncaught_exceptions.cpp
15050 // start catch_version.cpp
15051 
15052 #include <ostream>
15053 
15054 namespace Catch {
15055 
Version(unsigned int _majorVersion,unsigned int _minorVersion,unsigned int _patchNumber,char const * const _branchName,unsigned int _buildNumber)15056     Version::Version
15057         (   unsigned int _majorVersion,
15058             unsigned int _minorVersion,
15059             unsigned int _patchNumber,
15060             char const * const _branchName,
15061             unsigned int _buildNumber )
15062     :   majorVersion( _majorVersion ),
15063         minorVersion( _minorVersion ),
15064         patchNumber( _patchNumber ),
15065         branchName( _branchName ),
15066         buildNumber( _buildNumber )
15067     {}
15068 
operator <<(std::ostream & os,Version const & version)15069     std::ostream& operator << ( std::ostream& os, Version const& version ) {
15070         os  << version.majorVersion << '.'
15071             << version.minorVersion << '.'
15072             << version.patchNumber;
15073         // branchName is never null -> 0th char is \0 if it is empty
15074         if (version.branchName[0]) {
15075             os << '-' << version.branchName
15076                << '.' << version.buildNumber;
15077         }
15078         return os;
15079     }
15080 
libraryVersion()15081     Version const& libraryVersion() {
15082         static Version version( 2, 11, 3, "", 0 );
15083         return version;
15084     }
15085 
15086 }
15087 // end catch_version.cpp
15088 // start catch_wildcard_pattern.cpp
15089 
15090 namespace Catch {
15091 
WildcardPattern(std::string const & pattern,CaseSensitive::Choice caseSensitivity)15092     WildcardPattern::WildcardPattern( std::string const& pattern,
15093                                       CaseSensitive::Choice caseSensitivity )
15094     :   m_caseSensitivity( caseSensitivity ),
15095         m_pattern( normaliseString( pattern ) )
15096     {
15097         if( startsWith( m_pattern, '*' ) ) {
15098             m_pattern = m_pattern.substr( 1 );
15099             m_wildcard = WildcardAtStart;
15100         }
15101         if( endsWith( m_pattern, '*' ) ) {
15102             m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
15103             m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
15104         }
15105     }
15106 
matches(std::string const & str) const15107     bool WildcardPattern::matches( std::string const& str ) const {
15108         switch( m_wildcard ) {
15109             case NoWildcard:
15110                 return m_pattern == normaliseString( str );
15111             case WildcardAtStart:
15112                 return endsWith( normaliseString( str ), m_pattern );
15113             case WildcardAtEnd:
15114                 return startsWith( normaliseString( str ), m_pattern );
15115             case WildcardAtBothEnds:
15116                 return contains( normaliseString( str ), m_pattern );
15117             default:
15118                 CATCH_INTERNAL_ERROR( "Unknown enum" );
15119         }
15120     }
15121 
normaliseString(std::string const & str) const15122     std::string WildcardPattern::normaliseString( std::string const& str ) const {
15123         return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str );
15124     }
15125 }
15126 // end catch_wildcard_pattern.cpp
15127 // start catch_xmlwriter.cpp
15128 
15129 #include <iomanip>
15130 #include <type_traits>
15131 
15132 namespace Catch {
15133 
15134 namespace {
15135 
trailingBytes(unsigned char c)15136     size_t trailingBytes(unsigned char c) {
15137         if ((c & 0xE0) == 0xC0) {
15138             return 2;
15139         }
15140         if ((c & 0xF0) == 0xE0) {
15141             return 3;
15142         }
15143         if ((c & 0xF8) == 0xF0) {
15144             return 4;
15145         }
15146         CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
15147     }
15148 
headerValue(unsigned char c)15149     uint32_t headerValue(unsigned char c) {
15150         if ((c & 0xE0) == 0xC0) {
15151             return c & 0x1F;
15152         }
15153         if ((c & 0xF0) == 0xE0) {
15154             return c & 0x0F;
15155         }
15156         if ((c & 0xF8) == 0xF0) {
15157             return c & 0x07;
15158         }
15159         CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
15160     }
15161 
hexEscapeChar(std::ostream & os,unsigned char c)15162     void hexEscapeChar(std::ostream& os, unsigned char c) {
15163         std::ios_base::fmtflags f(os.flags());
15164         os << "\\x"
15165             << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
15166             << static_cast<int>(c);
15167         os.flags(f);
15168     }
15169 
shouldNewline(XmlFormatting fmt)15170     bool shouldNewline(XmlFormatting fmt) {
15171         return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Newline));
15172     }
15173 
shouldIndent(XmlFormatting fmt)15174     bool shouldIndent(XmlFormatting fmt) {
15175         return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Indent));
15176     }
15177 
15178 } // anonymous namespace
15179 
operator |(XmlFormatting lhs,XmlFormatting rhs)15180     XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) {
15181         return static_cast<XmlFormatting>(
15182             static_cast<std::underlying_type<XmlFormatting>::type>(lhs) |
15183             static_cast<std::underlying_type<XmlFormatting>::type>(rhs)
15184         );
15185     }
15186 
operator &(XmlFormatting lhs,XmlFormatting rhs)15187     XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) {
15188         return static_cast<XmlFormatting>(
15189             static_cast<std::underlying_type<XmlFormatting>::type>(lhs) &
15190             static_cast<std::underlying_type<XmlFormatting>::type>(rhs)
15191         );
15192     }
15193 
XmlEncode(std::string const & str,ForWhat forWhat)15194     XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
15195     :   m_str( str ),
15196         m_forWhat( forWhat )
15197     {}
15198 
encodeTo(std::ostream & os) const15199     void XmlEncode::encodeTo( std::ostream& os ) const {
15200         // Apostrophe escaping not necessary if we always use " to write attributes
15201         // (see: http://www.w3.org/TR/xml/#syntax)
15202 
15203         for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
15204             unsigned char c = m_str[idx];
15205             switch (c) {
15206             case '<':   os << "&lt;"; break;
15207             case '&':   os << "&amp;"; break;
15208 
15209             case '>':
15210                 // See: http://www.w3.org/TR/xml/#syntax
15211                 if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
15212                     os << "&gt;";
15213                 else
15214                     os << c;
15215                 break;
15216 
15217             case '\"':
15218                 if (m_forWhat == ForAttributes)
15219                     os << "&quot;";
15220                 else
15221                     os << c;
15222                 break;
15223 
15224             default:
15225                 // Check for control characters and invalid utf-8
15226 
15227                 // Escape control characters in standard ascii
15228                 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
15229                 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
15230                     hexEscapeChar(os, c);
15231                     break;
15232                 }
15233 
15234                 // Plain ASCII: Write it to stream
15235                 if (c < 0x7F) {
15236                     os << c;
15237                     break;
15238                 }
15239 
15240                 // UTF-8 territory
15241                 // Check if the encoding is valid and if it is not, hex escape bytes.
15242                 // Important: We do not check the exact decoded values for validity, only the encoding format
15243                 // First check that this bytes is a valid lead byte:
15244                 // This means that it is not encoded as 1111 1XXX
15245                 // Or as 10XX XXXX
15246                 if (c <  0xC0 ||
15247                     c >= 0xF8) {
15248                     hexEscapeChar(os, c);
15249                     break;
15250                 }
15251 
15252                 auto encBytes = trailingBytes(c);
15253                 // Are there enough bytes left to avoid accessing out-of-bounds memory?
15254                 if (idx + encBytes - 1 >= m_str.size()) {
15255                     hexEscapeChar(os, c);
15256                     break;
15257                 }
15258                 // The header is valid, check data
15259                 // The next encBytes bytes must together be a valid utf-8
15260                 // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
15261                 bool valid = true;
15262                 uint32_t value = headerValue(c);
15263                 for (std::size_t n = 1; n < encBytes; ++n) {
15264                     unsigned char nc = m_str[idx + n];
15265                     valid &= ((nc & 0xC0) == 0x80);
15266                     value = (value << 6) | (nc & 0x3F);
15267                 }
15268 
15269                 if (
15270                     // Wrong bit pattern of following bytes
15271                     (!valid) ||
15272                     // Overlong encodings
15273                     (value < 0x80) ||
15274                     (0x80 <= value && value < 0x800   && encBytes > 2) ||
15275                     (0x800 < value && value < 0x10000 && encBytes > 3) ||
15276                     // Encoded value out of range
15277                     (value >= 0x110000)
15278                     ) {
15279                     hexEscapeChar(os, c);
15280                     break;
15281                 }
15282 
15283                 // If we got here, this is in fact a valid(ish) utf-8 sequence
15284                 for (std::size_t n = 0; n < encBytes; ++n) {
15285                     os << m_str[idx + n];
15286                 }
15287                 idx += encBytes - 1;
15288                 break;
15289             }
15290         }
15291     }
15292 
operator <<(std::ostream & os,XmlEncode const & xmlEncode)15293     std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
15294         xmlEncode.encodeTo( os );
15295         return os;
15296     }
15297 
ScopedElement(XmlWriter * writer,XmlFormatting fmt)15298     XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt )
15299     :   m_writer( writer ),
15300         m_fmt(fmt)
15301     {}
15302 
ScopedElement(ScopedElement && other)15303     XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
15304     :   m_writer( other.m_writer ),
15305         m_fmt(other.m_fmt)
15306     {
15307         other.m_writer = nullptr;
15308         other.m_fmt = XmlFormatting::None;
15309     }
operator =(ScopedElement && other)15310     XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
15311         if ( m_writer ) {
15312             m_writer->endElement();
15313         }
15314         m_writer = other.m_writer;
15315         other.m_writer = nullptr;
15316         m_fmt = other.m_fmt;
15317         other.m_fmt = XmlFormatting::None;
15318         return *this;
15319     }
15320 
~ScopedElement()15321     XmlWriter::ScopedElement::~ScopedElement() {
15322         if (m_writer) {
15323             m_writer->endElement(m_fmt);
15324         }
15325     }
15326 
writeText(std::string const & text,XmlFormatting fmt)15327     XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, XmlFormatting fmt ) {
15328         m_writer->writeText( text, fmt );
15329         return *this;
15330     }
15331 
XmlWriter(std::ostream & os)15332     XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
15333     {
15334         writeDeclaration();
15335     }
15336 
~XmlWriter()15337     XmlWriter::~XmlWriter() {
15338         while (!m_tags.empty()) {
15339             endElement();
15340         }
15341         newlineIfNecessary();
15342     }
15343 
startElement(std::string const & name,XmlFormatting fmt)15344     XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) {
15345         ensureTagClosed();
15346         newlineIfNecessary();
15347         if (shouldIndent(fmt)) {
15348             m_os << m_indent;
15349             m_indent += "  ";
15350         }
15351         m_os << '<' << name;
15352         m_tags.push_back( name );
15353         m_tagIsOpen = true;
15354         applyFormatting(fmt);
15355         return *this;
15356     }
15357 
scopedElement(std::string const & name,XmlFormatting fmt)15358     XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) {
15359         ScopedElement scoped( this, fmt );
15360         startElement( name, fmt );
15361         return scoped;
15362     }
15363 
endElement(XmlFormatting fmt)15364     XmlWriter& XmlWriter::endElement(XmlFormatting fmt) {
15365         m_indent = m_indent.substr(0, m_indent.size() - 2);
15366 
15367         if( m_tagIsOpen ) {
15368             m_os << "/>";
15369             m_tagIsOpen = false;
15370         } else {
15371             newlineIfNecessary();
15372             if (shouldIndent(fmt)) {
15373                 m_os << m_indent;
15374             }
15375             m_os << "</" << m_tags.back() << ">";
15376         }
15377         m_os << std::flush;
15378         applyFormatting(fmt);
15379         m_tags.pop_back();
15380         return *this;
15381     }
15382 
writeAttribute(std::string const & name,std::string const & attribute)15383     XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {
15384         if( !name.empty() && !attribute.empty() )
15385             m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
15386         return *this;
15387     }
15388 
writeAttribute(std::string const & name,bool attribute)15389     XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {
15390         m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
15391         return *this;
15392     }
15393 
writeText(std::string const & text,XmlFormatting fmt)15394     XmlWriter& XmlWriter::writeText( std::string const& text, XmlFormatting fmt) {
15395         if( !text.empty() ){
15396             bool tagWasOpen = m_tagIsOpen;
15397             ensureTagClosed();
15398             if (tagWasOpen && shouldIndent(fmt)) {
15399                 m_os << m_indent;
15400             }
15401             m_os << XmlEncode( text );
15402             applyFormatting(fmt);
15403         }
15404         return *this;
15405     }
15406 
writeComment(std::string const & text,XmlFormatting fmt)15407     XmlWriter& XmlWriter::writeComment( std::string const& text, XmlFormatting fmt) {
15408         ensureTagClosed();
15409         if (shouldIndent(fmt)) {
15410             m_os << m_indent;
15411         }
15412         m_os << "<!--" << text << "-->";
15413         applyFormatting(fmt);
15414         return *this;
15415     }
15416 
writeStylesheetRef(std::string const & url)15417     void XmlWriter::writeStylesheetRef( std::string const& url ) {
15418         m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
15419     }
15420 
writeBlankLine()15421     XmlWriter& XmlWriter::writeBlankLine() {
15422         ensureTagClosed();
15423         m_os << '\n';
15424         return *this;
15425     }
15426 
ensureTagClosed()15427     void XmlWriter::ensureTagClosed() {
15428         if( m_tagIsOpen ) {
15429             m_os << '>' << std::flush;
15430             newlineIfNecessary();
15431             m_tagIsOpen = false;
15432         }
15433     }
15434 
applyFormatting(XmlFormatting fmt)15435     void XmlWriter::applyFormatting(XmlFormatting fmt) {
15436         m_needsNewline = shouldNewline(fmt);
15437     }
15438 
writeDeclaration()15439     void XmlWriter::writeDeclaration() {
15440         m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
15441     }
15442 
newlineIfNecessary()15443     void XmlWriter::newlineIfNecessary() {
15444         if( m_needsNewline ) {
15445             m_os << std::endl;
15446             m_needsNewline = false;
15447         }
15448     }
15449 }
15450 // end catch_xmlwriter.cpp
15451 // start catch_reporter_bases.cpp
15452 
15453 #include <cstring>
15454 #include <cfloat>
15455 #include <cstdio>
15456 #include <cassert>
15457 #include <memory>
15458 
15459 namespace Catch {
prepareExpandedExpression(AssertionResult & result)15460     void prepareExpandedExpression(AssertionResult& result) {
15461         result.getExpandedExpression();
15462     }
15463 
15464     // Because formatting using c++ streams is stateful, drop down to C is required
15465     // Alternatively we could use stringstream, but its performance is... not good.
getFormattedDuration(double duration)15466     std::string getFormattedDuration( double duration ) {
15467         // Max exponent + 1 is required to represent the whole part
15468         // + 1 for decimal point
15469         // + 3 for the 3 decimal places
15470         // + 1 for null terminator
15471         const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
15472         char buffer[maxDoubleSize];
15473 
15474         // Save previous errno, to prevent sprintf from overwriting it
15475         ErrnoGuard guard;
15476 #ifdef _MSC_VER
15477         sprintf_s(buffer, "%.3f", duration);
15478 #else
15479         std::sprintf(buffer, "%.3f", duration);
15480 #endif
15481         return std::string(buffer);
15482     }
15483 
serializeFilters(std::vector<std::string> const & container)15484     std::string serializeFilters( std::vector<std::string> const& container ) {
15485         ReusableStringStream oss;
15486         bool first = true;
15487         for (auto&& filter : container)
15488         {
15489             if (!first)
15490                 oss << ' ';
15491             else
15492                 first = false;
15493 
15494             oss << filter;
15495         }
15496         return oss.str();
15497     }
15498 
TestEventListenerBase(ReporterConfig const & _config)15499     TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
15500         :StreamingReporterBase(_config) {}
15501 
getSupportedVerbosities()15502     std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() {
15503         return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High };
15504     }
15505 
assertionStarting(AssertionInfo const &)15506     void TestEventListenerBase::assertionStarting(AssertionInfo const &) {}
15507 
assertionEnded(AssertionStats const &)15508     bool TestEventListenerBase::assertionEnded(AssertionStats const &) {
15509         return false;
15510     }
15511 
15512 } // end namespace Catch
15513 // end catch_reporter_bases.cpp
15514 // start catch_reporter_compact.cpp
15515 
15516 namespace {
15517 
15518 #ifdef CATCH_PLATFORM_MAC
failedString()15519     const char* failedString() { return "FAILED"; }
passedString()15520     const char* passedString() { return "PASSED"; }
15521 #else
15522     const char* failedString() { return "failed"; }
15523     const char* passedString() { return "passed"; }
15524 #endif
15525 
15526     // Colour::LightGrey
dimColour()15527     Catch::Colour::Code dimColour() { return Catch::Colour::FileName; }
15528 
bothOrAll(std::size_t count)15529     std::string bothOrAll( std::size_t count ) {
15530         return count == 1 ? std::string() :
15531                count == 2 ? "both " : "all " ;
15532     }
15533 
15534 } // anon namespace
15535 
15536 namespace Catch {
15537 namespace {
15538 // Colour, message variants:
15539 // - white: No tests ran.
15540 // -   red: Failed [both/all] N test cases, failed [both/all] M assertions.
15541 // - white: Passed [both/all] N test cases (no assertions).
15542 // -   red: Failed N tests cases, failed M assertions.
15543 // - green: Passed [both/all] N tests cases with M assertions.
printTotals(std::ostream & out,const Totals & totals)15544 void printTotals(std::ostream& out, const Totals& totals) {
15545     if (totals.testCases.total() == 0) {
15546         out << "No tests ran.";
15547     } else if (totals.testCases.failed == totals.testCases.total()) {
15548         Colour colour(Colour::ResultError);
15549         const std::string qualify_assertions_failed =
15550             totals.assertions.failed == totals.assertions.total() ?
15551             bothOrAll(totals.assertions.failed) : std::string();
15552         out <<
15553             "Failed " << bothOrAll(totals.testCases.failed)
15554             << pluralise(totals.testCases.failed, "test case") << ", "
15555             "failed " << qualify_assertions_failed <<
15556             pluralise(totals.assertions.failed, "assertion") << '.';
15557     } else if (totals.assertions.total() == 0) {
15558         out <<
15559             "Passed " << bothOrAll(totals.testCases.total())
15560             << pluralise(totals.testCases.total(), "test case")
15561             << " (no assertions).";
15562     } else if (totals.assertions.failed) {
15563         Colour colour(Colour::ResultError);
15564         out <<
15565             "Failed " << pluralise(totals.testCases.failed, "test case") << ", "
15566             "failed " << pluralise(totals.assertions.failed, "assertion") << '.';
15567     } else {
15568         Colour colour(Colour::ResultSuccess);
15569         out <<
15570             "Passed " << bothOrAll(totals.testCases.passed)
15571             << pluralise(totals.testCases.passed, "test case") <<
15572             " with " << pluralise(totals.assertions.passed, "assertion") << '.';
15573     }
15574 }
15575 
15576 // Implementation of CompactReporter formatting
15577 class AssertionPrinter {
15578 public:
15579     AssertionPrinter& operator= (AssertionPrinter const&) = delete;
15580     AssertionPrinter(AssertionPrinter const&) = delete;
AssertionPrinter(std::ostream & _stream,AssertionStats const & _stats,bool _printInfoMessages)15581     AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
15582         : stream(_stream)
15583         , result(_stats.assertionResult)
15584         , messages(_stats.infoMessages)
15585         , itMessage(_stats.infoMessages.begin())
15586         , printInfoMessages(_printInfoMessages) {}
15587 
print()15588     void print() {
15589         printSourceInfo();
15590 
15591         itMessage = messages.begin();
15592 
15593         switch (result.getResultType()) {
15594         case ResultWas::Ok:
15595             printResultType(Colour::ResultSuccess, passedString());
15596             printOriginalExpression();
15597             printReconstructedExpression();
15598             if (!result.hasExpression())
15599                 printRemainingMessages(Colour::None);
15600             else
15601                 printRemainingMessages();
15602             break;
15603         case ResultWas::ExpressionFailed:
15604             if (result.isOk())
15605                 printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok"));
15606             else
15607                 printResultType(Colour::Error, failedString());
15608             printOriginalExpression();
15609             printReconstructedExpression();
15610             printRemainingMessages();
15611             break;
15612         case ResultWas::ThrewException:
15613             printResultType(Colour::Error, failedString());
15614             printIssue("unexpected exception with message:");
15615             printMessage();
15616             printExpressionWas();
15617             printRemainingMessages();
15618             break;
15619         case ResultWas::FatalErrorCondition:
15620             printResultType(Colour::Error, failedString());
15621             printIssue("fatal error condition with message:");
15622             printMessage();
15623             printExpressionWas();
15624             printRemainingMessages();
15625             break;
15626         case ResultWas::DidntThrowException:
15627             printResultType(Colour::Error, failedString());
15628             printIssue("expected exception, got none");
15629             printExpressionWas();
15630             printRemainingMessages();
15631             break;
15632         case ResultWas::Info:
15633             printResultType(Colour::None, "info");
15634             printMessage();
15635             printRemainingMessages();
15636             break;
15637         case ResultWas::Warning:
15638             printResultType(Colour::None, "warning");
15639             printMessage();
15640             printRemainingMessages();
15641             break;
15642         case ResultWas::ExplicitFailure:
15643             printResultType(Colour::Error, failedString());
15644             printIssue("explicitly");
15645             printRemainingMessages(Colour::None);
15646             break;
15647             // These cases are here to prevent compiler warnings
15648         case ResultWas::Unknown:
15649         case ResultWas::FailureBit:
15650         case ResultWas::Exception:
15651             printResultType(Colour::Error, "** internal error **");
15652             break;
15653         }
15654     }
15655 
15656 private:
printSourceInfo() const15657     void printSourceInfo() const {
15658         Colour colourGuard(Colour::FileName);
15659         stream << result.getSourceInfo() << ':';
15660     }
15661 
printResultType(Colour::Code colour,std::string const & passOrFail) const15662     void printResultType(Colour::Code colour, std::string const& passOrFail) const {
15663         if (!passOrFail.empty()) {
15664             {
15665                 Colour colourGuard(colour);
15666                 stream << ' ' << passOrFail;
15667             }
15668             stream << ':';
15669         }
15670     }
15671 
printIssue(std::string const & issue) const15672     void printIssue(std::string const& issue) const {
15673         stream << ' ' << issue;
15674     }
15675 
printExpressionWas()15676     void printExpressionWas() {
15677         if (result.hasExpression()) {
15678             stream << ';';
15679             {
15680                 Colour colour(dimColour());
15681                 stream << " expression was:";
15682             }
15683             printOriginalExpression();
15684         }
15685     }
15686 
printOriginalExpression() const15687     void printOriginalExpression() const {
15688         if (result.hasExpression()) {
15689             stream << ' ' << result.getExpression();
15690         }
15691     }
15692 
printReconstructedExpression() const15693     void printReconstructedExpression() const {
15694         if (result.hasExpandedExpression()) {
15695             {
15696                 Colour colour(dimColour());
15697                 stream << " for: ";
15698             }
15699             stream << result.getExpandedExpression();
15700         }
15701     }
15702 
printMessage()15703     void printMessage() {
15704         if (itMessage != messages.end()) {
15705             stream << " '" << itMessage->message << '\'';
15706             ++itMessage;
15707         }
15708     }
15709 
printRemainingMessages(Colour::Code colour=dimColour ())15710     void printRemainingMessages(Colour::Code colour = dimColour()) {
15711         if (itMessage == messages.end())
15712             return;
15713 
15714         const auto itEnd = messages.cend();
15715         const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
15716 
15717         {
15718             Colour colourGuard(colour);
15719             stream << " with " << pluralise(N, "message") << ':';
15720         }
15721 
15722         while (itMessage != itEnd) {
15723             // If this assertion is a warning ignore any INFO messages
15724             if (printInfoMessages || itMessage->type != ResultWas::Info) {
15725                 printMessage();
15726                 if (itMessage != itEnd) {
15727                     Colour colourGuard(dimColour());
15728                     stream << " and";
15729                 }
15730                 continue;
15731             }
15732             ++itMessage;
15733         }
15734     }
15735 
15736 private:
15737     std::ostream& stream;
15738     AssertionResult const& result;
15739     std::vector<MessageInfo> messages;
15740     std::vector<MessageInfo>::const_iterator itMessage;
15741     bool printInfoMessages;
15742 };
15743 
15744 } // anon namespace
15745 
getDescription()15746         std::string CompactReporter::getDescription() {
15747             return "Reports test results on a single line, suitable for IDEs";
15748         }
15749 
getPreferences() const15750         ReporterPreferences CompactReporter::getPreferences() const {
15751             return m_reporterPrefs;
15752         }
15753 
noMatchingTestCases(std::string const & spec)15754         void CompactReporter::noMatchingTestCases( std::string const& spec ) {
15755             stream << "No test cases matched '" << spec << '\'' << std::endl;
15756         }
15757 
assertionStarting(AssertionInfo const &)15758         void CompactReporter::assertionStarting( AssertionInfo const& ) {}
15759 
assertionEnded(AssertionStats const & _assertionStats)15760         bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {
15761             AssertionResult const& result = _assertionStats.assertionResult;
15762 
15763             bool printInfoMessages = true;
15764 
15765             // Drop out if result was successful and we're not printing those
15766             if( !m_config->includeSuccessfulResults() && result.isOk() ) {
15767                 if( result.getResultType() != ResultWas::Warning )
15768                     return false;
15769                 printInfoMessages = false;
15770             }
15771 
15772             AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
15773             printer.print();
15774 
15775             stream << std::endl;
15776             return true;
15777         }
15778 
sectionEnded(SectionStats const & _sectionStats)15779         void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
15780             if (m_config->showDurations() == ShowDurations::Always) {
15781                 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
15782             }
15783         }
15784 
testRunEnded(TestRunStats const & _testRunStats)15785         void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) {
15786             printTotals( stream, _testRunStats.totals );
15787             stream << '\n' << std::endl;
15788             StreamingReporterBase::testRunEnded( _testRunStats );
15789         }
15790 
~CompactReporter()15791         CompactReporter::~CompactReporter() {}
15792 
15793     CATCH_REGISTER_REPORTER( "compact", CompactReporter )
15794 
15795 } // end namespace Catch
15796 // end catch_reporter_compact.cpp
15797 // start catch_reporter_console.cpp
15798 
15799 #include <cfloat>
15800 #include <cstdio>
15801 
15802 #if defined(_MSC_VER)
15803 #pragma warning(push)
15804 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
15805  // Note that 4062 (not all labels are handled and default is missing) is enabled
15806 #endif
15807 
15808 #if defined(__clang__)
15809 #  pragma clang diagnostic push
15810 // For simplicity, benchmarking-only helpers are always enabled
15811 #  pragma clang diagnostic ignored "-Wunused-function"
15812 #endif
15813 
15814 namespace Catch {
15815 
15816 namespace {
15817 
15818 // Formatter impl for ConsoleReporter
15819 class ConsoleAssertionPrinter {
15820 public:
15821     ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete;
15822     ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete;
ConsoleAssertionPrinter(std::ostream & _stream,AssertionStats const & _stats,bool _printInfoMessages)15823     ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
15824         : stream(_stream),
15825         stats(_stats),
15826         result(_stats.assertionResult),
15827         colour(Colour::None),
15828         message(result.getMessage()),
15829         messages(_stats.infoMessages),
15830         printInfoMessages(_printInfoMessages) {
15831         switch (result.getResultType()) {
15832         case ResultWas::Ok:
15833             colour = Colour::Success;
15834             passOrFail = "PASSED";
15835             //if( result.hasMessage() )
15836             if (_stats.infoMessages.size() == 1)
15837                 messageLabel = "with message";
15838             if (_stats.infoMessages.size() > 1)
15839                 messageLabel = "with messages";
15840             break;
15841         case ResultWas::ExpressionFailed:
15842             if (result.isOk()) {
15843                 colour = Colour::Success;
15844                 passOrFail = "FAILED - but was ok";
15845             } else {
15846                 colour = Colour::Error;
15847                 passOrFail = "FAILED";
15848             }
15849             if (_stats.infoMessages.size() == 1)
15850                 messageLabel = "with message";
15851             if (_stats.infoMessages.size() > 1)
15852                 messageLabel = "with messages";
15853             break;
15854         case ResultWas::ThrewException:
15855             colour = Colour::Error;
15856             passOrFail = "FAILED";
15857             messageLabel = "due to unexpected exception with ";
15858             if (_stats.infoMessages.size() == 1)
15859                 messageLabel += "message";
15860             if (_stats.infoMessages.size() > 1)
15861                 messageLabel += "messages";
15862             break;
15863         case ResultWas::FatalErrorCondition:
15864             colour = Colour::Error;
15865             passOrFail = "FAILED";
15866             messageLabel = "due to a fatal error condition";
15867             break;
15868         case ResultWas::DidntThrowException:
15869             colour = Colour::Error;
15870             passOrFail = "FAILED";
15871             messageLabel = "because no exception was thrown where one was expected";
15872             break;
15873         case ResultWas::Info:
15874             messageLabel = "info";
15875             break;
15876         case ResultWas::Warning:
15877             messageLabel = "warning";
15878             break;
15879         case ResultWas::ExplicitFailure:
15880             passOrFail = "FAILED";
15881             colour = Colour::Error;
15882             if (_stats.infoMessages.size() == 1)
15883                 messageLabel = "explicitly with message";
15884             if (_stats.infoMessages.size() > 1)
15885                 messageLabel = "explicitly with messages";
15886             break;
15887             // These cases are here to prevent compiler warnings
15888         case ResultWas::Unknown:
15889         case ResultWas::FailureBit:
15890         case ResultWas::Exception:
15891             passOrFail = "** internal error **";
15892             colour = Colour::Error;
15893             break;
15894         }
15895     }
15896 
print() const15897     void print() const {
15898         printSourceInfo();
15899         if (stats.totals.assertions.total() > 0) {
15900             printResultType();
15901             printOriginalExpression();
15902             printReconstructedExpression();
15903         } else {
15904             stream << '\n';
15905         }
15906         printMessage();
15907     }
15908 
15909 private:
printResultType() const15910     void printResultType() const {
15911         if (!passOrFail.empty()) {
15912             Colour colourGuard(colour);
15913             stream << passOrFail << ":\n";
15914         }
15915     }
printOriginalExpression() const15916     void printOriginalExpression() const {
15917         if (result.hasExpression()) {
15918             Colour colourGuard(Colour::OriginalExpression);
15919             stream << "  ";
15920             stream << result.getExpressionInMacro();
15921             stream << '\n';
15922         }
15923     }
printReconstructedExpression() const15924     void printReconstructedExpression() const {
15925         if (result.hasExpandedExpression()) {
15926             stream << "with expansion:\n";
15927             Colour colourGuard(Colour::ReconstructedExpression);
15928             stream << Column(result.getExpandedExpression()).indent(2) << '\n';
15929         }
15930     }
printMessage() const15931     void printMessage() const {
15932         if (!messageLabel.empty())
15933             stream << messageLabel << ':' << '\n';
15934         for (auto const& msg : messages) {
15935             // If this assertion is a warning ignore any INFO messages
15936             if (printInfoMessages || msg.type != ResultWas::Info)
15937                 stream << Column(msg.message).indent(2) << '\n';
15938         }
15939     }
printSourceInfo() const15940     void printSourceInfo() const {
15941         Colour colourGuard(Colour::FileName);
15942         stream << result.getSourceInfo() << ": ";
15943     }
15944 
15945     std::ostream& stream;
15946     AssertionStats const& stats;
15947     AssertionResult const& result;
15948     Colour::Code colour;
15949     std::string passOrFail;
15950     std::string messageLabel;
15951     std::string message;
15952     std::vector<MessageInfo> messages;
15953     bool printInfoMessages;
15954 };
15955 
makeRatio(std::size_t number,std::size_t total)15956 std::size_t makeRatio(std::size_t number, std::size_t total) {
15957     std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
15958     return (ratio == 0 && number > 0) ? 1 : ratio;
15959 }
15960 
findMax(std::size_t & i,std::size_t & j,std::size_t & k)15961 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {
15962     if (i > j && i > k)
15963         return i;
15964     else if (j > k)
15965         return j;
15966     else
15967         return k;
15968 }
15969 
15970 struct ColumnInfo {
15971     enum Justification { Left, Right };
15972     std::string name;
15973     int width;
15974     Justification justification;
15975 };
15976 struct ColumnBreak {};
15977 struct RowBreak {};
15978 
15979 class Duration {
15980     enum class Unit {
15981         Auto,
15982         Nanoseconds,
15983         Microseconds,
15984         Milliseconds,
15985         Seconds,
15986         Minutes
15987     };
15988     static const uint64_t s_nanosecondsInAMicrosecond = 1000;
15989     static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
15990     static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
15991     static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
15992 
15993     double m_inNanoseconds;
15994     Unit m_units;
15995 
15996 public:
Duration(double inNanoseconds,Unit units=Unit::Auto)15997     explicit Duration(double inNanoseconds, Unit units = Unit::Auto)
15998         : m_inNanoseconds(inNanoseconds),
15999         m_units(units) {
16000         if (m_units == Unit::Auto) {
16001             if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
16002                 m_units = Unit::Nanoseconds;
16003             else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
16004                 m_units = Unit::Microseconds;
16005             else if (m_inNanoseconds < s_nanosecondsInASecond)
16006                 m_units = Unit::Milliseconds;
16007             else if (m_inNanoseconds < s_nanosecondsInAMinute)
16008                 m_units = Unit::Seconds;
16009             else
16010                 m_units = Unit::Minutes;
16011         }
16012 
16013     }
16014 
value() const16015     auto value() const -> double {
16016         switch (m_units) {
16017         case Unit::Microseconds:
16018             return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond);
16019         case Unit::Milliseconds:
16020             return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond);
16021         case Unit::Seconds:
16022             return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond);
16023         case Unit::Minutes:
16024             return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
16025         default:
16026             return m_inNanoseconds;
16027         }
16028     }
unitsAsString() const16029     auto unitsAsString() const -> std::string {
16030         switch (m_units) {
16031         case Unit::Nanoseconds:
16032             return "ns";
16033         case Unit::Microseconds:
16034             return "us";
16035         case Unit::Milliseconds:
16036             return "ms";
16037         case Unit::Seconds:
16038             return "s";
16039         case Unit::Minutes:
16040             return "m";
16041         default:
16042             return "** internal error **";
16043         }
16044 
16045     }
operator <<(std::ostream & os,Duration const & duration)16046     friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {
16047         return os << duration.value() << ' ' << duration.unitsAsString();
16048     }
16049 };
16050 } // end anon namespace
16051 
16052 class TablePrinter {
16053     std::ostream& m_os;
16054     std::vector<ColumnInfo> m_columnInfos;
16055     std::ostringstream m_oss;
16056     int m_currentColumn = -1;
16057     bool m_isOpen = false;
16058 
16059 public:
TablePrinter(std::ostream & os,std::vector<ColumnInfo> columnInfos)16060     TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
16061     :   m_os( os ),
16062         m_columnInfos( std::move( columnInfos ) ) {}
16063 
columnInfos() const16064     auto columnInfos() const -> std::vector<ColumnInfo> const& {
16065         return m_columnInfos;
16066     }
16067 
open()16068     void open() {
16069         if (!m_isOpen) {
16070             m_isOpen = true;
16071             *this << RowBreak();
16072 
16073 			Columns headerCols;
16074 			Spacer spacer(2);
16075 			for (auto const& info : m_columnInfos) {
16076 				headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2));
16077 				headerCols += spacer;
16078 			}
16079 			m_os << headerCols << '\n';
16080 
16081             m_os << Catch::getLineOfChars<'-'>() << '\n';
16082         }
16083     }
close()16084     void close() {
16085         if (m_isOpen) {
16086             *this << RowBreak();
16087             m_os << std::endl;
16088             m_isOpen = false;
16089         }
16090     }
16091 
16092     template<typename T>
operator <<(TablePrinter & tp,T const & value)16093     friend TablePrinter& operator << (TablePrinter& tp, T const& value) {
16094         tp.m_oss << value;
16095         return tp;
16096     }
16097 
operator <<(TablePrinter & tp,ColumnBreak)16098     friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) {
16099         auto colStr = tp.m_oss.str();
16100         const auto strSize = colStr.size();
16101         tp.m_oss.str("");
16102         tp.open();
16103         if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
16104             tp.m_currentColumn = -1;
16105             tp.m_os << '\n';
16106         }
16107         tp.m_currentColumn++;
16108 
16109         auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
16110         auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width))
16111             ? std::string(colInfo.width - (strSize + 1), ' ')
16112             : std::string();
16113         if (colInfo.justification == ColumnInfo::Left)
16114             tp.m_os << colStr << padding << ' ';
16115         else
16116             tp.m_os << padding << colStr << ' ';
16117         return tp;
16118     }
16119 
operator <<(TablePrinter & tp,RowBreak)16120     friend TablePrinter& operator << (TablePrinter& tp, RowBreak) {
16121         if (tp.m_currentColumn > 0) {
16122             tp.m_os << '\n';
16123             tp.m_currentColumn = -1;
16124         }
16125         return tp;
16126     }
16127 };
16128 
ConsoleReporter(ReporterConfig const & config)16129 ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
16130     : StreamingReporterBase(config),
16131     m_tablePrinter(new TablePrinter(config.stream(),
16132         [&config]() -> std::vector<ColumnInfo> {
16133         if (config.fullConfig()->benchmarkNoAnalysis())
16134         {
16135             return{
16136                 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },
16137                 { "     samples", 14, ColumnInfo::Right },
16138                 { "  iterations", 14, ColumnInfo::Right },
16139                 { "        mean", 14, ColumnInfo::Right }
16140             };
16141         }
16142         else
16143         {
16144             return{
16145                 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
16146                 { "samples      mean       std dev", 14, ColumnInfo::Right },
16147                 { "iterations   low mean   low std dev", 14, ColumnInfo::Right },
16148                 { "estimated    high mean  high std dev", 14, ColumnInfo::Right }
16149             };
16150         }
16151     }())) {}
16152 ConsoleReporter::~ConsoleReporter() = default;
16153 
getDescription()16154 std::string ConsoleReporter::getDescription() {
16155     return "Reports test results as plain lines of text";
16156 }
16157 
noMatchingTestCases(std::string const & spec)16158 void ConsoleReporter::noMatchingTestCases(std::string const& spec) {
16159     stream << "No test cases matched '" << spec << '\'' << std::endl;
16160 }
16161 
reportInvalidArguments(std::string const & arg)16162 void ConsoleReporter::reportInvalidArguments(std::string const&arg){
16163     stream << "Invalid Filter: " << arg << std::endl;
16164 }
16165 
assertionStarting(AssertionInfo const &)16166 void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
16167 
assertionEnded(AssertionStats const & _assertionStats)16168 bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
16169     AssertionResult const& result = _assertionStats.assertionResult;
16170 
16171     bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
16172 
16173     // Drop out if result was successful but we're not printing them.
16174     if (!includeResults && result.getResultType() != ResultWas::Warning)
16175         return false;
16176 
16177     lazyPrint();
16178 
16179     ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
16180     printer.print();
16181     stream << std::endl;
16182     return true;
16183 }
16184 
sectionStarting(SectionInfo const & _sectionInfo)16185 void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) {
16186     m_tablePrinter->close();
16187     m_headerPrinted = false;
16188     StreamingReporterBase::sectionStarting(_sectionInfo);
16189 }
sectionEnded(SectionStats const & _sectionStats)16190 void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
16191     m_tablePrinter->close();
16192     if (_sectionStats.missingAssertions) {
16193         lazyPrint();
16194         Colour colour(Colour::ResultError);
16195         if (m_sectionStack.size() > 1)
16196             stream << "\nNo assertions in section";
16197         else
16198             stream << "\nNo assertions in test case";
16199         stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
16200     }
16201     if (m_config->showDurations() == ShowDurations::Always) {
16202         stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
16203     }
16204     if (m_headerPrinted) {
16205         m_headerPrinted = false;
16206     }
16207     StreamingReporterBase::sectionEnded(_sectionStats);
16208 }
16209 
16210 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
benchmarkPreparing(std::string const & name)16211 void ConsoleReporter::benchmarkPreparing(std::string const& name) {
16212 	lazyPrintWithoutClosingBenchmarkTable();
16213 
16214 	auto nameCol = Column(name).width(static_cast<std::size_t>(m_tablePrinter->columnInfos()[0].width - 2));
16215 
16216 	bool firstLine = true;
16217 	for (auto line : nameCol) {
16218 		if (!firstLine)
16219 			(*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
16220 		else
16221 			firstLine = false;
16222 
16223 		(*m_tablePrinter) << line << ColumnBreak();
16224 	}
16225 }
16226 
benchmarkStarting(BenchmarkInfo const & info)16227 void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
16228     (*m_tablePrinter) << info.samples << ColumnBreak()
16229         << info.iterations << ColumnBreak();
16230     if (!m_config->benchmarkNoAnalysis())
16231         (*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak();
16232 }
benchmarkEnded(BenchmarkStats<> const & stats)16233 void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
16234     if (m_config->benchmarkNoAnalysis())
16235     {
16236         (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
16237     }
16238     else
16239     {
16240         (*m_tablePrinter) << ColumnBreak()
16241             << Duration(stats.mean.point.count()) << ColumnBreak()
16242             << Duration(stats.mean.lower_bound.count()) << ColumnBreak()
16243             << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()
16244             << Duration(stats.standardDeviation.point.count()) << ColumnBreak()
16245             << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()
16246             << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak();
16247     }
16248 }
16249 
benchmarkFailed(std::string const & error)16250 void ConsoleReporter::benchmarkFailed(std::string const& error) {
16251 	Colour colour(Colour::Red);
16252     (*m_tablePrinter)
16253         << "Benchmark failed (" << error << ')'
16254         << ColumnBreak() << RowBreak();
16255 }
16256 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
16257 
testCaseEnded(TestCaseStats const & _testCaseStats)16258 void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
16259     m_tablePrinter->close();
16260     StreamingReporterBase::testCaseEnded(_testCaseStats);
16261     m_headerPrinted = false;
16262 }
testGroupEnded(TestGroupStats const & _testGroupStats)16263 void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) {
16264     if (currentGroupInfo.used) {
16265         printSummaryDivider();
16266         stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
16267         printTotals(_testGroupStats.totals);
16268         stream << '\n' << std::endl;
16269     }
16270     StreamingReporterBase::testGroupEnded(_testGroupStats);
16271 }
testRunEnded(TestRunStats const & _testRunStats)16272 void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
16273     printTotalsDivider(_testRunStats.totals);
16274     printTotals(_testRunStats.totals);
16275     stream << std::endl;
16276     StreamingReporterBase::testRunEnded(_testRunStats);
16277 }
testRunStarting(TestRunInfo const & _testInfo)16278 void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) {
16279     StreamingReporterBase::testRunStarting(_testInfo);
16280     printTestFilters();
16281 }
16282 
lazyPrint()16283 void ConsoleReporter::lazyPrint() {
16284 
16285     m_tablePrinter->close();
16286     lazyPrintWithoutClosingBenchmarkTable();
16287 }
16288 
lazyPrintWithoutClosingBenchmarkTable()16289 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
16290 
16291     if (!currentTestRunInfo.used)
16292         lazyPrintRunInfo();
16293     if (!currentGroupInfo.used)
16294         lazyPrintGroupInfo();
16295 
16296     if (!m_headerPrinted) {
16297         printTestCaseAndSectionHeader();
16298         m_headerPrinted = true;
16299     }
16300 }
lazyPrintRunInfo()16301 void ConsoleReporter::lazyPrintRunInfo() {
16302     stream << '\n' << getLineOfChars<'~'>() << '\n';
16303     Colour colour(Colour::SecondaryText);
16304     stream << currentTestRunInfo->name
16305         << " is a Catch v" << libraryVersion() << " host application.\n"
16306         << "Run with -? for options\n\n";
16307 
16308     if (m_config->rngSeed() != 0)
16309         stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
16310 
16311     currentTestRunInfo.used = true;
16312 }
lazyPrintGroupInfo()16313 void ConsoleReporter::lazyPrintGroupInfo() {
16314     if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
16315         printClosedHeader("Group: " + currentGroupInfo->name);
16316         currentGroupInfo.used = true;
16317     }
16318 }
printTestCaseAndSectionHeader()16319 void ConsoleReporter::printTestCaseAndSectionHeader() {
16320     assert(!m_sectionStack.empty());
16321     printOpenHeader(currentTestCaseInfo->name);
16322 
16323     if (m_sectionStack.size() > 1) {
16324         Colour colourGuard(Colour::Headers);
16325 
16326         auto
16327             it = m_sectionStack.begin() + 1, // Skip first section (test case)
16328             itEnd = m_sectionStack.end();
16329         for (; it != itEnd; ++it)
16330             printHeaderString(it->name, 2);
16331     }
16332 
16333     SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
16334 
16335     stream << getLineOfChars<'-'>() << '\n';
16336     Colour colourGuard(Colour::FileName);
16337     stream << lineInfo << '\n';
16338     stream << getLineOfChars<'.'>() << '\n' << std::endl;
16339 }
16340 
printClosedHeader(std::string const & _name)16341 void ConsoleReporter::printClosedHeader(std::string const& _name) {
16342     printOpenHeader(_name);
16343     stream << getLineOfChars<'.'>() << '\n';
16344 }
printOpenHeader(std::string const & _name)16345 void ConsoleReporter::printOpenHeader(std::string const& _name) {
16346     stream << getLineOfChars<'-'>() << '\n';
16347     {
16348         Colour colourGuard(Colour::Headers);
16349         printHeaderString(_name);
16350     }
16351 }
16352 
16353 // if string has a : in first line will set indent to follow it on
16354 // subsequent lines
printHeaderString(std::string const & _string,std::size_t indent)16355 void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) {
16356     std::size_t i = _string.find(": ");
16357     if (i != std::string::npos)
16358         i += 2;
16359     else
16360         i = 0;
16361     stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n';
16362 }
16363 
16364 struct SummaryColumn {
16365 
SummaryColumnCatch::SummaryColumn16366     SummaryColumn( std::string _label, Colour::Code _colour )
16367     :   label( std::move( _label ) ),
16368         colour( _colour ) {}
addRowCatch::SummaryColumn16369     SummaryColumn addRow( std::size_t count ) {
16370         ReusableStringStream rss;
16371         rss << count;
16372         std::string row = rss.str();
16373         for (auto& oldRow : rows) {
16374             while (oldRow.size() < row.size())
16375                 oldRow = ' ' + oldRow;
16376             while (oldRow.size() > row.size())
16377                 row = ' ' + row;
16378         }
16379         rows.push_back(row);
16380         return *this;
16381     }
16382 
16383     std::string label;
16384     Colour::Code colour;
16385     std::vector<std::string> rows;
16386 
16387 };
16388 
printTotals(Totals const & totals)16389 void ConsoleReporter::printTotals( Totals const& totals ) {
16390     if (totals.testCases.total() == 0) {
16391         stream << Colour(Colour::Warning) << "No tests ran\n";
16392     } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {
16393         stream << Colour(Colour::ResultSuccess) << "All tests passed";
16394         stream << " ("
16395             << pluralise(totals.assertions.passed, "assertion") << " in "
16396             << pluralise(totals.testCases.passed, "test case") << ')'
16397             << '\n';
16398     } else {
16399 
16400         std::vector<SummaryColumn> columns;
16401         columns.push_back(SummaryColumn("", Colour::None)
16402                           .addRow(totals.testCases.total())
16403                           .addRow(totals.assertions.total()));
16404         columns.push_back(SummaryColumn("passed", Colour::Success)
16405                           .addRow(totals.testCases.passed)
16406                           .addRow(totals.assertions.passed));
16407         columns.push_back(SummaryColumn("failed", Colour::ResultError)
16408                           .addRow(totals.testCases.failed)
16409                           .addRow(totals.assertions.failed));
16410         columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure)
16411                           .addRow(totals.testCases.failedButOk)
16412                           .addRow(totals.assertions.failedButOk));
16413 
16414         printSummaryRow("test cases", columns, 0);
16415         printSummaryRow("assertions", columns, 1);
16416     }
16417 }
printSummaryRow(std::string const & label,std::vector<SummaryColumn> const & cols,std::size_t row)16418 void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) {
16419     for (auto col : cols) {
16420         std::string value = col.rows[row];
16421         if (col.label.empty()) {
16422             stream << label << ": ";
16423             if (value != "0")
16424                 stream << value;
16425             else
16426                 stream << Colour(Colour::Warning) << "- none -";
16427         } else if (value != "0") {
16428             stream << Colour(Colour::LightGrey) << " | ";
16429             stream << Colour(col.colour)
16430                 << value << ' ' << col.label;
16431         }
16432     }
16433     stream << '\n';
16434 }
16435 
printTotalsDivider(Totals const & totals)16436 void ConsoleReporter::printTotalsDivider(Totals const& totals) {
16437     if (totals.testCases.total() > 0) {
16438         std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
16439         std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
16440         std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
16441         while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
16442             findMax(failedRatio, failedButOkRatio, passedRatio)++;
16443         while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
16444             findMax(failedRatio, failedButOkRatio, passedRatio)--;
16445 
16446         stream << Colour(Colour::Error) << std::string(failedRatio, '=');
16447         stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '=');
16448         if (totals.testCases.allPassed())
16449             stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '=');
16450         else
16451             stream << Colour(Colour::Success) << std::string(passedRatio, '=');
16452     } else {
16453         stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '=');
16454     }
16455     stream << '\n';
16456 }
printSummaryDivider()16457 void ConsoleReporter::printSummaryDivider() {
16458     stream << getLineOfChars<'-'>() << '\n';
16459 }
16460 
printTestFilters()16461 void ConsoleReporter::printTestFilters() {
16462     if (m_config->testSpec().hasFilters()) {
16463         Colour guard(Colour::BrightYellow);
16464         stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) << '\n';
16465     }
16466 }
16467 
16468 CATCH_REGISTER_REPORTER("console", ConsoleReporter)
16469 
16470 } // end namespace Catch
16471 
16472 #if defined(_MSC_VER)
16473 #pragma warning(pop)
16474 #endif
16475 
16476 #if defined(__clang__)
16477 #  pragma clang diagnostic pop
16478 #endif
16479 // end catch_reporter_console.cpp
16480 // start catch_reporter_junit.cpp
16481 
16482 #include <cassert>
16483 #include <sstream>
16484 #include <ctime>
16485 #include <algorithm>
16486 
16487 namespace Catch {
16488 
16489     namespace {
getCurrentTimestamp()16490         std::string getCurrentTimestamp() {
16491             // Beware, this is not reentrant because of backward compatibility issues
16492             // Also, UTC only, again because of backward compatibility (%z is C++11)
16493             time_t rawtime;
16494             std::time(&rawtime);
16495             auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
16496 
16497 #ifdef _MSC_VER
16498             std::tm timeInfo = {};
16499             gmtime_s(&timeInfo, &rawtime);
16500 #else
16501             std::tm* timeInfo;
16502             timeInfo = std::gmtime(&rawtime);
16503 #endif
16504 
16505             char timeStamp[timeStampSize];
16506             const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
16507 
16508 #ifdef _MSC_VER
16509             std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
16510 #else
16511             std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
16512 #endif
16513             return std::string(timeStamp);
16514         }
16515 
fileNameTag(const std::vector<std::string> & tags)16516         std::string fileNameTag(const std::vector<std::string> &tags) {
16517             auto it = std::find_if(begin(tags),
16518                                    end(tags),
16519                                    [] (std::string const& tag) {return tag.front() == '#'; });
16520             if (it != tags.end())
16521                 return it->substr(1);
16522             return std::string();
16523         }
16524     } // anonymous namespace
16525 
JunitReporter(ReporterConfig const & _config)16526     JunitReporter::JunitReporter( ReporterConfig const& _config )
16527         :   CumulativeReporterBase( _config ),
16528             xml( _config.stream() )
16529         {
16530             m_reporterPrefs.shouldRedirectStdOut = true;
16531             m_reporterPrefs.shouldReportAllAssertions = true;
16532         }
16533 
~JunitReporter()16534     JunitReporter::~JunitReporter() {}
16535 
getDescription()16536     std::string JunitReporter::getDescription() {
16537         return "Reports test results in an XML format that looks like Ant's junitreport target";
16538     }
16539 
noMatchingTestCases(std::string const &)16540     void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {}
16541 
testRunStarting(TestRunInfo const & runInfo)16542     void JunitReporter::testRunStarting( TestRunInfo const& runInfo )  {
16543         CumulativeReporterBase::testRunStarting( runInfo );
16544         xml.startElement( "testsuites" );
16545     }
16546 
testGroupStarting(GroupInfo const & groupInfo)16547     void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
16548         suiteTimer.start();
16549         stdOutForSuite.clear();
16550         stdErrForSuite.clear();
16551         unexpectedExceptions = 0;
16552         CumulativeReporterBase::testGroupStarting( groupInfo );
16553     }
16554 
testCaseStarting(TestCaseInfo const & testCaseInfo)16555     void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) {
16556         m_okToFail = testCaseInfo.okToFail();
16557     }
16558 
assertionEnded(AssertionStats const & assertionStats)16559     bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) {
16560         if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
16561             unexpectedExceptions++;
16562         return CumulativeReporterBase::assertionEnded( assertionStats );
16563     }
16564 
testCaseEnded(TestCaseStats const & testCaseStats)16565     void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
16566         stdOutForSuite += testCaseStats.stdOut;
16567         stdErrForSuite += testCaseStats.stdErr;
16568         CumulativeReporterBase::testCaseEnded( testCaseStats );
16569     }
16570 
testGroupEnded(TestGroupStats const & testGroupStats)16571     void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
16572         double suiteTime = suiteTimer.getElapsedSeconds();
16573         CumulativeReporterBase::testGroupEnded( testGroupStats );
16574         writeGroup( *m_testGroups.back(), suiteTime );
16575     }
16576 
testRunEndedCumulative()16577     void JunitReporter::testRunEndedCumulative() {
16578         xml.endElement();
16579     }
16580 
writeGroup(TestGroupNode const & groupNode,double suiteTime)16581     void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
16582         XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
16583 
16584         TestGroupStats const& stats = groupNode.value;
16585         xml.writeAttribute( "name", stats.groupInfo.name );
16586         xml.writeAttribute( "errors", unexpectedExceptions );
16587         xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
16588         xml.writeAttribute( "tests", stats.totals.assertions.total() );
16589         xml.writeAttribute( "hostname", "tbd" ); // !TBD
16590         if( m_config->showDurations() == ShowDurations::Never )
16591             xml.writeAttribute( "time", "" );
16592         else
16593             xml.writeAttribute( "time", suiteTime );
16594         xml.writeAttribute( "timestamp", getCurrentTimestamp() );
16595 
16596         // Write properties if there are any
16597         if (m_config->hasTestFilters() || m_config->rngSeed() != 0) {
16598             auto properties = xml.scopedElement("properties");
16599             if (m_config->hasTestFilters()) {
16600                 xml.scopedElement("property")
16601                     .writeAttribute("name", "filters")
16602                     .writeAttribute("value", serializeFilters(m_config->getTestsOrTags()));
16603             }
16604             if (m_config->rngSeed() != 0) {
16605                 xml.scopedElement("property")
16606                     .writeAttribute("name", "random-seed")
16607                     .writeAttribute("value", m_config->rngSeed());
16608             }
16609         }
16610 
16611         // Write test cases
16612         for( auto const& child : groupNode.children )
16613             writeTestCase( *child );
16614 
16615         xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline );
16616         xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline );
16617     }
16618 
writeTestCase(TestCaseNode const & testCaseNode)16619     void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
16620         TestCaseStats const& stats = testCaseNode.value;
16621 
16622         // All test cases have exactly one section - which represents the
16623         // test case itself. That section may have 0-n nested sections
16624         assert( testCaseNode.children.size() == 1 );
16625         SectionNode const& rootSection = *testCaseNode.children.front();
16626 
16627         std::string className = stats.testInfo.className;
16628 
16629         if( className.empty() ) {
16630             className = fileNameTag(stats.testInfo.tags);
16631             if ( className.empty() )
16632                 className = "global";
16633         }
16634 
16635         if ( !m_config->name().empty() )
16636             className = m_config->name() + "." + className;
16637 
16638         writeSection( className, "", rootSection );
16639     }
16640 
writeSection(std::string const & className,std::string const & rootName,SectionNode const & sectionNode)16641     void JunitReporter::writeSection(  std::string const& className,
16642                         std::string const& rootName,
16643                         SectionNode const& sectionNode ) {
16644         std::string name = trim( sectionNode.stats.sectionInfo.name );
16645         if( !rootName.empty() )
16646             name = rootName + '/' + name;
16647 
16648         if( !sectionNode.assertions.empty() ||
16649             !sectionNode.stdOut.empty() ||
16650             !sectionNode.stdErr.empty() ) {
16651             XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
16652             if( className.empty() ) {
16653                 xml.writeAttribute( "classname", name );
16654                 xml.writeAttribute( "name", "root" );
16655             }
16656             else {
16657                 xml.writeAttribute( "classname", className );
16658                 xml.writeAttribute( "name", name );
16659             }
16660             xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) );
16661 
16662             writeAssertions( sectionNode );
16663 
16664             if( !sectionNode.stdOut.empty() )
16665                 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline );
16666             if( !sectionNode.stdErr.empty() )
16667                 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline );
16668         }
16669         for( auto const& childNode : sectionNode.childSections )
16670             if( className.empty() )
16671                 writeSection( name, "", *childNode );
16672             else
16673                 writeSection( className, name, *childNode );
16674     }
16675 
writeAssertions(SectionNode const & sectionNode)16676     void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
16677         for( auto const& assertion : sectionNode.assertions )
16678             writeAssertion( assertion );
16679     }
16680 
writeAssertion(AssertionStats const & stats)16681     void JunitReporter::writeAssertion( AssertionStats const& stats ) {
16682         AssertionResult const& result = stats.assertionResult;
16683         if( !result.isOk() ) {
16684             std::string elementName;
16685             switch( result.getResultType() ) {
16686                 case ResultWas::ThrewException:
16687                 case ResultWas::FatalErrorCondition:
16688                     elementName = "error";
16689                     break;
16690                 case ResultWas::ExplicitFailure:
16691                 case ResultWas::ExpressionFailed:
16692                 case ResultWas::DidntThrowException:
16693                     elementName = "failure";
16694                     break;
16695 
16696                 // We should never see these here:
16697                 case ResultWas::Info:
16698                 case ResultWas::Warning:
16699                 case ResultWas::Ok:
16700                 case ResultWas::Unknown:
16701                 case ResultWas::FailureBit:
16702                 case ResultWas::Exception:
16703                     elementName = "internalError";
16704                     break;
16705             }
16706 
16707             XmlWriter::ScopedElement e = xml.scopedElement( elementName );
16708 
16709             xml.writeAttribute( "message", result.getExpression() );
16710             xml.writeAttribute( "type", result.getTestMacroName() );
16711 
16712             ReusableStringStream rss;
16713             if (stats.totals.assertions.total() > 0) {
16714                 rss << "FAILED" << ":\n";
16715                 if (result.hasExpression()) {
16716                     rss << "  ";
16717                     rss << result.getExpressionInMacro();
16718                     rss << '\n';
16719                 }
16720                 if (result.hasExpandedExpression()) {
16721                     rss << "with expansion:\n";
16722                     rss << Column(result.getExpandedExpression()).indent(2) << '\n';
16723                 }
16724             } else {
16725                 rss << '\n';
16726             }
16727 
16728             if( !result.getMessage().empty() )
16729                 rss << result.getMessage() << '\n';
16730             for( auto const& msg : stats.infoMessages )
16731                 if( msg.type == ResultWas::Info )
16732                     rss << msg.message << '\n';
16733 
16734             rss << "at " << result.getSourceInfo();
16735             xml.writeText( rss.str(), XmlFormatting::Newline );
16736         }
16737     }
16738 
16739     CATCH_REGISTER_REPORTER( "junit", JunitReporter )
16740 
16741 } // end namespace Catch
16742 // end catch_reporter_junit.cpp
16743 // start catch_reporter_listening.cpp
16744 
16745 #include <cassert>
16746 
16747 namespace Catch {
16748 
ListeningReporter()16749     ListeningReporter::ListeningReporter() {
16750         // We will assume that listeners will always want all assertions
16751         m_preferences.shouldReportAllAssertions = true;
16752     }
16753 
addListener(IStreamingReporterPtr && listener)16754     void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
16755         m_listeners.push_back( std::move( listener ) );
16756     }
16757 
addReporter(IStreamingReporterPtr && reporter)16758     void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
16759         assert(!m_reporter && "Listening reporter can wrap only 1 real reporter");
16760         m_reporter = std::move( reporter );
16761         m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;
16762     }
16763 
getPreferences() const16764     ReporterPreferences ListeningReporter::getPreferences() const {
16765         return m_preferences;
16766     }
16767 
getSupportedVerbosities()16768     std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
16769         return std::set<Verbosity>{ };
16770     }
16771 
noMatchingTestCases(std::string const & spec)16772     void ListeningReporter::noMatchingTestCases( std::string const& spec ) {
16773         for ( auto const& listener : m_listeners ) {
16774             listener->noMatchingTestCases( spec );
16775         }
16776         m_reporter->noMatchingTestCases( spec );
16777     }
16778 
reportInvalidArguments(std::string const & arg)16779     void ListeningReporter::reportInvalidArguments(std::string const&arg){
16780         for ( auto const& listener : m_listeners ) {
16781             listener->reportInvalidArguments( arg );
16782         }
16783         m_reporter->reportInvalidArguments( arg );
16784     }
16785 
16786 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
benchmarkPreparing(std::string const & name)16787     void ListeningReporter::benchmarkPreparing( std::string const& name ) {
16788 		for (auto const& listener : m_listeners) {
16789 			listener->benchmarkPreparing(name);
16790 		}
16791 		m_reporter->benchmarkPreparing(name);
16792 	}
benchmarkStarting(BenchmarkInfo const & benchmarkInfo)16793     void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
16794         for ( auto const& listener : m_listeners ) {
16795             listener->benchmarkStarting( benchmarkInfo );
16796         }
16797         m_reporter->benchmarkStarting( benchmarkInfo );
16798     }
benchmarkEnded(BenchmarkStats<> const & benchmarkStats)16799     void ListeningReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) {
16800         for ( auto const& listener : m_listeners ) {
16801             listener->benchmarkEnded( benchmarkStats );
16802         }
16803         m_reporter->benchmarkEnded( benchmarkStats );
16804     }
16805 
benchmarkFailed(std::string const & error)16806 	void ListeningReporter::benchmarkFailed( std::string const& error ) {
16807 		for (auto const& listener : m_listeners) {
16808 			listener->benchmarkFailed(error);
16809 		}
16810 		m_reporter->benchmarkFailed(error);
16811 	}
16812 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
16813 
testRunStarting(TestRunInfo const & testRunInfo)16814     void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
16815         for ( auto const& listener : m_listeners ) {
16816             listener->testRunStarting( testRunInfo );
16817         }
16818         m_reporter->testRunStarting( testRunInfo );
16819     }
16820 
testGroupStarting(GroupInfo const & groupInfo)16821     void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) {
16822         for ( auto const& listener : m_listeners ) {
16823             listener->testGroupStarting( groupInfo );
16824         }
16825         m_reporter->testGroupStarting( groupInfo );
16826     }
16827 
testCaseStarting(TestCaseInfo const & testInfo)16828     void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
16829         for ( auto const& listener : m_listeners ) {
16830             listener->testCaseStarting( testInfo );
16831         }
16832         m_reporter->testCaseStarting( testInfo );
16833     }
16834 
sectionStarting(SectionInfo const & sectionInfo)16835     void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) {
16836         for ( auto const& listener : m_listeners ) {
16837             listener->sectionStarting( sectionInfo );
16838         }
16839         m_reporter->sectionStarting( sectionInfo );
16840     }
16841 
assertionStarting(AssertionInfo const & assertionInfo)16842     void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) {
16843         for ( auto const& listener : m_listeners ) {
16844             listener->assertionStarting( assertionInfo );
16845         }
16846         m_reporter->assertionStarting( assertionInfo );
16847     }
16848 
16849     // The return value indicates if the messages buffer should be cleared:
assertionEnded(AssertionStats const & assertionStats)16850     bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) {
16851         for( auto const& listener : m_listeners ) {
16852             static_cast<void>( listener->assertionEnded( assertionStats ) );
16853         }
16854         return m_reporter->assertionEnded( assertionStats );
16855     }
16856 
sectionEnded(SectionStats const & sectionStats)16857     void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) {
16858         for ( auto const& listener : m_listeners ) {
16859             listener->sectionEnded( sectionStats );
16860         }
16861         m_reporter->sectionEnded( sectionStats );
16862     }
16863 
testCaseEnded(TestCaseStats const & testCaseStats)16864     void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
16865         for ( auto const& listener : m_listeners ) {
16866             listener->testCaseEnded( testCaseStats );
16867         }
16868         m_reporter->testCaseEnded( testCaseStats );
16869     }
16870 
testGroupEnded(TestGroupStats const & testGroupStats)16871     void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
16872         for ( auto const& listener : m_listeners ) {
16873             listener->testGroupEnded( testGroupStats );
16874         }
16875         m_reporter->testGroupEnded( testGroupStats );
16876     }
16877 
testRunEnded(TestRunStats const & testRunStats)16878     void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) {
16879         for ( auto const& listener : m_listeners ) {
16880             listener->testRunEnded( testRunStats );
16881         }
16882         m_reporter->testRunEnded( testRunStats );
16883     }
16884 
skipTest(TestCaseInfo const & testInfo)16885     void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) {
16886         for ( auto const& listener : m_listeners ) {
16887             listener->skipTest( testInfo );
16888         }
16889         m_reporter->skipTest( testInfo );
16890     }
16891 
isMulti() const16892     bool ListeningReporter::isMulti() const {
16893         return true;
16894     }
16895 
16896 } // end namespace Catch
16897 // end catch_reporter_listening.cpp
16898 // start catch_reporter_xml.cpp
16899 
16900 #if defined(_MSC_VER)
16901 #pragma warning(push)
16902 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
16903                               // Note that 4062 (not all labels are handled
16904                               // and default is missing) is enabled
16905 #endif
16906 
16907 namespace Catch {
XmlReporter(ReporterConfig const & _config)16908     XmlReporter::XmlReporter( ReporterConfig const& _config )
16909     :   StreamingReporterBase( _config ),
16910         m_xml(_config.stream())
16911     {
16912         m_reporterPrefs.shouldRedirectStdOut = true;
16913         m_reporterPrefs.shouldReportAllAssertions = true;
16914     }
16915 
16916     XmlReporter::~XmlReporter() = default;
16917 
getDescription()16918     std::string XmlReporter::getDescription() {
16919         return "Reports test results as an XML document";
16920     }
16921 
getStylesheetRef() const16922     std::string XmlReporter::getStylesheetRef() const {
16923         return std::string();
16924     }
16925 
writeSourceInfo(SourceLineInfo const & sourceInfo)16926     void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) {
16927         m_xml
16928             .writeAttribute( "filename", sourceInfo.file )
16929             .writeAttribute( "line", sourceInfo.line );
16930     }
16931 
noMatchingTestCases(std::string const & s)16932     void XmlReporter::noMatchingTestCases( std::string const& s ) {
16933         StreamingReporterBase::noMatchingTestCases( s );
16934     }
16935 
testRunStarting(TestRunInfo const & testInfo)16936     void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) {
16937         StreamingReporterBase::testRunStarting( testInfo );
16938         std::string stylesheetRef = getStylesheetRef();
16939         if( !stylesheetRef.empty() )
16940             m_xml.writeStylesheetRef( stylesheetRef );
16941         m_xml.startElement( "Catch" );
16942         if( !m_config->name().empty() )
16943             m_xml.writeAttribute( "name", m_config->name() );
16944         if (m_config->testSpec().hasFilters())
16945             m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) );
16946         if( m_config->rngSeed() != 0 )
16947             m_xml.scopedElement( "Randomness" )
16948                 .writeAttribute( "seed", m_config->rngSeed() );
16949     }
16950 
testGroupStarting(GroupInfo const & groupInfo)16951     void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) {
16952         StreamingReporterBase::testGroupStarting( groupInfo );
16953         m_xml.startElement( "Group" )
16954             .writeAttribute( "name", groupInfo.name );
16955     }
16956 
testCaseStarting(TestCaseInfo const & testInfo)16957     void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
16958         StreamingReporterBase::testCaseStarting(testInfo);
16959         m_xml.startElement( "TestCase" )
16960             .writeAttribute( "name", trim( testInfo.name ) )
16961             .writeAttribute( "description", testInfo.description )
16962             .writeAttribute( "tags", testInfo.tagsAsString() );
16963 
16964         writeSourceInfo( testInfo.lineInfo );
16965 
16966         if ( m_config->showDurations() == ShowDurations::Always )
16967             m_testCaseTimer.start();
16968         m_xml.ensureTagClosed();
16969     }
16970 
sectionStarting(SectionInfo const & sectionInfo)16971     void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) {
16972         StreamingReporterBase::sectionStarting( sectionInfo );
16973         if( m_sectionDepth++ > 0 ) {
16974             m_xml.startElement( "Section" )
16975                 .writeAttribute( "name", trim( sectionInfo.name ) );
16976             writeSourceInfo( sectionInfo.lineInfo );
16977             m_xml.ensureTagClosed();
16978         }
16979     }
16980 
assertionStarting(AssertionInfo const &)16981     void XmlReporter::assertionStarting( AssertionInfo const& ) { }
16982 
assertionEnded(AssertionStats const & assertionStats)16983     bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {
16984 
16985         AssertionResult const& result = assertionStats.assertionResult;
16986 
16987         bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
16988 
16989         if( includeResults || result.getResultType() == ResultWas::Warning ) {
16990             // Print any info messages in <Info> tags.
16991             for( auto const& msg : assertionStats.infoMessages ) {
16992                 if( msg.type == ResultWas::Info && includeResults ) {
16993                     m_xml.scopedElement( "Info" )
16994                             .writeText( msg.message );
16995                 } else if ( msg.type == ResultWas::Warning ) {
16996                     m_xml.scopedElement( "Warning" )
16997                             .writeText( msg.message );
16998                 }
16999             }
17000         }
17001 
17002         // Drop out if result was successful but we're not printing them.
17003         if( !includeResults && result.getResultType() != ResultWas::Warning )
17004             return true;
17005 
17006         // Print the expression if there is one.
17007         if( result.hasExpression() ) {
17008             m_xml.startElement( "Expression" )
17009                 .writeAttribute( "success", result.succeeded() )
17010                 .writeAttribute( "type", result.getTestMacroName() );
17011 
17012             writeSourceInfo( result.getSourceInfo() );
17013 
17014             m_xml.scopedElement( "Original" )
17015                 .writeText( result.getExpression() );
17016             m_xml.scopedElement( "Expanded" )
17017                 .writeText( result.getExpandedExpression() );
17018         }
17019 
17020         // And... Print a result applicable to each result type.
17021         switch( result.getResultType() ) {
17022             case ResultWas::ThrewException:
17023                 m_xml.startElement( "Exception" );
17024                 writeSourceInfo( result.getSourceInfo() );
17025                 m_xml.writeText( result.getMessage() );
17026                 m_xml.endElement();
17027                 break;
17028             case ResultWas::FatalErrorCondition:
17029                 m_xml.startElement( "FatalErrorCondition" );
17030                 writeSourceInfo( result.getSourceInfo() );
17031                 m_xml.writeText( result.getMessage() );
17032                 m_xml.endElement();
17033                 break;
17034             case ResultWas::Info:
17035                 m_xml.scopedElement( "Info" )
17036                     .writeText( result.getMessage() );
17037                 break;
17038             case ResultWas::Warning:
17039                 // Warning will already have been written
17040                 break;
17041             case ResultWas::ExplicitFailure:
17042                 m_xml.startElement( "Failure" );
17043                 writeSourceInfo( result.getSourceInfo() );
17044                 m_xml.writeText( result.getMessage() );
17045                 m_xml.endElement();
17046                 break;
17047             default:
17048                 break;
17049         }
17050 
17051         if( result.hasExpression() )
17052             m_xml.endElement();
17053 
17054         return true;
17055     }
17056 
sectionEnded(SectionStats const & sectionStats)17057     void XmlReporter::sectionEnded( SectionStats const& sectionStats ) {
17058         StreamingReporterBase::sectionEnded( sectionStats );
17059         if( --m_sectionDepth > 0 ) {
17060             XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
17061             e.writeAttribute( "successes", sectionStats.assertions.passed );
17062             e.writeAttribute( "failures", sectionStats.assertions.failed );
17063             e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
17064 
17065             if ( m_config->showDurations() == ShowDurations::Always )
17066                 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
17067 
17068             m_xml.endElement();
17069         }
17070     }
17071 
testCaseEnded(TestCaseStats const & testCaseStats)17072     void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
17073         StreamingReporterBase::testCaseEnded( testCaseStats );
17074         XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
17075         e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
17076 
17077         if ( m_config->showDurations() == ShowDurations::Always )
17078             e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
17079 
17080         if( !testCaseStats.stdOut.empty() )
17081             m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline );
17082         if( !testCaseStats.stdErr.empty() )
17083             m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline );
17084 
17085         m_xml.endElement();
17086     }
17087 
testGroupEnded(TestGroupStats const & testGroupStats)17088     void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
17089         StreamingReporterBase::testGroupEnded( testGroupStats );
17090         // TODO: Check testGroupStats.aborting and act accordingly.
17091         m_xml.scopedElement( "OverallResults" )
17092             .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
17093             .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
17094             .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
17095         m_xml.endElement();
17096     }
17097 
testRunEnded(TestRunStats const & testRunStats)17098     void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) {
17099         StreamingReporterBase::testRunEnded( testRunStats );
17100         m_xml.scopedElement( "OverallResults" )
17101             .writeAttribute( "successes", testRunStats.totals.assertions.passed )
17102             .writeAttribute( "failures", testRunStats.totals.assertions.failed )
17103             .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
17104         m_xml.endElement();
17105     }
17106 
17107 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
benchmarkPreparing(std::string const & name)17108     void XmlReporter::benchmarkPreparing(std::string const& name) {
17109         m_xml.startElement("BenchmarkResults")
17110             .writeAttribute("name", name);
17111     }
17112 
benchmarkStarting(BenchmarkInfo const & info)17113     void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) {
17114         m_xml.writeAttribute("samples", info.samples)
17115             .writeAttribute("resamples", info.resamples)
17116             .writeAttribute("iterations", info.iterations)
17117             .writeAttribute("clockResolution", info.clockResolution)
17118             .writeAttribute("estimatedDuration", info.estimatedDuration)
17119             .writeComment("All values in nano seconds");
17120     }
17121 
benchmarkEnded(BenchmarkStats<> const & benchmarkStats)17122     void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {
17123         m_xml.startElement("mean")
17124             .writeAttribute("value", benchmarkStats.mean.point.count())
17125             .writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count())
17126             .writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count())
17127             .writeAttribute("ci", benchmarkStats.mean.confidence_interval);
17128         m_xml.endElement();
17129         m_xml.startElement("standardDeviation")
17130             .writeAttribute("value", benchmarkStats.standardDeviation.point.count())
17131             .writeAttribute("lowerBound", benchmarkStats.standardDeviation.lower_bound.count())
17132             .writeAttribute("upperBound", benchmarkStats.standardDeviation.upper_bound.count())
17133             .writeAttribute("ci", benchmarkStats.standardDeviation.confidence_interval);
17134         m_xml.endElement();
17135         m_xml.startElement("outliers")
17136             .writeAttribute("variance", benchmarkStats.outlierVariance)
17137             .writeAttribute("lowMild", benchmarkStats.outliers.low_mild)
17138             .writeAttribute("lowSevere", benchmarkStats.outliers.low_severe)
17139             .writeAttribute("highMild", benchmarkStats.outliers.high_mild)
17140             .writeAttribute("highSevere", benchmarkStats.outliers.high_severe);
17141         m_xml.endElement();
17142         m_xml.endElement();
17143     }
17144 
benchmarkFailed(std::string const & error)17145     void XmlReporter::benchmarkFailed(std::string const &error) {
17146         m_xml.scopedElement("failed").
17147             writeAttribute("message", error);
17148         m_xml.endElement();
17149     }
17150 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
17151 
17152     CATCH_REGISTER_REPORTER( "xml", XmlReporter )
17153 
17154 } // end namespace Catch
17155 
17156 #if defined(_MSC_VER)
17157 #pragma warning(pop)
17158 #endif
17159 // end catch_reporter_xml.cpp
17160 
17161 namespace Catch {
17162     LeakDetector leakDetector;
17163 }
17164 
17165 #ifdef __clang__
17166 #pragma clang diagnostic pop
17167 #endif
17168 
17169 // end catch_impl.hpp
17170 #endif
17171 
17172 #ifdef CATCH_CONFIG_MAIN
17173 // start catch_default_main.hpp
17174 
17175 #ifndef __OBJC__
17176 
17177 #if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
17178 // Standard C/C++ Win32 Unicode wmain entry point
wmain(int argc,wchar_t * argv[],wchar_t * [])17179 extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
17180 #else
17181 // Standard C/C++ main entry point
17182 int main (int argc, char * argv[]) {
17183 #endif
17184 
17185     return Catch::Session().run( argc, argv );
17186 }
17187 
17188 #else // __OBJC__
17189 
17190 // Objective-C entry point
17191 int main (int argc, char * const argv[]) {
17192 #if !CATCH_ARC_ENABLED
17193     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
17194 #endif
17195 
17196     Catch::registerTestMethods();
17197     int result = Catch::Session().run( argc, (char**)argv );
17198 
17199 #if !CATCH_ARC_ENABLED
17200     [pool drain];
17201 #endif
17202 
17203     return result;
17204 }
17205 
17206 #endif // __OBJC__
17207 
17208 // end catch_default_main.hpp
17209 #endif
17210 
17211 #if !defined(CATCH_CONFIG_IMPL_ONLY)
17212 
17213 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
17214 #  undef CLARA_CONFIG_MAIN
17215 #endif
17216 
17217 #if !defined(CATCH_CONFIG_DISABLE)
17218 //////
17219 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
17220 #ifdef CATCH_CONFIG_PREFIX_ALL
17221 
17222 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17223 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17224 
17225 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17226 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
17227 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
17228 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17229 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
17230 #endif// CATCH_CONFIG_DISABLE_MATCHERS
17231 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17232 
17233 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17234 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17235 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17236 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17237 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
17238 
17239 #define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17240 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
17241 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
17242 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17243 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
17244 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17245 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17246 
17247 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17248 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
17249 
17250 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
17251 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17252 
17253 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
17254 #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
17255 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
17256 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )
17257 
17258 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
17259 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
17260 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
17261 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
17262 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
17263 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
17264 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
17265 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17266 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17267 
17268 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
17269 
17270 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
17271 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17272 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
17273 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17274 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
17275 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
17276 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
17277 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
17278 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
17279 #else
17280 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
17281 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
17282 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
17283 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
17284 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
17285 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
17286 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
17287 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
17288 #endif
17289 
17290 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
17291 #define CATCH_STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__ ,      #__VA_ARGS__ );     CATCH_SUCCEED( #__VA_ARGS__ )
17292 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
17293 #else
17294 #define CATCH_STATIC_REQUIRE( ... )       CATCH_REQUIRE( __VA_ARGS__ )
17295 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
17296 #endif
17297 
17298 // "BDD-style" convenience wrappers
17299 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
17300 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
17301 #define CATCH_GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
17302 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
17303 #define CATCH_WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
17304 #define CATCH_AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
17305 #define CATCH_THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
17306 #define CATCH_AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
17307 
17308 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
17309 #define CATCH_BENCHMARK(...) \
17310     INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
17311 #define CATCH_BENCHMARK_ADVANCED(name) \
17312     INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name)
17313 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
17314 
17315 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
17316 #else
17317 
17318 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__  )
17319 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17320 
17321 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17322 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
17323 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
17324 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17325 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
17326 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17327 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
17328 
17329 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17330 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
17331 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17332 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17333 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
17334 
17335 #define CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17336 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
17337 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
17338 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17339 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
17340 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17341 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17342 
17343 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17344 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
17345 
17346 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
17347 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17348 
17349 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
17350 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
17351 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
17352 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
17353 
17354 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
17355 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
17356 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
17357 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
17358 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
17359 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
17360 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
17361 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17362 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
17363 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
17364 
17365 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
17366 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17367 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
17368 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17369 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
17370 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
17371 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
17372 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
17373 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
17374 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)
17375 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )
17376 #else
17377 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
17378 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
17379 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
17380 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
17381 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
17382 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
17383 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
17384 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
17385 #define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )
17386 #define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
17387 #endif
17388 
17389 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
17390 #define STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__,  #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
17391 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
17392 #else
17393 #define STATIC_REQUIRE( ... )       REQUIRE( __VA_ARGS__ )
17394 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
17395 #endif
17396 
17397 #endif
17398 
17399 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
17400 
17401 // "BDD-style" convenience wrappers
17402 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
17403 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
17404 
17405 #define GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
17406 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
17407 #define WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
17408 #define AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
17409 #define THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
17410 #define AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
17411 
17412 #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)
17413 #define BENCHMARK(...) \
17414     INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))
17415 #define BENCHMARK_ADVANCED(name) \
17416     INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name)
17417 #endif // CATCH_CONFIG_ENABLE_BENCHMARKING
17418 
17419 using Catch::Detail::Approx;
17420 
17421 #else // CATCH_CONFIG_DISABLE
17422 
17423 //////
17424 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
17425 #ifdef CATCH_CONFIG_PREFIX_ALL
17426 
17427 #define CATCH_REQUIRE( ... )        (void)(0)
17428 #define CATCH_REQUIRE_FALSE( ... )  (void)(0)
17429 
17430 #define CATCH_REQUIRE_THROWS( ... ) (void)(0)
17431 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
17432 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher )     (void)(0)
17433 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17434 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
17435 #endif// CATCH_CONFIG_DISABLE_MATCHERS
17436 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
17437 
17438 #define CATCH_CHECK( ... )         (void)(0)
17439 #define CATCH_CHECK_FALSE( ... )   (void)(0)
17440 #define CATCH_CHECKED_IF( ... )    if (__VA_ARGS__)
17441 #define CATCH_CHECKED_ELSE( ... )  if (!(__VA_ARGS__))
17442 #define CATCH_CHECK_NOFAIL( ... )  (void)(0)
17443 
17444 #define CATCH_CHECK_THROWS( ... )  (void)(0)
17445 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
17446 #define CATCH_CHECK_THROWS_WITH( expr, matcher )     (void)(0)
17447 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17448 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
17449 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17450 #define CATCH_CHECK_NOTHROW( ... ) (void)(0)
17451 
17452 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17453 #define CATCH_CHECK_THAT( arg, matcher )   (void)(0)
17454 
17455 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
17456 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17457 
17458 #define CATCH_INFO( msg )          (void)(0)
17459 #define CATCH_UNSCOPED_INFO( msg ) (void)(0)
17460 #define CATCH_WARN( msg )          (void)(0)
17461 #define CATCH_CAPTURE( msg )       (void)(0)
17462 
17463 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
17464 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
17465 #define CATCH_METHOD_AS_TEST_CASE( method, ... )
17466 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
17467 #define CATCH_SECTION( ... )
17468 #define CATCH_DYNAMIC_SECTION( ... )
17469 #define CATCH_FAIL( ... ) (void)(0)
17470 #define CATCH_FAIL_CHECK( ... ) (void)(0)
17471 #define CATCH_SUCCEED( ... ) (void)(0)
17472 
17473 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
17474 
17475 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
17476 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
17477 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
17478 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
17479 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
17480 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17481 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17482 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17483 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17484 #else
17485 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
17486 #define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
17487 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
17488 #define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
17489 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17490 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
17491 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17492 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17493 #endif
17494 
17495 // "BDD-style" convenience wrappers
17496 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
17497 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
17498 #define CATCH_GIVEN( desc )
17499 #define CATCH_AND_GIVEN( desc )
17500 #define CATCH_WHEN( desc )
17501 #define CATCH_AND_WHEN( desc )
17502 #define CATCH_THEN( desc )
17503 #define CATCH_AND_THEN( desc )
17504 
17505 #define CATCH_STATIC_REQUIRE( ... )       (void)(0)
17506 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
17507 
17508 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
17509 #else
17510 
17511 #define REQUIRE( ... )       (void)(0)
17512 #define REQUIRE_FALSE( ... ) (void)(0)
17513 
17514 #define REQUIRE_THROWS( ... ) (void)(0)
17515 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
17516 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
17517 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17518 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
17519 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17520 #define REQUIRE_NOTHROW( ... ) (void)(0)
17521 
17522 #define CHECK( ... ) (void)(0)
17523 #define CHECK_FALSE( ... ) (void)(0)
17524 #define CHECKED_IF( ... ) if (__VA_ARGS__)
17525 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
17526 #define CHECK_NOFAIL( ... ) (void)(0)
17527 
17528 #define CHECK_THROWS( ... )  (void)(0)
17529 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
17530 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
17531 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17532 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
17533 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17534 #define CHECK_NOTHROW( ... ) (void)(0)
17535 
17536 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
17537 #define CHECK_THAT( arg, matcher ) (void)(0)
17538 
17539 #define REQUIRE_THAT( arg, matcher ) (void)(0)
17540 #endif // CATCH_CONFIG_DISABLE_MATCHERS
17541 
17542 #define INFO( msg ) (void)(0)
17543 #define UNSCOPED_INFO( msg ) (void)(0)
17544 #define WARN( msg ) (void)(0)
17545 #define CAPTURE( msg ) (void)(0)
17546 
17547 #define TEST_CASE( ... )  INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
17548 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
17549 #define METHOD_AS_TEST_CASE( method, ... )
17550 #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
17551 #define SECTION( ... )
17552 #define DYNAMIC_SECTION( ... )
17553 #define FAIL( ... ) (void)(0)
17554 #define FAIL_CHECK( ... ) (void)(0)
17555 #define SUCCEED( ... ) (void)(0)
17556 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
17557 
17558 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
17559 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
17560 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
17561 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
17562 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
17563 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
17564 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
17565 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17566 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17567 #else
17568 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
17569 #define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
17570 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
17571 #define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
17572 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
17573 #define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
17574 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17575 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
17576 #endif
17577 
17578 #define STATIC_REQUIRE( ... )       (void)(0)
17579 #define STATIC_REQUIRE_FALSE( ... ) (void)(0)
17580 
17581 #endif
17582 
17583 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
17584 
17585 // "BDD-style" convenience wrappers
17586 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )
17587 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
17588 
17589 #define GIVEN( desc )
17590 #define AND_GIVEN( desc )
17591 #define WHEN( desc )
17592 #define AND_WHEN( desc )
17593 #define THEN( desc )
17594 #define AND_THEN( desc )
17595 
17596 using Catch::Detail::Approx;
17597 
17598 #endif
17599 
17600 #endif // ! CATCH_CONFIG_IMPL_ONLY
17601 
17602 // start catch_reenable_warnings.h
17603 
17604 
17605 #ifdef __clang__
17606 #    ifdef __ICC // icpc defines the __clang__ macro
17607 #        pragma warning(pop)
17608 #    else
17609 #        pragma clang diagnostic pop
17610 #    endif
17611 #elif defined __GNUC__
17612 #    pragma GCC diagnostic pop
17613 #endif
17614 
17615 // end catch_reenable_warnings.h
17616 // end catch.hpp
17617 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
17618 
17619