1 /*
2  *  Catch v2.7.0
3  *  Generated: 2019-03-07 21:34:30.252164
4  *  ----------------------------------------------------------
5  *  This file has been merged from multiple headers. Please don't edit it directly
6  *  Copyright (c) 2019 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 7
18 #define CATCH_VERSION_PATCH 0
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 #ifdef __clang__
140 
141 #       define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
142             _Pragma( "clang diagnostic push" ) \
143             _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
144             _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
145 #       define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
146             _Pragma( "clang diagnostic pop" )
147 
148 #       define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
149             _Pragma( "clang diagnostic push" ) \
150             _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
151 #       define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
152             _Pragma( "clang diagnostic pop" )
153 
154 #       define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
155             _Pragma( "clang diagnostic push" ) \
156             _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )
157 #       define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \
158             _Pragma( "clang diagnostic pop" )
159 
160 #endif // __clang__
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 // Assume that non-Windows platforms support posix signals by default
164 #if !defined(CATCH_PLATFORM_WINDOWS)
165     #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
166 #endif
167 
168 ////////////////////////////////////////////////////////////////////////////////
169 // We know some environments not to support full POSIX signals
170 #if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
171     #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
172 #endif
173 
174 #ifdef __OS400__
175 #       define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
176 #       define CATCH_CONFIG_COLOUR_NONE
177 #endif
178 
179 ////////////////////////////////////////////////////////////////////////////////
180 // Android somehow still does not support std::to_string
181 #if defined(__ANDROID__)
182 #    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
183 #endif
184 
185 ////////////////////////////////////////////////////////////////////////////////
186 // Not all Windows environments support SEH properly
187 #if defined(__MINGW32__)
188 #    define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
189 #endif
190 
191 ////////////////////////////////////////////////////////////////////////////////
192 // PS4
193 #if defined(__ORBIS__)
194 #    define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE
195 #endif
196 
197 ////////////////////////////////////////////////////////////////////////////////
198 // Cygwin
199 #ifdef __CYGWIN__
200 
201 // Required for some versions of Cygwin to declare gettimeofday
202 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
203 #   define _BSD_SOURCE
204 // some versions of cygwin (most) do not support std::to_string. Use the libstd check.
205 // https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813
206 # if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
207 	       && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))
208 
209 #	define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
210 
211 # endif
212 #endif // __CYGWIN__
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 // Visual C++
216 #ifdef _MSC_VER
217 
218 #  if _MSC_VER >= 1900 // Visual Studio 2015 or newer
219 #    define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
220 #  endif
221 
222 // Universal Windows platform does not support SEH
223 // Or console colours (or console at all...)
224 #  if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
225 #    define CATCH_CONFIG_COLOUR_NONE
226 #  else
227 #    define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
228 #  endif
229 
230 // MSVC traditional preprocessor needs some workaround for __VA_ARGS__
231 // _MSVC_TRADITIONAL == 0 means new conformant preprocessor
232 // _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor
233 #  if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)
234 #    define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
235 #  endif
236 
237 #endif // _MSC_VER
238 
239 ////////////////////////////////////////////////////////////////////////////////
240 // Check if we are compiled with -fno-exceptions or equivalent
241 #if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
242 #  define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED
243 #endif
244 
245 ////////////////////////////////////////////////////////////////////////////////
246 // DJGPP
247 #ifdef __DJGPP__
248 #  define CATCH_INTERNAL_CONFIG_NO_WCHAR
249 #endif // __DJGPP__
250 
251 ////////////////////////////////////////////////////////////////////////////////
252 // Embarcadero C++Build
253 #if defined(__BORLANDC__)
254     #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN
255 #endif
256 
257 ////////////////////////////////////////////////////////////////////////////////
258 
259 // Use of __COUNTER__ is suppressed during code analysis in
260 // CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
261 // handled by it.
262 // Otherwise all supported compilers support COUNTER macro,
263 // but user still might want to turn it off
264 #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
265     #define CATCH_INTERNAL_CONFIG_COUNTER
266 #endif
267 
268 ////////////////////////////////////////////////////////////////////////////////
269 // Check if string_view is available and usable
270 // The check is split apart to work around v140 (VS2015) preprocessor issue...
271 #if defined(__has_include)
272 #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)
273 #    define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW
274 #endif
275 #endif
276 
277 ////////////////////////////////////////////////////////////////////////////////
278 // Check if optional is available and usable
279 #if defined(__has_include)
280 #  if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
281 #    define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL
282 #  endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)
283 #endif // __has_include
284 
285 ////////////////////////////////////////////////////////////////////////////////
286 // Check if variant is available and usable
287 #if defined(__has_include)
288 #  if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
289 #    if defined(__clang__) && (__clang_major__ < 8)
290        // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852
291        // fix should be in clang 8, workaround in libstdc++ 8.2
292 #      include <ciso646>
293 #      if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
294 #        define CATCH_CONFIG_NO_CPP17_VARIANT
295 #      else
296 #        define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
297 #      endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)
298 #    else
299 #      define CATCH_INTERNAL_CONFIG_CPP17_VARIANT
300 #    endif // defined(__clang__) && (__clang_major__ < 8)
301 #  endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)
302 #endif // __has_include
303 
304 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
305 #   define CATCH_CONFIG_COUNTER
306 #endif
307 #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)
308 #   define CATCH_CONFIG_WINDOWS_SEH
309 #endif
310 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
311 #if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
312 #   define CATCH_CONFIG_POSIX_SIGNALS
313 #endif
314 // This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
315 #if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
316 #   define CATCH_CONFIG_WCHAR
317 #endif
318 
319 #if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
320 #    define CATCH_CONFIG_CPP11_TO_STRING
321 #endif
322 
323 #if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)
324 #  define CATCH_CONFIG_CPP17_OPTIONAL
325 #endif
326 
327 #if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
328 #  define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
329 #endif
330 
331 #if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)
332 #  define CATCH_CONFIG_CPP17_STRING_VIEW
333 #endif
334 
335 #if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)
336 #  define CATCH_CONFIG_CPP17_VARIANT
337 #endif
338 
339 #if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
340 #  define CATCH_INTERNAL_CONFIG_NEW_CAPTURE
341 #endif
342 
343 #if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)
344 #  define CATCH_CONFIG_NEW_CAPTURE
345 #endif
346 
347 #if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
348 #  define CATCH_CONFIG_DISABLE_EXCEPTIONS
349 #endif
350 
351 #if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)
352 #  define CATCH_CONFIG_POLYFILL_ISNAN
353 #endif
354 
355 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
356 #   define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
357 #   define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
358 #endif
359 #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
360 #   define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
361 #   define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
362 #endif
363 #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)
364 #   define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS
365 #   define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
366 #endif
367 
368 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
369 #define CATCH_TRY if ((true))
370 #define CATCH_CATCH_ALL if ((false))
371 #define CATCH_CATCH_ANON(type) if ((false))
372 #else
373 #define CATCH_TRY try
374 #define CATCH_CATCH_ALL catch (...)
375 #define CATCH_CATCH_ANON(type) catch (type)
376 #endif
377 
378 #if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)
379 #define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
380 #endif
381 
382 // end catch_compiler_capabilities.h
383 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
384 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
385 #ifdef CATCH_CONFIG_COUNTER
386 #  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
387 #else
388 #  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
389 #endif
390 
391 #include <iosfwd>
392 #include <string>
393 #include <cstdint>
394 
395 // We need a dummy global operator<< so we can bring it into Catch namespace later
396 struct Catch_global_namespace_dummy {};
397 std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
398 
399 namespace Catch {
400 
401     struct CaseSensitive { enum Choice {
402         Yes,
403         No
404     }; };
405 
406     class NonCopyable {
407         NonCopyable( NonCopyable const& )              = delete;
408         NonCopyable( NonCopyable && )                  = delete;
409         NonCopyable& operator = ( NonCopyable const& ) = delete;
410         NonCopyable& operator = ( NonCopyable && )     = delete;
411 
412     protected:
413         NonCopyable();
414         virtual ~NonCopyable();
415     };
416 
417     struct SourceLineInfo {
418 
419         SourceLineInfo() = delete;
SourceLineInfoCatch::SourceLineInfo420         SourceLineInfo( char const* _file, std::size_t _line ) noexcept
421         :   file( _file ),
422             line( _line )
423         {}
424 
425         SourceLineInfo( SourceLineInfo const& other )            = default;
426         SourceLineInfo& operator = ( SourceLineInfo const& )     = default;
427         SourceLineInfo( SourceLineInfo&& )              noexcept = default;
428         SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;
429 
430         bool empty() const noexcept;
431         bool operator == ( SourceLineInfo const& other ) const noexcept;
432         bool operator < ( SourceLineInfo const& other ) const noexcept;
433 
434         char const* file;
435         std::size_t line;
436     };
437 
438     std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
439 
440     // Bring in operator<< from global namespace into Catch namespace
441     // This is necessary because the overload of operator<< above makes
442     // lookup stop at namespace Catch
443     using ::operator<<;
444 
445     // Use this in variadic streaming macros to allow
446     //    >> +StreamEndStop
447     // as well as
448     //    >> stuff +StreamEndStop
449     struct StreamEndStop {
450         std::string operator+() const;
451     };
452     template<typename T>
operator +(T const & value,StreamEndStop)453     T const& operator + ( T const& value, StreamEndStop ) {
454         return value;
455     }
456 }
457 
458 #define CATCH_INTERNAL_LINEINFO \
459     ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
460 
461 // end catch_common.h
462 namespace Catch {
463 
464     struct RegistrarForTagAliases {
465         RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
466     };
467 
468 } // end namespace Catch
469 
470 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
471     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
472     namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
473     CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
474 
475 // end catch_tag_alias_autoregistrar.h
476 // start catch_test_registry.h
477 
478 // start catch_interfaces_testcase.h
479 
480 #include <vector>
481 
482 namespace Catch {
483 
484     class TestSpec;
485 
486     struct ITestInvoker {
487         virtual void invoke () const = 0;
488         virtual ~ITestInvoker();
489     };
490 
491     class TestCase;
492     struct IConfig;
493 
494     struct ITestCaseRegistry {
495         virtual ~ITestCaseRegistry();
496         virtual std::vector<TestCase> const& getAllTests() const = 0;
497         virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
498     };
499 
500     bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
501     std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
502     std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
503 
504 }
505 
506 // end catch_interfaces_testcase.h
507 // start catch_stringref.h
508 
509 #include <cstddef>
510 #include <string>
511 #include <iosfwd>
512 
513 namespace Catch {
514 
515     /// A non-owning string class (similar to the forthcoming std::string_view)
516     /// Note that, because a StringRef may be a substring of another string,
517     /// it may not be null terminated. c_str() must return a null terminated
518     /// string, however, and so the StringRef will internally take ownership
519     /// (taking a copy), if necessary. In theory this ownership is not externally
520     /// visible - but it does mean (substring) StringRefs should not be shared between
521     /// threads.
522     class StringRef {
523     public:
524         using size_type = std::size_t;
525 
526     private:
527         friend struct StringRefTestAccess;
528 
529         char const* m_start;
530         size_type m_size;
531 
532         char* m_data = nullptr;
533 
534         void takeOwnership();
535 
536         static constexpr char const* const s_empty = "";
537 
538     public: // construction/ assignment
StringRef()539         StringRef() noexcept
540         :   StringRef( s_empty, 0 )
541         {}
542 
StringRef(StringRef const & other)543         StringRef( StringRef const& other ) noexcept
544         :   m_start( other.m_start ),
545             m_size( other.m_size )
546         {}
547 
StringRef(StringRef && other)548         StringRef( StringRef&& other ) noexcept
549         :   m_start( other.m_start ),
550             m_size( other.m_size ),
551             m_data( other.m_data )
552         {
553             other.m_data = nullptr;
554         }
555 
556         StringRef( char const* rawChars ) noexcept;
557 
StringRef(char const * rawChars,size_type size)558         StringRef( char const* rawChars, size_type size ) noexcept
559         :   m_start( rawChars ),
560             m_size( size )
561         {}
562 
StringRef(std::string const & stdString)563         StringRef( std::string const& stdString ) noexcept
564         :   m_start( stdString.c_str() ),
565             m_size( stdString.size() )
566         {}
567 
~StringRef()568         ~StringRef() noexcept {
569             delete[] m_data;
570         }
571 
operator =(StringRef const & other)572         auto operator = ( StringRef const &other ) noexcept -> StringRef& {
573             delete[] m_data;
574             m_data = nullptr;
575             m_start = other.m_start;
576             m_size = other.m_size;
577             return *this;
578         }
579 
580         operator std::string() const;
581 
582         void swap( StringRef& other ) noexcept;
583 
584     public: // operators
585         auto operator == ( StringRef const& other ) const noexcept -> bool;
586         auto operator != ( StringRef const& other ) const noexcept -> bool;
587 
588         auto operator[] ( size_type index ) const noexcept -> char;
589 
590     public: // named queries
empty() const591         auto empty() const noexcept -> bool {
592             return m_size == 0;
593         }
size() const594         auto size() const noexcept -> size_type {
595             return m_size;
596         }
597 
598         auto numberOfCharacters() const noexcept -> size_type;
599         auto c_str() const -> char const*;
600 
601     public: // substrings and searches
602         auto substr( size_type start, size_type size ) const noexcept -> StringRef;
603 
604         // Returns the current start pointer.
605         // Note that the pointer can change when if the StringRef is a substring
606         auto currentData() const noexcept -> char const*;
607 
608     private: // ownership queries - may not be consistent between calls
609         auto isOwned() const noexcept -> bool;
610         auto isSubstring() const noexcept -> bool;
611     };
612 
613     auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
614     auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
615     auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
616 
617     auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
618     auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
619 
operator ""_sr(char const * rawChars,std::size_t size)620     inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
621         return StringRef( rawChars, size );
622     }
623 
624 } // namespace Catch
625 
operator ""_catch_sr(char const * rawChars,std::size_t size)626 inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {
627     return Catch::StringRef( rawChars, size );
628 }
629 
630 // end catch_stringref.h
631 // start catch_type_traits.hpp
632 
633 
634 #include <type_traits>
635 
636 namespace Catch{
637 
638 #ifdef CATCH_CPP17_OR_GREATER
639 	template <typename...>
640 	inline constexpr auto is_unique = std::true_type{};
641 
642 	template <typename T, typename... Rest>
643 	inline constexpr auto is_unique<T, Rest...> = std::bool_constant<
644 		(!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>
645 	>{};
646 #else
647 
648 template <typename...>
649 struct is_unique : std::true_type{};
650 
651 template <typename T0, typename T1, typename... Rest>
652 struct is_unique<T0, T1, Rest...> : std::integral_constant
653 <bool,
654      !std::is_same<T0, T1>::value
655      && is_unique<T0, Rest...>::value
656      && is_unique<T1, Rest...>::value
657 >{};
658 
659 #endif
660 }
661 
662 // end catch_type_traits.hpp
663 // start catch_preprocessor.hpp
664 
665 
666 #define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__
667 #define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))
668 #define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))
669 #define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))
670 #define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))
671 #define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))
672 
673 #ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
674 #define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__
675 // MSVC needs more evaluations
676 #define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))
677 #define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))
678 #else
679 #define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL5(__VA_ARGS__)
680 #endif
681 
682 #define CATCH_REC_END(...)
683 #define CATCH_REC_OUT
684 
685 #define CATCH_EMPTY()
686 #define CATCH_DEFER(id) id CATCH_EMPTY()
687 
688 #define CATCH_REC_GET_END2() 0, CATCH_REC_END
689 #define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2
690 #define CATCH_REC_GET_END(...) CATCH_REC_GET_END1
691 #define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT
692 #define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)
693 #define CATCH_REC_NEXT(test, next)  CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)
694 
695 #define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
696 #define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )
697 #define CATCH_REC_LIST2(f, x, peek, ...)   f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )
698 
699 #define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
700 #define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )
701 #define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...)   f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )
702 
703 // Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,
704 // and passes userdata as the first parameter to each invocation,
705 // e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)
706 #define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
707 
708 #define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
709 
710 #define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
711 #define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
712 #define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
713 #define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
714 #define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)
715 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
716 #define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__
717 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))
718 #else
719 // MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
720 #define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)
721 #define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__
722 #define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)
723 #endif
724 
725 #define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)
726 
727 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name, __VA_ARGS__)
728 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
729 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " - " #__VA_ARGS__
730 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name,...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))
731 #else
732 // MSVC is adding extra space and needs more calls to properly remove ()
733 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME3(Name,...) Name " -" #__VA_ARGS__
734 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME2(Name, __VA_ARGS__)
735 #define INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME(Name, ...) INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME1(Name, INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))
736 #endif
737 
738 #define INTERNAL_CATCH_MAKE_TYPE_LIST(types) Catch::TypeList<INTERNAL_CATCH_REMOVE_PARENS(types)>
739 
740 #define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(types)\
741     CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,INTERNAL_CATCH_REMOVE_PARENS(types))
742 
743 // end catch_preprocessor.hpp
744 // start catch_meta.hpp
745 
746 
747 #include <type_traits>
748 
749 namespace Catch {
750 template< typename... >
751 struct TypeList {};
752 
753 template< typename... >
754 struct append;
755 
756 template< template<typename...> class L1
757     , typename...E1
758     , template<typename...> class L2
759     , typename...E2
760 >
761 struct append< L1<E1...>, L2<E2...> > {
762     using type = L1<E1..., E2...>;
763 };
764 
765 template< template<typename...> class L1
766     , typename...E1
767     , template<typename...> class L2
768     , typename...E2
769     , typename...Rest
770 >
771 struct append< L1<E1...>, L2<E2...>, Rest...> {
772     using type = typename append< L1<E1..., E2...>, Rest... >::type;
773 };
774 
775 template< template<typename...> class
776     , typename...
777 >
778 struct rewrap;
779 
780 template< template<typename...> class Container
781     , template<typename...> class List
782     , typename...elems
783 >
784 struct rewrap<Container, List<elems...>> {
785     using type = TypeList< Container< elems... > >;
786 };
787 
788 template< template<typename...> class Container
789     , template<typename...> class List
790     , class...Elems
791     , typename...Elements>
792     struct rewrap<Container, List<Elems...>, Elements...> {
793     using type = typename append<TypeList<Container<Elems...>>, typename rewrap<Container, Elements...>::type>::type;
794 };
795 
796 template< template<typename...> class...Containers >
797 struct combine {
798     template< typename...Types >
799     struct with_types {
800         template< template <typename...> class Final >
801         struct into {
802             using type = typename append<Final<>, typename rewrap<Containers, Types...>::type...>::type;
803         };
804     };
805 };
806 
807 template<typename T>
808 struct always_false : std::false_type {};
809 
810 } // namespace Catch
811 
812 // end catch_meta.hpp
813 namespace Catch {
814 
815 template<typename C>
816 class TestInvokerAsMethod : public ITestInvoker {
817     void (C::*m_testAsMethod)();
818 public:
TestInvokerAsMethod(void (C::* testAsMethod)())819     TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
820 
invoke() const821     void invoke() const override {
822         C obj;
823         (obj.*m_testAsMethod)();
824     }
825 };
826 
827 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;
828 
829 template<typename C>
makeTestInvoker(void (C::* testAsMethod)())830 auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
831     return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod );
832 }
833 
834 struct NameAndTags {
835     NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
836     StringRef name;
837     StringRef tags;
838 };
839 
840 struct AutoReg : NonCopyable {
841     AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
842     ~AutoReg();
843 };
844 
845 } // end namespace Catch
846 
847 #if defined(CATCH_CONFIG_DISABLE)
848     #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
849         static void TestName()
850     #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
851         namespace{                        \
852             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
853                 void test();              \
854             };                            \
855         }                                 \
856         void TestName::test()
857     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION( TestName, ... )  \
858         template<typename TestType>                                             \
859         static void TestName()
860     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... )    \
861         namespace{                                                                                  \
862             template<typename TestType>                                                             \
863             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) {     \
864                 void test();                                                                        \
865             };                                                                                      \
866         }                                                                                           \
867         template<typename TestType>                                                                 \
868         void TestName::test()
869 #endif
870 
871     ///////////////////////////////////////////////////////////////////////////////
872     #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
873         static void TestName(); \
874         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
875         namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
876         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
877         static void TestName()
878     #define INTERNAL_CATCH_TESTCASE( ... ) \
879         INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
880 
881     ///////////////////////////////////////////////////////////////////////////////
882     #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
883         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
884         namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
885         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
886 
887     ///////////////////////////////////////////////////////////////////////////////
888     #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
889         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
890         namespace{ \
891             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \
892                 void test(); \
893             }; \
894             Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
895         } \
896         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
897         void TestName::test()
898     #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
899         INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
900 
901     ///////////////////////////////////////////////////////////////////////////////
902     #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
903         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
904         Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
905         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
906 
907     ///////////////////////////////////////////////////////////////////////////////
908     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, ... )\
909         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
910         template<typename TestType> \
911         static void TestFunc();\
912         namespace {\
913             template<typename...Types> \
914             struct TestName{\
915                 template<typename...Ts> \
916                 TestName(Ts...names){\
917                     CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
918                     using expander = int[];\
919                     (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
920                 }\
921             };\
922             INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, __VA_ARGS__) \
923         }\
924         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
925         template<typename TestType> \
926         static void TestFunc()
927 
928 #if defined(CATCH_CPP17_OR_GREATER)
929 #define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>,"Duplicate type detected in declaration of template test case");
930 #else
931 #define CATCH_INTERNAL_CHECK_UNIQUE_TYPES(...) static_assert(Catch::is_unique<__VA_ARGS__>::value,"Duplicate type detected in declaration of template test case");
932 #endif
933 
934 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
935     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
936         INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ )
937 #else
938     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \
939         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )
940 #endif
941 
942     #define INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestName, Name, ...)\
943         static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
944             TestName<CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)>(CATCH_REC_LIST_UD(INTERNAL_CATCH_TEMPLATE_UNIQUE_NAME,Name, __VA_ARGS__));\
945             return 0;\
946         }();
947 
948     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, TmplTypes, TypesList) \
949         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                      \
950         template<typename TestType> static void TestFuncName();       \
951         namespace {                                                   \
952             template<typename... Types>                               \
953             struct TestName {                                         \
954                 TestName() {                                          \
955                     CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)       \
956                     int index = 0;                                    \
957                     using expander = int[];                           \
958                     constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
959                     constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
960                     constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
961                     (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */\
962                 }                                                     \
963             };                                                        \
964             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \
965                 using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)> \
966                             ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestName>::type; \
967                 TestInit();                                           \
968                 return 0;                                             \
969             }();                                                      \
970         }                                                             \
971         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS                    \
972         template<typename TestType>                                   \
973         static void TestFuncName()
974 
975 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
976     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
977         INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ),Name,Tags,__VA_ARGS__)
978 #else
979     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\
980         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, __VA_ARGS__ ) )
981 #endif
982 
983     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, ... ) \
984         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
985         namespace{ \
986             template<typename TestType> \
987             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
988                 void test();\
989             };\
990             template<typename...Types> \
991             struct TestNameClass{\
992                 template<typename...Ts> \
993                 TestNameClass(Ts...names){\
994                     CATCH_INTERNAL_CHECK_UNIQUE_TYPES(CATCH_REC_LIST(INTERNAL_CATCH_REMOVE_PARENS, __VA_ARGS__)) \
995                     using expander = int[];\
996                     (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ names, Tags } ), 0)... };/* NOLINT */ \
997                 }\
998             };\
999             INTERNAL_CATCH_TEMPLATE_REGISTRY_INITIATE(TestNameClass, Name, __VA_ARGS__)\
1000         }\
1001         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS\
1002         template<typename TestType> \
1003         void TestName<TestType>::test()
1004 
1005 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1006     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
1007         INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ )
1008 #else
1009     #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \
1010         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, __VA_ARGS__ ) )
1011 #endif
1012 
1013     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, TmplTypes, TypesList)\
1014         CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
1015         template<typename TestType> \
1016             struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \
1017                 void test();\
1018             };\
1019         namespace {\
1020             template<typename...Types>\
1021             struct TestNameClass{\
1022                 TestNameClass(){\
1023                     CATCH_INTERNAL_CHECK_UNIQUE_TYPES(Types...)\
1024                     int index = 0;\
1025                     using expander = int[];\
1026                     constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\
1027                     constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\
1028                     constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\
1029                     (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++, 0)... };/* NOLINT */ \
1030                 }\
1031             };\
1032             static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\
1033                 using TestInit = Catch::combine<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>\
1034                             ::with_types<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(TypesList)>::into<TestNameClass>::type;\
1035                 TestInit();\
1036                 return 0;\
1037             }(); \
1038         }\
1039         CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
1040         template<typename TestType> \
1041         void TestName<TestType>::test()
1042 
1043 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
1044     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
1045         INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ )
1046 #else
1047     #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\
1048         INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, __VA_ARGS__ ) )
1049 #endif
1050 
1051 // end catch_test_registry.h
1052 // start catch_capture.hpp
1053 
1054 // start catch_assertionhandler.h
1055 
1056 // start catch_assertioninfo.h
1057 
1058 // start catch_result_type.h
1059 
1060 namespace Catch {
1061 
1062     // ResultWas::OfType enum
1063     struct ResultWas { enum OfType {
1064         Unknown = -1,
1065         Ok = 0,
1066         Info = 1,
1067         Warning = 2,
1068 
1069         FailureBit = 0x10,
1070 
1071         ExpressionFailed = FailureBit | 1,
1072         ExplicitFailure = FailureBit | 2,
1073 
1074         Exception = 0x100 | FailureBit,
1075 
1076         ThrewException = Exception | 1,
1077         DidntThrowException = Exception | 2,
1078 
1079         FatalErrorCondition = 0x200 | FailureBit
1080 
1081     }; };
1082 
1083     bool isOk( ResultWas::OfType resultType );
1084     bool isJustInfo( int flags );
1085 
1086     // ResultDisposition::Flags enum
1087     struct ResultDisposition { enum Flags {
1088         Normal = 0x01,
1089 
1090         ContinueOnFailure = 0x02,   // Failures fail test, but execution continues
1091         FalseTest = 0x04,           // Prefix expression with !
1092         SuppressFail = 0x08         // Failures are reported but do not fail the test
1093     }; };
1094 
1095     ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs );
1096 
1097     bool shouldContinueOnFailure( int flags );
isFalseTest(int flags)1098     inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
1099     bool shouldSuppressFailure( int flags );
1100 
1101 } // end namespace Catch
1102 
1103 // end catch_result_type.h
1104 namespace Catch {
1105 
1106     struct AssertionInfo
1107     {
1108         StringRef macroName;
1109         SourceLineInfo lineInfo;
1110         StringRef capturedExpression;
1111         ResultDisposition::Flags resultDisposition;
1112 
1113         // We want to delete this constructor but a compiler bug in 4.8 means
1114         // the struct is then treated as non-aggregate
1115         //AssertionInfo() = delete;
1116     };
1117 
1118 } // end namespace Catch
1119 
1120 // end catch_assertioninfo.h
1121 // start catch_decomposer.h
1122 
1123 // start catch_tostring.h
1124 
1125 #include <vector>
1126 #include <cstddef>
1127 #include <type_traits>
1128 #include <string>
1129 // start catch_stream.h
1130 
1131 #include <iosfwd>
1132 #include <cstddef>
1133 #include <ostream>
1134 
1135 namespace Catch {
1136 
1137     std::ostream& cout();
1138     std::ostream& cerr();
1139     std::ostream& clog();
1140 
1141     class StringRef;
1142 
1143     struct IStream {
1144         virtual ~IStream();
1145         virtual std::ostream& stream() const = 0;
1146     };
1147 
1148     auto makeStream( StringRef const &filename ) -> IStream const*;
1149 
1150     class ReusableStringStream {
1151         std::size_t m_index;
1152         std::ostream* m_oss;
1153     public:
1154         ReusableStringStream();
1155         ~ReusableStringStream();
1156 
1157         auto str() const -> std::string;
1158 
1159         template<typename T>
operator <<(T const & value)1160         auto operator << ( T const& value ) -> ReusableStringStream& {
1161             *m_oss << value;
1162             return *this;
1163         }
get()1164         auto get() -> std::ostream& { return *m_oss; }
1165     };
1166 }
1167 
1168 // end catch_stream.h
1169 
1170 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1171 #include <string_view>
1172 #endif
1173 
1174 #ifdef __OBJC__
1175 // start catch_objc_arc.hpp
1176 
1177 #import <Foundation/Foundation.h>
1178 
1179 #ifdef __has_feature
1180 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1181 #else
1182 #define CATCH_ARC_ENABLED 0
1183 #endif
1184 
1185 void arcSafeRelease( NSObject* obj );
1186 id performOptionalSelector( id obj, SEL sel );
1187 
1188 #if !CATCH_ARC_ENABLED
arcSafeRelease(NSObject * obj)1189 inline void arcSafeRelease( NSObject* obj ) {
1190     [obj release];
1191 }
performOptionalSelector(id obj,SEL sel)1192 inline id performOptionalSelector( id obj, SEL sel ) {
1193     if( [obj respondsToSelector: sel] )
1194         return [obj performSelector: sel];
1195     return nil;
1196 }
1197 #define CATCH_UNSAFE_UNRETAINED
1198 #define CATCH_ARC_STRONG
1199 #else
arcSafeRelease(NSObject *)1200 inline void arcSafeRelease( NSObject* ){}
performOptionalSelector(id obj,SEL sel)1201 inline id performOptionalSelector( id obj, SEL sel ) {
1202 #ifdef __clang__
1203 #pragma clang diagnostic push
1204 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1205 #endif
1206     if( [obj respondsToSelector: sel] )
1207         return [obj performSelector: sel];
1208 #ifdef __clang__
1209 #pragma clang diagnostic pop
1210 #endif
1211     return nil;
1212 }
1213 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1214 #define CATCH_ARC_STRONG __strong
1215 #endif
1216 
1217 // end catch_objc_arc.hpp
1218 #endif
1219 
1220 #ifdef _MSC_VER
1221 #pragma warning(push)
1222 #pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
1223 #endif
1224 
1225 namespace Catch {
1226     namespace Detail {
1227 
1228         extern const std::string unprintableString;
1229 
1230         std::string rawMemoryToString( const void *object, std::size_t size );
1231 
1232         template<typename T>
rawMemoryToString(const T & object)1233         std::string rawMemoryToString( const T& object ) {
1234           return rawMemoryToString( &object, sizeof(object) );
1235         }
1236 
1237         template<typename T>
1238         class IsStreamInsertable {
1239             template<typename SS, typename TT>
1240             static auto test(int)
1241                 -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
1242 
1243             template<typename, typename>
1244             static auto test(...)->std::false_type;
1245 
1246         public:
1247             static const bool value = decltype(test<std::ostream, const T&>(0))::value;
1248         };
1249 
1250         template<typename E>
1251         std::string convertUnknownEnumToString( E e );
1252 
1253         template<typename T>
1254         typename std::enable_if<
1255             !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,
convertUnstreamable(T const &)1256         std::string>::type convertUnstreamable( T const& ) {
1257             return Detail::unprintableString;
1258         }
1259         template<typename T>
1260         typename std::enable_if<
1261             !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,
convertUnstreamable(T const & ex)1262          std::string>::type convertUnstreamable(T const& ex) {
1263             return ex.what();
1264         }
1265 
1266         template<typename T>
1267         typename std::enable_if<
1268             std::is_enum<T>::value
convertUnstreamable(T const & value)1269         , std::string>::type convertUnstreamable( T const& value ) {
1270             return convertUnknownEnumToString( value );
1271         }
1272 
1273 #if defined(_MANAGED)
1274         //! Convert a CLR string to a utf8 std::string
1275         template<typename T>
1276         std::string clrReferenceToString( T^ ref ) {
1277             if (ref == nullptr)
1278                 return std::string("null");
1279             auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
1280             cli::pin_ptr<System::Byte> p = &bytes[0];
1281             return std::string(reinterpret_cast<char const *>(p), bytes->Length);
1282         }
1283 #endif
1284 
1285     } // namespace Detail
1286 
1287     // If we decide for C++14, change these to enable_if_ts
1288     template <typename T, typename = void>
1289     struct StringMaker {
1290         template <typename Fake = T>
1291         static
1292         typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
convertCatch::StringMaker1293             convert(const Fake& value) {
1294                 ReusableStringStream rss;
1295                 // NB: call using the function-like syntax to avoid ambiguity with
1296                 // user-defined templated operator<< under clang.
1297                 rss.operator<<(value);
1298                 return rss.str();
1299         }
1300 
1301         template <typename Fake = T>
1302         static
1303         typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type
convertCatch::StringMaker1304             convert( const Fake& value ) {
1305 #if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
1306             return Detail::convertUnstreamable(value);
1307 #else
1308             return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
1309 #endif
1310         }
1311     };
1312 
1313     namespace Detail {
1314 
1315         // This function dispatches all stringification requests inside of Catch.
1316         // Should be preferably called fully qualified, like ::Catch::Detail::stringify
1317         template <typename T>
stringify(const T & e)1318         std::string stringify(const T& e) {
1319             return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e);
1320         }
1321 
1322         template<typename E>
convertUnknownEnumToString(E e)1323         std::string convertUnknownEnumToString( E e ) {
1324             return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));
1325         }
1326 
1327 #if defined(_MANAGED)
1328         template <typename T>
1329         std::string stringify( T^ e ) {
1330             return ::Catch::StringMaker<T^>::convert(e);
1331         }
1332 #endif
1333 
1334     } // namespace Detail
1335 
1336     // Some predefined specializations
1337 
1338     template<>
1339     struct StringMaker<std::string> {
1340         static std::string convert(const std::string& str);
1341     };
1342 
1343 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1344     template<>
1345     struct StringMaker<std::string_view> {
1346         static std::string convert(std::string_view str);
1347     };
1348 #endif
1349 
1350     template<>
1351     struct StringMaker<char const *> {
1352         static std::string convert(char const * str);
1353     };
1354     template<>
1355     struct StringMaker<char *> {
1356         static std::string convert(char * str);
1357     };
1358 
1359 #ifdef CATCH_CONFIG_WCHAR
1360     template<>
1361     struct StringMaker<std::wstring> {
1362         static std::string convert(const std::wstring& wstr);
1363     };
1364 
1365 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW
1366     template<>
1367     struct StringMaker<std::wstring_view> {
1368         static std::string convert(std::wstring_view str);
1369     };
1370 # endif
1371 
1372     template<>
1373     struct StringMaker<wchar_t const *> {
1374         static std::string convert(wchar_t const * str);
1375     };
1376     template<>
1377     struct StringMaker<wchar_t *> {
1378         static std::string convert(wchar_t * str);
1379     };
1380 #endif
1381 
1382     // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
1383     //      while keeping string semantics?
1384     template<int SZ>
1385     struct StringMaker<char[SZ]> {
convertCatch::StringMaker1386         static std::string convert(char const* str) {
1387             return ::Catch::Detail::stringify(std::string{ str });
1388         }
1389     };
1390     template<int SZ>
1391     struct StringMaker<signed char[SZ]> {
convertCatch::StringMaker1392         static std::string convert(signed char const* str) {
1393             return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
1394         }
1395     };
1396     template<int SZ>
1397     struct StringMaker<unsigned char[SZ]> {
convertCatch::StringMaker1398         static std::string convert(unsigned char const* str) {
1399             return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
1400         }
1401     };
1402 
1403     template<>
1404     struct StringMaker<int> {
1405         static std::string convert(int value);
1406     };
1407     template<>
1408     struct StringMaker<long> {
1409         static std::string convert(long value);
1410     };
1411     template<>
1412     struct StringMaker<long long> {
1413         static std::string convert(long long value);
1414     };
1415     template<>
1416     struct StringMaker<unsigned int> {
1417         static std::string convert(unsigned int value);
1418     };
1419     template<>
1420     struct StringMaker<unsigned long> {
1421         static std::string convert(unsigned long value);
1422     };
1423     template<>
1424     struct StringMaker<unsigned long long> {
1425         static std::string convert(unsigned long long value);
1426     };
1427 
1428     template<>
1429     struct StringMaker<bool> {
1430         static std::string convert(bool b);
1431     };
1432 
1433     template<>
1434     struct StringMaker<char> {
1435         static std::string convert(char c);
1436     };
1437     template<>
1438     struct StringMaker<signed char> {
1439         static std::string convert(signed char c);
1440     };
1441     template<>
1442     struct StringMaker<unsigned char> {
1443         static std::string convert(unsigned char c);
1444     };
1445 
1446     template<>
1447     struct StringMaker<std::nullptr_t> {
1448         static std::string convert(std::nullptr_t);
1449     };
1450 
1451     template<>
1452     struct StringMaker<float> {
1453         static std::string convert(float value);
1454     };
1455     template<>
1456     struct StringMaker<double> {
1457         static std::string convert(double value);
1458     };
1459 
1460     template <typename T>
1461     struct StringMaker<T*> {
1462         template <typename U>
convertCatch::StringMaker1463         static std::string convert(U* p) {
1464             if (p) {
1465                 return ::Catch::Detail::rawMemoryToString(p);
1466             } else {
1467                 return "nullptr";
1468             }
1469         }
1470     };
1471 
1472     template <typename R, typename C>
1473     struct StringMaker<R C::*> {
convertCatch::StringMaker1474         static std::string convert(R C::* p) {
1475             if (p) {
1476                 return ::Catch::Detail::rawMemoryToString(p);
1477             } else {
1478                 return "nullptr";
1479             }
1480         }
1481     };
1482 
1483 #if defined(_MANAGED)
1484     template <typename T>
1485     struct StringMaker<T^> {
1486         static std::string convert( T^ ref ) {
1487             return ::Catch::Detail::clrReferenceToString(ref);
1488         }
1489     };
1490 #endif
1491 
1492     namespace Detail {
1493         template<typename InputIterator>
rangeToString(InputIterator first,InputIterator last)1494         std::string rangeToString(InputIterator first, InputIterator last) {
1495             ReusableStringStream rss;
1496             rss << "{ ";
1497             if (first != last) {
1498                 rss << ::Catch::Detail::stringify(*first);
1499                 for (++first; first != last; ++first)
1500                     rss << ", " << ::Catch::Detail::stringify(*first);
1501             }
1502             rss << " }";
1503             return rss.str();
1504         }
1505     }
1506 
1507 #ifdef __OBJC__
1508     template<>
1509     struct StringMaker<NSString*> {
convertCatch::StringMaker1510         static std::string convert(NSString * nsstring) {
1511             if (!nsstring)
1512                 return "nil";
1513             return std::string("@") + [nsstring UTF8String];
1514         }
1515     };
1516     template<>
1517     struct StringMaker<NSObject*> {
convertCatch::StringMaker1518         static std::string convert(NSObject* nsObject) {
1519             return ::Catch::Detail::stringify([nsObject description]);
1520         }
1521 
1522     };
1523     namespace Detail {
stringify(NSString * nsstring)1524         inline std::string stringify( NSString* nsstring ) {
1525             return StringMaker<NSString*>::convert( nsstring );
1526         }
1527 
1528     } // namespace Detail
1529 #endif // __OBJC__
1530 
1531 } // namespace Catch
1532 
1533 //////////////////////////////////////////////////////
1534 // Separate std-lib types stringification, so it can be selectively enabled
1535 // This means that we do not bring in
1536 
1537 #if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
1538 #  define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
1539 #  define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
1540 #  define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
1541 #  define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
1542 #  define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
1543 #endif
1544 
1545 // Separate std::pair specialization
1546 #if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
1547 #include <utility>
1548 namespace Catch {
1549     template<typename T1, typename T2>
1550     struct StringMaker<std::pair<T1, T2> > {
convertCatch::StringMaker1551         static std::string convert(const std::pair<T1, T2>& pair) {
1552             ReusableStringStream rss;
1553             rss << "{ "
1554                 << ::Catch::Detail::stringify(pair.first)
1555                 << ", "
1556                 << ::Catch::Detail::stringify(pair.second)
1557                 << " }";
1558             return rss.str();
1559         }
1560     };
1561 }
1562 #endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
1563 
1564 #if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)
1565 #include <optional>
1566 namespace Catch {
1567     template<typename T>
1568     struct StringMaker<std::optional<T> > {
convertCatch::StringMaker1569         static std::string convert(const std::optional<T>& optional) {
1570             ReusableStringStream rss;
1571             if (optional.has_value()) {
1572                 rss << ::Catch::Detail::stringify(*optional);
1573             } else {
1574                 rss << "{ }";
1575             }
1576             return rss.str();
1577         }
1578     };
1579 }
1580 #endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER
1581 
1582 // Separate std::tuple specialization
1583 #if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
1584 #include <tuple>
1585 namespace Catch {
1586     namespace Detail {
1587         template<
1588             typename Tuple,
1589             std::size_t N = 0,
1590             bool = (N < std::tuple_size<Tuple>::value)
1591             >
1592             struct TupleElementPrinter {
printCatch::Detail::TupleElementPrinter1593             static void print(const Tuple& tuple, std::ostream& os) {
1594                 os << (N ? ", " : " ")
1595                     << ::Catch::Detail::stringify(std::get<N>(tuple));
1596                 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
1597             }
1598         };
1599 
1600         template<
1601             typename Tuple,
1602             std::size_t N
1603         >
1604             struct TupleElementPrinter<Tuple, N, false> {
printCatch::Detail::TupleElementPrinter1605             static void print(const Tuple&, std::ostream&) {}
1606         };
1607 
1608     }
1609 
1610     template<typename ...Types>
1611     struct StringMaker<std::tuple<Types...>> {
convertCatch::StringMaker1612         static std::string convert(const std::tuple<Types...>& tuple) {
1613             ReusableStringStream rss;
1614             rss << '{';
1615             Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
1616             rss << " }";
1617             return rss.str();
1618         }
1619     };
1620 }
1621 #endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
1622 
1623 #if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)
1624 #include <variant>
1625 namespace Catch {
1626     template<>
1627     struct StringMaker<std::monostate> {
convertCatch::StringMaker1628         static std::string convert(const std::monostate&) {
1629             return "{ }";
1630         }
1631     };
1632 
1633     template<typename... Elements>
1634     struct StringMaker<std::variant<Elements...>> {
convertCatch::StringMaker1635         static std::string convert(const std::variant<Elements...>& variant) {
1636             if (variant.valueless_by_exception()) {
1637                 return "{valueless variant}";
1638             } else {
1639                 return std::visit(
1640                     [](const auto& value) {
1641                         return ::Catch::Detail::stringify(value);
1642                     },
1643                     variant
1644                 );
1645             }
1646         }
1647     };
1648 }
1649 #endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER
1650 
1651 namespace Catch {
1652     struct not_this_one {}; // Tag type for detecting which begin/ end are being selected
1653 
1654     // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace
1655     using std::begin;
1656     using std::end;
1657 
1658     not_this_one begin( ... );
1659     not_this_one end( ... );
1660 
1661     template <typename T>
1662     struct is_range {
1663         static const bool value =
1664             !std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value &&
1665             !std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;
1666     };
1667 
1668 #if defined(_MANAGED) // Managed types are never ranges
1669     template <typename T>
1670     struct is_range<T^> {
1671         static const bool value = false;
1672     };
1673 #endif
1674 
1675     template<typename Range>
rangeToString(Range const & range)1676     std::string rangeToString( Range const& range ) {
1677         return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
1678     }
1679 
1680     // Handle vector<bool> specially
1681     template<typename Allocator>
rangeToString(std::vector<bool,Allocator> const & v)1682     std::string rangeToString( std::vector<bool, Allocator> const& v ) {
1683         ReusableStringStream rss;
1684         rss << "{ ";
1685         bool first = true;
1686         for( bool b : v ) {
1687             if( first )
1688                 first = false;
1689             else
1690                 rss << ", ";
1691             rss << ::Catch::Detail::stringify( b );
1692         }
1693         rss << " }";
1694         return rss.str();
1695     }
1696 
1697     template<typename R>
1698     struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
convertCatch::StringMaker1699         static std::string convert( R const& range ) {
1700             return rangeToString( range );
1701         }
1702     };
1703 
1704     template <typename T, int SZ>
1705     struct StringMaker<T[SZ]> {
convertCatch::StringMaker1706         static std::string convert(T const(&arr)[SZ]) {
1707             return rangeToString(arr);
1708         }
1709     };
1710 
1711 } // namespace Catch
1712 
1713 // Separate std::chrono::duration specialization
1714 #if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
1715 #include <ctime>
1716 #include <ratio>
1717 #include <chrono>
1718 
1719 namespace Catch {
1720 
1721 template <class Ratio>
1722 struct ratio_string {
1723     static std::string symbol();
1724 };
1725 
1726 template <class Ratio>
symbol()1727 std::string ratio_string<Ratio>::symbol() {
1728     Catch::ReusableStringStream rss;
1729     rss << '[' << Ratio::num << '/'
1730         << Ratio::den << ']';
1731     return rss.str();
1732 }
1733 template <>
1734 struct ratio_string<std::atto> {
1735     static std::string symbol();
1736 };
1737 template <>
1738 struct ratio_string<std::femto> {
1739     static std::string symbol();
1740 };
1741 template <>
1742 struct ratio_string<std::pico> {
1743     static std::string symbol();
1744 };
1745 template <>
1746 struct ratio_string<std::nano> {
1747     static std::string symbol();
1748 };
1749 template <>
1750 struct ratio_string<std::micro> {
1751     static std::string symbol();
1752 };
1753 template <>
1754 struct ratio_string<std::milli> {
1755     static std::string symbol();
1756 };
1757 
1758     ////////////
1759     // std::chrono::duration specializations
1760     template<typename Value, typename Ratio>
1761     struct StringMaker<std::chrono::duration<Value, Ratio>> {
convertCatch::StringMaker1762         static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
1763             ReusableStringStream rss;
1764             rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
1765             return rss.str();
1766         }
1767     };
1768     template<typename Value>
1769     struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
convertCatch::StringMaker1770         static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
1771             ReusableStringStream rss;
1772             rss << duration.count() << " s";
1773             return rss.str();
1774         }
1775     };
1776     template<typename Value>
1777     struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
convertCatch::StringMaker1778         static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
1779             ReusableStringStream rss;
1780             rss << duration.count() << " m";
1781             return rss.str();
1782         }
1783     };
1784     template<typename Value>
1785     struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
convertCatch::StringMaker1786         static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
1787             ReusableStringStream rss;
1788             rss << duration.count() << " h";
1789             return rss.str();
1790         }
1791     };
1792 
1793     ////////////
1794     // std::chrono::time_point specialization
1795     // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
1796     template<typename Clock, typename Duration>
1797     struct StringMaker<std::chrono::time_point<Clock, Duration>> {
convertCatch::StringMaker1798         static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
1799             return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
1800         }
1801     };
1802     // std::chrono::time_point<system_clock> specialization
1803     template<typename Duration>
1804     struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
convertCatch::StringMaker1805         static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
1806             auto converted = std::chrono::system_clock::to_time_t(time_point);
1807 
1808 #ifdef _MSC_VER
1809             std::tm timeInfo = {};
1810             gmtime_s(&timeInfo, &converted);
1811 #else
1812             std::tm* timeInfo = std::gmtime(&converted);
1813 #endif
1814 
1815             auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
1816             char timeStamp[timeStampSize];
1817             const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
1818 
1819 #ifdef _MSC_VER
1820             std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
1821 #else
1822             std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
1823 #endif
1824             return std::string(timeStamp);
1825         }
1826     };
1827 }
1828 #endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
1829 
1830 #ifdef _MSC_VER
1831 #pragma warning(pop)
1832 #endif
1833 
1834 // end catch_tostring.h
1835 #include <iosfwd>
1836 
1837 #ifdef _MSC_VER
1838 #pragma warning(push)
1839 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1840 #pragma warning(disable:4018) // more "signed/unsigned mismatch"
1841 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
1842 #pragma warning(disable:4180) // qualifier applied to function type has no meaning
1843 #pragma warning(disable:4800) // Forcing result to true or false
1844 #endif
1845 
1846 namespace Catch {
1847 
1848     struct ITransientExpression {
isBinaryExpressionCatch::ITransientExpression1849         auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
getResultCatch::ITransientExpression1850         auto getResult() const -> bool { return m_result; }
1851         virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
1852 
ITransientExpressionCatch::ITransientExpression1853         ITransientExpression( bool isBinaryExpression, bool result )
1854         :   m_isBinaryExpression( isBinaryExpression ),
1855             m_result( result )
1856         {}
1857 
1858         // We don't actually need a virtual destructor, but many static analysers
1859         // complain if it's not here :-(
1860         virtual ~ITransientExpression();
1861 
1862         bool m_isBinaryExpression;
1863         bool m_result;
1864 
1865     };
1866 
1867     void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
1868 
1869     template<typename LhsT, typename RhsT>
1870     class BinaryExpr  : public ITransientExpression {
1871         LhsT m_lhs;
1872         StringRef m_op;
1873         RhsT m_rhs;
1874 
streamReconstructedExpression(std::ostream & os) const1875         void streamReconstructedExpression( std::ostream &os ) const override {
1876             formatReconstructedExpression
1877                     ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
1878         }
1879 
1880     public:
BinaryExpr(bool comparisonResult,LhsT lhs,StringRef op,RhsT rhs)1881         BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
1882         :   ITransientExpression{ true, comparisonResult },
1883             m_lhs( lhs ),
1884             m_op( op ),
1885             m_rhs( rhs )
1886         {}
1887 
1888         template<typename T>
operator &&(T) const1889         auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
1890             static_assert(always_false<T>::value,
1891             "chained comparisons are not supported inside assertions, "
1892             "wrap the expression inside parentheses, or decompose it");
1893         }
1894 
1895         template<typename T>
operator ||(T) const1896         auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
1897             static_assert(always_false<T>::value,
1898             "chained comparisons are not supported inside assertions, "
1899             "wrap the expression inside parentheses, or decompose it");
1900         }
1901 
1902         template<typename T>
operator ==(T) const1903         auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
1904             static_assert(always_false<T>::value,
1905             "chained comparisons are not supported inside assertions, "
1906             "wrap the expression inside parentheses, or decompose it");
1907         }
1908 
1909         template<typename T>
operator !=(T) const1910         auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
1911             static_assert(always_false<T>::value,
1912             "chained comparisons are not supported inside assertions, "
1913             "wrap the expression inside parentheses, or decompose it");
1914         }
1915 
1916         template<typename T>
operator >(T) const1917         auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
1918             static_assert(always_false<T>::value,
1919             "chained comparisons are not supported inside assertions, "
1920             "wrap the expression inside parentheses, or decompose it");
1921         }
1922 
1923         template<typename T>
operator <(T) const1924         auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
1925             static_assert(always_false<T>::value,
1926             "chained comparisons are not supported inside assertions, "
1927             "wrap the expression inside parentheses, or decompose it");
1928         }
1929 
1930         template<typename T>
operator >=(T) const1931         auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
1932             static_assert(always_false<T>::value,
1933             "chained comparisons are not supported inside assertions, "
1934             "wrap the expression inside parentheses, or decompose it");
1935         }
1936 
1937         template<typename T>
operator <=(T) const1938         auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {
1939             static_assert(always_false<T>::value,
1940             "chained comparisons are not supported inside assertions, "
1941             "wrap the expression inside parentheses, or decompose it");
1942         }
1943     };
1944 
1945     template<typename LhsT>
1946     class UnaryExpr : public ITransientExpression {
1947         LhsT m_lhs;
1948 
streamReconstructedExpression(std::ostream & os) const1949         void streamReconstructedExpression( std::ostream &os ) const override {
1950             os << Catch::Detail::stringify( m_lhs );
1951         }
1952 
1953     public:
UnaryExpr(LhsT lhs)1954         explicit UnaryExpr( LhsT lhs )
1955         :   ITransientExpression{ false, static_cast<bool>(lhs) },
1956             m_lhs( lhs )
1957         {}
1958     };
1959 
1960     // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
1961     template<typename LhsT, typename RhsT>
compareEqual(LhsT const & lhs,RhsT const & rhs)1962     auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }
1963     template<typename T>
compareEqual(T * const & lhs,int rhs)1964     auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
1965     template<typename T>
compareEqual(T * const & lhs,long rhs)1966     auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
1967     template<typename T>
compareEqual(int lhs,T * const & rhs)1968     auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
1969     template<typename T>
compareEqual(long lhs,T * const & rhs)1970     auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
1971 
1972     template<typename LhsT, typename RhsT>
compareNotEqual(LhsT const & lhs,RhsT && rhs)1973     auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }
1974     template<typename T>
compareNotEqual(T * const & lhs,int rhs)1975     auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
1976     template<typename T>
compareNotEqual(T * const & lhs,long rhs)1977     auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
1978     template<typename T>
compareNotEqual(int lhs,T * const & rhs)1979     auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
1980     template<typename T>
compareNotEqual(long lhs,T * const & rhs)1981     auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
1982 
1983     template<typename LhsT>
1984     class ExprLhs {
1985         LhsT m_lhs;
1986     public:
ExprLhs(LhsT lhs)1987         explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
1988 
1989         template<typename RhsT>
operator ==(RhsT const & rhs)1990         auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
1991             return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs };
1992         }
operator ==(bool rhs)1993         auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
1994             return { m_lhs == rhs, m_lhs, "==", rhs };
1995         }
1996 
1997         template<typename RhsT>
operator !=(RhsT const & rhs)1998         auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
1999             return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs };
2000         }
operator !=(bool rhs)2001         auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
2002             return { m_lhs != rhs, m_lhs, "!=", rhs };
2003         }
2004 
2005         template<typename RhsT>
operator >(RhsT const & rhs)2006         auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2007             return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };
2008         }
2009         template<typename RhsT>
operator <(RhsT const & rhs)2010         auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2011             return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };
2012         }
2013         template<typename RhsT>
operator >=(RhsT const & rhs)2014         auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2015             return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };
2016         }
2017         template<typename RhsT>
operator <=(RhsT const & rhs)2018         auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
2019             return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
2020         }
2021 
2022         template<typename RhsT>
operator &&(RhsT const &)2023         auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
2024             static_assert(always_false<RhsT>::value,
2025             "operator&& is not supported inside assertions, "
2026             "wrap the expression inside parentheses, or decompose it");
2027         }
2028 
2029         template<typename RhsT>
operator ||(RhsT const &)2030         auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {
2031             static_assert(always_false<RhsT>::value,
2032             "operator|| is not supported inside assertions, "
2033             "wrap the expression inside parentheses, or decompose it");
2034         }
2035 
makeUnaryExpr() const2036         auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
2037             return UnaryExpr<LhsT>{ m_lhs };
2038         }
2039     };
2040 
2041     void handleExpression( ITransientExpression const& expr );
2042 
2043     template<typename T>
handleExpression(ExprLhs<T> const & expr)2044     void handleExpression( ExprLhs<T> const& expr ) {
2045         handleExpression( expr.makeUnaryExpr() );
2046     }
2047 
2048     struct Decomposer {
2049         template<typename T>
operator <=Catch::Decomposer2050         auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
2051             return ExprLhs<T const&>{ lhs };
2052         }
2053 
operator <=Catch::Decomposer2054         auto operator <=( bool value ) -> ExprLhs<bool> {
2055             return ExprLhs<bool>{ value };
2056         }
2057     };
2058 
2059 } // end namespace Catch
2060 
2061 #ifdef _MSC_VER
2062 #pragma warning(pop)
2063 #endif
2064 
2065 // end catch_decomposer.h
2066 // start catch_interfaces_capture.h
2067 
2068 #include <string>
2069 
2070 namespace Catch {
2071 
2072     class AssertionResult;
2073     struct AssertionInfo;
2074     struct SectionInfo;
2075     struct SectionEndInfo;
2076     struct MessageInfo;
2077     struct MessageBuilder;
2078     struct Counts;
2079     struct BenchmarkInfo;
2080     struct BenchmarkStats;
2081     struct AssertionReaction;
2082     struct SourceLineInfo;
2083 
2084     struct ITransientExpression;
2085     struct IGeneratorTracker;
2086 
2087     struct IResultCapture {
2088 
2089         virtual ~IResultCapture();
2090 
2091         virtual bool sectionStarted(    SectionInfo const& sectionInfo,
2092                                         Counts& assertions ) = 0;
2093         virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
2094         virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
2095 
2096         virtual auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;
2097 
2098         virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
2099         virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0;
2100 
2101         virtual void pushScopedMessage( MessageInfo const& message ) = 0;
2102         virtual void popScopedMessage( MessageInfo const& message ) = 0;
2103 
2104         virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;
2105 
2106         virtual void handleFatalErrorCondition( StringRef message ) = 0;
2107 
2108         virtual void handleExpr
2109                 (   AssertionInfo const& info,
2110                     ITransientExpression const& expr,
2111                     AssertionReaction& reaction ) = 0;
2112         virtual void handleMessage
2113                 (   AssertionInfo const& info,
2114                     ResultWas::OfType resultType,
2115                     StringRef const& message,
2116                     AssertionReaction& reaction ) = 0;
2117         virtual void handleUnexpectedExceptionNotThrown
2118                 (   AssertionInfo const& info,
2119                     AssertionReaction& reaction ) = 0;
2120         virtual void handleUnexpectedInflightException
2121                 (   AssertionInfo const& info,
2122                     std::string const& message,
2123                     AssertionReaction& reaction ) = 0;
2124         virtual void handleIncomplete
2125                 (   AssertionInfo const& info ) = 0;
2126         virtual void handleNonExpr
2127                 (   AssertionInfo const &info,
2128                     ResultWas::OfType resultType,
2129                     AssertionReaction &reaction ) = 0;
2130 
2131         virtual bool lastAssertionPassed() = 0;
2132         virtual void assertionPassed() = 0;
2133 
2134         // Deprecated, do not use:
2135         virtual std::string getCurrentTestName() const = 0;
2136         virtual const AssertionResult* getLastResult() const = 0;
2137         virtual void exceptionEarlyReported() = 0;
2138     };
2139 
2140     IResultCapture& getResultCapture();
2141 }
2142 
2143 // end catch_interfaces_capture.h
2144 namespace Catch {
2145 
2146     struct TestFailureException{};
2147     struct AssertionResultData;
2148     struct IResultCapture;
2149     class RunContext;
2150 
2151     class LazyExpression {
2152         friend class AssertionHandler;
2153         friend struct AssertionStats;
2154         friend class RunContext;
2155 
2156         ITransientExpression const* m_transientExpression = nullptr;
2157         bool m_isNegated;
2158     public:
2159         LazyExpression( bool isNegated );
2160         LazyExpression( LazyExpression const& other );
2161         LazyExpression& operator = ( LazyExpression const& ) = delete;
2162 
2163         explicit operator bool() const;
2164 
2165         friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
2166     };
2167 
2168     struct AssertionReaction {
2169         bool shouldDebugBreak = false;
2170         bool shouldThrow = false;
2171     };
2172 
2173     class AssertionHandler {
2174         AssertionInfo m_assertionInfo;
2175         AssertionReaction m_reaction;
2176         bool m_completed = false;
2177         IResultCapture& m_resultCapture;
2178 
2179     public:
2180         AssertionHandler
2181             (   StringRef const& macroName,
2182                 SourceLineInfo const& lineInfo,
2183                 StringRef capturedExpression,
2184                 ResultDisposition::Flags resultDisposition );
~AssertionHandler()2185         ~AssertionHandler() {
2186             if ( !m_completed ) {
2187                 m_resultCapture.handleIncomplete( m_assertionInfo );
2188             }
2189         }
2190 
2191         template<typename T>
handleExpr(ExprLhs<T> const & expr)2192         void handleExpr( ExprLhs<T> const& expr ) {
2193             handleExpr( expr.makeUnaryExpr() );
2194         }
2195         void handleExpr( ITransientExpression const& expr );
2196 
2197         void handleMessage(ResultWas::OfType resultType, StringRef const& message);
2198 
2199         void handleExceptionThrownAsExpected();
2200         void handleUnexpectedExceptionNotThrown();
2201         void handleExceptionNotThrownAsExpected();
2202         void handleThrowingCallSkipped();
2203         void handleUnexpectedInflightException();
2204 
2205         void complete();
2206         void setCompleted();
2207 
2208         // query
2209         auto allowThrows() const -> bool;
2210     };
2211 
2212     void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString );
2213 
2214 } // namespace Catch
2215 
2216 // end catch_assertionhandler.h
2217 // start catch_message.h
2218 
2219 #include <string>
2220 #include <vector>
2221 
2222 namespace Catch {
2223 
2224     struct MessageInfo {
2225         MessageInfo(    StringRef const& _macroName,
2226                         SourceLineInfo const& _lineInfo,
2227                         ResultWas::OfType _type );
2228 
2229         StringRef macroName;
2230         std::string message;
2231         SourceLineInfo lineInfo;
2232         ResultWas::OfType type;
2233         unsigned int sequence;
2234 
2235         bool operator == ( MessageInfo const& other ) const;
2236         bool operator < ( MessageInfo const& other ) const;
2237     private:
2238         static unsigned int globalCount;
2239     };
2240 
2241     struct MessageStream {
2242 
2243         template<typename T>
operator <<Catch::MessageStream2244         MessageStream& operator << ( T const& value ) {
2245             m_stream << value;
2246             return *this;
2247         }
2248 
2249         ReusableStringStream m_stream;
2250     };
2251 
2252     struct MessageBuilder : MessageStream {
2253         MessageBuilder( StringRef const& macroName,
2254                         SourceLineInfo const& lineInfo,
2255                         ResultWas::OfType type );
2256 
2257         template<typename T>
operator <<Catch::MessageBuilder2258         MessageBuilder& operator << ( T const& value ) {
2259             m_stream << value;
2260             return *this;
2261         }
2262 
2263         MessageInfo m_info;
2264     };
2265 
2266     class ScopedMessage {
2267     public:
2268         explicit ScopedMessage( MessageBuilder const& builder );
2269         ScopedMessage( ScopedMessage& duplicate ) = delete;
2270         ScopedMessage( ScopedMessage&& old );
2271         ~ScopedMessage();
2272 
2273         MessageInfo m_info;
2274         bool m_moved;
2275     };
2276 
2277     class Capturer {
2278         std::vector<MessageInfo> m_messages;
2279         IResultCapture& m_resultCapture = getResultCapture();
2280         size_t m_captured = 0;
2281     public:
2282         Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );
2283         ~Capturer();
2284 
2285         void captureValue( size_t index, std::string const& value );
2286 
2287         template<typename T>
captureValues(size_t index,T const & value)2288         void captureValues( size_t index, T const& value ) {
2289             captureValue( index, Catch::Detail::stringify( value ) );
2290         }
2291 
2292         template<typename T, typename... Ts>
captureValues(size_t index,T const & value,Ts const &...values)2293         void captureValues( size_t index, T const& value, Ts const&... values ) {
2294             captureValue( index, Catch::Detail::stringify(value) );
2295             captureValues( index+1, values... );
2296         }
2297     };
2298 
2299 } // end namespace Catch
2300 
2301 // end catch_message.h
2302 #if !defined(CATCH_CONFIG_DISABLE)
2303 
2304 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
2305   #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
2306 #else
2307   #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
2308 #endif
2309 
2310 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
2311 
2312 ///////////////////////////////////////////////////////////////////////////////
2313 // Another way to speed-up compilation is to omit local try-catch for REQUIRE*
2314 // macros.
2315 #define INTERNAL_CATCH_TRY
2316 #define INTERNAL_CATCH_CATCH( capturer )
2317 
2318 #else // CATCH_CONFIG_FAST_COMPILE
2319 
2320 #define INTERNAL_CATCH_TRY try
2321 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
2322 
2323 #endif
2324 
2325 #define INTERNAL_CATCH_REACT( handler ) handler.complete();
2326 
2327 ///////////////////////////////////////////////////////////////////////////////
2328 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
2329     do { \
2330         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
2331         INTERNAL_CATCH_TRY { \
2332             CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2333             catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
2334             CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
2335         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
2336         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2337     } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
2338     // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
2339 
2340 ///////////////////////////////////////////////////////////////////////////////
2341 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
2342     INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
2343     if( Catch::getResultCapture().lastAssertionPassed() )
2344 
2345 ///////////////////////////////////////////////////////////////////////////////
2346 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
2347     INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
2348     if( !Catch::getResultCapture().lastAssertionPassed() )
2349 
2350 ///////////////////////////////////////////////////////////////////////////////
2351 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
2352     do { \
2353         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
2354         try { \
2355             static_cast<void>(__VA_ARGS__); \
2356             catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
2357         } \
2358         catch( ... ) { \
2359             catchAssertionHandler.handleUnexpectedInflightException(); \
2360         } \
2361         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2362     } while( false )
2363 
2364 ///////////////////////////////////////////////////////////////////////////////
2365 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
2366     do { \
2367         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
2368         if( catchAssertionHandler.allowThrows() ) \
2369             try { \
2370                 static_cast<void>(__VA_ARGS__); \
2371                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2372             } \
2373             catch( ... ) { \
2374                 catchAssertionHandler.handleExceptionThrownAsExpected(); \
2375             } \
2376         else \
2377             catchAssertionHandler.handleThrowingCallSkipped(); \
2378         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2379     } while( false )
2380 
2381 ///////////////////////////////////////////////////////////////////////////////
2382 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
2383     do { \
2384         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
2385         if( catchAssertionHandler.allowThrows() ) \
2386             try { \
2387                 static_cast<void>(expr); \
2388                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2389             } \
2390             catch( exceptionType const& ) { \
2391                 catchAssertionHandler.handleExceptionThrownAsExpected(); \
2392             } \
2393             catch( ... ) { \
2394                 catchAssertionHandler.handleUnexpectedInflightException(); \
2395             } \
2396         else \
2397             catchAssertionHandler.handleThrowingCallSkipped(); \
2398         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2399     } while( false )
2400 
2401 ///////////////////////////////////////////////////////////////////////////////
2402 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
2403     do { \
2404         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
2405         catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
2406         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2407     } while( false )
2408 
2409 ///////////////////////////////////////////////////////////////////////////////
2410 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
2411     auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
2412     varName.captureValues( 0, __VA_ARGS__ )
2413 
2414 ///////////////////////////////////////////////////////////////////////////////
2415 #define INTERNAL_CATCH_INFO( macroName, log ) \
2416     Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
2417 
2418 ///////////////////////////////////////////////////////////////////////////////
2419 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
2420     Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
2421 
2422 ///////////////////////////////////////////////////////////////////////////////
2423 // Although this is matcher-based, it can be used with just a string
2424 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
2425     do { \
2426         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
2427         if( catchAssertionHandler.allowThrows() ) \
2428             try { \
2429                 static_cast<void>(__VA_ARGS__); \
2430                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2431             } \
2432             catch( ... ) { \
2433                 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \
2434             } \
2435         else \
2436             catchAssertionHandler.handleThrowingCallSkipped(); \
2437         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2438     } while( false )
2439 
2440 #endif // CATCH_CONFIG_DISABLE
2441 
2442 // end catch_capture.hpp
2443 // start catch_section.h
2444 
2445 // start catch_section_info.h
2446 
2447 // start catch_totals.h
2448 
2449 #include <cstddef>
2450 
2451 namespace Catch {
2452 
2453     struct Counts {
2454         Counts operator - ( Counts const& other ) const;
2455         Counts& operator += ( Counts const& other );
2456 
2457         std::size_t total() const;
2458         bool allPassed() const;
2459         bool allOk() const;
2460 
2461         std::size_t passed = 0;
2462         std::size_t failed = 0;
2463         std::size_t failedButOk = 0;
2464     };
2465 
2466     struct Totals {
2467 
2468         Totals operator - ( Totals const& other ) const;
2469         Totals& operator += ( Totals const& other );
2470 
2471         Totals delta( Totals const& prevTotals ) const;
2472 
2473         int error = 0;
2474         Counts assertions;
2475         Counts testCases;
2476     };
2477 }
2478 
2479 // end catch_totals.h
2480 #include <string>
2481 
2482 namespace Catch {
2483 
2484     struct SectionInfo {
2485         SectionInfo
2486             (   SourceLineInfo const& _lineInfo,
2487                 std::string const& _name );
2488 
2489         // Deprecated
SectionInfoCatch::SectionInfo2490         SectionInfo
2491             (   SourceLineInfo const& _lineInfo,
2492                 std::string const& _name,
2493                 std::string const& ) : SectionInfo( _lineInfo, _name ) {}
2494 
2495         std::string name;
2496         std::string description; // !Deprecated: this will always be empty
2497         SourceLineInfo lineInfo;
2498     };
2499 
2500     struct SectionEndInfo {
2501         SectionInfo sectionInfo;
2502         Counts prevAssertions;
2503         double durationInSeconds;
2504     };
2505 
2506 } // end namespace Catch
2507 
2508 // end catch_section_info.h
2509 // start catch_timer.h
2510 
2511 #include <cstdint>
2512 
2513 namespace Catch {
2514 
2515     auto getCurrentNanosecondsSinceEpoch() -> uint64_t;
2516     auto getEstimatedClockResolution() -> uint64_t;
2517 
2518     class Timer {
2519         uint64_t m_nanoseconds = 0;
2520     public:
2521         void start();
2522         auto getElapsedNanoseconds() const -> uint64_t;
2523         auto getElapsedMicroseconds() const -> uint64_t;
2524         auto getElapsedMilliseconds() const -> unsigned int;
2525         auto getElapsedSeconds() const -> double;
2526     };
2527 
2528 } // namespace Catch
2529 
2530 // end catch_timer.h
2531 #include <string>
2532 
2533 namespace Catch {
2534 
2535     class Section : NonCopyable {
2536     public:
2537         Section( SectionInfo const& info );
2538         ~Section();
2539 
2540         // This indicates whether the section should be executed or not
2541         explicit operator bool() const;
2542 
2543     private:
2544         SectionInfo m_info;
2545 
2546         std::string m_name;
2547         Counts m_assertions;
2548         bool m_sectionIncluded;
2549         Timer m_timer;
2550     };
2551 
2552 } // end namespace Catch
2553 
2554 #define INTERNAL_CATCH_SECTION( ... ) \
2555     CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
2556     if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \
2557     CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
2558 
2559 #define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \
2560     CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \
2561     if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \
2562     CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS
2563 
2564 // end catch_section.h
2565 // start catch_benchmark.h
2566 
2567 #include <cstdint>
2568 #include <string>
2569 
2570 namespace Catch {
2571 
2572     class BenchmarkLooper {
2573 
2574         std::string m_name;
2575         std::size_t m_count = 0;
2576         std::size_t m_iterationsToRun = 1;
2577         uint64_t m_resolution;
2578         Timer m_timer;
2579 
2580         static auto getResolution() -> uint64_t;
2581     public:
2582         // Keep most of this inline as it's on the code path that is being timed
BenchmarkLooper(StringRef name)2583         BenchmarkLooper( StringRef name )
2584         :   m_name( name ),
2585             m_resolution( getResolution() )
2586         {
2587             reportStart();
2588             m_timer.start();
2589         }
2590 
operator bool()2591         explicit operator bool() {
2592             if( m_count < m_iterationsToRun )
2593                 return true;
2594             return needsMoreIterations();
2595         }
2596 
increment()2597         void increment() {
2598             ++m_count;
2599         }
2600 
2601         void reportStart();
2602         auto needsMoreIterations() -> bool;
2603     };
2604 
2605 } // end namespace Catch
2606 
2607 #define BENCHMARK( name ) \
2608     for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() )
2609 
2610 // end catch_benchmark.h
2611 // start catch_interfaces_exception.h
2612 
2613 // start catch_interfaces_registry_hub.h
2614 
2615 #include <string>
2616 #include <memory>
2617 
2618 namespace Catch {
2619 
2620     class TestCase;
2621     struct ITestCaseRegistry;
2622     struct IExceptionTranslatorRegistry;
2623     struct IExceptionTranslator;
2624     struct IReporterRegistry;
2625     struct IReporterFactory;
2626     struct ITagAliasRegistry;
2627     class StartupExceptionRegistry;
2628 
2629     using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
2630 
2631     struct IRegistryHub {
2632         virtual ~IRegistryHub();
2633 
2634         virtual IReporterRegistry const& getReporterRegistry() const = 0;
2635         virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2636         virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
2637 
2638         virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;
2639 
2640         virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
2641     };
2642 
2643     struct IMutableRegistryHub {
2644         virtual ~IMutableRegistryHub();
2645         virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;
2646         virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;
2647         virtual void registerTest( TestCase const& testInfo ) = 0;
2648         virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2649         virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
2650         virtual void registerStartupException() noexcept = 0;
2651     };
2652 
2653     IRegistryHub const& getRegistryHub();
2654     IMutableRegistryHub& getMutableRegistryHub();
2655     void cleanUp();
2656     std::string translateActiveException();
2657 
2658 }
2659 
2660 // end catch_interfaces_registry_hub.h
2661 #if defined(CATCH_CONFIG_DISABLE)
2662     #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
2663         static std::string translatorName( signature )
2664 #endif
2665 
2666 #include <exception>
2667 #include <string>
2668 #include <vector>
2669 
2670 namespace Catch {
2671     using exceptionTranslateFunction = std::string(*)();
2672 
2673     struct IExceptionTranslator;
2674     using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;
2675 
2676     struct IExceptionTranslator {
2677         virtual ~IExceptionTranslator();
2678         virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
2679     };
2680 
2681     struct IExceptionTranslatorRegistry {
2682         virtual ~IExceptionTranslatorRegistry();
2683 
2684         virtual std::string translateActiveException() const = 0;
2685     };
2686 
2687     class ExceptionTranslatorRegistrar {
2688         template<typename T>
2689         class ExceptionTranslator : public IExceptionTranslator {
2690         public:
2691 
ExceptionTranslator(std::string (* translateFunction)(T &))2692             ExceptionTranslator( std::string(*translateFunction)( T& ) )
2693             : m_translateFunction( translateFunction )
2694             {}
2695 
translate(ExceptionTranslators::const_iterator it,ExceptionTranslators::const_iterator itEnd) const2696             std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
2697                 try {
2698                     if( it == itEnd )
2699                         std::rethrow_exception(std::current_exception());
2700                     else
2701                         return (*it)->translate( it+1, itEnd );
2702                 }
2703                 catch( T& ex ) {
2704                     return m_translateFunction( ex );
2705                 }
2706             }
2707 
2708         protected:
2709             std::string(*m_translateFunction)( T& );
2710         };
2711 
2712     public:
2713         template<typename T>
ExceptionTranslatorRegistrar(std::string (* translateFunction)(T &))2714         ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
2715             getMutableRegistryHub().registerTranslator
2716                 ( new ExceptionTranslator<T>( translateFunction ) );
2717         }
2718     };
2719 }
2720 
2721 ///////////////////////////////////////////////////////////////////////////////
2722 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2723     static std::string translatorName( signature ); \
2724     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
2725     namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
2726     CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
2727     static std::string translatorName( signature )
2728 
2729 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
2730 
2731 // end catch_interfaces_exception.h
2732 // start catch_approx.h
2733 
2734 #include <type_traits>
2735 
2736 namespace Catch {
2737 namespace Detail {
2738 
2739     class Approx {
2740     private:
2741         bool equalityComparisonImpl(double other) const;
2742         // Validates the new margin (margin >= 0)
2743         // out-of-line to avoid including stdexcept in the header
2744         void setMargin(double margin);
2745         // Validates the new epsilon (0 < epsilon < 1)
2746         // out-of-line to avoid including stdexcept in the header
2747         void setEpsilon(double epsilon);
2748 
2749     public:
2750         explicit Approx ( double value );
2751 
2752         static Approx custom();
2753 
2754         Approx operator-() const;
2755 
2756         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator ()(T const & value)2757         Approx operator()( T const& value ) {
2758             Approx approx( static_cast<double>(value) );
2759             approx.m_epsilon = m_epsilon;
2760             approx.m_margin = m_margin;
2761             approx.m_scale = m_scale;
2762             return approx;
2763         }
2764 
2765         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Approx(T const & value)2766         explicit Approx( T const& value ): Approx(static_cast<double>(value))
2767         {}
2768 
2769         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator ==(const T & lhs,Approx const & rhs)2770         friend bool operator == ( const T& lhs, Approx const& rhs ) {
2771             auto lhs_v = static_cast<double>(lhs);
2772             return rhs.equalityComparisonImpl(lhs_v);
2773         }
2774 
2775         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator ==(Approx const & lhs,const T & rhs)2776         friend bool operator == ( Approx const& lhs, const T& rhs ) {
2777             return operator==( rhs, lhs );
2778         }
2779 
2780         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator !=(T const & lhs,Approx const & rhs)2781         friend bool operator != ( T const& lhs, Approx const& rhs ) {
2782             return !operator==( lhs, rhs );
2783         }
2784 
2785         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator !=(Approx const & lhs,T const & rhs)2786         friend bool operator != ( Approx const& lhs, T const& rhs ) {
2787             return !operator==( rhs, lhs );
2788         }
2789 
2790         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator <=(T const & lhs,Approx const & rhs)2791         friend bool operator <= ( T const& lhs, Approx const& rhs ) {
2792             return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
2793         }
2794 
2795         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator <=(Approx const & lhs,T const & rhs)2796         friend bool operator <= ( Approx const& lhs, T const& rhs ) {
2797             return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
2798         }
2799 
2800         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator >=(T const & lhs,Approx const & rhs)2801         friend bool operator >= ( T const& lhs, Approx const& rhs ) {
2802             return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
2803         }
2804 
2805         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
operator >=(Approx const & lhs,T const & rhs)2806         friend bool operator >= ( Approx const& lhs, T const& rhs ) {
2807             return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
2808         }
2809 
2810         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
epsilon(T const & newEpsilon)2811         Approx& epsilon( T const& newEpsilon ) {
2812             double epsilonAsDouble = static_cast<double>(newEpsilon);
2813             setEpsilon(epsilonAsDouble);
2814             return *this;
2815         }
2816 
2817         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
margin(T const & newMargin)2818         Approx& margin( T const& newMargin ) {
2819             double marginAsDouble = static_cast<double>(newMargin);
2820             setMargin(marginAsDouble);
2821             return *this;
2822         }
2823 
2824         template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
scale(T const & newScale)2825         Approx& scale( T const& newScale ) {
2826             m_scale = static_cast<double>(newScale);
2827             return *this;
2828         }
2829 
2830         std::string toString() const;
2831 
2832     private:
2833         double m_epsilon;
2834         double m_margin;
2835         double m_scale;
2836         double m_value;
2837     };
2838 } // end namespace Detail
2839 
2840 namespace literals {
2841     Detail::Approx operator "" _a(long double val);
2842     Detail::Approx operator "" _a(unsigned long long val);
2843 } // end namespace literals
2844 
2845 template<>
2846 struct StringMaker<Catch::Detail::Approx> {
2847     static std::string convert(Catch::Detail::Approx const& value);
2848 };
2849 
2850 } // end namespace Catch
2851 
2852 // end catch_approx.h
2853 // start catch_string_manip.h
2854 
2855 #include <string>
2856 #include <iosfwd>
2857 
2858 namespace Catch {
2859 
2860     bool startsWith( std::string const& s, std::string const& prefix );
2861     bool startsWith( std::string const& s, char prefix );
2862     bool endsWith( std::string const& s, std::string const& suffix );
2863     bool endsWith( std::string const& s, char suffix );
2864     bool contains( std::string const& s, std::string const& infix );
2865     void toLowerInPlace( std::string& s );
2866     std::string toLower( std::string const& s );
2867     std::string trim( std::string const& str );
2868     bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
2869 
2870     struct pluralise {
2871         pluralise( std::size_t count, std::string const& label );
2872 
2873         friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
2874 
2875         std::size_t m_count;
2876         std::string m_label;
2877     };
2878 }
2879 
2880 // end catch_string_manip.h
2881 #ifndef CATCH_CONFIG_DISABLE_MATCHERS
2882 // start catch_capture_matchers.h
2883 
2884 // start catch_matchers.h
2885 
2886 #include <string>
2887 #include <vector>
2888 
2889 namespace Catch {
2890 namespace Matchers {
2891     namespace Impl {
2892 
2893         template<typename ArgT> struct MatchAllOf;
2894         template<typename ArgT> struct MatchAnyOf;
2895         template<typename ArgT> struct MatchNotOf;
2896 
2897         class MatcherUntypedBase {
2898         public:
2899             MatcherUntypedBase() = default;
2900             MatcherUntypedBase ( MatcherUntypedBase const& ) = default;
2901             MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;
2902             std::string toString() const;
2903 
2904         protected:
2905             virtual ~MatcherUntypedBase();
2906             virtual std::string describe() const = 0;
2907             mutable std::string m_cachedToString;
2908         };
2909 
2910 #ifdef __clang__
2911 #    pragma clang diagnostic push
2912 #    pragma clang diagnostic ignored "-Wnon-virtual-dtor"
2913 #endif
2914 
2915         template<typename ObjectT>
2916         struct MatcherMethod {
2917             virtual bool match( ObjectT const& arg ) const = 0;
2918         };
2919 
2920 #ifdef __clang__
2921 #    pragma clang diagnostic pop
2922 #endif
2923 
2924         template<typename T>
2925         struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {
2926 
2927             MatchAllOf<T> operator && ( MatcherBase const& other ) const;
2928             MatchAnyOf<T> operator || ( MatcherBase const& other ) const;
2929             MatchNotOf<T> operator ! () const;
2930         };
2931 
2932         template<typename ArgT>
2933         struct MatchAllOf : MatcherBase<ArgT> {
matchCatch::Matchers::Impl::MatchAllOf2934             bool match( ArgT const& arg ) const override {
2935                 for( auto matcher : m_matchers ) {
2936                     if (!matcher->match(arg))
2937                         return false;
2938                 }
2939                 return true;
2940             }
describeCatch::Matchers::Impl::MatchAllOf2941             std::string describe() const override {
2942                 std::string description;
2943                 description.reserve( 4 + m_matchers.size()*32 );
2944                 description += "( ";
2945                 bool first = true;
2946                 for( auto matcher : m_matchers ) {
2947                     if( first )
2948                         first = false;
2949                     else
2950                         description += " and ";
2951                     description += matcher->toString();
2952                 }
2953                 description += " )";
2954                 return description;
2955             }
2956 
operator &&Catch::Matchers::Impl::MatchAllOf2957             MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
2958                 m_matchers.push_back( &other );
2959                 return *this;
2960             }
2961 
2962             std::vector<MatcherBase<ArgT> const*> m_matchers;
2963         };
2964         template<typename ArgT>
2965         struct MatchAnyOf : MatcherBase<ArgT> {
2966 
matchCatch::Matchers::Impl::MatchAnyOf2967             bool match( ArgT const& arg ) const override {
2968                 for( auto matcher : m_matchers ) {
2969                     if (matcher->match(arg))
2970                         return true;
2971                 }
2972                 return false;
2973             }
describeCatch::Matchers::Impl::MatchAnyOf2974             std::string describe() const override {
2975                 std::string description;
2976                 description.reserve( 4 + m_matchers.size()*32 );
2977                 description += "( ";
2978                 bool first = true;
2979                 for( auto matcher : m_matchers ) {
2980                     if( first )
2981                         first = false;
2982                     else
2983                         description += " or ";
2984                     description += matcher->toString();
2985                 }
2986                 description += " )";
2987                 return description;
2988             }
2989 
operator ||Catch::Matchers::Impl::MatchAnyOf2990             MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
2991                 m_matchers.push_back( &other );
2992                 return *this;
2993             }
2994 
2995             std::vector<MatcherBase<ArgT> const*> m_matchers;
2996         };
2997 
2998         template<typename ArgT>
2999         struct MatchNotOf : MatcherBase<ArgT> {
3000 
MatchNotOfCatch::Matchers::Impl::MatchNotOf3001             MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
3002 
matchCatch::Matchers::Impl::MatchNotOf3003             bool match( ArgT const& arg ) const override {
3004                 return !m_underlyingMatcher.match( arg );
3005             }
3006 
describeCatch::Matchers::Impl::MatchNotOf3007             std::string describe() const override {
3008                 return "not " + m_underlyingMatcher.toString();
3009             }
3010             MatcherBase<ArgT> const& m_underlyingMatcher;
3011         };
3012 
3013         template<typename T>
operator &&(MatcherBase const & other) const3014         MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const {
3015             return MatchAllOf<T>() && *this && other;
3016         }
3017         template<typename T>
operator ||(MatcherBase const & other) const3018         MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const {
3019             return MatchAnyOf<T>() || *this || other;
3020         }
3021         template<typename T>
operator !() const3022         MatchNotOf<T> MatcherBase<T>::operator ! () const {
3023             return MatchNotOf<T>( *this );
3024         }
3025 
3026     } // namespace Impl
3027 
3028 } // namespace Matchers
3029 
3030 using namespace Matchers;
3031 using Matchers::Impl::MatcherBase;
3032 
3033 } // namespace Catch
3034 
3035 // end catch_matchers.h
3036 // start catch_matchers_floating.h
3037 
3038 #include <type_traits>
3039 #include <cmath>
3040 
3041 namespace Catch {
3042 namespace Matchers {
3043 
3044     namespace Floating {
3045 
3046         enum class FloatingPointKind : uint8_t;
3047 
3048         struct WithinAbsMatcher : MatcherBase<double> {
3049             WithinAbsMatcher(double target, double margin);
3050             bool match(double const& matchee) const override;
3051             std::string describe() const override;
3052         private:
3053             double m_target;
3054             double m_margin;
3055         };
3056 
3057         struct WithinUlpsMatcher : MatcherBase<double> {
3058             WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType);
3059             bool match(double const& matchee) const override;
3060             std::string describe() const override;
3061         private:
3062             double m_target;
3063             int m_ulps;
3064             FloatingPointKind m_type;
3065         };
3066 
3067     } // namespace Floating
3068 
3069     // The following functions create the actual matcher objects.
3070     // This allows the types to be inferred
3071     Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff);
3072     Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff);
3073     Floating::WithinAbsMatcher WithinAbs(double target, double margin);
3074 
3075 } // namespace Matchers
3076 } // namespace Catch
3077 
3078 // end catch_matchers_floating.h
3079 // start catch_matchers_generic.hpp
3080 
3081 #include <functional>
3082 #include <string>
3083 
3084 namespace Catch {
3085 namespace Matchers {
3086 namespace Generic {
3087 
3088 namespace Detail {
3089     std::string finalizeDescription(const std::string& desc);
3090 }
3091 
3092 template <typename T>
3093 class PredicateMatcher : public MatcherBase<T> {
3094     std::function<bool(T const&)> m_predicate;
3095     std::string m_description;
3096 public:
3097 
PredicateMatcher(std::function<bool (T const &)> const & elem,std::string const & descr)3098     PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
3099         :m_predicate(std::move(elem)),
3100         m_description(Detail::finalizeDescription(descr))
3101     {}
3102 
match(T const & item) const3103     bool match( T const& item ) const override {
3104         return m_predicate(item);
3105     }
3106 
describe() const3107     std::string describe() const override {
3108         return m_description;
3109     }
3110 };
3111 
3112 } // namespace Generic
3113 
3114     // The following functions create the actual matcher objects.
3115     // The user has to explicitly specify type to the function, because
3116     // infering std::function<bool(T const&)> is hard (but possible) and
3117     // requires a lot of TMP.
3118     template<typename T>
Predicate(std::function<bool (T const &)> const & predicate,std::string const & description="")3119     Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
3120         return Generic::PredicateMatcher<T>(predicate, description);
3121     }
3122 
3123 } // namespace Matchers
3124 } // namespace Catch
3125 
3126 // end catch_matchers_generic.hpp
3127 // start catch_matchers_string.h
3128 
3129 #include <string>
3130 
3131 namespace Catch {
3132 namespace Matchers {
3133 
3134     namespace StdString {
3135 
3136         struct CasedString
3137         {
3138             CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
3139             std::string adjustString( std::string const& str ) const;
3140             std::string caseSensitivitySuffix() const;
3141 
3142             CaseSensitive::Choice m_caseSensitivity;
3143             std::string m_str;
3144         };
3145 
3146         struct StringMatcherBase : MatcherBase<std::string> {
3147             StringMatcherBase( std::string const& operation, CasedString const& comparator );
3148             std::string describe() const override;
3149 
3150             CasedString m_comparator;
3151             std::string m_operation;
3152         };
3153 
3154         struct EqualsMatcher : StringMatcherBase {
3155             EqualsMatcher( CasedString const& comparator );
3156             bool match( std::string const& source ) const override;
3157         };
3158         struct ContainsMatcher : StringMatcherBase {
3159             ContainsMatcher( CasedString const& comparator );
3160             bool match( std::string const& source ) const override;
3161         };
3162         struct StartsWithMatcher : StringMatcherBase {
3163             StartsWithMatcher( CasedString const& comparator );
3164             bool match( std::string const& source ) const override;
3165         };
3166         struct EndsWithMatcher : StringMatcherBase {
3167             EndsWithMatcher( CasedString const& comparator );
3168             bool match( std::string const& source ) const override;
3169         };
3170 
3171         struct RegexMatcher : MatcherBase<std::string> {
3172             RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity );
3173             bool match( std::string const& matchee ) const override;
3174             std::string describe() const override;
3175 
3176         private:
3177             std::string m_regex;
3178             CaseSensitive::Choice m_caseSensitivity;
3179         };
3180 
3181     } // namespace StdString
3182 
3183     // The following functions create the actual matcher objects.
3184     // This allows the types to be inferred
3185 
3186     StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3187     StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3188     StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3189     StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3190     StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
3191 
3192 } // namespace Matchers
3193 } // namespace Catch
3194 
3195 // end catch_matchers_string.h
3196 // start catch_matchers_vector.h
3197 
3198 #include <algorithm>
3199 
3200 namespace Catch {
3201 namespace Matchers {
3202 
3203     namespace Vector {
3204         namespace Detail {
3205             template <typename InputIterator, typename T>
count(InputIterator first,InputIterator last,T const & item)3206             size_t count(InputIterator first, InputIterator last, T const& item) {
3207                 size_t cnt = 0;
3208                 for (; first != last; ++first) {
3209                     if (*first == item) {
3210                         ++cnt;
3211                     }
3212                 }
3213                 return cnt;
3214             }
3215             template <typename InputIterator, typename T>
contains(InputIterator first,InputIterator last,T const & item)3216             bool contains(InputIterator first, InputIterator last, T const& item) {
3217                 for (; first != last; ++first) {
3218                     if (*first == item) {
3219                         return true;
3220                     }
3221                 }
3222                 return false;
3223             }
3224         }
3225 
3226         template<typename T>
3227         struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
3228 
ContainsElementMatcherCatch::Matchers::Vector::ContainsElementMatcher3229             ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
3230 
matchCatch::Matchers::Vector::ContainsElementMatcher3231             bool match(std::vector<T> const &v) const override {
3232                 for (auto const& el : v) {
3233                     if (el == m_comparator) {
3234                         return true;
3235                     }
3236                 }
3237                 return false;
3238             }
3239 
describeCatch::Matchers::Vector::ContainsElementMatcher3240             std::string describe() const override {
3241                 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
3242             }
3243 
3244             T const& m_comparator;
3245         };
3246 
3247         template<typename T>
3248         struct ContainsMatcher : MatcherBase<std::vector<T>> {
3249 
ContainsMatcherCatch::Matchers::Vector::ContainsMatcher3250             ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3251 
matchCatch::Matchers::Vector::ContainsMatcher3252             bool match(std::vector<T> const &v) const override {
3253                 // !TBD: see note in EqualsMatcher
3254                 if (m_comparator.size() > v.size())
3255                     return false;
3256                 for (auto const& comparator : m_comparator) {
3257                     auto present = false;
3258                     for (const auto& el : v) {
3259                         if (el == comparator) {
3260                             present = true;
3261                             break;
3262                         }
3263                     }
3264                     if (!present) {
3265                         return false;
3266                     }
3267                 }
3268                 return true;
3269             }
describeCatch::Matchers::Vector::ContainsMatcher3270             std::string describe() const override {
3271                 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
3272             }
3273 
3274             std::vector<T> const& m_comparator;
3275         };
3276 
3277         template<typename T>
3278         struct EqualsMatcher : MatcherBase<std::vector<T>> {
3279 
EqualsMatcherCatch::Matchers::Vector::EqualsMatcher3280             EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3281 
matchCatch::Matchers::Vector::EqualsMatcher3282             bool match(std::vector<T> const &v) const override {
3283                 // !TBD: This currently works if all elements can be compared using !=
3284                 // - a more general approach would be via a compare template that defaults
3285                 // to using !=. but could be specialised for, e.g. std::vector<T> etc
3286                 // - then just call that directly
3287                 if (m_comparator.size() != v.size())
3288                     return false;
3289                 for (std::size_t i = 0; i < v.size(); ++i)
3290                     if (m_comparator[i] != v[i])
3291                         return false;
3292                 return true;
3293             }
describeCatch::Matchers::Vector::EqualsMatcher3294             std::string describe() const override {
3295                 return "Equals: " + ::Catch::Detail::stringify( m_comparator );
3296             }
3297             std::vector<T> const& m_comparator;
3298         };
3299 
3300         template<typename T>
3301         struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
UnorderedEqualsMatcherCatch::Matchers::Vector::UnorderedEqualsMatcher3302             UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
matchCatch::Matchers::Vector::UnorderedEqualsMatcher3303             bool match(std::vector<T> const& vec) const override {
3304                 // Note: This is a reimplementation of std::is_permutation,
3305                 //       because I don't want to include <algorithm> inside the common path
3306                 if (m_target.size() != vec.size()) {
3307                     return false;
3308                 }
3309                 auto lfirst = m_target.begin(), llast = m_target.end();
3310                 auto rfirst = vec.begin(), rlast = vec.end();
3311                 // Cut common prefix to optimize checking of permuted parts
3312                 while (lfirst != llast && *lfirst == *rfirst) {
3313                     ++lfirst; ++rfirst;
3314                 }
3315                 if (lfirst == llast) {
3316                     return true;
3317                 }
3318 
3319                 for (auto mid = lfirst; mid != llast; ++mid) {
3320                     // Skip already counted items
3321                     if (Detail::contains(lfirst, mid, *mid)) {
3322                         continue;
3323                     }
3324                     size_t num_vec = Detail::count(rfirst, rlast, *mid);
3325                     if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
3326                         return false;
3327                     }
3328                 }
3329 
3330                 return true;
3331             }
3332 
describeCatch::Matchers::Vector::UnorderedEqualsMatcher3333             std::string describe() const override {
3334                 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
3335             }
3336         private:
3337             std::vector<T> const& m_target;
3338         };
3339 
3340     } // namespace Vector
3341 
3342     // The following functions create the actual matcher objects.
3343     // This allows the types to be inferred
3344 
3345     template<typename T>
Contains(std::vector<T> const & comparator)3346     Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
3347         return Vector::ContainsMatcher<T>( comparator );
3348     }
3349 
3350     template<typename T>
VectorContains(T const & comparator)3351     Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
3352         return Vector::ContainsElementMatcher<T>( comparator );
3353     }
3354 
3355     template<typename T>
Equals(std::vector<T> const & comparator)3356     Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
3357         return Vector::EqualsMatcher<T>( comparator );
3358     }
3359 
3360     template<typename T>
UnorderedEquals(std::vector<T> const & target)3361     Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
3362         return Vector::UnorderedEqualsMatcher<T>(target);
3363     }
3364 
3365 } // namespace Matchers
3366 } // namespace Catch
3367 
3368 // end catch_matchers_vector.h
3369 namespace Catch {
3370 
3371     template<typename ArgT, typename MatcherT>
3372     class MatchExpr : public ITransientExpression {
3373         ArgT const& m_arg;
3374         MatcherT m_matcher;
3375         StringRef m_matcherString;
3376     public:
MatchExpr(ArgT const & arg,MatcherT const & matcher,StringRef const & matcherString)3377         MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )
3378         :   ITransientExpression{ true, matcher.match( arg ) },
3379             m_arg( arg ),
3380             m_matcher( matcher ),
3381             m_matcherString( matcherString )
3382         {}
3383 
streamReconstructedExpression(std::ostream & os) const3384         void streamReconstructedExpression( std::ostream &os ) const override {
3385             auto matcherAsString = m_matcher.toString();
3386             os << Catch::Detail::stringify( m_arg ) << ' ';
3387             if( matcherAsString == Detail::unprintableString )
3388                 os << m_matcherString;
3389             else
3390                 os << matcherAsString;
3391         }
3392     };
3393 
3394     using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
3395 
3396     void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  );
3397 
3398     template<typename ArgT, typename MatcherT>
makeMatchExpr(ArgT const & arg,MatcherT const & matcher,StringRef const & matcherString)3399     auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString  ) -> MatchExpr<ArgT, MatcherT> {
3400         return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
3401     }
3402 
3403 } // namespace Catch
3404 
3405 ///////////////////////////////////////////////////////////////////////////////
3406 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
3407     do { \
3408         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3409         INTERNAL_CATCH_TRY { \
3410             catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \
3411         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
3412         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3413     } while( false )
3414 
3415 ///////////////////////////////////////////////////////////////////////////////
3416 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
3417     do { \
3418         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3419         if( catchAssertionHandler.allowThrows() ) \
3420             try { \
3421                 static_cast<void>(__VA_ARGS__ ); \
3422                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
3423             } \
3424             catch( exceptionType const& ex ) { \
3425                 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \
3426             } \
3427             catch( ... ) { \
3428                 catchAssertionHandler.handleUnexpectedInflightException(); \
3429             } \
3430         else \
3431             catchAssertionHandler.handleThrowingCallSkipped(); \
3432         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3433     } while( false )
3434 
3435 // end catch_capture_matchers.h
3436 #endif
3437 // start catch_generators.hpp
3438 
3439 // start catch_interfaces_generatortracker.h
3440 
3441 
3442 #include <memory>
3443 
3444 namespace Catch {
3445 
3446     namespace Generators {
3447         class GeneratorUntypedBase {
3448         public:
3449             GeneratorUntypedBase() = default;
3450             virtual ~GeneratorUntypedBase();
3451             // Attempts to move the generator to the next element
3452              //
3453              // Returns true iff the move succeeded (and a valid element
3454              // can be retrieved).
3455             virtual bool next() = 0;
3456         };
3457         using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;
3458 
3459     } // namespace Generators
3460 
3461     struct IGeneratorTracker {
3462         virtual ~IGeneratorTracker();
3463         virtual auto hasGenerator() const -> bool = 0;
3464         virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
3465         virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
3466     };
3467 
3468 } // namespace Catch
3469 
3470 // end catch_interfaces_generatortracker.h
3471 // start catch_enforce.h
3472 
3473 #include <stdexcept>
3474 
3475 namespace Catch {
3476 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
3477     template <typename Ex>
3478     [[noreturn]]
throw_exception(Ex const & e)3479     void throw_exception(Ex const& e) {
3480         throw e;
3481     }
3482 #else // ^^ Exceptions are enabled //  Exceptions are disabled vv
3483     [[noreturn]]
3484     void throw_exception(std::exception const& e);
3485 #endif
3486 } // namespace Catch;
3487 
3488 #define CATCH_PREPARE_EXCEPTION( type, msg ) \
3489     type( ( Catch::ReusableStringStream() << msg ).str() )
3490 #define CATCH_INTERNAL_ERROR( msg ) \
3491     Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg))
3492 #define CATCH_ERROR( msg ) \
3493     Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg ))
3494 #define CATCH_RUNTIME_ERROR( msg ) \
3495     Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg ))
3496 #define CATCH_ENFORCE( condition, msg ) \
3497     do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
3498 
3499 // end catch_enforce.h
3500 #include <memory>
3501 #include <vector>
3502 #include <cassert>
3503 
3504 #include <utility>
3505 #include <exception>
3506 
3507 namespace Catch {
3508 
3509 class GeneratorException : public std::exception {
3510     const char* const m_msg = "";
3511 
3512 public:
GeneratorException(const char * msg)3513     GeneratorException(const char* msg):
3514         m_msg(msg)
3515     {}
3516 
3517     const char* what() const noexcept override final;
3518 };
3519 
3520 namespace Generators {
3521 
3522     // !TBD move this into its own location?
3523     namespace pf{
3524         template<typename T, typename... Args>
make_unique(Args &&...args)3525         std::unique_ptr<T> make_unique( Args&&... args ) {
3526             return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
3527         }
3528     }
3529 
3530     template<typename T>
3531     struct IGenerator : GeneratorUntypedBase {
3532         virtual ~IGenerator() = default;
3533 
3534         // Returns the current element of the generator
3535         //
3536         // \Precondition The generator is either freshly constructed,
3537         // or the last call to `next()` returned true
3538         virtual T const& get() const = 0;
3539         using type = T;
3540     };
3541 
3542     template<typename T>
3543     class SingleValueGenerator final : public IGenerator<T> {
3544         T m_value;
3545     public:
SingleValueGenerator(T const & value)3546         SingleValueGenerator(T const& value) : m_value( value ) {}
SingleValueGenerator(T && value)3547         SingleValueGenerator(T&& value) : m_value(std::move(value)) {}
3548 
get() const3549         T const& get() const override {
3550             return m_value;
3551         }
next()3552         bool next() override {
3553             return false;
3554         }
3555     };
3556 
3557     template<typename T>
3558     class FixedValuesGenerator final : public IGenerator<T> {
3559         std::vector<T> m_values;
3560         size_t m_idx = 0;
3561     public:
FixedValuesGenerator(std::initializer_list<T> values)3562         FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}
3563 
get() const3564         T const& get() const override {
3565             return m_values[m_idx];
3566         }
next()3567         bool next() override {
3568             ++m_idx;
3569             return m_idx < m_values.size();
3570         }
3571     };
3572 
3573     template <typename T>
3574     class GeneratorWrapper final {
3575         std::unique_ptr<IGenerator<T>> m_generator;
3576     public:
GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator)3577         GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator):
3578             m_generator(std::move(generator))
3579         {}
get() const3580         T const& get() const {
3581             return m_generator->get();
3582         }
next()3583         bool next() {
3584             return m_generator->next();
3585         }
3586     };
3587 
3588     template <typename T>
value(T && value)3589     GeneratorWrapper<T> value(T&& value) {
3590         return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value)));
3591     }
3592     template <typename T>
values(std::initializer_list<T> values)3593     GeneratorWrapper<T> values(std::initializer_list<T> values) {
3594         return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));
3595     }
3596 
3597     template<typename T>
3598     class Generators : public IGenerator<T> {
3599         std::vector<GeneratorWrapper<T>> m_generators;
3600         size_t m_current = 0;
3601 
populate(GeneratorWrapper<T> && generator)3602         void populate(GeneratorWrapper<T>&& generator) {
3603             m_generators.emplace_back(std::move(generator));
3604         }
populate(T && val)3605         void populate(T&& val) {
3606             m_generators.emplace_back(value(std::move(val)));
3607         }
3608         template<typename U>
populate(U && val)3609         void populate(U&& val) {
3610             populate(T(std::move(val)));
3611         }
3612         template<typename U, typename... Gs>
populate(U && valueOrGenerator,Gs...moreGenerators)3613         void populate(U&& valueOrGenerator, Gs... moreGenerators) {
3614             populate(std::forward<U>(valueOrGenerator));
3615             populate(std::forward<Gs>(moreGenerators)...);
3616         }
3617 
3618     public:
3619         template <typename... Gs>
Generators(Gs...moreGenerators)3620         Generators(Gs... moreGenerators) {
3621             m_generators.reserve(sizeof...(Gs));
3622             populate(std::forward<Gs>(moreGenerators)...);
3623         }
3624 
get() const3625         T const& get() const override {
3626             return m_generators[m_current].get();
3627         }
3628 
next()3629         bool next() override {
3630             if (m_current >= m_generators.size()) {
3631                 return false;
3632             }
3633             const bool current_status = m_generators[m_current].next();
3634             if (!current_status) {
3635                 ++m_current;
3636             }
3637             return m_current < m_generators.size();
3638         }
3639     };
3640 
3641     template<typename... Ts>
table(std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples)3642     GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) {
3643         return values<std::tuple<Ts...>>( tuples );
3644     }
3645 
3646     // Tag type to signal that a generator sequence should convert arguments to a specific type
3647     template <typename T>
3648     struct as {};
3649 
3650     template<typename T, typename... Gs>
makeGenerators(GeneratorWrapper<T> && generator,Gs...moreGenerators)3651     auto makeGenerators( GeneratorWrapper<T>&& generator, Gs... moreGenerators ) -> Generators<T> {
3652         return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);
3653     }
3654     template<typename T>
makeGenerators(GeneratorWrapper<T> && generator)3655     auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {
3656         return Generators<T>(std::move(generator));
3657     }
3658     template<typename T, typename... Gs>
makeGenerators(T && val,Gs...moreGenerators)3659     auto makeGenerators( T&& val, Gs... moreGenerators ) -> Generators<T> {
3660         return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );
3661     }
3662     template<typename T, typename U, typename... Gs>
makeGenerators(as<T>,U && val,Gs...moreGenerators)3663     auto makeGenerators( as<T>, U&& val, Gs... moreGenerators ) -> Generators<T> {
3664         return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );
3665     }
3666 
3667     auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;
3668 
3669     template<typename L>
3670     // Note: The type after -> is weird, because VS2015 cannot parse
3671     //       the expression used in the typedef inside, when it is in
3672     //       return type. Yeah.
generate(SourceLineInfo const & lineInfo,L const & generatorExpression)3673     auto generate( SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {
3674         using UnderlyingType = typename decltype(generatorExpression())::type;
3675 
3676         IGeneratorTracker& tracker = acquireGeneratorTracker( lineInfo );
3677         if (!tracker.hasGenerator()) {
3678             tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));
3679         }
3680 
3681         auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );
3682         return generator.get();
3683     }
3684 
3685 } // namespace Generators
3686 } // namespace Catch
3687 
3688 #define GENERATE( ... ) \
3689     Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
3690 
3691 // end catch_generators.hpp
3692 // start catch_generators_generic.hpp
3693 
3694 namespace Catch {
3695 namespace Generators {
3696 
3697     template <typename T>
3698     class TakeGenerator : public IGenerator<T> {
3699         GeneratorWrapper<T> m_generator;
3700         size_t m_returned = 0;
3701         size_t m_target;
3702     public:
TakeGenerator(size_t target,GeneratorWrapper<T> && generator)3703         TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):
3704             m_generator(std::move(generator)),
3705             m_target(target)
3706         {
3707             assert(target != 0 && "Empty generators are not allowed");
3708         }
get() const3709         T const& get() const override {
3710             return m_generator.get();
3711         }
next()3712         bool next() override {
3713             ++m_returned;
3714             if (m_returned >= m_target) {
3715                 return false;
3716             }
3717 
3718             const auto success = m_generator.next();
3719             // If the underlying generator does not contain enough values
3720             // then we cut short as well
3721             if (!success) {
3722                 m_returned = m_target;
3723             }
3724             return success;
3725         }
3726     };
3727 
3728     template <typename T>
take(size_t target,GeneratorWrapper<T> && generator)3729     GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {
3730         return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));
3731     }
3732 
3733     template <typename T, typename Predicate>
3734     class FilterGenerator : public IGenerator<T> {
3735         GeneratorWrapper<T> m_generator;
3736         Predicate m_predicate;
3737     public:
3738         template <typename P = Predicate>
FilterGenerator(P && pred,GeneratorWrapper<T> && generator)3739         FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):
3740             m_generator(std::move(generator)),
3741             m_predicate(std::forward<P>(pred))
3742         {
3743             if (!m_predicate(m_generator.get())) {
3744                 // It might happen that there are no values that pass the
3745                 // filter. In that case we throw an exception.
3746                 auto has_initial_value = next();
3747                 if (!has_initial_value) {
3748                     Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));
3749                 }
3750             }
3751         }
3752 
get() const3753         T const& get() const override {
3754             return m_generator.get();
3755         }
3756 
next()3757         bool next() override {
3758             bool success = m_generator.next();
3759             if (!success) {
3760                 return false;
3761             }
3762             while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);
3763             return success;
3764         }
3765     };
3766 
3767     template <typename T, typename Predicate>
filter(Predicate && pred,GeneratorWrapper<T> && generator)3768     GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {
3769         return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));
3770     }
3771 
3772     template <typename T>
3773     class RepeatGenerator : public IGenerator<T> {
3774         GeneratorWrapper<T> m_generator;
3775         mutable std::vector<T> m_returned;
3776         size_t m_target_repeats;
3777         size_t m_current_repeat = 0;
3778         size_t m_repeat_index = 0;
3779     public:
RepeatGenerator(size_t repeats,GeneratorWrapper<T> && generator)3780         RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):
3781             m_generator(std::move(generator)),
3782             m_target_repeats(repeats)
3783         {
3784             assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");
3785         }
3786 
get() const3787         T const& get() const override {
3788             if (m_current_repeat == 0) {
3789                 m_returned.push_back(m_generator.get());
3790                 return m_returned.back();
3791             }
3792             return m_returned[m_repeat_index];
3793         }
3794 
next()3795         bool next() override {
3796             // There are 2 basic cases:
3797             // 1) We are still reading the generator
3798             // 2) We are reading our own cache
3799 
3800             // In the first case, we need to poke the underlying generator.
3801             // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache
3802             if (m_current_repeat == 0) {
3803                 const auto success = m_generator.next();
3804                 if (!success) {
3805                     ++m_current_repeat;
3806                 }
3807                 return m_current_repeat < m_target_repeats;
3808             }
3809 
3810             // In the second case, we need to move indices forward and check that we haven't run up against the end
3811             ++m_repeat_index;
3812             if (m_repeat_index == m_returned.size()) {
3813                 m_repeat_index = 0;
3814                 ++m_current_repeat;
3815             }
3816             return m_current_repeat < m_target_repeats;
3817         }
3818     };
3819 
3820     template <typename T>
repeat(size_t repeats,GeneratorWrapper<T> && generator)3821     GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {
3822         return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));
3823     }
3824 
3825     template <typename T, typename U, typename Func>
3826     class MapGenerator : public IGenerator<T> {
3827         // TBD: provide static assert for mapping function, for friendly error message
3828         GeneratorWrapper<U> m_generator;
3829         Func m_function;
3830         // To avoid returning dangling reference, we have to save the values
3831         T m_cache;
3832     public:
3833         template <typename F2 = Func>
MapGenerator(F2 && function,GeneratorWrapper<U> && generator)3834         MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :
3835             m_generator(std::move(generator)),
3836             m_function(std::forward<F2>(function)),
3837             m_cache(m_function(m_generator.get()))
3838         {}
3839 
get() const3840         T const& get() const override {
3841             return m_cache;
3842         }
next()3843         bool next() override {
3844             const auto success = m_generator.next();
3845             if (success) {
3846                 m_cache = m_function(m_generator.get());
3847             }
3848             return success;
3849         }
3850     };
3851 
3852     template <typename T, typename U, typename Func>
map(Func && function,GeneratorWrapper<U> && generator)3853     GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
3854         return GeneratorWrapper<T>(
3855             pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
3856         );
3857     }
3858     template <typename T, typename Func>
map(Func && function,GeneratorWrapper<T> && generator)3859     GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<T>&& generator) {
3860         return GeneratorWrapper<T>(
3861             pf::make_unique<MapGenerator<T, T, Func>>(std::forward<Func>(function), std::move(generator))
3862         );
3863     }
3864 
3865     template <typename T>
3866     class ChunkGenerator final : public IGenerator<std::vector<T>> {
3867         std::vector<T> m_chunk;
3868         size_t m_chunk_size;
3869         GeneratorWrapper<T> m_generator;
3870         bool m_used_up = false;
3871     public:
ChunkGenerator(size_t size,GeneratorWrapper<T> generator)3872         ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :
3873             m_chunk_size(size), m_generator(std::move(generator))
3874         {
3875             m_chunk.reserve(m_chunk_size);
3876             m_chunk.push_back(m_generator.get());
3877             for (size_t i = 1; i < m_chunk_size; ++i) {
3878                 if (!m_generator.next()) {
3879                     Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));
3880                 }
3881                 m_chunk.push_back(m_generator.get());
3882             }
3883         }
get() const3884         std::vector<T> const& get() const override {
3885             return m_chunk;
3886         }
next()3887         bool next() override {
3888             m_chunk.clear();
3889             for (size_t idx = 0; idx < m_chunk_size; ++idx) {
3890                 if (!m_generator.next()) {
3891                     return false;
3892                 }
3893                 m_chunk.push_back(m_generator.get());
3894             }
3895             return true;
3896         }
3897     };
3898 
3899     template <typename T>
chunk(size_t size,GeneratorWrapper<T> && generator)3900     GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {
3901         return GeneratorWrapper<std::vector<T>>(
3902             pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
3903         );
3904     }
3905 
3906 } // namespace Generators
3907 } // namespace Catch
3908 
3909 // end catch_generators_generic.hpp
3910 // start catch_generators_specific.hpp
3911 
3912 // start catch_context.h
3913 
3914 #include <memory>
3915 
3916 namespace Catch {
3917 
3918     struct IResultCapture;
3919     struct IRunner;
3920     struct IConfig;
3921     struct IMutableContext;
3922 
3923     using IConfigPtr = std::shared_ptr<IConfig const>;
3924 
3925     struct IContext
3926     {
3927         virtual ~IContext();
3928 
3929         virtual IResultCapture* getResultCapture() = 0;
3930         virtual IRunner* getRunner() = 0;
3931         virtual IConfigPtr const& getConfig() const = 0;
3932     };
3933 
3934     struct IMutableContext : IContext
3935     {
3936         virtual ~IMutableContext();
3937         virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
3938         virtual void setRunner( IRunner* runner ) = 0;
3939         virtual void setConfig( IConfigPtr const& config ) = 0;
3940 
3941     private:
3942         static IMutableContext *currentContext;
3943         friend IMutableContext& getCurrentMutableContext();
3944         friend void cleanUpContext();
3945         static void createContext();
3946     };
3947 
getCurrentMutableContext()3948     inline IMutableContext& getCurrentMutableContext()
3949     {
3950         if( !IMutableContext::currentContext )
3951             IMutableContext::createContext();
3952         return *IMutableContext::currentContext;
3953     }
3954 
getCurrentContext()3955     inline IContext& getCurrentContext()
3956     {
3957         return getCurrentMutableContext();
3958     }
3959 
3960     void cleanUpContext();
3961 }
3962 
3963 // end catch_context.h
3964 // start catch_interfaces_config.h
3965 
3966 #include <iosfwd>
3967 #include <string>
3968 #include <vector>
3969 #include <memory>
3970 
3971 namespace Catch {
3972 
3973     enum class Verbosity {
3974         Quiet = 0,
3975         Normal,
3976         High
3977     };
3978 
3979     struct WarnAbout { enum What {
3980         Nothing = 0x00,
3981         NoAssertions = 0x01,
3982         NoTests = 0x02
3983     }; };
3984 
3985     struct ShowDurations { enum OrNot {
3986         DefaultForReporter,
3987         Always,
3988         Never
3989     }; };
3990     struct RunTests { enum InWhatOrder {
3991         InDeclarationOrder,
3992         InLexicographicalOrder,
3993         InRandomOrder
3994     }; };
3995     struct UseColour { enum YesOrNo {
3996         Auto,
3997         Yes,
3998         No
3999     }; };
4000     struct WaitForKeypress { enum When {
4001         Never,
4002         BeforeStart = 1,
4003         BeforeExit = 2,
4004         BeforeStartAndExit = BeforeStart | BeforeExit
4005     }; };
4006 
4007     class TestSpec;
4008 
4009     struct IConfig : NonCopyable {
4010 
4011         virtual ~IConfig();
4012 
4013         virtual bool allowThrows() const = 0;
4014         virtual std::ostream& stream() const = 0;
4015         virtual std::string name() const = 0;
4016         virtual bool includeSuccessfulResults() const = 0;
4017         virtual bool shouldDebugBreak() const = 0;
4018         virtual bool warnAboutMissingAssertions() const = 0;
4019         virtual bool warnAboutNoTests() const = 0;
4020         virtual int abortAfter() const = 0;
4021         virtual bool showInvisibles() const = 0;
4022         virtual ShowDurations::OrNot showDurations() const = 0;
4023         virtual TestSpec const& testSpec() const = 0;
4024         virtual bool hasTestFilters() const = 0;
4025         virtual RunTests::InWhatOrder runOrder() const = 0;
4026         virtual unsigned int rngSeed() const = 0;
4027         virtual int benchmarkResolutionMultiple() const = 0;
4028         virtual UseColour::YesOrNo useColour() const = 0;
4029         virtual std::vector<std::string> const& getSectionsToRun() const = 0;
4030         virtual Verbosity verbosity() const = 0;
4031     };
4032 
4033     using IConfigPtr = std::shared_ptr<IConfig const>;
4034 }
4035 
4036 // end catch_interfaces_config.h
4037 #include <random>
4038 
4039 namespace Catch {
4040 namespace Generators {
4041 
4042 template <typename Float>
4043 class RandomFloatingGenerator final : public IGenerator<Float> {
4044     // FIXME: What is the right seed?
4045     std::minstd_rand m_rand;
4046     std::uniform_real_distribution<Float> m_dist;
4047     Float m_current_number;
4048 public:
4049 
RandomFloatingGenerator(Float a,Float b)4050     RandomFloatingGenerator(Float a, Float b):
4051         m_rand(getCurrentContext().getConfig()->rngSeed()),
4052         m_dist(a, b) {
4053         static_cast<void>(next());
4054     }
4055 
get() const4056     Float const& get() const override {
4057         return m_current_number;
4058     }
next()4059     bool next() override {
4060         m_current_number = m_dist(m_rand);
4061         return true;
4062     }
4063 };
4064 
4065 template <typename Integer>
4066 class RandomIntegerGenerator final : public IGenerator<Integer> {
4067     std::minstd_rand m_rand;
4068     std::uniform_int_distribution<Integer> m_dist;
4069     Integer m_current_number;
4070 public:
4071 
RandomIntegerGenerator(Integer a,Integer b)4072     RandomIntegerGenerator(Integer a, Integer b):
4073         m_rand(getCurrentContext().getConfig()->rngSeed()),
4074         m_dist(a, b) {
4075         static_cast<void>(next());
4076     }
4077 
get() const4078     Integer const& get() const override {
4079         return m_current_number;
4080     }
next()4081     bool next() override {
4082         m_current_number = m_dist(m_rand);
4083         return true;
4084     }
4085 };
4086 
4087 // TODO: Ideally this would be also constrained against the various char types,
4088 //       but I don't expect users to run into that in practice.
4089 template <typename T>
4090 typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value,
4091 GeneratorWrapper<T>>::type
random(T a,T b)4092 random(T a, T b) {
4093     return GeneratorWrapper<T>(
4094         pf::make_unique<RandomIntegerGenerator<T>>(a, b)
4095     );
4096 }
4097 
4098 template <typename T>
4099 typename std::enable_if<std::is_floating_point<T>::value,
4100 GeneratorWrapper<T>>::type
random(T a,T b)4101 random(T a, T b) {
4102     return GeneratorWrapper<T>(
4103         pf::make_unique<RandomFloatingGenerator<T>>(a, b)
4104     );
4105 }
4106 
4107 template <typename T>
4108 class RangeGenerator final : public IGenerator<T> {
4109     T m_current;
4110     T m_end;
4111     T m_step;
4112     bool m_positive;
4113 
4114 public:
RangeGenerator(T const & start,T const & end,T const & step)4115     RangeGenerator(T const& start, T const& end, T const& step):
4116         m_current(start),
4117         m_end(end),
4118         m_step(step),
4119         m_positive(m_step > T(0))
4120     {
4121         assert(m_current != m_end && "Range start and end cannot be equal");
4122         assert(m_step != T(0) && "Step size cannot be zero");
4123         assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");
4124     }
4125 
RangeGenerator(T const & start,T const & end)4126     RangeGenerator(T const& start, T const& end):
4127         RangeGenerator(start, end, (start < end) ? T(1) : T(-1))
4128     {}
4129 
get() const4130     T const& get() const override {
4131         return m_current;
4132     }
4133 
next()4134     bool next() override {
4135         m_current += m_step;
4136         return (m_positive) ? (m_current < m_end) : (m_current > m_end);
4137     }
4138 };
4139 
4140 template <typename T>
range(T const & start,T const & end,T const & step)4141 GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {
4142     static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
4143     return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));
4144 }
4145 
4146 template <typename T>
range(T const & start,T const & end)4147 GeneratorWrapper<T> range(T const& start, T const& end) {
4148     static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");
4149     return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end));
4150 }
4151 
4152 } // namespace Generators
4153 } // namespace Catch
4154 
4155 // end catch_generators_specific.hpp
4156 
4157 // These files are included here so the single_include script doesn't put them
4158 // in the conditionally compiled sections
4159 // start catch_test_case_info.h
4160 
4161 #include <string>
4162 #include <vector>
4163 #include <memory>
4164 
4165 #ifdef __clang__
4166 #pragma clang diagnostic push
4167 #pragma clang diagnostic ignored "-Wpadded"
4168 #endif
4169 
4170 namespace Catch {
4171 
4172     struct ITestInvoker;
4173 
4174     struct TestCaseInfo {
4175         enum SpecialProperties{
4176             None = 0,
4177             IsHidden = 1 << 1,
4178             ShouldFail = 1 << 2,
4179             MayFail = 1 << 3,
4180             Throws = 1 << 4,
4181             NonPortable = 1 << 5,
4182             Benchmark = 1 << 6
4183         };
4184 
4185         TestCaseInfo(   std::string const& _name,
4186                         std::string const& _className,
4187                         std::string const& _description,
4188                         std::vector<std::string> const& _tags,
4189                         SourceLineInfo const& _lineInfo );
4190 
4191         friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags );
4192 
4193         bool isHidden() const;
4194         bool throws() const;
4195         bool okToFail() const;
4196         bool expectedToFail() const;
4197 
4198         std::string tagsAsString() const;
4199 
4200         std::string name;
4201         std::string className;
4202         std::string description;
4203         std::vector<std::string> tags;
4204         std::vector<std::string> lcaseTags;
4205         SourceLineInfo lineInfo;
4206         SpecialProperties properties;
4207     };
4208 
4209     class TestCase : public TestCaseInfo {
4210     public:
4211 
4212         TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
4213 
4214         TestCase withName( std::string const& _newName ) const;
4215 
4216         void invoke() const;
4217 
4218         TestCaseInfo const& getTestCaseInfo() const;
4219 
4220         bool operator == ( TestCase const& other ) const;
4221         bool operator < ( TestCase const& other ) const;
4222 
4223     private:
4224         std::shared_ptr<ITestInvoker> test;
4225     };
4226 
4227     TestCase makeTestCase(  ITestInvoker* testCase,
4228                             std::string const& className,
4229                             NameAndTags const& nameAndTags,
4230                             SourceLineInfo const& lineInfo );
4231 }
4232 
4233 #ifdef __clang__
4234 #pragma clang diagnostic pop
4235 #endif
4236 
4237 // end catch_test_case_info.h
4238 // start catch_interfaces_runner.h
4239 
4240 namespace Catch {
4241 
4242     struct IRunner {
4243         virtual ~IRunner();
4244         virtual bool aborting() const = 0;
4245     };
4246 }
4247 
4248 // end catch_interfaces_runner.h
4249 
4250 #ifdef __OBJC__
4251 // start catch_objc.hpp
4252 
4253 #import <objc/runtime.h>
4254 
4255 #include <string>
4256 
4257 // NB. Any general catch headers included here must be included
4258 // in catch.hpp first to make sure they are included by the single
4259 // header for non obj-usage
4260 
4261 ///////////////////////////////////////////////////////////////////////////////
4262 // This protocol is really only here for (self) documenting purposes, since
4263 // all its methods are optional.
4264 @protocol OcFixture
4265 
4266 @optional
4267 
4268 -(void) setUp;
4269 -(void) tearDown;
4270 
4271 @end
4272 
4273 namespace Catch {
4274 
4275     class OcMethod : public ITestInvoker {
4276 
4277     public:
OcMethod(Class cls,SEL sel)4278         OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
4279 
invoke() const4280         virtual void invoke() const {
4281             id obj = [[m_cls alloc] init];
4282 
4283             performOptionalSelector( obj, @selector(setUp)  );
4284             performOptionalSelector( obj, m_sel );
4285             performOptionalSelector( obj, @selector(tearDown)  );
4286 
4287             arcSafeRelease( obj );
4288         }
4289     private:
~OcMethod()4290         virtual ~OcMethod() {}
4291 
4292         Class m_cls;
4293         SEL m_sel;
4294     };
4295 
4296     namespace Detail{
4297 
getAnnotation(Class cls,std::string const & annotationName,std::string const & testCaseName)4298         inline std::string getAnnotation(   Class cls,
4299                                             std::string const& annotationName,
4300                                             std::string const& testCaseName ) {
4301             NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
4302             SEL sel = NSSelectorFromString( selStr );
4303             arcSafeRelease( selStr );
4304             id value = performOptionalSelector( cls, sel );
4305             if( value )
4306                 return [(NSString*)value UTF8String];
4307             return "";
4308         }
4309     }
4310 
registerTestMethods()4311     inline std::size_t registerTestMethods() {
4312         std::size_t noTestMethods = 0;
4313         int noClasses = objc_getClassList( nullptr, 0 );
4314 
4315         Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
4316         objc_getClassList( classes, noClasses );
4317 
4318         for( int c = 0; c < noClasses; c++ ) {
4319             Class cls = classes[c];
4320             {
4321                 u_int count;
4322                 Method* methods = class_copyMethodList( cls, &count );
4323                 for( u_int m = 0; m < count ; m++ ) {
4324                     SEL selector = method_getName(methods[m]);
4325                     std::string methodName = sel_getName(selector);
4326                     if( startsWith( methodName, "Catch_TestCase_" ) ) {
4327                         std::string testCaseName = methodName.substr( 15 );
4328                         std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
4329                         std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
4330                         const char* className = class_getName( cls );
4331 
4332                         getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );
4333                         noTestMethods++;
4334                     }
4335                 }
4336                 free(methods);
4337             }
4338         }
4339         return noTestMethods;
4340     }
4341 
4342 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
4343 
4344     namespace Matchers {
4345         namespace Impl {
4346         namespace NSStringMatchers {
4347 
4348             struct StringHolder : MatcherBase<NSString*>{
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder4349                 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder4350                 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
StringHolderCatch::Matchers::Impl::NSStringMatchers::StringHolder4351                 StringHolder() {
4352                     arcSafeRelease( m_substr );
4353                 }
4354 
matchCatch::Matchers::Impl::NSStringMatchers::StringHolder4355                 bool match( NSString* arg ) const override {
4356                     return false;
4357                 }
4358 
4359                 NSString* CATCH_ARC_STRONG m_substr;
4360             };
4361 
4362             struct Equals : StringHolder {
EqualsCatch::Matchers::Impl::NSStringMatchers::Equals4363                 Equals( NSString* substr ) : StringHolder( substr ){}
4364 
matchCatch::Matchers::Impl::NSStringMatchers::Equals4365                 bool match( NSString* str ) const override {
4366                     return  (str != nil || m_substr == nil ) &&
4367                             [str isEqualToString:m_substr];
4368                 }
4369 
describeCatch::Matchers::Impl::NSStringMatchers::Equals4370                 std::string describe() const override {
4371                     return "equals string: " + Catch::Detail::stringify( m_substr );
4372                 }
4373             };
4374 
4375             struct Contains : StringHolder {
ContainsCatch::Matchers::Impl::NSStringMatchers::Contains4376                 Contains( NSString* substr ) : StringHolder( substr ){}
4377 
matchCatch::Matchers::Impl::NSStringMatchers::Contains4378                 bool match( NSString* str ) const {
4379                     return  (str != nil || m_substr == nil ) &&
4380                             [str rangeOfString:m_substr].location != NSNotFound;
4381                 }
4382 
describeCatch::Matchers::Impl::NSStringMatchers::Contains4383                 std::string describe() const override {
4384                     return "contains string: " + Catch::Detail::stringify( m_substr );
4385                 }
4386             };
4387 
4388             struct StartsWith : StringHolder {
StartsWithCatch::Matchers::Impl::NSStringMatchers::StartsWith4389                 StartsWith( NSString* substr ) : StringHolder( substr ){}
4390 
matchCatch::Matchers::Impl::NSStringMatchers::StartsWith4391                 bool match( NSString* str ) const override {
4392                     return  (str != nil || m_substr == nil ) &&
4393                             [str rangeOfString:m_substr].location == 0;
4394                 }
4395 
describeCatch::Matchers::Impl::NSStringMatchers::StartsWith4396                 std::string describe() const override {
4397                     return "starts with: " + Catch::Detail::stringify( m_substr );
4398                 }
4399             };
4400             struct EndsWith : StringHolder {
EndsWithCatch::Matchers::Impl::NSStringMatchers::EndsWith4401                 EndsWith( NSString* substr ) : StringHolder( substr ){}
4402 
matchCatch::Matchers::Impl::NSStringMatchers::EndsWith4403                 bool match( NSString* str ) const override {
4404                     return  (str != nil || m_substr == nil ) &&
4405                             [str rangeOfString:m_substr].location == [str length] - [m_substr length];
4406                 }
4407 
describeCatch::Matchers::Impl::NSStringMatchers::EndsWith4408                 std::string describe() const override {
4409                     return "ends with: " + Catch::Detail::stringify( m_substr );
4410                 }
4411             };
4412 
4413         } // namespace NSStringMatchers
4414         } // namespace Impl
4415 
4416         inline Impl::NSStringMatchers::Equals
Equals(NSString * substr)4417             Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
4418 
4419         inline Impl::NSStringMatchers::Contains
Contains(NSString * substr)4420             Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
4421 
4422         inline Impl::NSStringMatchers::StartsWith
StartsWith(NSString * substr)4423             StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
4424 
4425         inline Impl::NSStringMatchers::EndsWith
EndsWith(NSString * substr)4426             EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
4427 
4428     } // namespace Matchers
4429 
4430     using namespace Matchers;
4431 
4432 #endif // CATCH_CONFIG_DISABLE_MATCHERS
4433 
4434 } // namespace Catch
4435 
4436 ///////////////////////////////////////////////////////////////////////////////
4437 #define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix
4438 #define OC_TEST_CASE2( name, desc, uniqueSuffix ) \
4439 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \
4440 { \
4441 return @ name; \
4442 } \
4443 +(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \
4444 { \
4445 return @ desc; \
4446 } \
4447 -(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )
4448 
4449 #define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )
4450 
4451 // end catch_objc.hpp
4452 #endif
4453 
4454 #ifdef CATCH_CONFIG_EXTERNAL_INTERFACES
4455 // start catch_external_interfaces.h
4456 
4457 // start catch_reporter_bases.hpp
4458 
4459 // start catch_interfaces_reporter.h
4460 
4461 // start catch_config.hpp
4462 
4463 // start catch_test_spec_parser.h
4464 
4465 #ifdef __clang__
4466 #pragma clang diagnostic push
4467 #pragma clang diagnostic ignored "-Wpadded"
4468 #endif
4469 
4470 // start catch_test_spec.h
4471 
4472 #ifdef __clang__
4473 #pragma clang diagnostic push
4474 #pragma clang diagnostic ignored "-Wpadded"
4475 #endif
4476 
4477 // start catch_wildcard_pattern.h
4478 
4479 namespace Catch
4480 {
4481     class WildcardPattern {
4482         enum WildcardPosition {
4483             NoWildcard = 0,
4484             WildcardAtStart = 1,
4485             WildcardAtEnd = 2,
4486             WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
4487         };
4488 
4489     public:
4490 
4491         WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity );
4492         virtual ~WildcardPattern() = default;
4493         virtual bool matches( std::string const& str ) const;
4494 
4495     private:
4496         std::string adjustCase( std::string const& str ) const;
4497         CaseSensitive::Choice m_caseSensitivity;
4498         WildcardPosition m_wildcard = NoWildcard;
4499         std::string m_pattern;
4500     };
4501 }
4502 
4503 // end catch_wildcard_pattern.h
4504 #include <string>
4505 #include <vector>
4506 #include <memory>
4507 
4508 namespace Catch {
4509 
4510     class TestSpec {
4511         struct Pattern {
4512             virtual ~Pattern();
4513             virtual bool matches( TestCaseInfo const& testCase ) const = 0;
4514         };
4515         using PatternPtr = std::shared_ptr<Pattern>;
4516 
4517         class NamePattern : public Pattern {
4518         public:
4519             NamePattern( std::string const& name );
4520             virtual ~NamePattern();
4521             virtual bool matches( TestCaseInfo const& testCase ) const override;
4522         private:
4523             WildcardPattern m_wildcardPattern;
4524         };
4525 
4526         class TagPattern : public Pattern {
4527         public:
4528             TagPattern( std::string const& tag );
4529             virtual ~TagPattern();
4530             virtual bool matches( TestCaseInfo const& testCase ) const override;
4531         private:
4532             std::string m_tag;
4533         };
4534 
4535         class ExcludedPattern : public Pattern {
4536         public:
4537             ExcludedPattern( PatternPtr const& underlyingPattern );
4538             virtual ~ExcludedPattern();
4539             virtual bool matches( TestCaseInfo const& testCase ) const override;
4540         private:
4541             PatternPtr m_underlyingPattern;
4542         };
4543 
4544         struct Filter {
4545             std::vector<PatternPtr> m_patterns;
4546 
4547             bool matches( TestCaseInfo const& testCase ) const;
4548         };
4549 
4550     public:
4551         bool hasFilters() const;
4552         bool matches( TestCaseInfo const& testCase ) const;
4553 
4554     private:
4555         std::vector<Filter> m_filters;
4556 
4557         friend class TestSpecParser;
4558     };
4559 }
4560 
4561 #ifdef __clang__
4562 #pragma clang diagnostic pop
4563 #endif
4564 
4565 // end catch_test_spec.h
4566 // start catch_interfaces_tag_alias_registry.h
4567 
4568 #include <string>
4569 
4570 namespace Catch {
4571 
4572     struct TagAlias;
4573 
4574     struct ITagAliasRegistry {
4575         virtual ~ITagAliasRegistry();
4576         // Nullptr if not present
4577         virtual TagAlias const* find( std::string const& alias ) const = 0;
4578         virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
4579 
4580         static ITagAliasRegistry const& get();
4581     };
4582 
4583 } // end namespace Catch
4584 
4585 // end catch_interfaces_tag_alias_registry.h
4586 namespace Catch {
4587 
4588     class TestSpecParser {
4589         enum Mode{ None, Name, QuotedName, Tag, EscapedName };
4590         Mode m_mode = None;
4591         bool m_exclusion = false;
4592         std::size_t m_start = std::string::npos, m_pos = 0;
4593         std::string m_arg;
4594         std::vector<std::size_t> m_escapeChars;
4595         TestSpec::Filter m_currentFilter;
4596         TestSpec m_testSpec;
4597         ITagAliasRegistry const* m_tagAliases = nullptr;
4598 
4599     public:
4600         TestSpecParser( ITagAliasRegistry const& tagAliases );
4601 
4602         TestSpecParser& parse( std::string const& arg );
4603         TestSpec testSpec();
4604 
4605     private:
4606         void visitChar( char c );
4607         void startNewMode( Mode mode, std::size_t start );
4608         void escape();
4609         std::string subString() const;
4610 
4611         template<typename T>
addPattern()4612         void addPattern() {
4613             std::string token = subString();
4614             for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
4615                 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
4616             m_escapeChars.clear();
4617             if( startsWith( token, "exclude:" ) ) {
4618                 m_exclusion = true;
4619                 token = token.substr( 8 );
4620             }
4621             if( !token.empty() ) {
4622                 TestSpec::PatternPtr pattern = std::make_shared<T>( token );
4623                 if( m_exclusion )
4624                     pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
4625                 m_currentFilter.m_patterns.push_back( pattern );
4626             }
4627             m_exclusion = false;
4628             m_mode = None;
4629         }
4630 
4631         void addFilter();
4632     };
4633     TestSpec parseTestSpec( std::string const& arg );
4634 
4635 } // namespace Catch
4636 
4637 #ifdef __clang__
4638 #pragma clang diagnostic pop
4639 #endif
4640 
4641 // end catch_test_spec_parser.h
4642 // Libstdc++ doesn't like incomplete classes for unique_ptr
4643 
4644 #include <memory>
4645 #include <vector>
4646 #include <string>
4647 
4648 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
4649 #define CATCH_CONFIG_CONSOLE_WIDTH 80
4650 #endif
4651 
4652 namespace Catch {
4653 
4654     struct IStream;
4655 
4656     struct ConfigData {
4657         bool listTests = false;
4658         bool listTags = false;
4659         bool listReporters = false;
4660         bool listTestNamesOnly = false;
4661 
4662         bool showSuccessfulTests = false;
4663         bool shouldDebugBreak = false;
4664         bool noThrow = false;
4665         bool showHelp = false;
4666         bool showInvisibles = false;
4667         bool filenamesAsTags = false;
4668         bool libIdentify = false;
4669 
4670         int abortAfter = -1;
4671         unsigned int rngSeed = 0;
4672         int benchmarkResolutionMultiple = 100;
4673 
4674         Verbosity verbosity = Verbosity::Normal;
4675         WarnAbout::What warnings = WarnAbout::Nothing;
4676         ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
4677         RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
4678         UseColour::YesOrNo useColour = UseColour::Auto;
4679         WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
4680 
4681         std::string outputFilename;
4682         std::string name;
4683         std::string processName;
4684 #ifndef CATCH_CONFIG_DEFAULT_REPORTER
4685 #define CATCH_CONFIG_DEFAULT_REPORTER "console"
4686 #endif
4687         std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
4688 #undef CATCH_CONFIG_DEFAULT_REPORTER
4689 
4690         std::vector<std::string> testsOrTags;
4691         std::vector<std::string> sectionsToRun;
4692     };
4693 
4694     class Config : public IConfig {
4695     public:
4696 
4697         Config() = default;
4698         Config( ConfigData const& data );
4699         virtual ~Config() = default;
4700 
4701         std::string const& getFilename() const;
4702 
4703         bool listTests() const;
4704         bool listTestNamesOnly() const;
4705         bool listTags() const;
4706         bool listReporters() const;
4707 
4708         std::string getProcessName() const;
4709         std::string const& getReporterName() const;
4710 
4711         std::vector<std::string> const& getTestsOrTags() const;
4712         std::vector<std::string> const& getSectionsToRun() const override;
4713 
4714         virtual TestSpec const& testSpec() const override;
4715         bool hasTestFilters() const override;
4716 
4717         bool showHelp() const;
4718 
4719         // IConfig interface
4720         bool allowThrows() const override;
4721         std::ostream& stream() const override;
4722         std::string name() const override;
4723         bool includeSuccessfulResults() const override;
4724         bool warnAboutMissingAssertions() const override;
4725         bool warnAboutNoTests() const override;
4726         ShowDurations::OrNot showDurations() const override;
4727         RunTests::InWhatOrder runOrder() const override;
4728         unsigned int rngSeed() const override;
4729         int benchmarkResolutionMultiple() const override;
4730         UseColour::YesOrNo useColour() const override;
4731         bool shouldDebugBreak() const override;
4732         int abortAfter() const override;
4733         bool showInvisibles() const override;
4734         Verbosity verbosity() const override;
4735 
4736     private:
4737 
4738         IStream const* openStream();
4739         ConfigData m_data;
4740 
4741         std::unique_ptr<IStream const> m_stream;
4742         TestSpec m_testSpec;
4743         bool m_hasTestFilters = false;
4744     };
4745 
4746 } // end namespace Catch
4747 
4748 // end catch_config.hpp
4749 // start catch_assertionresult.h
4750 
4751 #include <string>
4752 
4753 namespace Catch {
4754 
4755     struct AssertionResultData
4756     {
4757         AssertionResultData() = delete;
4758 
4759         AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
4760 
4761         std::string message;
4762         mutable std::string reconstructedExpression;
4763         LazyExpression lazyExpression;
4764         ResultWas::OfType resultType;
4765 
4766         std::string reconstructExpression() const;
4767     };
4768 
4769     class AssertionResult {
4770     public:
4771         AssertionResult() = delete;
4772         AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
4773 
4774         bool isOk() const;
4775         bool succeeded() const;
4776         ResultWas::OfType getResultType() const;
4777         bool hasExpression() const;
4778         bool hasMessage() const;
4779         std::string getExpression() const;
4780         std::string getExpressionInMacro() const;
4781         bool hasExpandedExpression() const;
4782         std::string getExpandedExpression() const;
4783         std::string getMessage() const;
4784         SourceLineInfo getSourceInfo() const;
4785         StringRef getTestMacroName() const;
4786 
4787     //protected:
4788         AssertionInfo m_info;
4789         AssertionResultData m_resultData;
4790     };
4791 
4792 } // end namespace Catch
4793 
4794 // end catch_assertionresult.h
4795 // start catch_option.hpp
4796 
4797 namespace Catch {
4798 
4799     // An optional type
4800     template<typename T>
4801     class Option {
4802     public:
Option()4803         Option() : nullableValue( nullptr ) {}
Option(T const & _value)4804         Option( T const& _value )
4805         : nullableValue( new( storage ) T( _value ) )
4806         {}
Option(Option const & _other)4807         Option( Option const& _other )
4808         : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )
4809         {}
4810 
~Option()4811         ~Option() {
4812             reset();
4813         }
4814 
operator =(Option const & _other)4815         Option& operator= ( Option const& _other ) {
4816             if( &_other != this ) {
4817                 reset();
4818                 if( _other )
4819                     nullableValue = new( storage ) T( *_other );
4820             }
4821             return *this;
4822         }
operator =(T const & _value)4823         Option& operator = ( T const& _value ) {
4824             reset();
4825             nullableValue = new( storage ) T( _value );
4826             return *this;
4827         }
4828 
reset()4829         void reset() {
4830             if( nullableValue )
4831                 nullableValue->~T();
4832             nullableValue = nullptr;
4833         }
4834 
operator *()4835         T& operator*() { return *nullableValue; }
operator *() const4836         T const& operator*() const { return *nullableValue; }
operator ->()4837         T* operator->() { return nullableValue; }
operator ->() const4838         const T* operator->() const { return nullableValue; }
4839 
valueOr(T const & defaultValue) const4840         T valueOr( T const& defaultValue ) const {
4841             return nullableValue ? *nullableValue : defaultValue;
4842         }
4843 
some() const4844         bool some() const { return nullableValue != nullptr; }
none() const4845         bool none() const { return nullableValue == nullptr; }
4846 
operator !() const4847         bool operator !() const { return nullableValue == nullptr; }
operator bool() const4848         explicit operator bool() const {
4849             return some();
4850         }
4851 
4852     private:
4853         T *nullableValue;
4854         alignas(alignof(T)) char storage[sizeof(T)];
4855     };
4856 
4857 } // end namespace Catch
4858 
4859 // end catch_option.hpp
4860 #include <string>
4861 #include <iosfwd>
4862 #include <map>
4863 #include <set>
4864 #include <memory>
4865 
4866 namespace Catch {
4867 
4868     struct ReporterConfig {
4869         explicit ReporterConfig( IConfigPtr const& _fullConfig );
4870 
4871         ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream );
4872 
4873         std::ostream& stream() const;
4874         IConfigPtr fullConfig() const;
4875 
4876     private:
4877         std::ostream* m_stream;
4878         IConfigPtr m_fullConfig;
4879     };
4880 
4881     struct ReporterPreferences {
4882         bool shouldRedirectStdOut = false;
4883         bool shouldReportAllAssertions = false;
4884     };
4885 
4886     template<typename T>
4887     struct LazyStat : Option<T> {
operator =Catch::LazyStat4888         LazyStat& operator=( T const& _value ) {
4889             Option<T>::operator=( _value );
4890             used = false;
4891             return *this;
4892         }
resetCatch::LazyStat4893         void reset() {
4894             Option<T>::reset();
4895             used = false;
4896         }
4897         bool used = false;
4898     };
4899 
4900     struct TestRunInfo {
4901         TestRunInfo( std::string const& _name );
4902         std::string name;
4903     };
4904     struct GroupInfo {
4905         GroupInfo(  std::string const& _name,
4906                     std::size_t _groupIndex,
4907                     std::size_t _groupsCount );
4908 
4909         std::string name;
4910         std::size_t groupIndex;
4911         std::size_t groupsCounts;
4912     };
4913 
4914     struct AssertionStats {
4915         AssertionStats( AssertionResult const& _assertionResult,
4916                         std::vector<MessageInfo> const& _infoMessages,
4917                         Totals const& _totals );
4918 
4919         AssertionStats( AssertionStats const& )              = default;
4920         AssertionStats( AssertionStats && )                  = default;
4921         AssertionStats& operator = ( AssertionStats const& ) = delete;
4922         AssertionStats& operator = ( AssertionStats && )     = delete;
4923         virtual ~AssertionStats();
4924 
4925         AssertionResult assertionResult;
4926         std::vector<MessageInfo> infoMessages;
4927         Totals totals;
4928     };
4929 
4930     struct SectionStats {
4931         SectionStats(   SectionInfo const& _sectionInfo,
4932                         Counts const& _assertions,
4933                         double _durationInSeconds,
4934                         bool _missingAssertions );
4935         SectionStats( SectionStats const& )              = default;
4936         SectionStats( SectionStats && )                  = default;
4937         SectionStats& operator = ( SectionStats const& ) = default;
4938         SectionStats& operator = ( SectionStats && )     = default;
4939         virtual ~SectionStats();
4940 
4941         SectionInfo sectionInfo;
4942         Counts assertions;
4943         double durationInSeconds;
4944         bool missingAssertions;
4945     };
4946 
4947     struct TestCaseStats {
4948         TestCaseStats(  TestCaseInfo const& _testInfo,
4949                         Totals const& _totals,
4950                         std::string const& _stdOut,
4951                         std::string const& _stdErr,
4952                         bool _aborting );
4953 
4954         TestCaseStats( TestCaseStats const& )              = default;
4955         TestCaseStats( TestCaseStats && )                  = default;
4956         TestCaseStats& operator = ( TestCaseStats const& ) = default;
4957         TestCaseStats& operator = ( TestCaseStats && )     = default;
4958         virtual ~TestCaseStats();
4959 
4960         TestCaseInfo testInfo;
4961         Totals totals;
4962         std::string stdOut;
4963         std::string stdErr;
4964         bool aborting;
4965     };
4966 
4967     struct TestGroupStats {
4968         TestGroupStats( GroupInfo const& _groupInfo,
4969                         Totals const& _totals,
4970                         bool _aborting );
4971         TestGroupStats( GroupInfo const& _groupInfo );
4972 
4973         TestGroupStats( TestGroupStats const& )              = default;
4974         TestGroupStats( TestGroupStats && )                  = default;
4975         TestGroupStats& operator = ( TestGroupStats const& ) = default;
4976         TestGroupStats& operator = ( TestGroupStats && )     = default;
4977         virtual ~TestGroupStats();
4978 
4979         GroupInfo groupInfo;
4980         Totals totals;
4981         bool aborting;
4982     };
4983 
4984     struct TestRunStats {
4985         TestRunStats(   TestRunInfo const& _runInfo,
4986                         Totals const& _totals,
4987                         bool _aborting );
4988 
4989         TestRunStats( TestRunStats const& )              = default;
4990         TestRunStats( TestRunStats && )                  = default;
4991         TestRunStats& operator = ( TestRunStats const& ) = default;
4992         TestRunStats& operator = ( TestRunStats && )     = default;
4993         virtual ~TestRunStats();
4994 
4995         TestRunInfo runInfo;
4996         Totals totals;
4997         bool aborting;
4998     };
4999 
5000     struct BenchmarkInfo {
5001         std::string name;
5002     };
5003     struct BenchmarkStats {
5004         BenchmarkInfo info;
5005         std::size_t iterations;
5006         uint64_t elapsedTimeInNanoseconds;
5007     };
5008 
5009     struct IStreamingReporter {
5010         virtual ~IStreamingReporter() = default;
5011 
5012         // Implementing class must also provide the following static methods:
5013         // static std::string getDescription();
5014         // static std::set<Verbosity> getSupportedVerbosities()
5015 
5016         virtual ReporterPreferences getPreferences() const = 0;
5017 
5018         virtual void noMatchingTestCases( std::string const& spec ) = 0;
5019 
5020         virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5021         virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5022 
5023         virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5024         virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5025 
5026         // *** experimental ***
benchmarkStartingCatch::IStreamingReporter5027         virtual void benchmarkStarting( BenchmarkInfo const& ) {}
5028 
5029         virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5030 
5031         // The return value indicates if the messages buffer should be cleared:
5032         virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
5033 
5034         // *** experimental ***
benchmarkEndedCatch::IStreamingReporter5035         virtual void benchmarkEnded( BenchmarkStats const& ) {}
5036 
5037         virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5038         virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5039         virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5040         virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
5041 
5042         virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
5043 
5044         // Default empty implementation provided
5045         virtual void fatalErrorEncountered( StringRef name );
5046 
5047         virtual bool isMulti() const;
5048     };
5049     using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
5050 
5051     struct IReporterFactory {
5052         virtual ~IReporterFactory();
5053         virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0;
5054         virtual std::string getDescription() const = 0;
5055     };
5056     using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
5057 
5058     struct IReporterRegistry {
5059         using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
5060         using Listeners = std::vector<IReporterFactoryPtr>;
5061 
5062         virtual ~IReporterRegistry();
5063         virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0;
5064         virtual FactoryMap const& getFactories() const = 0;
5065         virtual Listeners const& getListeners() const = 0;
5066     };
5067 
5068 } // end namespace Catch
5069 
5070 // end catch_interfaces_reporter.h
5071 #include <algorithm>
5072 #include <cstring>
5073 #include <cfloat>
5074 #include <cstdio>
5075 #include <cassert>
5076 #include <memory>
5077 #include <ostream>
5078 
5079 namespace Catch {
5080     void prepareExpandedExpression(AssertionResult& result);
5081 
5082     // Returns double formatted as %.3f (format expected on output)
5083     std::string getFormattedDuration( double duration );
5084 
5085     template<typename DerivedT>
5086     struct StreamingReporterBase : IStreamingReporter {
5087 
StreamingReporterBaseCatch::StreamingReporterBase5088         StreamingReporterBase( ReporterConfig const& _config )
5089         :   m_config( _config.fullConfig() ),
5090             stream( _config.stream() )
5091         {
5092             m_reporterPrefs.shouldRedirectStdOut = false;
5093             if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
5094                 CATCH_ERROR( "Verbosity level not supported by this reporter" );
5095         }
5096 
getPreferencesCatch::StreamingReporterBase5097         ReporterPreferences getPreferences() const override {
5098             return m_reporterPrefs;
5099         }
5100 
getSupportedVerbositiesCatch::StreamingReporterBase5101         static std::set<Verbosity> getSupportedVerbosities() {
5102             return { Verbosity::Normal };
5103         }
5104 
5105         ~StreamingReporterBase() override = default;
5106 
noMatchingTestCasesCatch::StreamingReporterBase5107         void noMatchingTestCases(std::string const&) override {}
5108 
testRunStartingCatch::StreamingReporterBase5109         void testRunStarting(TestRunInfo const& _testRunInfo) override {
5110             currentTestRunInfo = _testRunInfo;
5111         }
testGroupStartingCatch::StreamingReporterBase5112         void testGroupStarting(GroupInfo const& _groupInfo) override {
5113             currentGroupInfo = _groupInfo;
5114         }
5115 
testCaseStartingCatch::StreamingReporterBase5116         void testCaseStarting(TestCaseInfo const& _testInfo) override  {
5117             currentTestCaseInfo = _testInfo;
5118         }
sectionStartingCatch::StreamingReporterBase5119         void sectionStarting(SectionInfo const& _sectionInfo) override {
5120             m_sectionStack.push_back(_sectionInfo);
5121         }
5122 
sectionEndedCatch::StreamingReporterBase5123         void sectionEnded(SectionStats const& /* _sectionStats */) override {
5124             m_sectionStack.pop_back();
5125         }
testCaseEndedCatch::StreamingReporterBase5126         void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
5127             currentTestCaseInfo.reset();
5128         }
testGroupEndedCatch::StreamingReporterBase5129         void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override {
5130             currentGroupInfo.reset();
5131         }
testRunEndedCatch::StreamingReporterBase5132         void testRunEnded(TestRunStats const& /* _testRunStats */) override {
5133             currentTestCaseInfo.reset();
5134             currentGroupInfo.reset();
5135             currentTestRunInfo.reset();
5136         }
5137 
skipTestCatch::StreamingReporterBase5138         void skipTest(TestCaseInfo const&) override {
5139             // Don't do anything with this by default.
5140             // It can optionally be overridden in the derived class.
5141         }
5142 
5143         IConfigPtr m_config;
5144         std::ostream& stream;
5145 
5146         LazyStat<TestRunInfo> currentTestRunInfo;
5147         LazyStat<GroupInfo> currentGroupInfo;
5148         LazyStat<TestCaseInfo> currentTestCaseInfo;
5149 
5150         std::vector<SectionInfo> m_sectionStack;
5151         ReporterPreferences m_reporterPrefs;
5152     };
5153 
5154     template<typename DerivedT>
5155     struct CumulativeReporterBase : IStreamingReporter {
5156         template<typename T, typename ChildNodeT>
5157         struct Node {
NodeCatch::CumulativeReporterBase::Node5158             explicit Node( T const& _value ) : value( _value ) {}
~NodeCatch::CumulativeReporterBase::Node5159             virtual ~Node() {}
5160 
5161             using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
5162             T value;
5163             ChildNodes children;
5164         };
5165         struct SectionNode {
SectionNodeCatch::CumulativeReporterBase::SectionNode5166             explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
5167             virtual ~SectionNode() = default;
5168 
operator ==Catch::CumulativeReporterBase::SectionNode5169             bool operator == (SectionNode const& other) const {
5170                 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
5171             }
operator ==Catch::CumulativeReporterBase::SectionNode5172             bool operator == (std::shared_ptr<SectionNode> const& other) const {
5173                 return operator==(*other);
5174             }
5175 
5176             SectionStats stats;
5177             using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
5178             using Assertions = std::vector<AssertionStats>;
5179             ChildSections childSections;
5180             Assertions assertions;
5181             std::string stdOut;
5182             std::string stdErr;
5183         };
5184 
5185         struct BySectionInfo {
BySectionInfoCatch::CumulativeReporterBase::BySectionInfo5186             BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
BySectionInfoCatch::CumulativeReporterBase::BySectionInfo5187             BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
operator ()Catch::CumulativeReporterBase::BySectionInfo5188             bool operator() (std::shared_ptr<SectionNode> const& node) const {
5189                 return ((node->stats.sectionInfo.name == m_other.name) &&
5190                         (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
5191             }
5192             void operator=(BySectionInfo const&) = delete;
5193 
5194         private:
5195             SectionInfo const& m_other;
5196         };
5197 
5198         using TestCaseNode = Node<TestCaseStats, SectionNode>;
5199         using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
5200         using TestRunNode = Node<TestRunStats, TestGroupNode>;
5201 
CumulativeReporterBaseCatch::CumulativeReporterBase5202         CumulativeReporterBase( ReporterConfig const& _config )
5203         :   m_config( _config.fullConfig() ),
5204             stream( _config.stream() )
5205         {
5206             m_reporterPrefs.shouldRedirectStdOut = false;
5207             if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
5208                 CATCH_ERROR( "Verbosity level not supported by this reporter" );
5209         }
5210         ~CumulativeReporterBase() override = default;
5211 
getPreferencesCatch::CumulativeReporterBase5212         ReporterPreferences getPreferences() const override {
5213             return m_reporterPrefs;
5214         }
5215 
getSupportedVerbositiesCatch::CumulativeReporterBase5216         static std::set<Verbosity> getSupportedVerbosities() {
5217             return { Verbosity::Normal };
5218         }
5219 
testRunStartingCatch::CumulativeReporterBase5220         void testRunStarting( TestRunInfo const& ) override {}
testGroupStartingCatch::CumulativeReporterBase5221         void testGroupStarting( GroupInfo const& ) override {}
5222 
testCaseStartingCatch::CumulativeReporterBase5223         void testCaseStarting( TestCaseInfo const& ) override {}
5224 
sectionStartingCatch::CumulativeReporterBase5225         void sectionStarting( SectionInfo const& sectionInfo ) override {
5226             SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
5227             std::shared_ptr<SectionNode> node;
5228             if( m_sectionStack.empty() ) {
5229                 if( !m_rootSection )
5230                     m_rootSection = std::make_shared<SectionNode>( incompleteStats );
5231                 node = m_rootSection;
5232             }
5233             else {
5234                 SectionNode& parentNode = *m_sectionStack.back();
5235                 auto it =
5236                     std::find_if(   parentNode.childSections.begin(),
5237                                     parentNode.childSections.end(),
5238                                     BySectionInfo( sectionInfo ) );
5239                 if( it == parentNode.childSections.end() ) {
5240                     node = std::make_shared<SectionNode>( incompleteStats );
5241                     parentNode.childSections.push_back( node );
5242                 }
5243                 else
5244                     node = *it;
5245             }
5246             m_sectionStack.push_back( node );
5247             m_deepestSection = std::move(node);
5248         }
5249 
assertionStartingCatch::CumulativeReporterBase5250         void assertionStarting(AssertionInfo const&) override {}
5251 
assertionEndedCatch::CumulativeReporterBase5252         bool assertionEnded(AssertionStats const& assertionStats) override {
5253             assert(!m_sectionStack.empty());
5254             // AssertionResult holds a pointer to a temporary DecomposedExpression,
5255             // which getExpandedExpression() calls to build the expression string.
5256             // Our section stack copy of the assertionResult will likely outlive the
5257             // temporary, so it must be expanded or discarded now to avoid calling
5258             // a destroyed object later.
5259             prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );
5260             SectionNode& sectionNode = *m_sectionStack.back();
5261             sectionNode.assertions.push_back(assertionStats);
5262             return true;
5263         }
sectionEndedCatch::CumulativeReporterBase5264         void sectionEnded(SectionStats const& sectionStats) override {
5265             assert(!m_sectionStack.empty());
5266             SectionNode& node = *m_sectionStack.back();
5267             node.stats = sectionStats;
5268             m_sectionStack.pop_back();
5269         }
testCaseEndedCatch::CumulativeReporterBase5270         void testCaseEnded(TestCaseStats const& testCaseStats) override {
5271             auto node = std::make_shared<TestCaseNode>(testCaseStats);
5272             assert(m_sectionStack.size() == 0);
5273             node->children.push_back(m_rootSection);
5274             m_testCases.push_back(node);
5275             m_rootSection.reset();
5276 
5277             assert(m_deepestSection);
5278             m_deepestSection->stdOut = testCaseStats.stdOut;
5279             m_deepestSection->stdErr = testCaseStats.stdErr;
5280         }
testGroupEndedCatch::CumulativeReporterBase5281         void testGroupEnded(TestGroupStats const& testGroupStats) override {
5282             auto node = std::make_shared<TestGroupNode>(testGroupStats);
5283             node->children.swap(m_testCases);
5284             m_testGroups.push_back(node);
5285         }
testRunEndedCatch::CumulativeReporterBase5286         void testRunEnded(TestRunStats const& testRunStats) override {
5287             auto node = std::make_shared<TestRunNode>(testRunStats);
5288             node->children.swap(m_testGroups);
5289             m_testRuns.push_back(node);
5290             testRunEndedCumulative();
5291         }
5292         virtual void testRunEndedCumulative() = 0;
5293 
skipTestCatch::CumulativeReporterBase5294         void skipTest(TestCaseInfo const&) override {}
5295 
5296         IConfigPtr m_config;
5297         std::ostream& stream;
5298         std::vector<AssertionStats> m_assertions;
5299         std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
5300         std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
5301         std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
5302 
5303         std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
5304 
5305         std::shared_ptr<SectionNode> m_rootSection;
5306         std::shared_ptr<SectionNode> m_deepestSection;
5307         std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
5308         ReporterPreferences m_reporterPrefs;
5309     };
5310 
5311     template<char C>
getLineOfChars()5312     char const* getLineOfChars() {
5313         static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
5314         if( !*line ) {
5315             std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
5316             line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
5317         }
5318         return line;
5319     }
5320 
5321     struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
5322         TestEventListenerBase( ReporterConfig const& _config );
5323 
5324         static std::set<Verbosity> getSupportedVerbosities();
5325 
5326         void assertionStarting(AssertionInfo const&) override;
5327         bool assertionEnded(AssertionStats const&) override;
5328     };
5329 
5330 } // end namespace Catch
5331 
5332 // end catch_reporter_bases.hpp
5333 // start catch_console_colour.h
5334 
5335 namespace Catch {
5336 
5337     struct Colour {
5338         enum Code {
5339             None = 0,
5340 
5341             White,
5342             Red,
5343             Green,
5344             Blue,
5345             Cyan,
5346             Yellow,
5347             Grey,
5348 
5349             Bright = 0x10,
5350 
5351             BrightRed = Bright | Red,
5352             BrightGreen = Bright | Green,
5353             LightGrey = Bright | Grey,
5354             BrightWhite = Bright | White,
5355             BrightYellow = Bright | Yellow,
5356 
5357             // By intention
5358             FileName = LightGrey,
5359             Warning = BrightYellow,
5360             ResultError = BrightRed,
5361             ResultSuccess = BrightGreen,
5362             ResultExpectedFailure = Warning,
5363 
5364             Error = BrightRed,
5365             Success = Green,
5366 
5367             OriginalExpression = Cyan,
5368             ReconstructedExpression = BrightYellow,
5369 
5370             SecondaryText = LightGrey,
5371             Headers = White
5372         };
5373 
5374         // Use constructed object for RAII guard
5375         Colour( Code _colourCode );
5376         Colour( Colour&& other ) noexcept;
5377         Colour& operator=( Colour&& other ) noexcept;
5378         ~Colour();
5379 
5380         // Use static method for one-shot changes
5381         static void use( Code _colourCode );
5382 
5383     private:
5384         bool m_moved = false;
5385     };
5386 
5387     std::ostream& operator << ( std::ostream& os, Colour const& );
5388 
5389 } // end namespace Catch
5390 
5391 // end catch_console_colour.h
5392 // start catch_reporter_registrars.hpp
5393 
5394 
5395 namespace Catch {
5396 
5397     template<typename T>
5398     class ReporterRegistrar {
5399 
5400         class ReporterFactory : public IReporterFactory {
5401 
create(ReporterConfig const & config) const5402             virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
5403                 return std::unique_ptr<T>( new T( config ) );
5404             }
5405 
getDescription() const5406             virtual std::string getDescription() const override {
5407                 return T::getDescription();
5408             }
5409         };
5410 
5411     public:
5412 
ReporterRegistrar(std::string const & name)5413         explicit ReporterRegistrar( std::string const& name ) {
5414             getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() );
5415         }
5416     };
5417 
5418     template<typename T>
5419     class ListenerRegistrar {
5420 
5421         class ListenerFactory : public IReporterFactory {
5422 
create(ReporterConfig const & config) const5423             virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
5424                 return std::unique_ptr<T>( new T( config ) );
5425             }
getDescription() const5426             virtual std::string getDescription() const override {
5427                 return std::string();
5428             }
5429         };
5430 
5431     public:
5432 
ListenerRegistrar()5433         ListenerRegistrar() {
5434             getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() );
5435         }
5436     };
5437 }
5438 
5439 #if !defined(CATCH_CONFIG_DISABLE)
5440 
5441 #define CATCH_REGISTER_REPORTER( name, reporterType ) \
5442     CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS          \
5443     namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
5444     CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
5445 
5446 #define CATCH_REGISTER_LISTENER( listenerType ) \
5447      CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS   \
5448      namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
5449      CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
5450 #else // CATCH_CONFIG_DISABLE
5451 
5452 #define CATCH_REGISTER_REPORTER(name, reporterType)
5453 #define CATCH_REGISTER_LISTENER(listenerType)
5454 
5455 #endif // CATCH_CONFIG_DISABLE
5456 
5457 // end catch_reporter_registrars.hpp
5458 // Allow users to base their work off existing reporters
5459 // start catch_reporter_compact.h
5460 
5461 namespace Catch {
5462 
5463     struct CompactReporter : StreamingReporterBase<CompactReporter> {
5464 
5465         using StreamingReporterBase::StreamingReporterBase;
5466 
5467         ~CompactReporter() override;
5468 
5469         static std::string getDescription();
5470 
5471         ReporterPreferences getPreferences() const override;
5472 
5473         void noMatchingTestCases(std::string const& spec) override;
5474 
5475         void assertionStarting(AssertionInfo const&) override;
5476 
5477         bool assertionEnded(AssertionStats const& _assertionStats) override;
5478 
5479         void sectionEnded(SectionStats const& _sectionStats) override;
5480 
5481         void testRunEnded(TestRunStats const& _testRunStats) override;
5482 
5483     };
5484 
5485 } // end namespace Catch
5486 
5487 // end catch_reporter_compact.h
5488 // start catch_reporter_console.h
5489 
5490 #if defined(_MSC_VER)
5491 #pragma warning(push)
5492 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
5493                               // Note that 4062 (not all labels are handled
5494                               // and default is missing) is enabled
5495 #endif
5496 
5497 namespace Catch {
5498     // Fwd decls
5499     struct SummaryColumn;
5500     class TablePrinter;
5501 
5502     struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
5503         std::unique_ptr<TablePrinter> m_tablePrinter;
5504 
5505         ConsoleReporter(ReporterConfig const& config);
5506         ~ConsoleReporter() override;
5507         static std::string getDescription();
5508 
5509         void noMatchingTestCases(std::string const& spec) override;
5510 
5511         void assertionStarting(AssertionInfo const&) override;
5512 
5513         bool assertionEnded(AssertionStats const& _assertionStats) override;
5514 
5515         void sectionStarting(SectionInfo const& _sectionInfo) override;
5516         void sectionEnded(SectionStats const& _sectionStats) override;
5517 
5518         void benchmarkStarting(BenchmarkInfo const& info) override;
5519         void benchmarkEnded(BenchmarkStats const& stats) override;
5520 
5521         void testCaseEnded(TestCaseStats const& _testCaseStats) override;
5522         void testGroupEnded(TestGroupStats const& _testGroupStats) override;
5523         void testRunEnded(TestRunStats const& _testRunStats) override;
5524 
5525     private:
5526 
5527         void lazyPrint();
5528 
5529         void lazyPrintWithoutClosingBenchmarkTable();
5530         void lazyPrintRunInfo();
5531         void lazyPrintGroupInfo();
5532         void printTestCaseAndSectionHeader();
5533 
5534         void printClosedHeader(std::string const& _name);
5535         void printOpenHeader(std::string const& _name);
5536 
5537         // if string has a : in first line will set indent to follow it on
5538         // subsequent lines
5539         void printHeaderString(std::string const& _string, std::size_t indent = 0);
5540 
5541         void printTotals(Totals const& totals);
5542         void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row);
5543 
5544         void printTotalsDivider(Totals const& totals);
5545         void printSummaryDivider();
5546 
5547     private:
5548         bool m_headerPrinted = false;
5549     };
5550 
5551 } // end namespace Catch
5552 
5553 #if defined(_MSC_VER)
5554 #pragma warning(pop)
5555 #endif
5556 
5557 // end catch_reporter_console.h
5558 // start catch_reporter_junit.h
5559 
5560 // start catch_xmlwriter.h
5561 
5562 #include <vector>
5563 
5564 namespace Catch {
5565 
5566     class XmlEncode {
5567     public:
5568         enum ForWhat { ForTextNodes, ForAttributes };
5569 
5570         XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes );
5571 
5572         void encodeTo( std::ostream& os ) const;
5573 
5574         friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
5575 
5576     private:
5577         std::string m_str;
5578         ForWhat m_forWhat;
5579     };
5580 
5581     class XmlWriter {
5582     public:
5583 
5584         class ScopedElement {
5585         public:
5586             ScopedElement( XmlWriter* writer );
5587 
5588             ScopedElement( ScopedElement&& other ) noexcept;
5589             ScopedElement& operator=( ScopedElement&& other ) noexcept;
5590 
5591             ~ScopedElement();
5592 
5593             ScopedElement& writeText( std::string const& text, bool indent = true );
5594 
5595             template<typename T>
writeAttribute(std::string const & name,T const & attribute)5596             ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
5597                 m_writer->writeAttribute( name, attribute );
5598                 return *this;
5599             }
5600 
5601         private:
5602             mutable XmlWriter* m_writer = nullptr;
5603         };
5604 
5605         XmlWriter( std::ostream& os = Catch::cout() );
5606         ~XmlWriter();
5607 
5608         XmlWriter( XmlWriter const& ) = delete;
5609         XmlWriter& operator=( XmlWriter const& ) = delete;
5610 
5611         XmlWriter& startElement( std::string const& name );
5612 
5613         ScopedElement scopedElement( std::string const& name );
5614 
5615         XmlWriter& endElement();
5616 
5617         XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
5618 
5619         XmlWriter& writeAttribute( std::string const& name, bool attribute );
5620 
5621         template<typename T>
writeAttribute(std::string const & name,T const & attribute)5622         XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
5623             ReusableStringStream rss;
5624             rss << attribute;
5625             return writeAttribute( name, rss.str() );
5626         }
5627 
5628         XmlWriter& writeText( std::string const& text, bool indent = true );
5629 
5630         XmlWriter& writeComment( std::string const& text );
5631 
5632         void writeStylesheetRef( std::string const& url );
5633 
5634         XmlWriter& writeBlankLine();
5635 
5636         void ensureTagClosed();
5637 
5638     private:
5639 
5640         void writeDeclaration();
5641 
5642         void newlineIfNecessary();
5643 
5644         bool m_tagIsOpen = false;
5645         bool m_needsNewline = false;
5646         std::vector<std::string> m_tags;
5647         std::string m_indent;
5648         std::ostream& m_os;
5649     };
5650 
5651 }
5652 
5653 // end catch_xmlwriter.h
5654 namespace Catch {
5655 
5656     class JunitReporter : public CumulativeReporterBase<JunitReporter> {
5657     public:
5658         JunitReporter(ReporterConfig const& _config);
5659 
5660         ~JunitReporter() override;
5661 
5662         static std::string getDescription();
5663 
5664         void noMatchingTestCases(std::string const& /*spec*/) override;
5665 
5666         void testRunStarting(TestRunInfo const& runInfo) override;
5667 
5668         void testGroupStarting(GroupInfo const& groupInfo) override;
5669 
5670         void testCaseStarting(TestCaseInfo const& testCaseInfo) override;
5671         bool assertionEnded(AssertionStats const& assertionStats) override;
5672 
5673         void testCaseEnded(TestCaseStats const& testCaseStats) override;
5674 
5675         void testGroupEnded(TestGroupStats const& testGroupStats) override;
5676 
5677         void testRunEndedCumulative() override;
5678 
5679         void writeGroup(TestGroupNode const& groupNode, double suiteTime);
5680 
5681         void writeTestCase(TestCaseNode const& testCaseNode);
5682 
5683         void writeSection(std::string const& className,
5684                           std::string const& rootName,
5685                           SectionNode const& sectionNode);
5686 
5687         void writeAssertions(SectionNode const& sectionNode);
5688         void writeAssertion(AssertionStats const& stats);
5689 
5690         XmlWriter xml;
5691         Timer suiteTimer;
5692         std::string stdOutForSuite;
5693         std::string stdErrForSuite;
5694         unsigned int unexpectedExceptions = 0;
5695         bool m_okToFail = false;
5696     };
5697 
5698 } // end namespace Catch
5699 
5700 // end catch_reporter_junit.h
5701 // start catch_reporter_xml.h
5702 
5703 namespace Catch {
5704     class XmlReporter : public StreamingReporterBase<XmlReporter> {
5705     public:
5706         XmlReporter(ReporterConfig const& _config);
5707 
5708         ~XmlReporter() override;
5709 
5710         static std::string getDescription();
5711 
5712         virtual std::string getStylesheetRef() const;
5713 
5714         void writeSourceInfo(SourceLineInfo const& sourceInfo);
5715 
5716     public: // StreamingReporterBase
5717 
5718         void noMatchingTestCases(std::string const& s) override;
5719 
5720         void testRunStarting(TestRunInfo const& testInfo) override;
5721 
5722         void testGroupStarting(GroupInfo const& groupInfo) override;
5723 
5724         void testCaseStarting(TestCaseInfo const& testInfo) override;
5725 
5726         void sectionStarting(SectionInfo const& sectionInfo) override;
5727 
5728         void assertionStarting(AssertionInfo const&) override;
5729 
5730         bool assertionEnded(AssertionStats const& assertionStats) override;
5731 
5732         void sectionEnded(SectionStats const& sectionStats) override;
5733 
5734         void testCaseEnded(TestCaseStats const& testCaseStats) override;
5735 
5736         void testGroupEnded(TestGroupStats const& testGroupStats) override;
5737 
5738         void testRunEnded(TestRunStats const& testRunStats) override;
5739 
5740     private:
5741         Timer m_testCaseTimer;
5742         XmlWriter m_xml;
5743         int m_sectionDepth = 0;
5744     };
5745 
5746 } // end namespace Catch
5747 
5748 // end catch_reporter_xml.h
5749 
5750 // end catch_external_interfaces.h
5751 #endif
5752 
5753 #endif // ! CATCH_CONFIG_IMPL_ONLY
5754 
5755 #ifdef CATCH_IMPL
5756 // start catch_impl.hpp
5757 
5758 #ifdef __clang__
5759 #pragma clang diagnostic push
5760 #pragma clang diagnostic ignored "-Wweak-vtables"
5761 #endif
5762 
5763 // Keep these here for external reporters
5764 // start catch_test_case_tracker.h
5765 
5766 #include <string>
5767 #include <vector>
5768 #include <memory>
5769 
5770 namespace Catch {
5771 namespace TestCaseTracking {
5772 
5773     struct NameAndLocation {
5774         std::string name;
5775         SourceLineInfo location;
5776 
5777         NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
5778     };
5779 
5780     struct ITracker;
5781 
5782     using ITrackerPtr = std::shared_ptr<ITracker>;
5783 
5784     struct ITracker {
5785         virtual ~ITracker();
5786 
5787         // static queries
5788         virtual NameAndLocation const& nameAndLocation() const = 0;
5789 
5790         // dynamic queries
5791         virtual bool isComplete() const = 0; // Successfully completed or failed
5792         virtual bool isSuccessfullyCompleted() const = 0;
5793         virtual bool isOpen() const = 0; // Started but not complete
5794         virtual bool hasChildren() const = 0;
5795 
5796         virtual ITracker& parent() = 0;
5797 
5798         // actions
5799         virtual void close() = 0; // Successfully complete
5800         virtual void fail() = 0;
5801         virtual void markAsNeedingAnotherRun() = 0;
5802 
5803         virtual void addChild( ITrackerPtr const& child ) = 0;
5804         virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0;
5805         virtual void openChild() = 0;
5806 
5807         // Debug/ checking
5808         virtual bool isSectionTracker() const = 0;
5809         virtual bool isGeneratorTracker() const = 0;
5810     };
5811 
5812     class TrackerContext {
5813 
5814         enum RunState {
5815             NotStarted,
5816             Executing,
5817             CompletedCycle
5818         };
5819 
5820         ITrackerPtr m_rootTracker;
5821         ITracker* m_currentTracker = nullptr;
5822         RunState m_runState = NotStarted;
5823 
5824     public:
5825 
5826         static TrackerContext& instance();
5827 
5828         ITracker& startRun();
5829         void endRun();
5830 
5831         void startCycle();
5832         void completeCycle();
5833 
5834         bool completedCycle() const;
5835         ITracker& currentTracker();
5836         void setCurrentTracker( ITracker* tracker );
5837     };
5838 
5839     class TrackerBase : public ITracker {
5840     protected:
5841         enum CycleState {
5842             NotStarted,
5843             Executing,
5844             ExecutingChildren,
5845             NeedsAnotherRun,
5846             CompletedSuccessfully,
5847             Failed
5848         };
5849 
5850         using Children = std::vector<ITrackerPtr>;
5851         NameAndLocation m_nameAndLocation;
5852         TrackerContext& m_ctx;
5853         ITracker* m_parent;
5854         Children m_children;
5855         CycleState m_runState = NotStarted;
5856 
5857     public:
5858         TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
5859 
5860         NameAndLocation const& nameAndLocation() const override;
5861         bool isComplete() const override;
5862         bool isSuccessfullyCompleted() const override;
5863         bool isOpen() const override;
5864         bool hasChildren() const override;
5865 
5866         void addChild( ITrackerPtr const& child ) override;
5867 
5868         ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override;
5869         ITracker& parent() override;
5870 
5871         void openChild() override;
5872 
5873         bool isSectionTracker() const override;
5874         bool isGeneratorTracker() const override;
5875 
5876         void open();
5877 
5878         void close() override;
5879         void fail() override;
5880         void markAsNeedingAnotherRun() override;
5881 
5882     private:
5883         void moveToParent();
5884         void moveToThis();
5885     };
5886 
5887     class SectionTracker : public TrackerBase {
5888         std::vector<std::string> m_filters;
5889     public:
5890         SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
5891 
5892         bool isSectionTracker() const override;
5893 
5894         bool isComplete() const override;
5895 
5896         static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
5897 
5898         void tryOpen();
5899 
5900         void addInitialFilters( std::vector<std::string> const& filters );
5901         void addNextFilters( std::vector<std::string> const& filters );
5902     };
5903 
5904 } // namespace TestCaseTracking
5905 
5906 using TestCaseTracking::ITracker;
5907 using TestCaseTracking::TrackerContext;
5908 using TestCaseTracking::SectionTracker;
5909 
5910 } // namespace Catch
5911 
5912 // end catch_test_case_tracker.h
5913 
5914 // start catch_leak_detector.h
5915 
5916 namespace Catch {
5917 
5918     struct LeakDetector {
5919         LeakDetector();
5920         ~LeakDetector();
5921     };
5922 
5923 }
5924 // end catch_leak_detector.h
5925 // Cpp files will be included in the single-header file here
5926 // start catch_approx.cpp
5927 
5928 #include <cmath>
5929 #include <limits>
5930 
5931 namespace {
5932 
5933 // Performs equivalent check of std::fabs(lhs - rhs) <= margin
5934 // But without the subtraction to allow for INFINITY in comparison
marginComparison(double lhs,double rhs,double margin)5935 bool marginComparison(double lhs, double rhs, double margin) {
5936     return (lhs + margin >= rhs) && (rhs + margin >= lhs);
5937 }
5938 
5939 }
5940 
5941 namespace Catch {
5942 namespace Detail {
5943 
Approx(double value)5944     Approx::Approx ( double value )
5945     :   m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
5946         m_margin( 0.0 ),
5947         m_scale( 0.0 ),
5948         m_value( value )
5949     {}
5950 
custom()5951     Approx Approx::custom() {
5952         return Approx( 0 );
5953     }
5954 
operator -() const5955     Approx Approx::operator-() const {
5956         auto temp(*this);
5957         temp.m_value = -temp.m_value;
5958         return temp;
5959     }
5960 
toString() const5961     std::string Approx::toString() const {
5962         ReusableStringStream rss;
5963         rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
5964         return rss.str();
5965     }
5966 
equalityComparisonImpl(const double other) const5967     bool Approx::equalityComparisonImpl(const double other) const {
5968         // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
5969         // Thanks to Richard Harris for his help refining the scaled margin value
5970         return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
5971     }
5972 
setMargin(double margin)5973     void Approx::setMargin(double margin) {
5974         CATCH_ENFORCE(margin >= 0,
5975             "Invalid Approx::margin: " << margin << '.'
5976             << " Approx::Margin has to be non-negative.");
5977         m_margin = margin;
5978     }
5979 
setEpsilon(double epsilon)5980     void Approx::setEpsilon(double epsilon) {
5981         CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0,
5982             "Invalid Approx::epsilon: " << epsilon << '.'
5983             << " Approx::epsilon has to be in [0, 1]");
5984         m_epsilon = epsilon;
5985     }
5986 
5987 } // end namespace Detail
5988 
5989 namespace literals {
operator ""_a(long double val)5990     Detail::Approx operator "" _a(long double val) {
5991         return Detail::Approx(val);
5992     }
operator ""_a(unsigned long long val)5993     Detail::Approx operator "" _a(unsigned long long val) {
5994         return Detail::Approx(val);
5995     }
5996 } // end namespace literals
5997 
convert(Catch::Detail::Approx const & value)5998 std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
5999     return value.toString();
6000 }
6001 
6002 } // end namespace Catch
6003 // end catch_approx.cpp
6004 // start catch_assertionhandler.cpp
6005 
6006 // start catch_debugger.h
6007 
6008 namespace Catch {
6009     bool isDebuggerActive();
6010 }
6011 
6012 #ifdef CATCH_PLATFORM_MAC
6013 
6014     #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
6015 
6016 #elif defined(CATCH_PLATFORM_LINUX)
6017     // If we can use inline assembler, do it because this allows us to break
6018     // directly at the location of the failing check instead of breaking inside
6019     // raise() called from it, i.e. one stack frame below.
6020     #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
6021         #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */
6022     #else // Fall back to the generic way.
6023         #include <signal.h>
6024 
6025         #define CATCH_TRAP() raise(SIGTRAP)
6026     #endif
6027 #elif defined(_MSC_VER)
6028     #define CATCH_TRAP() __debugbreak()
6029 #elif defined(__MINGW32__)
6030     extern "C" __declspec(dllimport) void __stdcall DebugBreak();
6031     #define CATCH_TRAP() DebugBreak()
6032 #endif
6033 
6034 #ifdef CATCH_TRAP
6035     #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
6036 #else
6037     #define CATCH_BREAK_INTO_DEBUGGER() []{}()
6038 #endif
6039 
6040 // end catch_debugger.h
6041 // start catch_run_context.h
6042 
6043 // start catch_fatal_condition.h
6044 
6045 // start catch_windows_h_proxy.h
6046 
6047 
6048 #if defined(CATCH_PLATFORM_WINDOWS)
6049 
6050 #if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
6051 #  define CATCH_DEFINED_NOMINMAX
6052 #  define NOMINMAX
6053 #endif
6054 #if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
6055 #  define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
6056 #  define WIN32_LEAN_AND_MEAN
6057 #endif
6058 
6059 #ifdef __AFXDLL
6060 #include <AfxWin.h>
6061 #else
6062 #include <windows.h>
6063 #endif
6064 
6065 #ifdef CATCH_DEFINED_NOMINMAX
6066 #  undef NOMINMAX
6067 #endif
6068 #ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
6069 #  undef WIN32_LEAN_AND_MEAN
6070 #endif
6071 
6072 #endif // defined(CATCH_PLATFORM_WINDOWS)
6073 
6074 // end catch_windows_h_proxy.h
6075 #if defined( CATCH_CONFIG_WINDOWS_SEH )
6076 
6077 namespace Catch {
6078 
6079     struct FatalConditionHandler {
6080 
6081         static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
6082         FatalConditionHandler();
6083         static void reset();
6084         ~FatalConditionHandler();
6085 
6086     private:
6087         static bool isSet;
6088         static ULONG guaranteeSize;
6089         static PVOID exceptionHandlerHandle;
6090     };
6091 
6092 } // namespace Catch
6093 
6094 #elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
6095 
6096 #include <signal.h>
6097 
6098 namespace Catch {
6099 
6100     struct FatalConditionHandler {
6101 
6102         static bool isSet;
6103         static struct sigaction oldSigActions[];
6104         static stack_t oldSigStack;
6105         static char altStackMem[];
6106 
6107         static void handleSignal( int sig );
6108 
6109         FatalConditionHandler();
6110         ~FatalConditionHandler();
6111         static void reset();
6112     };
6113 
6114 } // namespace Catch
6115 
6116 #else
6117 
6118 namespace Catch {
6119     struct FatalConditionHandler {
6120         void reset();
6121     };
6122 }
6123 
6124 #endif
6125 
6126 // end catch_fatal_condition.h
6127 #include <string>
6128 
6129 namespace Catch {
6130 
6131     struct IMutableContext;
6132 
6133     ///////////////////////////////////////////////////////////////////////////
6134 
6135     class RunContext : public IResultCapture, public IRunner {
6136 
6137     public:
6138         RunContext( RunContext const& ) = delete;
6139         RunContext& operator =( RunContext const& ) = delete;
6140 
6141         explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter );
6142 
6143         ~RunContext() override;
6144 
6145         void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
6146         void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );
6147 
6148         Totals runTest(TestCase const& testCase);
6149 
6150         IConfigPtr config() const;
6151         IStreamingReporter& reporter() const;
6152 
6153     public: // IResultCapture
6154 
6155         // Assertion handlers
6156         void handleExpr
6157                 (   AssertionInfo const& info,
6158                     ITransientExpression const& expr,
6159                     AssertionReaction& reaction ) override;
6160         void handleMessage
6161                 (   AssertionInfo const& info,
6162                     ResultWas::OfType resultType,
6163                     StringRef const& message,
6164                     AssertionReaction& reaction ) override;
6165         void handleUnexpectedExceptionNotThrown
6166                 (   AssertionInfo const& info,
6167                     AssertionReaction& reaction ) override;
6168         void handleUnexpectedInflightException
6169                 (   AssertionInfo const& info,
6170                     std::string const& message,
6171                     AssertionReaction& reaction ) override;
6172         void handleIncomplete
6173                 (   AssertionInfo const& info ) override;
6174         void handleNonExpr
6175                 (   AssertionInfo const &info,
6176                     ResultWas::OfType resultType,
6177                     AssertionReaction &reaction ) override;
6178 
6179         bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;
6180 
6181         void sectionEnded( SectionEndInfo const& endInfo ) override;
6182         void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
6183 
6184         auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;
6185 
6186         void benchmarkStarting( BenchmarkInfo const& info ) override;
6187         void benchmarkEnded( BenchmarkStats const& stats ) override;
6188 
6189         void pushScopedMessage( MessageInfo const& message ) override;
6190         void popScopedMessage( MessageInfo const& message ) override;
6191 
6192         void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
6193 
6194         std::string getCurrentTestName() const override;
6195 
6196         const AssertionResult* getLastResult() const override;
6197 
6198         void exceptionEarlyReported() override;
6199 
6200         void handleFatalErrorCondition( StringRef message ) override;
6201 
6202         bool lastAssertionPassed() override;
6203 
6204         void assertionPassed() override;
6205 
6206     public:
6207         // !TBD We need to do this another way!
6208         bool aborting() const final;
6209 
6210     private:
6211 
6212         void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );
6213         void invokeActiveTestCase();
6214 
6215         void resetAssertionInfo();
6216         bool testForMissingAssertions( Counts& assertions );
6217 
6218         void assertionEnded( AssertionResult const& result );
6219         void reportExpr
6220                 (   AssertionInfo const &info,
6221                     ResultWas::OfType resultType,
6222                     ITransientExpression const *expr,
6223                     bool negated );
6224 
6225         void populateReaction( AssertionReaction& reaction );
6226 
6227     private:
6228 
6229         void handleUnfinishedSections();
6230 
6231         TestRunInfo m_runInfo;
6232         IMutableContext& m_context;
6233         TestCase const* m_activeTestCase = nullptr;
6234         ITracker* m_testCaseTracker = nullptr;
6235         Option<AssertionResult> m_lastResult;
6236 
6237         IConfigPtr m_config;
6238         Totals m_totals;
6239         IStreamingReporterPtr m_reporter;
6240         std::vector<MessageInfo> m_messages;
6241         std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
6242         AssertionInfo m_lastAssertionInfo;
6243         std::vector<SectionEndInfo> m_unfinishedSections;
6244         std::vector<ITracker*> m_activeSections;
6245         TrackerContext m_trackerContext;
6246         bool m_lastAssertionPassed = false;
6247         bool m_shouldReportUnexpected = true;
6248         bool m_includeSuccessfulResults;
6249     };
6250 
6251 } // end namespace Catch
6252 
6253 // end catch_run_context.h
6254 namespace Catch {
6255 
6256     namespace {
operator <<(std::ostream & os,ITransientExpression const & expr)6257         auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
6258             expr.streamReconstructedExpression( os );
6259             return os;
6260         }
6261     }
6262 
LazyExpression(bool isNegated)6263     LazyExpression::LazyExpression( bool isNegated )
6264     :   m_isNegated( isNegated )
6265     {}
6266 
LazyExpression(LazyExpression const & other)6267     LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {}
6268 
operator bool() const6269     LazyExpression::operator bool() const {
6270         return m_transientExpression != nullptr;
6271     }
6272 
operator <<(std::ostream & os,LazyExpression const & lazyExpr)6273     auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& {
6274         if( lazyExpr.m_isNegated )
6275             os << "!";
6276 
6277         if( lazyExpr ) {
6278             if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
6279                 os << "(" << *lazyExpr.m_transientExpression << ")";
6280             else
6281                 os << *lazyExpr.m_transientExpression;
6282         }
6283         else {
6284             os << "{** error - unchecked empty expression requested **}";
6285         }
6286         return os;
6287     }
6288 
AssertionHandler(StringRef const & macroName,SourceLineInfo const & lineInfo,StringRef capturedExpression,ResultDisposition::Flags resultDisposition)6289     AssertionHandler::AssertionHandler
6290         (   StringRef const& macroName,
6291             SourceLineInfo const& lineInfo,
6292             StringRef capturedExpression,
6293             ResultDisposition::Flags resultDisposition )
6294     :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
6295         m_resultCapture( getResultCapture() )
6296     {}
6297 
handleExpr(ITransientExpression const & expr)6298     void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
6299         m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
6300     }
handleMessage(ResultWas::OfType resultType,StringRef const & message)6301     void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) {
6302         m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
6303     }
6304 
allowThrows() const6305     auto AssertionHandler::allowThrows() const -> bool {
6306         return getCurrentContext().getConfig()->allowThrows();
6307     }
6308 
complete()6309     void AssertionHandler::complete() {
6310         setCompleted();
6311         if( m_reaction.shouldDebugBreak ) {
6312 
6313             // If you find your debugger stopping you here then go one level up on the
6314             // call-stack for the code that caused it (typically a failed assertion)
6315 
6316             // (To go back to the test and change execution, jump over the throw, next)
6317             CATCH_BREAK_INTO_DEBUGGER();
6318         }
6319         if (m_reaction.shouldThrow) {
6320 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
6321             throw Catch::TestFailureException();
6322 #else
6323             CATCH_ERROR( "Test failure requires aborting test!" );
6324 #endif
6325         }
6326     }
setCompleted()6327     void AssertionHandler::setCompleted() {
6328         m_completed = true;
6329     }
6330 
handleUnexpectedInflightException()6331     void AssertionHandler::handleUnexpectedInflightException() {
6332         m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
6333     }
6334 
handleExceptionThrownAsExpected()6335     void AssertionHandler::handleExceptionThrownAsExpected() {
6336         m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
6337     }
handleExceptionNotThrownAsExpected()6338     void AssertionHandler::handleExceptionNotThrownAsExpected() {
6339         m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
6340     }
6341 
handleUnexpectedExceptionNotThrown()6342     void AssertionHandler::handleUnexpectedExceptionNotThrown() {
6343         m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
6344     }
6345 
handleThrowingCallSkipped()6346     void AssertionHandler::handleThrowingCallSkipped() {
6347         m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
6348     }
6349 
6350     // This is the overload that takes a string and infers the Equals matcher from it
6351     // 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)6352     void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString  ) {
6353         handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
6354     }
6355 
6356 } // namespace Catch
6357 // end catch_assertionhandler.cpp
6358 // start catch_assertionresult.cpp
6359 
6360 namespace Catch {
AssertionResultData(ResultWas::OfType _resultType,LazyExpression const & _lazyExpression)6361     AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):
6362         lazyExpression(_lazyExpression),
6363         resultType(_resultType) {}
6364 
reconstructExpression() const6365     std::string AssertionResultData::reconstructExpression() const {
6366 
6367         if( reconstructedExpression.empty() ) {
6368             if( lazyExpression ) {
6369                 ReusableStringStream rss;
6370                 rss << lazyExpression;
6371                 reconstructedExpression = rss.str();
6372             }
6373         }
6374         return reconstructedExpression;
6375     }
6376 
AssertionResult(AssertionInfo const & info,AssertionResultData const & data)6377     AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
6378     :   m_info( info ),
6379         m_resultData( data )
6380     {}
6381 
6382     // Result was a success
succeeded() const6383     bool AssertionResult::succeeded() const {
6384         return Catch::isOk( m_resultData.resultType );
6385     }
6386 
6387     // Result was a success, or failure is suppressed
isOk() const6388     bool AssertionResult::isOk() const {
6389         return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
6390     }
6391 
getResultType() const6392     ResultWas::OfType AssertionResult::getResultType() const {
6393         return m_resultData.resultType;
6394     }
6395 
hasExpression() const6396     bool AssertionResult::hasExpression() const {
6397         return m_info.capturedExpression[0] != 0;
6398     }
6399 
hasMessage() const6400     bool AssertionResult::hasMessage() const {
6401         return !m_resultData.message.empty();
6402     }
6403 
getExpression() const6404     std::string AssertionResult::getExpression() const {
6405         if( isFalseTest( m_info.resultDisposition ) )
6406             return "!(" + m_info.capturedExpression + ")";
6407         else
6408             return m_info.capturedExpression;
6409     }
6410 
getExpressionInMacro() const6411     std::string AssertionResult::getExpressionInMacro() const {
6412         std::string expr;
6413         if( m_info.macroName[0] == 0 )
6414             expr = m_info.capturedExpression;
6415         else {
6416             expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
6417             expr += m_info.macroName;
6418             expr += "( ";
6419             expr += m_info.capturedExpression;
6420             expr += " )";
6421         }
6422         return expr;
6423     }
6424 
hasExpandedExpression() const6425     bool AssertionResult::hasExpandedExpression() const {
6426         return hasExpression() && getExpandedExpression() != getExpression();
6427     }
6428 
getExpandedExpression() const6429     std::string AssertionResult::getExpandedExpression() const {
6430         std::string expr = m_resultData.reconstructExpression();
6431         return expr.empty()
6432                 ? getExpression()
6433                 : expr;
6434     }
6435 
getMessage() const6436     std::string AssertionResult::getMessage() const {
6437         return m_resultData.message;
6438     }
getSourceInfo() const6439     SourceLineInfo AssertionResult::getSourceInfo() const {
6440         return m_info.lineInfo;
6441     }
6442 
getTestMacroName() const6443     StringRef AssertionResult::getTestMacroName() const {
6444         return m_info.macroName;
6445     }
6446 
6447 } // end namespace Catch
6448 // end catch_assertionresult.cpp
6449 // start catch_benchmark.cpp
6450 
6451 namespace Catch {
6452 
getResolution()6453     auto BenchmarkLooper::getResolution() -> uint64_t {
6454         return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple();
6455     }
6456 
reportStart()6457     void BenchmarkLooper::reportStart() {
6458         getResultCapture().benchmarkStarting( { m_name } );
6459     }
needsMoreIterations()6460     auto BenchmarkLooper::needsMoreIterations() -> bool {
6461         auto elapsed = m_timer.getElapsedNanoseconds();
6462 
6463         // Exponentially increasing iterations until we're confident in our timer resolution
6464         if( elapsed < m_resolution ) {
6465             m_iterationsToRun *= 10;
6466             return true;
6467         }
6468 
6469         getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } );
6470         return false;
6471     }
6472 
6473 } // end namespace Catch
6474 // end catch_benchmark.cpp
6475 // start catch_capture_matchers.cpp
6476 
6477 namespace Catch {
6478 
6479     using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
6480 
6481     // This is the general overload that takes a any string matcher
6482     // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
6483     // the Equals matcher (so the header does not mention matchers)
handleExceptionMatchExpr(AssertionHandler & handler,StringMatcher const & matcher,StringRef const & matcherString)6484     void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  ) {
6485         std::string exceptionMessage = Catch::translateActiveException();
6486         MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
6487         handler.handleExpr( expr );
6488     }
6489 
6490 } // namespace Catch
6491 // end catch_capture_matchers.cpp
6492 // start catch_commandline.cpp
6493 
6494 // start catch_commandline.h
6495 
6496 // start catch_clara.h
6497 
6498 // Use Catch's value for console width (store Clara's off to the side, if present)
6499 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
6500 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6501 #undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6502 #endif
6503 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
6504 
6505 #ifdef __clang__
6506 #pragma clang diagnostic push
6507 #pragma clang diagnostic ignored "-Wweak-vtables"
6508 #pragma clang diagnostic ignored "-Wexit-time-destructors"
6509 #pragma clang diagnostic ignored "-Wshadow"
6510 #endif
6511 
6512 // start clara.hpp
6513 // Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
6514 //
6515 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6516 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6517 //
6518 // See https://github.com/philsquared/Clara for more details
6519 
6520 // Clara v1.1.5
6521 
6522 
6523 #ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
6524 #define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
6525 #endif
6526 
6527 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6528 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
6529 #endif
6530 
6531 #ifndef CLARA_CONFIG_OPTIONAL_TYPE
6532 #ifdef __has_include
6533 #if __has_include(<optional>) && __cplusplus >= 201703L
6534 #include <optional>
6535 #define CLARA_CONFIG_OPTIONAL_TYPE std::optional
6536 #endif
6537 #endif
6538 #endif
6539 
6540 // ----------- #included from clara_textflow.hpp -----------
6541 
6542 // TextFlowCpp
6543 //
6544 // A single-header library for wrapping and laying out basic text, by Phil Nash
6545 //
6546 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6547 // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6548 //
6549 // This project is hosted at https://github.com/philsquared/textflowcpp
6550 
6551 
6552 #include <cassert>
6553 #include <ostream>
6554 #include <sstream>
6555 #include <vector>
6556 
6557 #ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6558 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
6559 #endif
6560 
6561 namespace Catch {
6562 namespace clara {
6563 namespace TextFlow {
6564 
isWhitespace(char c)6565 inline auto isWhitespace(char c) -> bool {
6566 	static std::string chars = " \t\n\r";
6567 	return chars.find(c) != std::string::npos;
6568 }
isBreakableBefore(char c)6569 inline auto isBreakableBefore(char c) -> bool {
6570 	static std::string chars = "[({<|";
6571 	return chars.find(c) != std::string::npos;
6572 }
isBreakableAfter(char c)6573 inline auto isBreakableAfter(char c) -> bool {
6574 	static std::string chars = "])}>.,:;*+-=&/\\";
6575 	return chars.find(c) != std::string::npos;
6576 }
6577 
6578 class Columns;
6579 
6580 class Column {
6581 	std::vector<std::string> m_strings;
6582 	size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
6583 	size_t m_indent = 0;
6584 	size_t m_initialIndent = std::string::npos;
6585 
6586 public:
6587 	class iterator {
6588 		friend Column;
6589 
6590 		Column const& m_column;
6591 		size_t m_stringIndex = 0;
6592 		size_t m_pos = 0;
6593 
6594 		size_t m_len = 0;
6595 		size_t m_end = 0;
6596 		bool m_suffix = false;
6597 
iterator(Column const & column,size_t stringIndex)6598 		iterator(Column const& column, size_t stringIndex)
6599 			: m_column(column),
6600 			m_stringIndex(stringIndex) {}
6601 
line() const6602 		auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
6603 
isBoundary(size_t at) const6604 		auto isBoundary(size_t at) const -> bool {
6605 			assert(at > 0);
6606 			assert(at <= line().size());
6607 
6608 			return at == line().size() ||
6609 				(isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
6610 				isBreakableBefore(line()[at]) ||
6611 				isBreakableAfter(line()[at - 1]);
6612 		}
6613 
calcLength()6614 		void calcLength() {
6615 			assert(m_stringIndex < m_column.m_strings.size());
6616 
6617 			m_suffix = false;
6618 			auto width = m_column.m_width - indent();
6619 			m_end = m_pos;
6620 			while (m_end < line().size() && line()[m_end] != '\n')
6621 				++m_end;
6622 
6623 			if (m_end < m_pos + width) {
6624 				m_len = m_end - m_pos;
6625 			} else {
6626 				size_t len = width;
6627 				while (len > 0 && !isBoundary(m_pos + len))
6628 					--len;
6629 				while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
6630 					--len;
6631 
6632 				if (len > 0) {
6633 					m_len = len;
6634 				} else {
6635 					m_suffix = true;
6636 					m_len = width - 1;
6637 				}
6638 			}
6639 		}
6640 
indent() const6641 		auto indent() const -> size_t {
6642 			auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
6643 			return initial == std::string::npos ? m_column.m_indent : initial;
6644 		}
6645 
addIndentAndSuffix(std::string const & plain) const6646 		auto addIndentAndSuffix(std::string const &plain) const -> std::string {
6647 			return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);
6648 		}
6649 
6650 	public:
6651 		using difference_type = std::ptrdiff_t;
6652 		using value_type = std::string;
6653 		using pointer = value_type * ;
6654 		using reference = value_type & ;
6655 		using iterator_category = std::forward_iterator_tag;
6656 
iterator(Column const & column)6657 		explicit iterator(Column const& column) : m_column(column) {
6658 			assert(m_column.m_width > m_column.m_indent);
6659 			assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
6660 			calcLength();
6661 			if (m_len == 0)
6662 				m_stringIndex++; // Empty string
6663 		}
6664 
operator *() const6665 		auto operator *() const -> std::string {
6666 			assert(m_stringIndex < m_column.m_strings.size());
6667 			assert(m_pos <= m_end);
6668 			return addIndentAndSuffix(line().substr(m_pos, m_len));
6669 		}
6670 
operator ++()6671 		auto operator ++() -> iterator& {
6672 			m_pos += m_len;
6673 			if (m_pos < line().size() && line()[m_pos] == '\n')
6674 				m_pos += 1;
6675 			else
6676 				while (m_pos < line().size() && isWhitespace(line()[m_pos]))
6677 					++m_pos;
6678 
6679 			if (m_pos == line().size()) {
6680 				m_pos = 0;
6681 				++m_stringIndex;
6682 			}
6683 			if (m_stringIndex < m_column.m_strings.size())
6684 				calcLength();
6685 			return *this;
6686 		}
operator ++(int)6687 		auto operator ++(int) -> iterator {
6688 			iterator prev(*this);
6689 			operator++();
6690 			return prev;
6691 		}
6692 
operator ==(iterator const & other) const6693 		auto operator ==(iterator const& other) const -> bool {
6694 			return
6695 				m_pos == other.m_pos &&
6696 				m_stringIndex == other.m_stringIndex &&
6697 				&m_column == &other.m_column;
6698 		}
operator !=(iterator const & other) const6699 		auto operator !=(iterator const& other) const -> bool {
6700 			return !operator==(other);
6701 		}
6702 	};
6703 	using const_iterator = iterator;
6704 
Column(std::string const & text)6705 	explicit Column(std::string const& text) { m_strings.push_back(text); }
6706 
width(size_t newWidth)6707 	auto width(size_t newWidth) -> Column& {
6708 		assert(newWidth > 0);
6709 		m_width = newWidth;
6710 		return *this;
6711 	}
indent(size_t newIndent)6712 	auto indent(size_t newIndent) -> Column& {
6713 		m_indent = newIndent;
6714 		return *this;
6715 	}
initialIndent(size_t newIndent)6716 	auto initialIndent(size_t newIndent) -> Column& {
6717 		m_initialIndent = newIndent;
6718 		return *this;
6719 	}
6720 
width() const6721 	auto width() const -> size_t { return m_width; }
begin() const6722 	auto begin() const -> iterator { return iterator(*this); }
end() const6723 	auto end() const -> iterator { return { *this, m_strings.size() }; }
6724 
operator <<(std::ostream & os,Column const & col)6725 	inline friend std::ostream& operator << (std::ostream& os, Column const& col) {
6726 		bool first = true;
6727 		for (auto line : col) {
6728 			if (first)
6729 				first = false;
6730 			else
6731 				os << "\n";
6732 			os << line;
6733 		}
6734 		return os;
6735 	}
6736 
6737 	auto operator + (Column const& other)->Columns;
6738 
toString() const6739 	auto toString() const -> std::string {
6740 		std::ostringstream oss;
6741 		oss << *this;
6742 		return oss.str();
6743 	}
6744 };
6745 
6746 class Spacer : public Column {
6747 
6748 public:
Spacer(size_t spaceWidth)6749 	explicit Spacer(size_t spaceWidth) : Column("") {
6750 		width(spaceWidth);
6751 	}
6752 };
6753 
6754 class Columns {
6755 	std::vector<Column> m_columns;
6756 
6757 public:
6758 
6759 	class iterator {
6760 		friend Columns;
6761 		struct EndTag {};
6762 
6763 		std::vector<Column> const& m_columns;
6764 		std::vector<Column::iterator> m_iterators;
6765 		size_t m_activeIterators;
6766 
iterator(Columns const & columns,EndTag)6767 		iterator(Columns const& columns, EndTag)
6768 			: m_columns(columns.m_columns),
6769 			m_activeIterators(0) {
6770 			m_iterators.reserve(m_columns.size());
6771 
6772 			for (auto const& col : m_columns)
6773 				m_iterators.push_back(col.end());
6774 		}
6775 
6776 	public:
6777 		using difference_type = std::ptrdiff_t;
6778 		using value_type = std::string;
6779 		using pointer = value_type * ;
6780 		using reference = value_type & ;
6781 		using iterator_category = std::forward_iterator_tag;
6782 
iterator(Columns const & columns)6783 		explicit iterator(Columns const& columns)
6784 			: m_columns(columns.m_columns),
6785 			m_activeIterators(m_columns.size()) {
6786 			m_iterators.reserve(m_columns.size());
6787 
6788 			for (auto const& col : m_columns)
6789 				m_iterators.push_back(col.begin());
6790 		}
6791 
operator ==(iterator const & other) const6792 		auto operator ==(iterator const& other) const -> bool {
6793 			return m_iterators == other.m_iterators;
6794 		}
operator !=(iterator const & other) const6795 		auto operator !=(iterator const& other) const -> bool {
6796 			return m_iterators != other.m_iterators;
6797 		}
operator *() const6798 		auto operator *() const -> std::string {
6799 			std::string row, padding;
6800 
6801 			for (size_t i = 0; i < m_columns.size(); ++i) {
6802 				auto width = m_columns[i].width();
6803 				if (m_iterators[i] != m_columns[i].end()) {
6804 					std::string col = *m_iterators[i];
6805 					row += padding + col;
6806 					if (col.size() < width)
6807 						padding = std::string(width - col.size(), ' ');
6808 					else
6809 						padding = "";
6810 				} else {
6811 					padding += std::string(width, ' ');
6812 				}
6813 			}
6814 			return row;
6815 		}
operator ++()6816 		auto operator ++() -> iterator& {
6817 			for (size_t i = 0; i < m_columns.size(); ++i) {
6818 				if (m_iterators[i] != m_columns[i].end())
6819 					++m_iterators[i];
6820 			}
6821 			return *this;
6822 		}
operator ++(int)6823 		auto operator ++(int) -> iterator {
6824 			iterator prev(*this);
6825 			operator++();
6826 			return prev;
6827 		}
6828 	};
6829 	using const_iterator = iterator;
6830 
begin() const6831 	auto begin() const -> iterator { return iterator(*this); }
end() const6832 	auto end() const -> iterator { return { *this, iterator::EndTag() }; }
6833 
operator +=(Column const & col)6834 	auto operator += (Column const& col) -> Columns& {
6835 		m_columns.push_back(col);
6836 		return *this;
6837 	}
operator +(Column const & col)6838 	auto operator + (Column const& col) -> Columns {
6839 		Columns combined = *this;
6840 		combined += col;
6841 		return combined;
6842 	}
6843 
operator <<(std::ostream & os,Columns const & cols)6844 	inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) {
6845 
6846 		bool first = true;
6847 		for (auto line : cols) {
6848 			if (first)
6849 				first = false;
6850 			else
6851 				os << "\n";
6852 			os << line;
6853 		}
6854 		return os;
6855 	}
6856 
toString() const6857 	auto toString() const -> std::string {
6858 		std::ostringstream oss;
6859 		oss << *this;
6860 		return oss.str();
6861 	}
6862 };
6863 
operator +(Column const & other)6864 inline auto Column::operator + (Column const& other) -> Columns {
6865 	Columns cols;
6866 	cols += *this;
6867 	cols += other;
6868 	return cols;
6869 }
6870 }
6871 
6872 }
6873 }
6874 
6875 // ----------- end of #include from clara_textflow.hpp -----------
6876 // ........... back in clara.hpp
6877 
6878 #include <cctype>
6879 #include <string>
6880 #include <memory>
6881 #include <set>
6882 #include <algorithm>
6883 
6884 #if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
6885 #define CATCH_PLATFORM_WINDOWS
6886 #endif
6887 
6888 namespace Catch { namespace clara {
6889 namespace detail {
6890 
6891     // Traits for extracting arg and return type of lambdas (for single argument lambdas)
6892     template<typename L>
6893     struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
6894 
6895     template<typename ClassT, typename ReturnT, typename... Args>
6896     struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
6897         static const bool isValid = false;
6898     };
6899 
6900     template<typename ClassT, typename ReturnT, typename ArgT>
6901     struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
6902         static const bool isValid = true;
6903         using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
6904         using ReturnType = ReturnT;
6905     };
6906 
6907     class TokenStream;
6908 
6909     // Transport for raw args (copied from main args, or supplied via init list for testing)
6910     class Args {
6911         friend TokenStream;
6912         std::string m_exeName;
6913         std::vector<std::string> m_args;
6914 
6915     public:
Args(int argc,char const * const * argv)6916         Args( int argc, char const* const* argv )
6917             : m_exeName(argv[0]),
6918               m_args(argv + 1, argv + argc) {}
6919 
Args(std::initializer_list<std::string> args)6920         Args( std::initializer_list<std::string> args )
6921         :   m_exeName( *args.begin() ),
6922             m_args( args.begin()+1, args.end() )
6923         {}
6924 
exeName() const6925         auto exeName() const -> std::string {
6926             return m_exeName;
6927         }
6928     };
6929 
6930     // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string
6931     // may encode an option + its argument if the : or = form is used
6932     enum class TokenType {
6933         Option, Argument
6934     };
6935     struct Token {
6936         TokenType type;
6937         std::string token;
6938     };
6939 
isOptPrefix(char c)6940     inline auto isOptPrefix( char c ) -> bool {
6941         return c == '-'
6942 #ifdef CATCH_PLATFORM_WINDOWS
6943             || c == '/'
6944 #endif
6945         ;
6946     }
6947 
6948     // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled
6949     class TokenStream {
6950         using Iterator = std::vector<std::string>::const_iterator;
6951         Iterator it;
6952         Iterator itEnd;
6953         std::vector<Token> m_tokenBuffer;
6954 
loadBuffer()6955         void loadBuffer() {
6956             m_tokenBuffer.resize( 0 );
6957 
6958             // Skip any empty strings
6959             while( it != itEnd && it->empty() )
6960                 ++it;
6961 
6962             if( it != itEnd ) {
6963                 auto const &next = *it;
6964                 if( isOptPrefix( next[0] ) ) {
6965                     auto delimiterPos = next.find_first_of( " :=" );
6966                     if( delimiterPos != std::string::npos ) {
6967                         m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
6968                         m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
6969                     } else {
6970                         if( next[1] != '-' && next.size() > 2 ) {
6971                             std::string opt = "- ";
6972                             for( size_t i = 1; i < next.size(); ++i ) {
6973                                 opt[1] = next[i];
6974                                 m_tokenBuffer.push_back( { TokenType::Option, opt } );
6975                             }
6976                         } else {
6977                             m_tokenBuffer.push_back( { TokenType::Option, next } );
6978                         }
6979                     }
6980                 } else {
6981                     m_tokenBuffer.push_back( { TokenType::Argument, next } );
6982                 }
6983             }
6984         }
6985 
6986     public:
TokenStream(Args const & args)6987         explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
6988 
TokenStream(Iterator it,Iterator itEnd)6989         TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
6990             loadBuffer();
6991         }
6992 
operator bool() const6993         explicit operator bool() const {
6994             return !m_tokenBuffer.empty() || it != itEnd;
6995         }
6996 
count() const6997         auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
6998 
operator *() const6999         auto operator*() const -> Token {
7000             assert( !m_tokenBuffer.empty() );
7001             return m_tokenBuffer.front();
7002         }
7003 
operator ->() const7004         auto operator->() const -> Token const * {
7005             assert( !m_tokenBuffer.empty() );
7006             return &m_tokenBuffer.front();
7007         }
7008 
operator ++()7009         auto operator++() -> TokenStream & {
7010             if( m_tokenBuffer.size() >= 2 ) {
7011                 m_tokenBuffer.erase( m_tokenBuffer.begin() );
7012             } else {
7013                 if( it != itEnd )
7014                     ++it;
7015                 loadBuffer();
7016             }
7017             return *this;
7018         }
7019     };
7020 
7021     class ResultBase {
7022     public:
7023         enum Type {
7024             Ok, LogicError, RuntimeError
7025         };
7026 
7027     protected:
ResultBase(Type type)7028         ResultBase( Type type ) : m_type( type ) {}
7029         virtual ~ResultBase() = default;
7030 
7031         virtual void enforceOk() const = 0;
7032 
7033         Type m_type;
7034     };
7035 
7036     template<typename T>
7037     class ResultValueBase : public ResultBase {
7038     public:
value() const7039         auto value() const -> T const & {
7040             enforceOk();
7041             return m_value;
7042         }
7043 
7044     protected:
ResultValueBase(Type type)7045         ResultValueBase( Type type ) : ResultBase( type ) {}
7046 
ResultValueBase(ResultValueBase const & other)7047         ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) {
7048             if( m_type == ResultBase::Ok )
7049                 new( &m_value ) T( other.m_value );
7050         }
7051 
ResultValueBase(Type,T const & value)7052         ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {
7053             new( &m_value ) T( value );
7054         }
7055 
operator =(ResultValueBase const & other)7056         auto operator=( ResultValueBase const &other ) -> ResultValueBase & {
7057             if( m_type == ResultBase::Ok )
7058                 m_value.~T();
7059             ResultBase::operator=(other);
7060             if( m_type == ResultBase::Ok )
7061                 new( &m_value ) T( other.m_value );
7062             return *this;
7063         }
7064 
~ResultValueBase()7065         ~ResultValueBase() override {
7066             if( m_type == Ok )
7067                 m_value.~T();
7068         }
7069 
7070         union {
7071             T m_value;
7072         };
7073     };
7074 
7075     template<>
7076     class ResultValueBase<void> : public ResultBase {
7077     protected:
7078         using ResultBase::ResultBase;
7079     };
7080 
7081     template<typename T = void>
7082     class BasicResult : public ResultValueBase<T> {
7083     public:
7084         template<typename U>
BasicResult(BasicResult<U> const & other)7085         explicit BasicResult( BasicResult<U> const &other )
7086         :   ResultValueBase<T>( other.type() ),
7087             m_errorMessage( other.errorMessage() )
7088         {
7089             assert( type() != ResultBase::Ok );
7090         }
7091 
7092         template<typename U>
ok(U const & value)7093         static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; }
ok()7094         static auto ok() -> BasicResult { return { ResultBase::Ok }; }
logicError(std::string const & message)7095         static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; }
runtimeError(std::string const & message)7096         static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; }
7097 
operator bool() const7098         explicit operator bool() const { return m_type == ResultBase::Ok; }
type() const7099         auto type() const -> ResultBase::Type { return m_type; }
errorMessage() const7100         auto errorMessage() const -> std::string { return m_errorMessage; }
7101 
7102     protected:
enforceOk() const7103         void enforceOk() const override {
7104 
7105             // Errors shouldn't reach this point, but if they do
7106             // the actual error message will be in m_errorMessage
7107             assert( m_type != ResultBase::LogicError );
7108             assert( m_type != ResultBase::RuntimeError );
7109             if( m_type != ResultBase::Ok )
7110                 std::abort();
7111         }
7112 
7113         std::string m_errorMessage; // Only populated if resultType is an error
7114 
BasicResult(ResultBase::Type type,std::string const & message)7115         BasicResult( ResultBase::Type type, std::string const &message )
7116         :   ResultValueBase<T>(type),
7117             m_errorMessage(message)
7118         {
7119             assert( m_type != ResultBase::Ok );
7120         }
7121 
7122         using ResultValueBase<T>::ResultValueBase;
7123         using ResultBase::m_type;
7124     };
7125 
7126     enum class ParseResultType {
7127         Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
7128     };
7129 
7130     class ParseState {
7131     public:
7132 
ParseState(ParseResultType type,TokenStream const & remainingTokens)7133         ParseState( ParseResultType type, TokenStream const &remainingTokens )
7134         : m_type(type),
7135           m_remainingTokens( remainingTokens )
7136         {}
7137 
type() const7138         auto type() const -> ParseResultType { return m_type; }
remainingTokens() const7139         auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
7140 
7141     private:
7142         ParseResultType m_type;
7143         TokenStream m_remainingTokens;
7144     };
7145 
7146     using Result = BasicResult<void>;
7147     using ParserResult = BasicResult<ParseResultType>;
7148     using InternalParseResult = BasicResult<ParseState>;
7149 
7150     struct HelpColumns {
7151         std::string left;
7152         std::string right;
7153     };
7154 
7155     template<typename T>
convertInto(std::string const & source,T & target)7156     inline auto convertInto( std::string const &source, T& target ) -> ParserResult {
7157         std::stringstream ss;
7158         ss << source;
7159         ss >> target;
7160         if( ss.fail() )
7161             return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" );
7162         else
7163             return ParserResult::ok( ParseResultType::Matched );
7164     }
convertInto(std::string const & source,std::string & target)7165     inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult {
7166         target = source;
7167         return ParserResult::ok( ParseResultType::Matched );
7168     }
convertInto(std::string const & source,bool & target)7169     inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
7170         std::string srcLC = source;
7171         std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( std::tolower(c) ); } );
7172         if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
7173             target = true;
7174         else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
7175             target = false;
7176         else
7177             return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
7178         return ParserResult::ok( ParseResultType::Matched );
7179     }
7180 #ifdef CLARA_CONFIG_OPTIONAL_TYPE
7181     template<typename T>
convertInto(std::string const & source,CLARA_CONFIG_OPTIONAL_TYPE<T> & target)7182     inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
7183         T temp;
7184         auto result = convertInto( source, temp );
7185         if( result )
7186             target = std::move(temp);
7187         return result;
7188     }
7189 #endif // CLARA_CONFIG_OPTIONAL_TYPE
7190 
7191     struct NonCopyable {
7192         NonCopyable() = default;
7193         NonCopyable( NonCopyable const & ) = delete;
7194         NonCopyable( NonCopyable && ) = delete;
7195         NonCopyable &operator=( NonCopyable const & ) = delete;
7196         NonCopyable &operator=( NonCopyable && ) = delete;
7197     };
7198 
7199     struct BoundRef : NonCopyable {
7200         virtual ~BoundRef() = default;
isContainerCatch::clara::detail::BoundRef7201         virtual auto isContainer() const -> bool { return false; }
isFlagCatch::clara::detail::BoundRef7202         virtual auto isFlag() const -> bool { return false; }
7203     };
7204     struct BoundValueRefBase : BoundRef {
7205         virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
7206     };
7207     struct BoundFlagRefBase : BoundRef {
7208         virtual auto setFlag( bool flag ) -> ParserResult = 0;
isFlagCatch::clara::detail::BoundFlagRefBase7209         virtual auto isFlag() const -> bool { return true; }
7210     };
7211 
7212     template<typename T>
7213     struct BoundValueRef : BoundValueRefBase {
7214         T &m_ref;
7215 
BoundValueRefCatch::clara::detail::BoundValueRef7216         explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
7217 
setValueCatch::clara::detail::BoundValueRef7218         auto setValue( std::string const &arg ) -> ParserResult override {
7219             return convertInto( arg, m_ref );
7220         }
7221     };
7222 
7223     template<typename T>
7224     struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
7225         std::vector<T> &m_ref;
7226 
BoundValueRefCatch::clara::detail::BoundValueRef7227         explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
7228 
isContainerCatch::clara::detail::BoundValueRef7229         auto isContainer() const -> bool override { return true; }
7230 
setValueCatch::clara::detail::BoundValueRef7231         auto setValue( std::string const &arg ) -> ParserResult override {
7232             T temp;
7233             auto result = convertInto( arg, temp );
7234             if( result )
7235                 m_ref.push_back( temp );
7236             return result;
7237         }
7238     };
7239 
7240     struct BoundFlagRef : BoundFlagRefBase {
7241         bool &m_ref;
7242 
BoundFlagRefCatch::clara::detail::BoundFlagRef7243         explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}
7244 
setFlagCatch::clara::detail::BoundFlagRef7245         auto setFlag( bool flag ) -> ParserResult override {
7246             m_ref = flag;
7247             return ParserResult::ok( ParseResultType::Matched );
7248         }
7249     };
7250 
7251     template<typename ReturnType>
7252     struct LambdaInvoker {
7253         static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" );
7254 
7255         template<typename L, typename ArgType>
invokeCatch::clara::detail::LambdaInvoker7256         static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
7257             return lambda( arg );
7258         }
7259     };
7260 
7261     template<>
7262     struct LambdaInvoker<void> {
7263         template<typename L, typename ArgType>
invokeCatch::clara::detail::LambdaInvoker7264         static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
7265             lambda( arg );
7266             return ParserResult::ok( ParseResultType::Matched );
7267         }
7268     };
7269 
7270     template<typename ArgType, typename L>
invokeLambda(L const & lambda,std::string const & arg)7271     inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
7272         ArgType temp{};
7273         auto result = convertInto( arg, temp );
7274         return !result
7275            ? result
7276            : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
7277     }
7278 
7279     template<typename L>
7280     struct BoundLambda : BoundValueRefBase {
7281         L m_lambda;
7282 
7283         static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
BoundLambdaCatch::clara::detail::BoundLambda7284         explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}
7285 
setValueCatch::clara::detail::BoundLambda7286         auto setValue( std::string const &arg ) -> ParserResult override {
7287             return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
7288         }
7289     };
7290 
7291     template<typename L>
7292     struct BoundFlagLambda : BoundFlagRefBase {
7293         L m_lambda;
7294 
7295         static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
7296         static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" );
7297 
BoundFlagLambdaCatch::clara::detail::BoundFlagLambda7298         explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}
7299 
setFlagCatch::clara::detail::BoundFlagLambda7300         auto setFlag( bool flag ) -> ParserResult override {
7301             return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
7302         }
7303     };
7304 
7305     enum class Optionality { Optional, Required };
7306 
7307     struct Parser;
7308 
7309     class ParserBase {
7310     public:
7311         virtual ~ParserBase() = default;
validate() const7312         virtual auto validate() const -> Result { return Result::ok(); }
7313         virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult  = 0;
cardinality() const7314         virtual auto cardinality() const -> size_t { return 1; }
7315 
parse(Args const & args) const7316         auto parse( Args const &args ) const -> InternalParseResult {
7317             return parse( args.exeName(), TokenStream( args ) );
7318         }
7319     };
7320 
7321     template<typename DerivedT>
7322     class ComposableParserImpl : public ParserBase {
7323     public:
7324         template<typename T>
7325         auto operator|( T const &other ) const -> Parser;
7326 
7327 		template<typename T>
7328         auto operator+( T const &other ) const -> Parser;
7329     };
7330 
7331     // Common code and state for Args and Opts
7332     template<typename DerivedT>
7333     class ParserRefImpl : public ComposableParserImpl<DerivedT> {
7334     protected:
7335         Optionality m_optionality = Optionality::Optional;
7336         std::shared_ptr<BoundRef> m_ref;
7337         std::string m_hint;
7338         std::string m_description;
7339 
ParserRefImpl(std::shared_ptr<BoundRef> const & ref)7340         explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
7341 
7342     public:
7343         template<typename T>
ParserRefImpl(T & ref,std::string const & hint)7344         ParserRefImpl( T &ref, std::string const &hint )
7345         :   m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
7346             m_hint( hint )
7347         {}
7348 
7349         template<typename LambdaT>
ParserRefImpl(LambdaT const & ref,std::string const & hint)7350         ParserRefImpl( LambdaT const &ref, std::string const &hint )
7351         :   m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
7352             m_hint(hint)
7353         {}
7354 
operator ()(std::string const & description)7355         auto operator()( std::string const &description ) -> DerivedT & {
7356             m_description = description;
7357             return static_cast<DerivedT &>( *this );
7358         }
7359 
optional()7360         auto optional() -> DerivedT & {
7361             m_optionality = Optionality::Optional;
7362             return static_cast<DerivedT &>( *this );
7363         };
7364 
required()7365         auto required() -> DerivedT & {
7366             m_optionality = Optionality::Required;
7367             return static_cast<DerivedT &>( *this );
7368         };
7369 
isOptional() const7370         auto isOptional() const -> bool {
7371             return m_optionality == Optionality::Optional;
7372         }
7373 
cardinality() const7374         auto cardinality() const -> size_t override {
7375             if( m_ref->isContainer() )
7376                 return 0;
7377             else
7378                 return 1;
7379         }
7380 
hint() const7381         auto hint() const -> std::string { return m_hint; }
7382     };
7383 
7384     class ExeName : public ComposableParserImpl<ExeName> {
7385         std::shared_ptr<std::string> m_name;
7386         std::shared_ptr<BoundValueRefBase> m_ref;
7387 
7388         template<typename LambdaT>
makeRef(LambdaT const & lambda)7389         static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
7390             return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
7391         }
7392 
7393     public:
ExeName()7394         ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
7395 
ExeName(std::string & ref)7396         explicit ExeName( std::string &ref ) : ExeName() {
7397             m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
7398         }
7399 
7400         template<typename LambdaT>
ExeName(LambdaT const & lambda)7401         explicit ExeName( LambdaT const& lambda ) : ExeName() {
7402             m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );
7403         }
7404 
7405         // The exe name is not parsed out of the normal tokens, but is handled specially
parse(std::string const &,TokenStream const & tokens) const7406         auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
7407             return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
7408         }
7409 
name() const7410         auto name() const -> std::string { return *m_name; }
set(std::string const & newName)7411         auto set( std::string const& newName ) -> ParserResult {
7412 
7413             auto lastSlash = newName.find_last_of( "\\/" );
7414             auto filename = ( lastSlash == std::string::npos )
7415                     ? newName
7416                     : newName.substr( lastSlash+1 );
7417 
7418             *m_name = filename;
7419             if( m_ref )
7420                 return m_ref->setValue( filename );
7421             else
7422                 return ParserResult::ok( ParseResultType::Matched );
7423         }
7424     };
7425 
7426     class Arg : public ParserRefImpl<Arg> {
7427     public:
7428         using ParserRefImpl::ParserRefImpl;
7429 
parse(std::string const &,TokenStream const & tokens) const7430         auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override {
7431             auto validationResult = validate();
7432             if( !validationResult )
7433                 return InternalParseResult( validationResult );
7434 
7435             auto remainingTokens = tokens;
7436             auto const &token = *remainingTokens;
7437             if( token.type != TokenType::Argument )
7438                 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
7439 
7440             assert( !m_ref->isFlag() );
7441             auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
7442 
7443             auto result = valueRef->setValue( remainingTokens->token );
7444             if( !result )
7445                 return InternalParseResult( result );
7446             else
7447                 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
7448         }
7449     };
7450 
normaliseOpt(std::string const & optName)7451     inline auto normaliseOpt( std::string const &optName ) -> std::string {
7452 #ifdef CATCH_PLATFORM_WINDOWS
7453         if( optName[0] == '/' )
7454             return "-" + optName.substr( 1 );
7455         else
7456 #endif
7457             return optName;
7458     }
7459 
7460     class Opt : public ParserRefImpl<Opt> {
7461     protected:
7462         std::vector<std::string> m_optNames;
7463 
7464     public:
7465         template<typename LambdaT>
Opt(LambdaT const & ref)7466         explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
7467 
Opt(bool & ref)7468         explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}
7469 
7470         template<typename LambdaT>
Opt(LambdaT const & ref,std::string const & hint)7471         Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
7472 
7473         template<typename T>
Opt(T & ref,std::string const & hint)7474         Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
7475 
operator [](std::string const & optName)7476         auto operator[]( std::string const &optName ) -> Opt & {
7477             m_optNames.push_back( optName );
7478             return *this;
7479         }
7480 
getHelpColumns() const7481         auto getHelpColumns() const -> std::vector<HelpColumns> {
7482             std::ostringstream oss;
7483             bool first = true;
7484             for( auto const &opt : m_optNames ) {
7485                 if (first)
7486                     first = false;
7487                 else
7488                     oss << ", ";
7489                 oss << opt;
7490             }
7491             if( !m_hint.empty() )
7492                 oss << " <" << m_hint << ">";
7493             return { { oss.str(), m_description } };
7494         }
7495 
isMatch(std::string const & optToken) const7496         auto isMatch( std::string const &optToken ) const -> bool {
7497             auto normalisedToken = normaliseOpt( optToken );
7498             for( auto const &name : m_optNames ) {
7499                 if( normaliseOpt( name ) == normalisedToken )
7500                     return true;
7501             }
7502             return false;
7503         }
7504 
7505         using ParserBase::parse;
7506 
parse(std::string const &,TokenStream const & tokens) const7507         auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
7508             auto validationResult = validate();
7509             if( !validationResult )
7510                 return InternalParseResult( validationResult );
7511 
7512             auto remainingTokens = tokens;
7513             if( remainingTokens && remainingTokens->type == TokenType::Option ) {
7514                 auto const &token = *remainingTokens;
7515                 if( isMatch(token.token ) ) {
7516                     if( m_ref->isFlag() ) {
7517                         auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
7518                         auto result = flagRef->setFlag( true );
7519                         if( !result )
7520                             return InternalParseResult( result );
7521                         if( result.value() == ParseResultType::ShortCircuitAll )
7522                             return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
7523                     } else {
7524                         auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
7525                         ++remainingTokens;
7526                         if( !remainingTokens )
7527                             return InternalParseResult::runtimeError( "Expected argument following " + token.token );
7528                         auto const &argToken = *remainingTokens;
7529                         if( argToken.type != TokenType::Argument )
7530                             return InternalParseResult::runtimeError( "Expected argument following " + token.token );
7531                         auto result = valueRef->setValue( argToken.token );
7532                         if( !result )
7533                             return InternalParseResult( result );
7534                         if( result.value() == ParseResultType::ShortCircuitAll )
7535                             return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
7536                     }
7537                     return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
7538                 }
7539             }
7540             return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
7541         }
7542 
validate() const7543         auto validate() const -> Result override {
7544             if( m_optNames.empty() )
7545                 return Result::logicError( "No options supplied to Opt" );
7546             for( auto const &name : m_optNames ) {
7547                 if( name.empty() )
7548                     return Result::logicError( "Option name cannot be empty" );
7549 #ifdef CATCH_PLATFORM_WINDOWS
7550                 if( name[0] != '-' && name[0] != '/' )
7551                     return Result::logicError( "Option name must begin with '-' or '/'" );
7552 #else
7553                 if( name[0] != '-' )
7554                     return Result::logicError( "Option name must begin with '-'" );
7555 #endif
7556             }
7557             return ParserRefImpl::validate();
7558         }
7559     };
7560 
7561     struct Help : Opt {
HelpCatch::clara::detail::Help7562         Help( bool &showHelpFlag )
7563         :   Opt([&]( bool flag ) {
7564                 showHelpFlag = flag;
7565                 return ParserResult::ok( ParseResultType::ShortCircuitAll );
7566             })
7567         {
7568             static_cast<Opt &>( *this )
7569                     ("display usage information")
7570                     ["-?"]["-h"]["--help"]
7571                     .optional();
7572         }
7573     };
7574 
7575     struct Parser : ParserBase {
7576 
7577         mutable ExeName m_exeName;
7578         std::vector<Opt> m_options;
7579         std::vector<Arg> m_args;
7580 
operator |=Catch::clara::detail::Parser7581         auto operator|=( ExeName const &exeName ) -> Parser & {
7582             m_exeName = exeName;
7583             return *this;
7584         }
7585 
operator |=Catch::clara::detail::Parser7586         auto operator|=( Arg const &arg ) -> Parser & {
7587             m_args.push_back(arg);
7588             return *this;
7589         }
7590 
operator |=Catch::clara::detail::Parser7591         auto operator|=( Opt const &opt ) -> Parser & {
7592             m_options.push_back(opt);
7593             return *this;
7594         }
7595 
operator |=Catch::clara::detail::Parser7596         auto operator|=( Parser const &other ) -> Parser & {
7597             m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
7598             m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
7599             return *this;
7600         }
7601 
7602         template<typename T>
operator |Catch::clara::detail::Parser7603         auto operator|( T const &other ) const -> Parser {
7604             return Parser( *this ) |= other;
7605         }
7606 
7607         // Forward deprecated interface with '+' instead of '|'
7608         template<typename T>
operator +=Catch::clara::detail::Parser7609         auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
7610         template<typename T>
operator +Catch::clara::detail::Parser7611         auto operator+( T const &other ) const -> Parser { return operator|( other ); }
7612 
getHelpColumnsCatch::clara::detail::Parser7613         auto getHelpColumns() const -> std::vector<HelpColumns> {
7614             std::vector<HelpColumns> cols;
7615             for (auto const &o : m_options) {
7616                 auto childCols = o.getHelpColumns();
7617                 cols.insert( cols.end(), childCols.begin(), childCols.end() );
7618             }
7619             return cols;
7620         }
7621 
writeToStreamCatch::clara::detail::Parser7622         void writeToStream( std::ostream &os ) const {
7623             if (!m_exeName.name().empty()) {
7624                 os << "usage:\n" << "  " << m_exeName.name() << " ";
7625                 bool required = true, first = true;
7626                 for( auto const &arg : m_args ) {
7627                     if (first)
7628                         first = false;
7629                     else
7630                         os << " ";
7631                     if( arg.isOptional() && required ) {
7632                         os << "[";
7633                         required = false;
7634                     }
7635                     os << "<" << arg.hint() << ">";
7636                     if( arg.cardinality() == 0 )
7637                         os << " ... ";
7638                 }
7639                 if( !required )
7640                     os << "]";
7641                 if( !m_options.empty() )
7642                     os << " options";
7643                 os << "\n\nwhere options are:" << std::endl;
7644             }
7645 
7646             auto rows = getHelpColumns();
7647             size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
7648             size_t optWidth = 0;
7649             for( auto const &cols : rows )
7650                 optWidth = (std::max)(optWidth, cols.left.size() + 2);
7651 
7652             optWidth = (std::min)(optWidth, consoleWidth/2);
7653 
7654             for( auto const &cols : rows ) {
7655                 auto row =
7656                         TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
7657                         TextFlow::Spacer(4) +
7658                         TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
7659                 os << row << std::endl;
7660             }
7661         }
7662 
operator <<(std::ostream & os,Parser const & parser)7663         friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& {
7664             parser.writeToStream( os );
7665             return os;
7666         }
7667 
validateCatch::clara::detail::Parser7668         auto validate() const -> Result override {
7669             for( auto const &opt : m_options ) {
7670                 auto result = opt.validate();
7671                 if( !result )
7672                     return result;
7673             }
7674             for( auto const &arg : m_args ) {
7675                 auto result = arg.validate();
7676                 if( !result )
7677                     return result;
7678             }
7679             return Result::ok();
7680         }
7681 
7682         using ParserBase::parse;
7683 
parseCatch::clara::detail::Parser7684         auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override {
7685 
7686             struct ParserInfo {
7687                 ParserBase const* parser = nullptr;
7688                 size_t count = 0;
7689             };
7690             const size_t totalParsers = m_options.size() + m_args.size();
7691             assert( totalParsers < 512 );
7692             // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do
7693             ParserInfo parseInfos[512];
7694 
7695             {
7696                 size_t i = 0;
7697                 for (auto const &opt : m_options) parseInfos[i++].parser = &opt;
7698                 for (auto const &arg : m_args) parseInfos[i++].parser = &arg;
7699             }
7700 
7701             m_exeName.set( exeName );
7702 
7703             auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
7704             while( result.value().remainingTokens() ) {
7705                 bool tokenParsed = false;
7706 
7707                 for( size_t i = 0; i < totalParsers; ++i ) {
7708                     auto&  parseInfo = parseInfos[i];
7709                     if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
7710                         result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
7711                         if (!result)
7712                             return result;
7713                         if (result.value().type() != ParseResultType::NoMatch) {
7714                             tokenParsed = true;
7715                             ++parseInfo.count;
7716                             break;
7717                         }
7718                     }
7719                 }
7720 
7721                 if( result.value().type() == ParseResultType::ShortCircuitAll )
7722                     return result;
7723                 if( !tokenParsed )
7724                     return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token );
7725             }
7726             // !TBD Check missing required options
7727             return result;
7728         }
7729     };
7730 
7731     template<typename DerivedT>
7732     template<typename T>
operator |(T const & other) const7733     auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser {
7734         return Parser() | static_cast<DerivedT const &>( *this ) | other;
7735     }
7736 } // namespace detail
7737 
7738 // A Combined parser
7739 using detail::Parser;
7740 
7741 // A parser for options
7742 using detail::Opt;
7743 
7744 // A parser for arguments
7745 using detail::Arg;
7746 
7747 // Wrapper for argc, argv from main()
7748 using detail::Args;
7749 
7750 // Specifies the name of the executable
7751 using detail::ExeName;
7752 
7753 // Convenience wrapper for option parser that specifies the help option
7754 using detail::Help;
7755 
7756 // enum of result types from a parse
7757 using detail::ParseResultType;
7758 
7759 // Result type for parser operation
7760 using detail::ParserResult;
7761 
7762 }} // namespace Catch::clara
7763 
7764 // end clara.hpp
7765 #ifdef __clang__
7766 #pragma clang diagnostic pop
7767 #endif
7768 
7769 // Restore Clara's value for console width, if present
7770 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
7771 #define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
7772 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
7773 #endif
7774 
7775 // end catch_clara.h
7776 namespace Catch {
7777 
7778     clara::Parser makeCommandLineParser( ConfigData& config );
7779 
7780 } // end namespace Catch
7781 
7782 // end catch_commandline.h
7783 #include <fstream>
7784 #include <ctime>
7785 
7786 namespace Catch {
7787 
makeCommandLineParser(ConfigData & config)7788     clara::Parser makeCommandLineParser( ConfigData& config ) {
7789 
7790         using namespace clara;
7791 
7792         auto const setWarning = [&]( std::string const& warning ) {
7793                 auto warningSet = [&]() {
7794                     if( warning == "NoAssertions" )
7795                         return WarnAbout::NoAssertions;
7796 
7797                     if ( warning == "NoTests" )
7798                         return WarnAbout::NoTests;
7799 
7800                     return WarnAbout::Nothing;
7801                 }();
7802 
7803                 if (warningSet == WarnAbout::Nothing)
7804                     return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );
7805                 config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );
7806                 return ParserResult::ok( ParseResultType::Matched );
7807             };
7808         auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
7809                 std::ifstream f( filename.c_str() );
7810                 if( !f.is_open() )
7811                     return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" );
7812 
7813                 std::string line;
7814                 while( std::getline( f, line ) ) {
7815                     line = trim(line);
7816                     if( !line.empty() && !startsWith( line, '#' ) ) {
7817                         if( !startsWith( line, '"' ) )
7818                             line = '"' + line + '"';
7819                         config.testsOrTags.push_back( line + ',' );
7820                     }
7821                 }
7822                 return ParserResult::ok( ParseResultType::Matched );
7823             };
7824         auto const setTestOrder = [&]( std::string const& order ) {
7825                 if( startsWith( "declared", order ) )
7826                     config.runOrder = RunTests::InDeclarationOrder;
7827                 else if( startsWith( "lexical", order ) )
7828                     config.runOrder = RunTests::InLexicographicalOrder;
7829                 else if( startsWith( "random", order ) )
7830                     config.runOrder = RunTests::InRandomOrder;
7831                 else
7832                     return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" );
7833                 return ParserResult::ok( ParseResultType::Matched );
7834             };
7835         auto const setRngSeed = [&]( std::string const& seed ) {
7836                 if( seed != "time" )
7837                     return clara::detail::convertInto( seed, config.rngSeed );
7838                 config.rngSeed = static_cast<unsigned int>( std::time(nullptr) );
7839                 return ParserResult::ok( ParseResultType::Matched );
7840             };
7841         auto const setColourUsage = [&]( std::string const& useColour ) {
7842                     auto mode = toLower( useColour );
7843 
7844                     if( mode == "yes" )
7845                         config.useColour = UseColour::Yes;
7846                     else if( mode == "no" )
7847                         config.useColour = UseColour::No;
7848                     else if( mode == "auto" )
7849                         config.useColour = UseColour::Auto;
7850                     else
7851                         return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" );
7852                 return ParserResult::ok( ParseResultType::Matched );
7853             };
7854         auto const setWaitForKeypress = [&]( std::string const& keypress ) {
7855                 auto keypressLc = toLower( keypress );
7856                 if( keypressLc == "start" )
7857                     config.waitForKeypress = WaitForKeypress::BeforeStart;
7858                 else if( keypressLc == "exit" )
7859                     config.waitForKeypress = WaitForKeypress::BeforeExit;
7860                 else if( keypressLc == "both" )
7861                     config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
7862                 else
7863                     return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
7864             return ParserResult::ok( ParseResultType::Matched );
7865             };
7866         auto const setVerbosity = [&]( std::string const& verbosity ) {
7867             auto lcVerbosity = toLower( verbosity );
7868             if( lcVerbosity == "quiet" )
7869                 config.verbosity = Verbosity::Quiet;
7870             else if( lcVerbosity == "normal" )
7871                 config.verbosity = Verbosity::Normal;
7872             else if( lcVerbosity == "high" )
7873                 config.verbosity = Verbosity::High;
7874             else
7875                 return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" );
7876             return ParserResult::ok( ParseResultType::Matched );
7877         };
7878         auto const setReporter = [&]( std::string const& reporter ) {
7879             IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
7880 
7881             auto lcReporter = toLower( reporter );
7882             auto result = factories.find( lcReporter );
7883 
7884             if( factories.end() != result )
7885                 config.reporterName = lcReporter;
7886             else
7887                 return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" );
7888             return ParserResult::ok( ParseResultType::Matched );
7889         };
7890 
7891         auto cli
7892             = ExeName( config.processName )
7893             | Help( config.showHelp )
7894             | Opt( config.listTests )
7895                 ["-l"]["--list-tests"]
7896                 ( "list all/matching test cases" )
7897             | Opt( config.listTags )
7898                 ["-t"]["--list-tags"]
7899                 ( "list all/matching tags" )
7900             | Opt( config.showSuccessfulTests )
7901                 ["-s"]["--success"]
7902                 ( "include successful tests in output" )
7903             | Opt( config.shouldDebugBreak )
7904                 ["-b"]["--break"]
7905                 ( "break into debugger on failure" )
7906             | Opt( config.noThrow )
7907                 ["-e"]["--nothrow"]
7908                 ( "skip exception tests" )
7909             | Opt( config.showInvisibles )
7910                 ["-i"]["--invisibles"]
7911                 ( "show invisibles (tabs, newlines)" )
7912             | Opt( config.outputFilename, "filename" )
7913                 ["-o"]["--out"]
7914                 ( "output filename" )
7915             | Opt( setReporter, "name" )
7916                 ["-r"]["--reporter"]
7917                 ( "reporter to use (defaults to console)" )
7918             | Opt( config.name, "name" )
7919                 ["-n"]["--name"]
7920                 ( "suite name" )
7921             | Opt( [&]( bool ){ config.abortAfter = 1; } )
7922                 ["-a"]["--abort"]
7923                 ( "abort at first failure" )
7924             | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
7925                 ["-x"]["--abortx"]
7926                 ( "abort after x failures" )
7927             | Opt( setWarning, "warning name" )
7928                 ["-w"]["--warn"]
7929                 ( "enable warnings" )
7930             | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
7931                 ["-d"]["--durations"]
7932                 ( "show test durations" )
7933             | Opt( loadTestNamesFromFile, "filename" )
7934                 ["-f"]["--input-file"]
7935                 ( "load test names to run from a file" )
7936             | Opt( config.filenamesAsTags )
7937                 ["-#"]["--filenames-as-tags"]
7938                 ( "adds a tag for the filename" )
7939             | Opt( config.sectionsToRun, "section name" )
7940                 ["-c"]["--section"]
7941                 ( "specify section to run" )
7942             | Opt( setVerbosity, "quiet|normal|high" )
7943                 ["-v"]["--verbosity"]
7944                 ( "set output verbosity" )
7945             | Opt( config.listTestNamesOnly )
7946                 ["--list-test-names-only"]
7947                 ( "list all/matching test cases names only" )
7948             | Opt( config.listReporters )
7949                 ["--list-reporters"]
7950                 ( "list all reporters" )
7951             | Opt( setTestOrder, "decl|lex|rand" )
7952                 ["--order"]
7953                 ( "test case order (defaults to decl)" )
7954             | Opt( setRngSeed, "'time'|number" )
7955                 ["--rng-seed"]
7956                 ( "set a specific seed for random numbers" )
7957             | Opt( setColourUsage, "yes|no" )
7958                 ["--use-colour"]
7959                 ( "should output be colourised" )
7960             | Opt( config.libIdentify )
7961                 ["--libidentify"]
7962                 ( "report name and version according to libidentify standard" )
7963             | Opt( setWaitForKeypress, "start|exit|both" )
7964                 ["--wait-for-keypress"]
7965                 ( "waits for a keypress before exiting" )
7966             | Opt( config.benchmarkResolutionMultiple, "multiplier" )
7967                 ["--benchmark-resolution-multiple"]
7968                 ( "multiple of clock resolution to run benchmarks" )
7969 
7970             | Arg( config.testsOrTags, "test name|pattern|tags" )
7971                 ( "which test or tests to use" );
7972 
7973         return cli;
7974     }
7975 
7976 } // end namespace Catch
7977 // end catch_commandline.cpp
7978 // start catch_common.cpp
7979 
7980 #include <cstring>
7981 #include <ostream>
7982 
7983 namespace Catch {
7984 
empty() const7985     bool SourceLineInfo::empty() const noexcept {
7986         return file[0] == '\0';
7987     }
operator ==(SourceLineInfo const & other) const7988     bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
7989         return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
7990     }
operator <(SourceLineInfo const & other) const7991     bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
7992         // We can assume that the same file will usually have the same pointer.
7993         // Thus, if the pointers are the same, there is no point in calling the strcmp
7994         return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));
7995     }
7996 
operator <<(std::ostream & os,SourceLineInfo const & info)7997     std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
7998 #ifndef __GNUG__
7999         os << info.file << '(' << info.line << ')';
8000 #else
8001         os << info.file << ':' << info.line;
8002 #endif
8003         return os;
8004     }
8005 
operator +() const8006     std::string StreamEndStop::operator+() const {
8007         return std::string();
8008     }
8009 
8010     NonCopyable::NonCopyable() = default;
8011     NonCopyable::~NonCopyable() = default;
8012 
8013 }
8014 // end catch_common.cpp
8015 // start catch_config.cpp
8016 
8017 namespace Catch {
8018 
Config(ConfigData const & data)8019     Config::Config( ConfigData const& data )
8020     :   m_data( data ),
8021         m_stream( openStream() )
8022     {
8023         TestSpecParser parser(ITagAliasRegistry::get());
8024         if (data.testsOrTags.empty()) {
8025             parser.parse("~[.]"); // All not hidden tests
8026         }
8027         else {
8028             m_hasTestFilters = true;
8029             for( auto const& testOrTags : data.testsOrTags )
8030                 parser.parse( testOrTags );
8031         }
8032         m_testSpec = parser.testSpec();
8033     }
8034 
getFilename() const8035     std::string const& Config::getFilename() const {
8036         return m_data.outputFilename ;
8037     }
8038 
listTests() const8039     bool Config::listTests() const          { return m_data.listTests; }
listTestNamesOnly() const8040     bool Config::listTestNamesOnly() const  { return m_data.listTestNamesOnly; }
listTags() const8041     bool Config::listTags() const           { return m_data.listTags; }
listReporters() const8042     bool Config::listReporters() const      { return m_data.listReporters; }
8043 
getProcessName() const8044     std::string Config::getProcessName() const { return m_data.processName; }
getReporterName() const8045     std::string const& Config::getReporterName() const { return m_data.reporterName; }
8046 
getTestsOrTags() const8047     std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
getSectionsToRun() const8048     std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
8049 
testSpec() const8050     TestSpec const& Config::testSpec() const { return m_testSpec; }
hasTestFilters() const8051     bool Config::hasTestFilters() const { return m_hasTestFilters; }
8052 
showHelp() const8053     bool Config::showHelp() const { return m_data.showHelp; }
8054 
8055     // IConfig interface
allowThrows() const8056     bool Config::allowThrows() const                   { return !m_data.noThrow; }
stream() const8057     std::ostream& Config::stream() const               { return m_stream->stream(); }
name() const8058     std::string Config::name() const                   { return m_data.name.empty() ? m_data.processName : m_data.name; }
includeSuccessfulResults() const8059     bool Config::includeSuccessfulResults() const      { return m_data.showSuccessfulTests; }
warnAboutMissingAssertions() const8060     bool Config::warnAboutMissingAssertions() const    { return !!(m_data.warnings & WarnAbout::NoAssertions); }
warnAboutNoTests() const8061     bool Config::warnAboutNoTests() const              { return !!(m_data.warnings & WarnAbout::NoTests); }
showDurations() const8062     ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
runOrder() const8063     RunTests::InWhatOrder Config::runOrder() const     { return m_data.runOrder; }
rngSeed() const8064     unsigned int Config::rngSeed() const               { return m_data.rngSeed; }
benchmarkResolutionMultiple() const8065     int Config::benchmarkResolutionMultiple() const    { return m_data.benchmarkResolutionMultiple; }
useColour() const8066     UseColour::YesOrNo Config::useColour() const       { return m_data.useColour; }
shouldDebugBreak() const8067     bool Config::shouldDebugBreak() const              { return m_data.shouldDebugBreak; }
abortAfter() const8068     int Config::abortAfter() const                     { return m_data.abortAfter; }
showInvisibles() const8069     bool Config::showInvisibles() const                { return m_data.showInvisibles; }
verbosity() const8070     Verbosity Config::verbosity() const                { return m_data.verbosity; }
8071 
openStream()8072     IStream const* Config::openStream() {
8073         return Catch::makeStream(m_data.outputFilename);
8074     }
8075 
8076 } // end namespace Catch
8077 // end catch_config.cpp
8078 // start catch_console_colour.cpp
8079 
8080 #if defined(__clang__)
8081 #    pragma clang diagnostic push
8082 #    pragma clang diagnostic ignored "-Wexit-time-destructors"
8083 #endif
8084 
8085 // start catch_errno_guard.h
8086 
8087 namespace Catch {
8088 
8089     class ErrnoGuard {
8090     public:
8091         ErrnoGuard();
8092         ~ErrnoGuard();
8093     private:
8094         int m_oldErrno;
8095     };
8096 
8097 }
8098 
8099 // end catch_errno_guard.h
8100 #include <sstream>
8101 
8102 namespace Catch {
8103     namespace {
8104 
8105         struct IColourImpl {
8106             virtual ~IColourImpl() = default;
8107             virtual void use( Colour::Code _colourCode ) = 0;
8108         };
8109 
8110         struct NoColourImpl : IColourImpl {
useCatch::__anonc5acfb671311::NoColourImpl8111             void use( Colour::Code ) {}
8112 
instanceCatch::__anonc5acfb671311::NoColourImpl8113             static IColourImpl* instance() {
8114                 static NoColourImpl s_instance;
8115                 return &s_instance;
8116             }
8117         };
8118 
8119     } // anon namespace
8120 } // namespace Catch
8121 
8122 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
8123 #   ifdef CATCH_PLATFORM_WINDOWS
8124 #       define CATCH_CONFIG_COLOUR_WINDOWS
8125 #   else
8126 #       define CATCH_CONFIG_COLOUR_ANSI
8127 #   endif
8128 #endif
8129 
8130 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
8131 
8132 namespace Catch {
8133 namespace {
8134 
8135     class Win32ColourImpl : public IColourImpl {
8136     public:
Win32ColourImpl()8137         Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
8138         {
8139             CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
8140             GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
8141             originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
8142             originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
8143         }
8144 
use(Colour::Code _colourCode)8145         virtual void use( Colour::Code _colourCode ) override {
8146             switch( _colourCode ) {
8147                 case Colour::None:      return setTextAttribute( originalForegroundAttributes );
8148                 case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
8149                 case Colour::Red:       return setTextAttribute( FOREGROUND_RED );
8150                 case Colour::Green:     return setTextAttribute( FOREGROUND_GREEN );
8151                 case Colour::Blue:      return setTextAttribute( FOREGROUND_BLUE );
8152                 case Colour::Cyan:      return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
8153                 case Colour::Yellow:    return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
8154                 case Colour::Grey:      return setTextAttribute( 0 );
8155 
8156                 case Colour::LightGrey:     return setTextAttribute( FOREGROUND_INTENSITY );
8157                 case Colour::BrightRed:     return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
8158                 case Colour::BrightGreen:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
8159                 case Colour::BrightWhite:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
8160                 case Colour::BrightYellow:  return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
8161 
8162                 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
8163 
8164                 default:
8165                     CATCH_ERROR( "Unknown colour requested" );
8166             }
8167         }
8168 
8169     private:
setTextAttribute(WORD _textAttribute)8170         void setTextAttribute( WORD _textAttribute ) {
8171             SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
8172         }
8173         HANDLE stdoutHandle;
8174         WORD originalForegroundAttributes;
8175         WORD originalBackgroundAttributes;
8176     };
8177 
platformColourInstance()8178     IColourImpl* platformColourInstance() {
8179         static Win32ColourImpl s_instance;
8180 
8181         IConfigPtr config = getCurrentContext().getConfig();
8182         UseColour::YesOrNo colourMode = config
8183             ? config->useColour()
8184             : UseColour::Auto;
8185         if( colourMode == UseColour::Auto )
8186             colourMode = UseColour::Yes;
8187         return colourMode == UseColour::Yes
8188             ? &s_instance
8189             : NoColourImpl::instance();
8190     }
8191 
8192 } // end anon namespace
8193 } // end namespace Catch
8194 
8195 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
8196 
8197 #include <unistd.h>
8198 
8199 namespace Catch {
8200 namespace {
8201 
8202     // use POSIX/ ANSI console terminal codes
8203     // Thanks to Adam Strzelecki for original contribution
8204     // (http://github.com/nanoant)
8205     // https://github.com/philsquared/Catch/pull/131
8206     class PosixColourImpl : public IColourImpl {
8207     public:
use(Colour::Code _colourCode)8208         virtual void use( Colour::Code _colourCode ) override {
8209             switch( _colourCode ) {
8210                 case Colour::None:
8211                 case Colour::White:     return setColour( "[0m" );
8212                 case Colour::Red:       return setColour( "[0;31m" );
8213                 case Colour::Green:     return setColour( "[0;32m" );
8214                 case Colour::Blue:      return setColour( "[0;34m" );
8215                 case Colour::Cyan:      return setColour( "[0;36m" );
8216                 case Colour::Yellow:    return setColour( "[0;33m" );
8217                 case Colour::Grey:      return setColour( "[1;30m" );
8218 
8219                 case Colour::LightGrey:     return setColour( "[0;37m" );
8220                 case Colour::BrightRed:     return setColour( "[1;31m" );
8221                 case Colour::BrightGreen:   return setColour( "[1;32m" );
8222                 case Colour::BrightWhite:   return setColour( "[1;37m" );
8223                 case Colour::BrightYellow:  return setColour( "[1;33m" );
8224 
8225                 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
8226                 default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
8227             }
8228         }
instance()8229         static IColourImpl* instance() {
8230             static PosixColourImpl s_instance;
8231             return &s_instance;
8232         }
8233 
8234     private:
setColour(const char * _escapeCode)8235         void setColour( const char* _escapeCode ) {
8236             getCurrentContext().getConfig()->stream()
8237                 << '\033' << _escapeCode;
8238         }
8239     };
8240 
useColourOnPlatform()8241     bool useColourOnPlatform() {
8242         return
8243 #ifdef CATCH_PLATFORM_MAC
8244             !isDebuggerActive() &&
8245 #endif
8246 #if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
8247             isatty(STDOUT_FILENO)
8248 #else
8249             false
8250 #endif
8251             ;
8252     }
platformColourInstance()8253     IColourImpl* platformColourInstance() {
8254         ErrnoGuard guard;
8255         IConfigPtr config = getCurrentContext().getConfig();
8256         UseColour::YesOrNo colourMode = config
8257             ? config->useColour()
8258             : UseColour::Auto;
8259         if( colourMode == UseColour::Auto )
8260             colourMode = useColourOnPlatform()
8261                 ? UseColour::Yes
8262                 : UseColour::No;
8263         return colourMode == UseColour::Yes
8264             ? PosixColourImpl::instance()
8265             : NoColourImpl::instance();
8266     }
8267 
8268 } // end anon namespace
8269 } // end namespace Catch
8270 
8271 #else  // not Windows or ANSI ///////////////////////////////////////////////
8272 
8273 namespace Catch {
8274 
platformColourInstance()8275     static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
8276 
8277 } // end namespace Catch
8278 
8279 #endif // Windows/ ANSI/ None
8280 
8281 namespace Catch {
8282 
Colour(Code _colourCode)8283     Colour::Colour( Code _colourCode ) { use( _colourCode ); }
Colour(Colour && rhs)8284     Colour::Colour( Colour&& rhs ) noexcept {
8285         m_moved = rhs.m_moved;
8286         rhs.m_moved = true;
8287     }
operator =(Colour && rhs)8288     Colour& Colour::operator=( Colour&& rhs ) noexcept {
8289         m_moved = rhs.m_moved;
8290         rhs.m_moved  = true;
8291         return *this;
8292     }
8293 
~Colour()8294     Colour::~Colour(){ if( !m_moved ) use( None ); }
8295 
use(Code _colourCode)8296     void Colour::use( Code _colourCode ) {
8297         static IColourImpl* impl = platformColourInstance();
8298         impl->use( _colourCode );
8299     }
8300 
operator <<(std::ostream & os,Colour const &)8301     std::ostream& operator << ( std::ostream& os, Colour const& ) {
8302         return os;
8303     }
8304 
8305 } // end namespace Catch
8306 
8307 #if defined(__clang__)
8308 #    pragma clang diagnostic pop
8309 #endif
8310 
8311 // end catch_console_colour.cpp
8312 // start catch_context.cpp
8313 
8314 namespace Catch {
8315 
8316     class Context : public IMutableContext, NonCopyable {
8317 
8318     public: // IContext
getResultCapture()8319         virtual IResultCapture* getResultCapture() override {
8320             return m_resultCapture;
8321         }
getRunner()8322         virtual IRunner* getRunner() override {
8323             return m_runner;
8324         }
8325 
getConfig() const8326         virtual IConfigPtr const& getConfig() const override {
8327             return m_config;
8328         }
8329 
8330         virtual ~Context() override;
8331 
8332     public: // IMutableContext
setResultCapture(IResultCapture * resultCapture)8333         virtual void setResultCapture( IResultCapture* resultCapture ) override {
8334             m_resultCapture = resultCapture;
8335         }
setRunner(IRunner * runner)8336         virtual void setRunner( IRunner* runner ) override {
8337             m_runner = runner;
8338         }
setConfig(IConfigPtr const & config)8339         virtual void setConfig( IConfigPtr const& config ) override {
8340             m_config = config;
8341         }
8342 
8343         friend IMutableContext& getCurrentMutableContext();
8344 
8345     private:
8346         IConfigPtr m_config;
8347         IRunner* m_runner = nullptr;
8348         IResultCapture* m_resultCapture = nullptr;
8349     };
8350 
8351     IMutableContext *IMutableContext::currentContext = nullptr;
8352 
createContext()8353     void IMutableContext::createContext()
8354     {
8355         currentContext = new Context();
8356     }
8357 
cleanUpContext()8358     void cleanUpContext() {
8359         delete IMutableContext::currentContext;
8360         IMutableContext::currentContext = nullptr;
8361     }
8362     IContext::~IContext() = default;
8363     IMutableContext::~IMutableContext() = default;
8364     Context::~Context() = default;
8365 }
8366 // end catch_context.cpp
8367 // start catch_debug_console.cpp
8368 
8369 // start catch_debug_console.h
8370 
8371 #include <string>
8372 
8373 namespace Catch {
8374     void writeToDebugConsole( std::string const& text );
8375 }
8376 
8377 // end catch_debug_console.h
8378 #ifdef CATCH_PLATFORM_WINDOWS
8379 
8380     namespace Catch {
writeToDebugConsole(std::string const & text)8381         void writeToDebugConsole( std::string const& text ) {
8382             ::OutputDebugStringA( text.c_str() );
8383         }
8384     }
8385 
8386 #else
8387 
8388     namespace Catch {
writeToDebugConsole(std::string const & text)8389         void writeToDebugConsole( std::string const& text ) {
8390             // !TBD: Need a version for Mac/ XCode and other IDEs
8391             Catch::cout() << text;
8392         }
8393     }
8394 
8395 #endif // Platform
8396 // end catch_debug_console.cpp
8397 // start catch_debugger.cpp
8398 
8399 #ifdef CATCH_PLATFORM_MAC
8400 
8401 #  include <assert.h>
8402 #  include <stdbool.h>
8403 #  include <sys/types.h>
8404 #  include <unistd.h>
8405 #  include <sys/sysctl.h>
8406 #  include <cstddef>
8407 #  include <ostream>
8408 
8409 namespace Catch {
8410 
8411         // The following function is taken directly from the following technical note:
8412         // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
8413 
8414         // Returns true if the current process is being debugged (either
8415         // running under the debugger or has a debugger attached post facto).
isDebuggerActive()8416         bool isDebuggerActive(){
8417 
8418             int                 mib[4];
8419             struct kinfo_proc   info;
8420             std::size_t         size;
8421 
8422             // Initialize the flags so that, if sysctl fails for some bizarre
8423             // reason, we get a predictable result.
8424 
8425             info.kp_proc.p_flag = 0;
8426 
8427             // Initialize mib, which tells sysctl the info we want, in this case
8428             // we're looking for information about a specific process ID.
8429 
8430             mib[0] = CTL_KERN;
8431             mib[1] = KERN_PROC;
8432             mib[2] = KERN_PROC_PID;
8433             mib[3] = getpid();
8434 
8435             // Call sysctl.
8436 
8437             size = sizeof(info);
8438             if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {
8439                 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
8440                 return false;
8441             }
8442 
8443             // We're being debugged if the P_TRACED flag is set.
8444 
8445             return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
8446         }
8447     } // namespace Catch
8448 
8449 #elif defined(CATCH_PLATFORM_LINUX)
8450     #include <fstream>
8451     #include <string>
8452 
8453     namespace Catch{
8454         // The standard POSIX way of detecting a debugger is to attempt to
8455         // ptrace() the process, but this needs to be done from a child and not
8456         // this process itself to still allow attaching to this process later
8457         // if wanted, so is rather heavy. Under Linux we have the PID of the
8458         // "debugger" (which doesn't need to be gdb, of course, it could also
8459         // be strace, for example) in /proc/$PID/status, so just get it from
8460         // there instead.
isDebuggerActive()8461         bool isDebuggerActive(){
8462             // Libstdc++ has a bug, where std::ifstream sets errno to 0
8463             // This way our users can properly assert over errno values
8464             ErrnoGuard guard;
8465             std::ifstream in("/proc/self/status");
8466             for( std::string line; std::getline(in, line); ) {
8467                 static const int PREFIX_LEN = 11;
8468                 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
8469                     // We're traced if the PID is not 0 and no other PID starts
8470                     // with 0 digit, so it's enough to check for just a single
8471                     // character.
8472                     return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
8473                 }
8474             }
8475 
8476             return false;
8477         }
8478     } // namespace Catch
8479 #elif defined(_MSC_VER)
8480     extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8481     namespace Catch {
isDebuggerActive()8482         bool isDebuggerActive() {
8483             return IsDebuggerPresent() != 0;
8484         }
8485     }
8486 #elif defined(__MINGW32__)
8487     extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8488     namespace Catch {
isDebuggerActive()8489         bool isDebuggerActive() {
8490             return IsDebuggerPresent() != 0;
8491         }
8492     }
8493 #else
8494     namespace Catch {
isDebuggerActive()8495        bool isDebuggerActive() { return false; }
8496     }
8497 #endif // Platform
8498 // end catch_debugger.cpp
8499 // start catch_decomposer.cpp
8500 
8501 namespace Catch {
8502 
8503     ITransientExpression::~ITransientExpression() = default;
8504 
formatReconstructedExpression(std::ostream & os,std::string const & lhs,StringRef op,std::string const & rhs)8505     void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
8506         if( lhs.size() + rhs.size() < 40 &&
8507                 lhs.find('\n') == std::string::npos &&
8508                 rhs.find('\n') == std::string::npos )
8509             os << lhs << " " << op << " " << rhs;
8510         else
8511             os << lhs << "\n" << op << "\n" << rhs;
8512     }
8513 }
8514 // end catch_decomposer.cpp
8515 // start catch_enforce.cpp
8516 
8517 namespace Catch {
8518 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
8519     [[noreturn]]
throw_exception(std::exception const & e)8520     void throw_exception(std::exception const& e) {
8521         Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"
8522                       << "The message was: " << e.what() << '\n';
8523         std::terminate();
8524     }
8525 #endif
8526 } // namespace Catch;
8527 // end catch_enforce.cpp
8528 // start catch_errno_guard.cpp
8529 
8530 #include <cerrno>
8531 
8532 namespace Catch {
ErrnoGuard()8533         ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
~ErrnoGuard()8534         ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
8535 }
8536 // end catch_errno_guard.cpp
8537 // start catch_exception_translator_registry.cpp
8538 
8539 // start catch_exception_translator_registry.h
8540 
8541 #include <vector>
8542 #include <string>
8543 #include <memory>
8544 
8545 namespace Catch {
8546 
8547     class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
8548     public:
8549         ~ExceptionTranslatorRegistry();
8550         virtual void registerTranslator( const IExceptionTranslator* translator );
8551         virtual std::string translateActiveException() const override;
8552         std::string tryTranslators() const;
8553 
8554     private:
8555         std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
8556     };
8557 }
8558 
8559 // end catch_exception_translator_registry.h
8560 #ifdef __OBJC__
8561 #import "Foundation/Foundation.h"
8562 #endif
8563 
8564 namespace Catch {
8565 
~ExceptionTranslatorRegistry()8566     ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
8567     }
8568 
registerTranslator(const IExceptionTranslator * translator)8569     void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) {
8570         m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
8571     }
8572 
8573 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
translateActiveException() const8574     std::string ExceptionTranslatorRegistry::translateActiveException() const {
8575         try {
8576 #ifdef __OBJC__
8577             // In Objective-C try objective-c exceptions first
8578             @try {
8579                 return tryTranslators();
8580             }
8581             @catch (NSException *exception) {
8582                 return Catch::Detail::stringify( [exception description] );
8583             }
8584 #else
8585             // Compiling a mixed mode project with MSVC means that CLR
8586             // exceptions will be caught in (...) as well. However, these
8587             // do not fill-in std::current_exception and thus lead to crash
8588             // when attempting rethrow.
8589             // /EHa switch also causes structured exceptions to be caught
8590             // here, but they fill-in current_exception properly, so
8591             // at worst the output should be a little weird, instead of
8592             // causing a crash.
8593             if (std::current_exception() == nullptr) {
8594                 return "Non C++ exception. Possibly a CLR exception.";
8595             }
8596             return tryTranslators();
8597 #endif
8598         }
8599         catch( TestFailureException& ) {
8600             std::rethrow_exception(std::current_exception());
8601         }
8602         catch( std::exception& ex ) {
8603             return ex.what();
8604         }
8605         catch( std::string& msg ) {
8606             return msg;
8607         }
8608         catch( const char* msg ) {
8609             return msg;
8610         }
8611         catch(...) {
8612             return "Unknown exception";
8613         }
8614     }
8615 
tryTranslators() const8616     std::string ExceptionTranslatorRegistry::tryTranslators() const {
8617         if (m_translators.empty()) {
8618             std::rethrow_exception(std::current_exception());
8619         } else {
8620             return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
8621         }
8622     }
8623 
8624 #else // ^^ Exceptions are enabled // Exceptions are disabled vv
translateActiveException() const8625     std::string ExceptionTranslatorRegistry::translateActiveException() const {
8626         CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
8627     }
8628 
tryTranslators() const8629     std::string ExceptionTranslatorRegistry::tryTranslators() const {
8630         CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
8631     }
8632 #endif
8633 
8634 }
8635 // end catch_exception_translator_registry.cpp
8636 // start catch_fatal_condition.cpp
8637 
8638 #if defined(__GNUC__)
8639 #    pragma GCC diagnostic push
8640 #    pragma GCC diagnostic ignored "-Wmissing-field-initializers"
8641 #endif
8642 
8643 #if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
8644 
8645 namespace {
8646     // Report the error condition
reportFatal(char const * const message)8647     void reportFatal( char const * const message ) {
8648         Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
8649     }
8650 }
8651 
8652 #endif // signals/SEH handling
8653 
8654 #if defined( CATCH_CONFIG_WINDOWS_SEH )
8655 
8656 namespace Catch {
8657     struct SignalDefs { DWORD id; const char* name; };
8658 
8659     // There is no 1-1 mapping between signals and windows exceptions.
8660     // Windows can easily distinguish between SO and SigSegV,
8661     // but SigInt, SigTerm, etc are handled differently.
8662     static SignalDefs signalDefs[] = {
8663         { EXCEPTION_ILLEGAL_INSTRUCTION,  "SIGILL - Illegal instruction signal" },
8664         { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
8665         { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
8666         { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
8667     };
8668 
handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo)8669     LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
8670         for (auto const& def : signalDefs) {
8671             if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
8672                 reportFatal(def.name);
8673             }
8674         }
8675         // If its not an exception we care about, pass it along.
8676         // This stops us from eating debugger breaks etc.
8677         return EXCEPTION_CONTINUE_SEARCH;
8678     }
8679 
FatalConditionHandler()8680     FatalConditionHandler::FatalConditionHandler() {
8681         isSet = true;
8682         // 32k seems enough for Catch to handle stack overflow,
8683         // but the value was found experimentally, so there is no strong guarantee
8684         guaranteeSize = 32 * 1024;
8685         exceptionHandlerHandle = nullptr;
8686         // Register as first handler in current chain
8687         exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
8688         // Pass in guarantee size to be filled
8689         SetThreadStackGuarantee(&guaranteeSize);
8690     }
8691 
reset()8692     void FatalConditionHandler::reset() {
8693         if (isSet) {
8694             RemoveVectoredExceptionHandler(exceptionHandlerHandle);
8695             SetThreadStackGuarantee(&guaranteeSize);
8696             exceptionHandlerHandle = nullptr;
8697             isSet = false;
8698         }
8699     }
8700 
~FatalConditionHandler()8701     FatalConditionHandler::~FatalConditionHandler() {
8702         reset();
8703     }
8704 
8705 bool FatalConditionHandler::isSet = false;
8706 ULONG FatalConditionHandler::guaranteeSize = 0;
8707 PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
8708 
8709 } // namespace Catch
8710 
8711 #elif defined( CATCH_CONFIG_POSIX_SIGNALS )
8712 
8713 namespace Catch {
8714 
8715     struct SignalDefs {
8716         int id;
8717         const char* name;
8718     };
8719 
8720     // 32kb for the alternate stack seems to be sufficient. However, this value
8721     // is experimentally determined, so that's not guaranteed.
8722     constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
8723 
8724     static SignalDefs signalDefs[] = {
8725         { SIGINT,  "SIGINT - Terminal interrupt signal" },
8726         { SIGILL,  "SIGILL - Illegal instruction signal" },
8727         { SIGFPE,  "SIGFPE - Floating point error signal" },
8728         { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
8729         { SIGTERM, "SIGTERM - Termination request signal" },
8730         { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
8731     };
8732 
handleSignal(int sig)8733     void FatalConditionHandler::handleSignal( int sig ) {
8734         char const * name = "<unknown signal>";
8735         for (auto const& def : signalDefs) {
8736             if (sig == def.id) {
8737                 name = def.name;
8738                 break;
8739             }
8740         }
8741         reset();
8742         reportFatal(name);
8743         raise( sig );
8744     }
8745 
FatalConditionHandler()8746     FatalConditionHandler::FatalConditionHandler() {
8747         isSet = true;
8748         stack_t sigStack;
8749         sigStack.ss_sp = altStackMem;
8750         sigStack.ss_size = sigStackSize;
8751         sigStack.ss_flags = 0;
8752         sigaltstack(&sigStack, &oldSigStack);
8753         struct sigaction sa = { };
8754 
8755         sa.sa_handler = handleSignal;
8756         sa.sa_flags = SA_ONSTACK;
8757         for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
8758             sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
8759         }
8760     }
8761 
~FatalConditionHandler()8762     FatalConditionHandler::~FatalConditionHandler() {
8763         reset();
8764     }
8765 
reset()8766     void FatalConditionHandler::reset() {
8767         if( isSet ) {
8768             // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
8769             for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
8770                 sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
8771             }
8772             // Return the old stack
8773             sigaltstack(&oldSigStack, nullptr);
8774             isSet = false;
8775         }
8776     }
8777 
8778     bool FatalConditionHandler::isSet = false;
8779     struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
8780     stack_t FatalConditionHandler::oldSigStack = {};
8781     char FatalConditionHandler::altStackMem[sigStackSize] = {};
8782 
8783 } // namespace Catch
8784 
8785 #else
8786 
8787 namespace Catch {
reset()8788     void FatalConditionHandler::reset() {}
8789 }
8790 
8791 #endif // signals/SEH handling
8792 
8793 #if defined(__GNUC__)
8794 #    pragma GCC diagnostic pop
8795 #endif
8796 // end catch_fatal_condition.cpp
8797 // start catch_generators.cpp
8798 
8799 // start catch_random_number_generator.h
8800 
8801 #include <algorithm>
8802 #include <random>
8803 
8804 namespace Catch {
8805 
8806     struct IConfig;
8807 
8808     std::mt19937& rng();
8809     void seedRng( IConfig const& config );
8810     unsigned int rngSeed();
8811 
8812 }
8813 
8814 // end catch_random_number_generator.h
8815 #include <limits>
8816 #include <set>
8817 
8818 namespace Catch {
8819 
~IGeneratorTracker()8820 IGeneratorTracker::~IGeneratorTracker() {}
8821 
what() const8822 const char* GeneratorException::what() const noexcept {
8823     return m_msg;
8824 }
8825 
8826 namespace Generators {
8827 
~GeneratorUntypedBase()8828     GeneratorUntypedBase::~GeneratorUntypedBase() {}
8829 
acquireGeneratorTracker(SourceLineInfo const & lineInfo)8830     auto acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
8831         return getResultCapture().acquireGeneratorTracker( lineInfo );
8832     }
8833 
8834 } // namespace Generators
8835 } // namespace Catch
8836 // end catch_generators.cpp
8837 // start catch_interfaces_capture.cpp
8838 
8839 namespace Catch {
8840     IResultCapture::~IResultCapture() = default;
8841 }
8842 // end catch_interfaces_capture.cpp
8843 // start catch_interfaces_config.cpp
8844 
8845 namespace Catch {
8846     IConfig::~IConfig() = default;
8847 }
8848 // end catch_interfaces_config.cpp
8849 // start catch_interfaces_exception.cpp
8850 
8851 namespace Catch {
8852     IExceptionTranslator::~IExceptionTranslator() = default;
8853     IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;
8854 }
8855 // end catch_interfaces_exception.cpp
8856 // start catch_interfaces_registry_hub.cpp
8857 
8858 namespace Catch {
8859     IRegistryHub::~IRegistryHub() = default;
8860     IMutableRegistryHub::~IMutableRegistryHub() = default;
8861 }
8862 // end catch_interfaces_registry_hub.cpp
8863 // start catch_interfaces_reporter.cpp
8864 
8865 // start catch_reporter_listening.h
8866 
8867 namespace Catch {
8868 
8869     class ListeningReporter : public IStreamingReporter {
8870         using Reporters = std::vector<IStreamingReporterPtr>;
8871         Reporters m_listeners;
8872         IStreamingReporterPtr m_reporter = nullptr;
8873         ReporterPreferences m_preferences;
8874 
8875     public:
8876         ListeningReporter();
8877 
8878         void addListener( IStreamingReporterPtr&& listener );
8879         void addReporter( IStreamingReporterPtr&& reporter );
8880 
8881     public: // IStreamingReporter
8882 
8883         ReporterPreferences getPreferences() const override;
8884 
8885         void noMatchingTestCases( std::string const& spec ) override;
8886 
8887         static std::set<Verbosity> getSupportedVerbosities();
8888 
8889         void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
8890         void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override;
8891 
8892         void testRunStarting( TestRunInfo const& testRunInfo ) override;
8893         void testGroupStarting( GroupInfo const& groupInfo ) override;
8894         void testCaseStarting( TestCaseInfo const& testInfo ) override;
8895         void sectionStarting( SectionInfo const& sectionInfo ) override;
8896         void assertionStarting( AssertionInfo const& assertionInfo ) override;
8897 
8898         // The return value indicates if the messages buffer should be cleared:
8899         bool assertionEnded( AssertionStats const& assertionStats ) override;
8900         void sectionEnded( SectionStats const& sectionStats ) override;
8901         void testCaseEnded( TestCaseStats const& testCaseStats ) override;
8902         void testGroupEnded( TestGroupStats const& testGroupStats ) override;
8903         void testRunEnded( TestRunStats const& testRunStats ) override;
8904 
8905         void skipTest( TestCaseInfo const& testInfo ) override;
8906         bool isMulti() const override;
8907 
8908     };
8909 
8910 } // end namespace Catch
8911 
8912 // end catch_reporter_listening.h
8913 namespace Catch {
8914 
ReporterConfig(IConfigPtr const & _fullConfig)8915     ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig )
8916     :   m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
8917 
ReporterConfig(IConfigPtr const & _fullConfig,std::ostream & _stream)8918     ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream )
8919     :   m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
8920 
stream() const8921     std::ostream& ReporterConfig::stream() const { return *m_stream; }
fullConfig() const8922     IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; }
8923 
TestRunInfo(std::string const & _name)8924     TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {}
8925 
GroupInfo(std::string const & _name,std::size_t _groupIndex,std::size_t _groupsCount)8926     GroupInfo::GroupInfo(  std::string const& _name,
8927                            std::size_t _groupIndex,
8928                            std::size_t _groupsCount )
8929     :   name( _name ),
8930         groupIndex( _groupIndex ),
8931         groupsCounts( _groupsCount )
8932     {}
8933 
AssertionStats(AssertionResult const & _assertionResult,std::vector<MessageInfo> const & _infoMessages,Totals const & _totals)8934      AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
8935                                      std::vector<MessageInfo> const& _infoMessages,
8936                                      Totals const& _totals )
8937     :   assertionResult( _assertionResult ),
8938         infoMessages( _infoMessages ),
8939         totals( _totals )
8940     {
8941         assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
8942 
8943         if( assertionResult.hasMessage() ) {
8944             // Copy message into messages list.
8945             // !TBD This should have been done earlier, somewhere
8946             MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
8947             builder << assertionResult.getMessage();
8948             builder.m_info.message = builder.m_stream.str();
8949 
8950             infoMessages.push_back( builder.m_info );
8951         }
8952     }
8953 
8954      AssertionStats::~AssertionStats() = default;
8955 
SectionStats(SectionInfo const & _sectionInfo,Counts const & _assertions,double _durationInSeconds,bool _missingAssertions)8956     SectionStats::SectionStats(  SectionInfo const& _sectionInfo,
8957                                  Counts const& _assertions,
8958                                  double _durationInSeconds,
8959                                  bool _missingAssertions )
8960     :   sectionInfo( _sectionInfo ),
8961         assertions( _assertions ),
8962         durationInSeconds( _durationInSeconds ),
8963         missingAssertions( _missingAssertions )
8964     {}
8965 
8966     SectionStats::~SectionStats() = default;
8967 
TestCaseStats(TestCaseInfo const & _testInfo,Totals const & _totals,std::string const & _stdOut,std::string const & _stdErr,bool _aborting)8968     TestCaseStats::TestCaseStats(  TestCaseInfo const& _testInfo,
8969                                    Totals const& _totals,
8970                                    std::string const& _stdOut,
8971                                    std::string const& _stdErr,
8972                                    bool _aborting )
8973     : testInfo( _testInfo ),
8974         totals( _totals ),
8975         stdOut( _stdOut ),
8976         stdErr( _stdErr ),
8977         aborting( _aborting )
8978     {}
8979 
8980     TestCaseStats::~TestCaseStats() = default;
8981 
TestGroupStats(GroupInfo const & _groupInfo,Totals const & _totals,bool _aborting)8982     TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo,
8983                                     Totals const& _totals,
8984                                     bool _aborting )
8985     :   groupInfo( _groupInfo ),
8986         totals( _totals ),
8987         aborting( _aborting )
8988     {}
8989 
TestGroupStats(GroupInfo const & _groupInfo)8990     TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo )
8991     :   groupInfo( _groupInfo ),
8992         aborting( false )
8993     {}
8994 
8995     TestGroupStats::~TestGroupStats() = default;
8996 
TestRunStats(TestRunInfo const & _runInfo,Totals const & _totals,bool _aborting)8997     TestRunStats::TestRunStats(   TestRunInfo const& _runInfo,
8998                     Totals const& _totals,
8999                     bool _aborting )
9000     :   runInfo( _runInfo ),
9001         totals( _totals ),
9002         aborting( _aborting )
9003     {}
9004 
9005     TestRunStats::~TestRunStats() = default;
9006 
fatalErrorEncountered(StringRef)9007     void IStreamingReporter::fatalErrorEncountered( StringRef ) {}
isMulti() const9008     bool IStreamingReporter::isMulti() const { return false; }
9009 
9010     IReporterFactory::~IReporterFactory() = default;
9011     IReporterRegistry::~IReporterRegistry() = default;
9012 
9013 } // end namespace Catch
9014 // end catch_interfaces_reporter.cpp
9015 // start catch_interfaces_runner.cpp
9016 
9017 namespace Catch {
9018     IRunner::~IRunner() = default;
9019 }
9020 // end catch_interfaces_runner.cpp
9021 // start catch_interfaces_testcase.cpp
9022 
9023 namespace Catch {
9024     ITestInvoker::~ITestInvoker() = default;
9025     ITestCaseRegistry::~ITestCaseRegistry() = default;
9026 }
9027 // end catch_interfaces_testcase.cpp
9028 // start catch_leak_detector.cpp
9029 
9030 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG
9031 #include <crtdbg.h>
9032 
9033 namespace Catch {
9034 
LeakDetector()9035     LeakDetector::LeakDetector() {
9036         int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
9037         flag |= _CRTDBG_LEAK_CHECK_DF;
9038         flag |= _CRTDBG_ALLOC_MEM_DF;
9039         _CrtSetDbgFlag(flag);
9040         _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
9041         _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
9042         // Change this to leaking allocation's number to break there
9043         _CrtSetBreakAlloc(-1);
9044     }
9045 }
9046 
9047 #else
9048 
LeakDetector()9049     Catch::LeakDetector::LeakDetector() {}
9050 
9051 #endif
9052 
~LeakDetector()9053 Catch::LeakDetector::~LeakDetector() {
9054     Catch::cleanUp();
9055 }
9056 // end catch_leak_detector.cpp
9057 // start catch_list.cpp
9058 
9059 // start catch_list.h
9060 
9061 #include <set>
9062 
9063 namespace Catch {
9064 
9065     std::size_t listTests( Config const& config );
9066 
9067     std::size_t listTestsNamesOnly( Config const& config );
9068 
9069     struct TagInfo {
9070         void add( std::string const& spelling );
9071         std::string all() const;
9072 
9073         std::set<std::string> spellings;
9074         std::size_t count = 0;
9075     };
9076 
9077     std::size_t listTags( Config const& config );
9078 
9079     std::size_t listReporters();
9080 
9081     Option<std::size_t> list( std::shared_ptr<Config> const& config );
9082 
9083 } // end namespace Catch
9084 
9085 // end catch_list.h
9086 // start catch_text.h
9087 
9088 namespace Catch {
9089     using namespace clara::TextFlow;
9090 }
9091 
9092 // end catch_text.h
9093 #include <limits>
9094 #include <algorithm>
9095 #include <iomanip>
9096 
9097 namespace Catch {
9098 
listTests(Config const & config)9099     std::size_t listTests( Config const& config ) {
9100         TestSpec testSpec = config.testSpec();
9101         if( config.hasTestFilters() )
9102             Catch::cout() << "Matching test cases:\n";
9103         else {
9104             Catch::cout() << "All available test cases:\n";
9105         }
9106 
9107         auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
9108         for( auto const& testCaseInfo : matchedTestCases ) {
9109             Colour::Code colour = testCaseInfo.isHidden()
9110                 ? Colour::SecondaryText
9111                 : Colour::None;
9112             Colour colourGuard( colour );
9113 
9114             Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n";
9115             if( config.verbosity() >= Verbosity::High ) {
9116                 Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl;
9117                 std::string description = testCaseInfo.description;
9118                 if( description.empty() )
9119                     description = "(NO DESCRIPTION)";
9120                 Catch::cout() << Column( description ).indent(4) << std::endl;
9121             }
9122             if( !testCaseInfo.tags.empty() )
9123                 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";
9124         }
9125 
9126         if( !config.hasTestFilters() )
9127             Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl;
9128         else
9129             Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;
9130         return matchedTestCases.size();
9131     }
9132 
listTestsNamesOnly(Config const & config)9133     std::size_t listTestsNamesOnly( Config const& config ) {
9134         TestSpec testSpec = config.testSpec();
9135         std::size_t matchedTests = 0;
9136         std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
9137         for( auto const& testCaseInfo : matchedTestCases ) {
9138             matchedTests++;
9139             if( startsWith( testCaseInfo.name, '#' ) )
9140                Catch::cout() << '"' << testCaseInfo.name << '"';
9141             else
9142                Catch::cout() << testCaseInfo.name;
9143             if ( config.verbosity() >= Verbosity::High )
9144                 Catch::cout() << "\t@" << testCaseInfo.lineInfo;
9145             Catch::cout() << std::endl;
9146         }
9147         return matchedTests;
9148     }
9149 
add(std::string const & spelling)9150     void TagInfo::add( std::string const& spelling ) {
9151         ++count;
9152         spellings.insert( spelling );
9153     }
9154 
all() const9155     std::string TagInfo::all() const {
9156         std::string out;
9157         for( auto const& spelling : spellings )
9158             out += "[" + spelling + "]";
9159         return out;
9160     }
9161 
listTags(Config const & config)9162     std::size_t listTags( Config const& config ) {
9163         TestSpec testSpec = config.testSpec();
9164         if( config.hasTestFilters() )
9165             Catch::cout() << "Tags for matching test cases:\n";
9166         else {
9167             Catch::cout() << "All available tags:\n";
9168         }
9169 
9170         std::map<std::string, TagInfo> tagCounts;
9171 
9172         std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
9173         for( auto const& testCase : matchedTestCases ) {
9174             for( auto const& tagName : testCase.getTestCaseInfo().tags ) {
9175                 std::string lcaseTagName = toLower( tagName );
9176                 auto countIt = tagCounts.find( lcaseTagName );
9177                 if( countIt == tagCounts.end() )
9178                     countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
9179                 countIt->second.add( tagName );
9180             }
9181         }
9182 
9183         for( auto const& tagCount : tagCounts ) {
9184             ReusableStringStream rss;
9185             rss << "  " << std::setw(2) << tagCount.second.count << "  ";
9186             auto str = rss.str();
9187             auto wrapper = Column( tagCount.second.all() )
9188                                                     .initialIndent( 0 )
9189                                                     .indent( str.size() )
9190                                                     .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
9191             Catch::cout() << str << wrapper << '\n';
9192         }
9193         Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
9194         return tagCounts.size();
9195     }
9196 
listReporters()9197     std::size_t listReporters() {
9198         Catch::cout() << "Available reporters:\n";
9199         IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
9200         std::size_t maxNameLen = 0;
9201         for( auto const& factoryKvp : factories )
9202             maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );
9203 
9204         for( auto const& factoryKvp : factories ) {
9205             Catch::cout()
9206                     << Column( factoryKvp.first + ":" )
9207                             .indent(2)
9208                             .width( 5+maxNameLen )
9209                     +  Column( factoryKvp.second->getDescription() )
9210                             .initialIndent(0)
9211                             .indent(2)
9212                             .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
9213                     << "\n";
9214         }
9215         Catch::cout() << std::endl;
9216         return factories.size();
9217     }
9218 
list(std::shared_ptr<Config> const & config)9219     Option<std::size_t> list( std::shared_ptr<Config> const& config ) {
9220         Option<std::size_t> listedCount;
9221         getCurrentMutableContext().setConfig( config );
9222         if( config->listTests() )
9223             listedCount = listedCount.valueOr(0) + listTests( *config );
9224         if( config->listTestNamesOnly() )
9225             listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config );
9226         if( config->listTags() )
9227             listedCount = listedCount.valueOr(0) + listTags( *config );
9228         if( config->listReporters() )
9229             listedCount = listedCount.valueOr(0) + listReporters();
9230         return listedCount;
9231     }
9232 
9233 } // end namespace Catch
9234 // end catch_list.cpp
9235 // start catch_matchers.cpp
9236 
9237 namespace Catch {
9238 namespace Matchers {
9239     namespace Impl {
9240 
toString() const9241         std::string MatcherUntypedBase::toString() const {
9242             if( m_cachedToString.empty() )
9243                 m_cachedToString = describe();
9244             return m_cachedToString;
9245         }
9246 
9247         MatcherUntypedBase::~MatcherUntypedBase() = default;
9248 
9249     } // namespace Impl
9250 } // namespace Matchers
9251 
9252 using namespace Matchers;
9253 using Matchers::Impl::MatcherBase;
9254 
9255 } // namespace Catch
9256 // end catch_matchers.cpp
9257 // start catch_matchers_floating.cpp
9258 
9259 // start catch_polyfills.hpp
9260 
9261 namespace Catch {
9262     bool isnan(float f);
9263     bool isnan(double d);
9264 }
9265 
9266 // end catch_polyfills.hpp
9267 // start catch_to_string.hpp
9268 
9269 #include <string>
9270 
9271 namespace Catch {
9272     template <typename T>
to_string(T const & t)9273     std::string to_string(T const& t) {
9274 #if defined(CATCH_CONFIG_CPP11_TO_STRING)
9275         return std::to_string(t);
9276 #else
9277         ReusableStringStream rss;
9278         rss << t;
9279         return rss.str();
9280 #endif
9281     }
9282 } // end namespace Catch
9283 
9284 // end catch_to_string.hpp
9285 #include <cstdlib>
9286 #include <cstdint>
9287 #include <cstring>
9288 
9289 namespace Catch {
9290 namespace Matchers {
9291 namespace Floating {
9292 enum class FloatingPointKind : uint8_t {
9293     Float,
9294     Double
9295 };
9296 }
9297 }
9298 }
9299 
9300 namespace {
9301 
9302 template <typename T>
9303 struct Converter;
9304 
9305 template <>
9306 struct Converter<float> {
9307     static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
Converter__anonc5acfb671711::Converter9308     Converter(float f) {
9309         std::memcpy(&i, &f, sizeof(f));
9310     }
9311     int32_t i;
9312 };
9313 
9314 template <>
9315 struct Converter<double> {
9316     static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");
Converter__anonc5acfb671711::Converter9317     Converter(double d) {
9318         std::memcpy(&i, &d, sizeof(d));
9319     }
9320     int64_t i;
9321 };
9322 
9323 template <typename T>
convert(T t)9324 auto convert(T t) -> Converter<T> {
9325     return Converter<T>(t);
9326 }
9327 
9328 template <typename FP>
almostEqualUlps(FP lhs,FP rhs,int maxUlpDiff)9329 bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) {
9330     // Comparison with NaN should always be false.
9331     // This way we can rule it out before getting into the ugly details
9332     if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
9333         return false;
9334     }
9335 
9336     auto lc = convert(lhs);
9337     auto rc = convert(rhs);
9338 
9339     if ((lc.i < 0) != (rc.i < 0)) {
9340         // Potentially we can have +0 and -0
9341         return lhs == rhs;
9342     }
9343 
9344     auto ulpDiff = std::abs(lc.i - rc.i);
9345     return ulpDiff <= maxUlpDiff;
9346 }
9347 
9348 }
9349 
9350 namespace Catch {
9351 namespace Matchers {
9352 namespace Floating {
WithinAbsMatcher(double target,double margin)9353     WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
9354         :m_target{ target }, m_margin{ margin } {
9355         CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'
9356             << " Margin has to be non-negative.");
9357     }
9358 
9359     // Performs equivalent check of std::fabs(lhs - rhs) <= margin
9360     // But without the subtraction to allow for INFINITY in comparison
match(double const & matchee) const9361     bool WithinAbsMatcher::match(double const& matchee) const {
9362         return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
9363     }
9364 
describe() const9365     std::string WithinAbsMatcher::describe() const {
9366         return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
9367     }
9368 
WithinUlpsMatcher(double target,int ulps,FloatingPointKind baseType)9369     WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
9370         :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
9371         CATCH_ENFORCE(ulps >= 0, "Invalid ULP setting: " << ulps << '.'
9372             << " ULPs have to be non-negative.");
9373     }
9374 
9375 #if defined(__clang__)
9376 #pragma clang diagnostic push
9377 // Clang <3.5 reports on the default branch in the switch below
9378 #pragma clang diagnostic ignored "-Wunreachable-code"
9379 #endif
9380 
match(double const & matchee) const9381     bool WithinUlpsMatcher::match(double const& matchee) const {
9382         switch (m_type) {
9383         case FloatingPointKind::Float:
9384             return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
9385         case FloatingPointKind::Double:
9386             return almostEqualUlps<double>(matchee, m_target, m_ulps);
9387         default:
9388             CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" );
9389         }
9390     }
9391 
9392 #if defined(__clang__)
9393 #pragma clang diagnostic pop
9394 #endif
9395 
describe() const9396     std::string WithinUlpsMatcher::describe() const {
9397         return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
9398     }
9399 
9400 }// namespace Floating
9401 
WithinULP(double target,int maxUlpDiff)9402 Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) {
9403     return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
9404 }
9405 
WithinULP(float target,int maxUlpDiff)9406 Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) {
9407     return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
9408 }
9409 
WithinAbs(double target,double margin)9410 Floating::WithinAbsMatcher WithinAbs(double target, double margin) {
9411     return Floating::WithinAbsMatcher(target, margin);
9412 }
9413 
9414 } // namespace Matchers
9415 } // namespace Catch
9416 
9417 // end catch_matchers_floating.cpp
9418 // start catch_matchers_generic.cpp
9419 
finalizeDescription(const std::string & desc)9420 std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {
9421     if (desc.empty()) {
9422         return "matches undescribed predicate";
9423     } else {
9424         return "matches predicate: \"" + desc + '"';
9425     }
9426 }
9427 // end catch_matchers_generic.cpp
9428 // start catch_matchers_string.cpp
9429 
9430 #include <regex>
9431 
9432 namespace Catch {
9433 namespace Matchers {
9434 
9435     namespace StdString {
9436 
CasedString(std::string const & str,CaseSensitive::Choice caseSensitivity)9437         CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
9438         :   m_caseSensitivity( caseSensitivity ),
9439             m_str( adjustString( str ) )
9440         {}
adjustString(std::string const & str) const9441         std::string CasedString::adjustString( std::string const& str ) const {
9442             return m_caseSensitivity == CaseSensitive::No
9443                    ? toLower( str )
9444                    : str;
9445         }
caseSensitivitySuffix() const9446         std::string CasedString::caseSensitivitySuffix() const {
9447             return m_caseSensitivity == CaseSensitive::No
9448                    ? " (case insensitive)"
9449                    : std::string();
9450         }
9451 
StringMatcherBase(std::string const & operation,CasedString const & comparator)9452         StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
9453         : m_comparator( comparator ),
9454           m_operation( operation ) {
9455         }
9456 
describe() const9457         std::string StringMatcherBase::describe() const {
9458             std::string description;
9459             description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
9460                                         m_comparator.caseSensitivitySuffix().size());
9461             description += m_operation;
9462             description += ": \"";
9463             description += m_comparator.m_str;
9464             description += "\"";
9465             description += m_comparator.caseSensitivitySuffix();
9466             return description;
9467         }
9468 
EqualsMatcher(CasedString const & comparator)9469         EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
9470 
match(std::string const & source) const9471         bool EqualsMatcher::match( std::string const& source ) const {
9472             return m_comparator.adjustString( source ) == m_comparator.m_str;
9473         }
9474 
ContainsMatcher(CasedString const & comparator)9475         ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
9476 
match(std::string const & source) const9477         bool ContainsMatcher::match( std::string const& source ) const {
9478             return contains( m_comparator.adjustString( source ), m_comparator.m_str );
9479         }
9480 
StartsWithMatcher(CasedString const & comparator)9481         StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
9482 
match(std::string const & source) const9483         bool StartsWithMatcher::match( std::string const& source ) const {
9484             return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9485         }
9486 
EndsWithMatcher(CasedString const & comparator)9487         EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
9488 
match(std::string const & source) const9489         bool EndsWithMatcher::match( std::string const& source ) const {
9490             return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9491         }
9492 
RegexMatcher(std::string regex,CaseSensitive::Choice caseSensitivity)9493         RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}
9494 
match(std::string const & matchee) const9495         bool RegexMatcher::match(std::string const& matchee) const {
9496             auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway
9497             if (m_caseSensitivity == CaseSensitive::Choice::No) {
9498                 flags |= std::regex::icase;
9499             }
9500             auto reg = std::regex(m_regex, flags);
9501             return std::regex_match(matchee, reg);
9502         }
9503 
describe() const9504         std::string RegexMatcher::describe() const {
9505             return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");
9506         }
9507 
9508     } // namespace StdString
9509 
Equals(std::string const & str,CaseSensitive::Choice caseSensitivity)9510     StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9511         return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
9512     }
Contains(std::string const & str,CaseSensitive::Choice caseSensitivity)9513     StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9514         return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
9515     }
EndsWith(std::string const & str,CaseSensitive::Choice caseSensitivity)9516     StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9517         return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9518     }
StartsWith(std::string const & str,CaseSensitive::Choice caseSensitivity)9519     StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9520         return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9521     }
9522 
Matches(std::string const & regex,CaseSensitive::Choice caseSensitivity)9523     StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) {
9524         return StdString::RegexMatcher(regex, caseSensitivity);
9525     }
9526 
9527 } // namespace Matchers
9528 } // namespace Catch
9529 // end catch_matchers_string.cpp
9530 // start catch_message.cpp
9531 
9532 // start catch_uncaught_exceptions.h
9533 
9534 namespace Catch {
9535     bool uncaught_exceptions();
9536 } // end namespace Catch
9537 
9538 // end catch_uncaught_exceptions.h
9539 #include <cassert>
9540 #include <stack>
9541 
9542 namespace Catch {
9543 
MessageInfo(StringRef const & _macroName,SourceLineInfo const & _lineInfo,ResultWas::OfType _type)9544     MessageInfo::MessageInfo(   StringRef const& _macroName,
9545                                 SourceLineInfo const& _lineInfo,
9546                                 ResultWas::OfType _type )
9547     :   macroName( _macroName ),
9548         lineInfo( _lineInfo ),
9549         type( _type ),
9550         sequence( ++globalCount )
9551     {}
9552 
operator ==(MessageInfo const & other) const9553     bool MessageInfo::operator==( MessageInfo const& other ) const {
9554         return sequence == other.sequence;
9555     }
9556 
operator <(MessageInfo const & other) const9557     bool MessageInfo::operator<( MessageInfo const& other ) const {
9558         return sequence < other.sequence;
9559     }
9560 
9561     // This may need protecting if threading support is added
9562     unsigned int MessageInfo::globalCount = 0;
9563 
9564     ////////////////////////////////////////////////////////////////////////////
9565 
MessageBuilder(StringRef const & macroName,SourceLineInfo const & lineInfo,ResultWas::OfType type)9566     Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,
9567                                            SourceLineInfo const& lineInfo,
9568                                            ResultWas::OfType type )
9569         :m_info(macroName, lineInfo, type) {}
9570 
9571     ////////////////////////////////////////////////////////////////////////////
9572 
ScopedMessage(MessageBuilder const & builder)9573     ScopedMessage::ScopedMessage( MessageBuilder const& builder )
9574     : m_info( builder.m_info ), m_moved()
9575     {
9576         m_info.message = builder.m_stream.str();
9577         getResultCapture().pushScopedMessage( m_info );
9578     }
9579 
ScopedMessage(ScopedMessage && old)9580     ScopedMessage::ScopedMessage( ScopedMessage&& old )
9581     : m_info( old.m_info ), m_moved()
9582     {
9583         old.m_moved = true;
9584     }
9585 
~ScopedMessage()9586     ScopedMessage::~ScopedMessage() {
9587         if ( !uncaught_exceptions() && !m_moved ){
9588             getResultCapture().popScopedMessage(m_info);
9589         }
9590     }
9591 
Capturer(StringRef macroName,SourceLineInfo const & lineInfo,ResultWas::OfType resultType,StringRef names)9592     Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {
9593         auto trimmed = [&] (size_t start, size_t end) {
9594             while (names[start] == ',' || isspace(names[start])) {
9595                 ++start;
9596             }
9597             while (names[end] == ',' || isspace(names[end])) {
9598                 --end;
9599             }
9600             return names.substr(start, end - start + 1);
9601         };
9602 
9603         size_t start = 0;
9604         std::stack<char> openings;
9605         for (size_t pos = 0; pos < names.size(); ++pos) {
9606             char c = names[pos];
9607             switch (c) {
9608             case '[':
9609             case '{':
9610             case '(':
9611             // It is basically impossible to disambiguate between
9612             // comparison and start of template args in this context
9613 //            case '<':
9614                 openings.push(c);
9615                 break;
9616             case ']':
9617             case '}':
9618             case ')':
9619 //           case '>':
9620                 openings.pop();
9621                 break;
9622             case ',':
9623                 if (start != pos && openings.size() == 0) {
9624                     m_messages.emplace_back(macroName, lineInfo, resultType);
9625                     m_messages.back().message = trimmed(start, pos);
9626                     m_messages.back().message += " := ";
9627                     start = pos;
9628                 }
9629             }
9630         }
9631         assert(openings.size() == 0 && "Mismatched openings");
9632         m_messages.emplace_back(macroName, lineInfo, resultType);
9633         m_messages.back().message = trimmed(start, names.size() - 1);
9634         m_messages.back().message += " := ";
9635     }
~Capturer()9636     Capturer::~Capturer() {
9637         if ( !uncaught_exceptions() ){
9638             assert( m_captured == m_messages.size() );
9639             for( size_t i = 0; i < m_captured; ++i  )
9640                 m_resultCapture.popScopedMessage( m_messages[i] );
9641         }
9642     }
9643 
captureValue(size_t index,std::string const & value)9644     void Capturer::captureValue( size_t index, std::string const& value ) {
9645         assert( index < m_messages.size() );
9646         m_messages[index].message += value;
9647         m_resultCapture.pushScopedMessage( m_messages[index] );
9648         m_captured++;
9649     }
9650 
9651 } // end namespace Catch
9652 // end catch_message.cpp
9653 // start catch_output_redirect.cpp
9654 
9655 // start catch_output_redirect.h
9656 #ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
9657 #define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
9658 
9659 #include <cstdio>
9660 #include <iosfwd>
9661 #include <string>
9662 
9663 namespace Catch {
9664 
9665     class RedirectedStream {
9666         std::ostream& m_originalStream;
9667         std::ostream& m_redirectionStream;
9668         std::streambuf* m_prevBuf;
9669 
9670     public:
9671         RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
9672         ~RedirectedStream();
9673     };
9674 
9675     class RedirectedStdOut {
9676         ReusableStringStream m_rss;
9677         RedirectedStream m_cout;
9678     public:
9679         RedirectedStdOut();
9680         auto str() const -> std::string;
9681     };
9682 
9683     // StdErr has two constituent streams in C++, std::cerr and std::clog
9684     // This means that we need to redirect 2 streams into 1 to keep proper
9685     // order of writes
9686     class RedirectedStdErr {
9687         ReusableStringStream m_rss;
9688         RedirectedStream m_cerr;
9689         RedirectedStream m_clog;
9690     public:
9691         RedirectedStdErr();
9692         auto str() const -> std::string;
9693     };
9694 
9695     class RedirectedStreams {
9696     public:
9697         RedirectedStreams(RedirectedStreams const&) = delete;
9698         RedirectedStreams& operator=(RedirectedStreams const&) = delete;
9699         RedirectedStreams(RedirectedStreams&&) = delete;
9700         RedirectedStreams& operator=(RedirectedStreams&&) = delete;
9701 
9702         RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);
9703         ~RedirectedStreams();
9704     private:
9705         std::string& m_redirectedCout;
9706         std::string& m_redirectedCerr;
9707         RedirectedStdOut m_redirectedStdOut;
9708         RedirectedStdErr m_redirectedStdErr;
9709     };
9710 
9711 #if defined(CATCH_CONFIG_NEW_CAPTURE)
9712 
9713     // Windows's implementation of std::tmpfile is terrible (it tries
9714     // to create a file inside system folder, thus requiring elevated
9715     // privileges for the binary), so we have to use tmpnam(_s) and
9716     // create the file ourselves there.
9717     class TempFile {
9718     public:
9719         TempFile(TempFile const&) = delete;
9720         TempFile& operator=(TempFile const&) = delete;
9721         TempFile(TempFile&&) = delete;
9722         TempFile& operator=(TempFile&&) = delete;
9723 
9724         TempFile();
9725         ~TempFile();
9726 
9727         std::FILE* getFile();
9728         std::string getContents();
9729 
9730     private:
9731         std::FILE* m_file = nullptr;
9732     #if defined(_MSC_VER)
9733         char m_buffer[L_tmpnam] = { 0 };
9734     #endif
9735     };
9736 
9737     class OutputRedirect {
9738     public:
9739         OutputRedirect(OutputRedirect const&) = delete;
9740         OutputRedirect& operator=(OutputRedirect const&) = delete;
9741         OutputRedirect(OutputRedirect&&) = delete;
9742         OutputRedirect& operator=(OutputRedirect&&) = delete;
9743 
9744         OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
9745         ~OutputRedirect();
9746 
9747     private:
9748         int m_originalStdout = -1;
9749         int m_originalStderr = -1;
9750         TempFile m_stdoutFile;
9751         TempFile m_stderrFile;
9752         std::string& m_stdoutDest;
9753         std::string& m_stderrDest;
9754     };
9755 
9756 #endif
9757 
9758 } // end namespace Catch
9759 
9760 #endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
9761 // end catch_output_redirect.h
9762 #include <cstdio>
9763 #include <cstring>
9764 #include <fstream>
9765 #include <sstream>
9766 #include <stdexcept>
9767 
9768 #if defined(CATCH_CONFIG_NEW_CAPTURE)
9769     #if defined(_MSC_VER)
9770     #include <io.h>      //_dup and _dup2
9771     #define dup _dup
9772     #define dup2 _dup2
9773     #define fileno _fileno
9774     #else
9775     #include <unistd.h>  // dup and dup2
9776     #endif
9777 #endif
9778 
9779 namespace Catch {
9780 
RedirectedStream(std::ostream & originalStream,std::ostream & redirectionStream)9781     RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
9782     :   m_originalStream( originalStream ),
9783         m_redirectionStream( redirectionStream ),
9784         m_prevBuf( m_originalStream.rdbuf() )
9785     {
9786         m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
9787     }
9788 
~RedirectedStream()9789     RedirectedStream::~RedirectedStream() {
9790         m_originalStream.rdbuf( m_prevBuf );
9791     }
9792 
RedirectedStdOut()9793     RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
str() const9794     auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }
9795 
RedirectedStdErr()9796     RedirectedStdErr::RedirectedStdErr()
9797     :   m_cerr( Catch::cerr(), m_rss.get() ),
9798         m_clog( Catch::clog(), m_rss.get() )
9799     {}
str() const9800     auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
9801 
RedirectedStreams(std::string & redirectedCout,std::string & redirectedCerr)9802     RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)
9803     :   m_redirectedCout(redirectedCout),
9804         m_redirectedCerr(redirectedCerr)
9805     {}
9806 
~RedirectedStreams()9807     RedirectedStreams::~RedirectedStreams() {
9808         m_redirectedCout += m_redirectedStdOut.str();
9809         m_redirectedCerr += m_redirectedStdErr.str();
9810     }
9811 
9812 #if defined(CATCH_CONFIG_NEW_CAPTURE)
9813 
9814 #if defined(_MSC_VER)
TempFile()9815     TempFile::TempFile() {
9816         if (tmpnam_s(m_buffer)) {
9817             CATCH_RUNTIME_ERROR("Could not get a temp filename");
9818         }
9819         if (fopen_s(&m_file, m_buffer, "w")) {
9820             char buffer[100];
9821             if (strerror_s(buffer, errno)) {
9822                 CATCH_RUNTIME_ERROR("Could not translate errno to a string");
9823             }
9824             CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer);
9825         }
9826     }
9827 #else
TempFile()9828     TempFile::TempFile() {
9829         m_file = std::tmpfile();
9830         if (!m_file) {
9831             CATCH_RUNTIME_ERROR("Could not create a temp file.");
9832         }
9833     }
9834 
9835 #endif
9836 
~TempFile()9837     TempFile::~TempFile() {
9838          // TBD: What to do about errors here?
9839          std::fclose(m_file);
9840          // We manually create the file on Windows only, on Linux
9841          // it will be autodeleted
9842 #if defined(_MSC_VER)
9843          std::remove(m_buffer);
9844 #endif
9845     }
9846 
getFile()9847     FILE* TempFile::getFile() {
9848         return m_file;
9849     }
9850 
getContents()9851     std::string TempFile::getContents() {
9852         std::stringstream sstr;
9853         char buffer[100] = {};
9854         std::rewind(m_file);
9855         while (std::fgets(buffer, sizeof(buffer), m_file)) {
9856             sstr << buffer;
9857         }
9858         return sstr.str();
9859     }
9860 
OutputRedirect(std::string & stdout_dest,std::string & stderr_dest)9861     OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
9862         m_originalStdout(dup(1)),
9863         m_originalStderr(dup(2)),
9864         m_stdoutDest(stdout_dest),
9865         m_stderrDest(stderr_dest) {
9866         dup2(fileno(m_stdoutFile.getFile()), 1);
9867         dup2(fileno(m_stderrFile.getFile()), 2);
9868     }
9869 
~OutputRedirect()9870     OutputRedirect::~OutputRedirect() {
9871         Catch::cout() << std::flush;
9872         fflush(stdout);
9873         // Since we support overriding these streams, we flush cerr
9874         // even though std::cerr is unbuffered
9875         Catch::cerr() << std::flush;
9876         Catch::clog() << std::flush;
9877         fflush(stderr);
9878 
9879         dup2(m_originalStdout, 1);
9880         dup2(m_originalStderr, 2);
9881 
9882         m_stdoutDest += m_stdoutFile.getContents();
9883         m_stderrDest += m_stderrFile.getContents();
9884     }
9885 
9886 #endif // CATCH_CONFIG_NEW_CAPTURE
9887 
9888 } // namespace Catch
9889 
9890 #if defined(CATCH_CONFIG_NEW_CAPTURE)
9891     #if defined(_MSC_VER)
9892     #undef dup
9893     #undef dup2
9894     #undef fileno
9895     #endif
9896 #endif
9897 // end catch_output_redirect.cpp
9898 // start catch_polyfills.cpp
9899 
9900 #include <cmath>
9901 
9902 namespace Catch {
9903 
9904 #if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
isnan(float f)9905     bool isnan(float f) {
9906         return std::isnan(f);
9907     }
isnan(double d)9908     bool isnan(double d) {
9909         return std::isnan(d);
9910     }
9911 #else
9912     // For now we only use this for embarcadero
9913     bool isnan(float f) {
9914         return std::_isnan(f);
9915     }
9916     bool isnan(double d) {
9917         return std::_isnan(d);
9918     }
9919 #endif
9920 
9921 } // end namespace Catch
9922 // end catch_polyfills.cpp
9923 // start catch_random_number_generator.cpp
9924 
9925 namespace Catch {
9926 
rng()9927     std::mt19937& rng() {
9928         static std::mt19937 s_rng;
9929         return s_rng;
9930     }
9931 
seedRng(IConfig const & config)9932     void seedRng( IConfig const& config ) {
9933         if( config.rngSeed() != 0 ) {
9934             std::srand( config.rngSeed() );
9935             rng().seed( config.rngSeed() );
9936         }
9937     }
9938 
rngSeed()9939     unsigned int rngSeed() {
9940         return getCurrentContext().getConfig()->rngSeed();
9941     }
9942 }
9943 // end catch_random_number_generator.cpp
9944 // start catch_registry_hub.cpp
9945 
9946 // start catch_test_case_registry_impl.h
9947 
9948 #include <vector>
9949 #include <set>
9950 #include <algorithm>
9951 #include <ios>
9952 
9953 namespace Catch {
9954 
9955     class TestCase;
9956     struct IConfig;
9957 
9958     std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
9959     bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
9960 
9961     void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
9962 
9963     std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
9964     std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
9965 
9966     class TestRegistry : public ITestCaseRegistry {
9967     public:
9968         virtual ~TestRegistry() = default;
9969 
9970         virtual void registerTest( TestCase const& testCase );
9971 
9972         std::vector<TestCase> const& getAllTests() const override;
9973         std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override;
9974 
9975     private:
9976         std::vector<TestCase> m_functions;
9977         mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
9978         mutable std::vector<TestCase> m_sortedFunctions;
9979         std::size_t m_unnamedCount = 0;
9980         std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
9981     };
9982 
9983     ///////////////////////////////////////////////////////////////////////////
9984 
9985     class TestInvokerAsFunction : public ITestInvoker {
9986         void(*m_testAsFunction)();
9987     public:
9988         TestInvokerAsFunction( void(*testAsFunction)() ) noexcept;
9989 
9990         void invoke() const override;
9991     };
9992 
9993     std::string extractClassName( StringRef const& classOrQualifiedMethodName );
9994 
9995     ///////////////////////////////////////////////////////////////////////////
9996 
9997 } // end namespace Catch
9998 
9999 // end catch_test_case_registry_impl.h
10000 // start catch_reporter_registry.h
10001 
10002 #include <map>
10003 
10004 namespace Catch {
10005 
10006     class ReporterRegistry : public IReporterRegistry {
10007 
10008     public:
10009 
10010         ~ReporterRegistry() override;
10011 
10012         IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override;
10013 
10014         void registerReporter( std::string const& name, IReporterFactoryPtr const& factory );
10015         void registerListener( IReporterFactoryPtr const& factory );
10016 
10017         FactoryMap const& getFactories() const override;
10018         Listeners const& getListeners() const override;
10019 
10020     private:
10021         FactoryMap m_factories;
10022         Listeners m_listeners;
10023     };
10024 }
10025 
10026 // end catch_reporter_registry.h
10027 // start catch_tag_alias_registry.h
10028 
10029 // start catch_tag_alias.h
10030 
10031 #include <string>
10032 
10033 namespace Catch {
10034 
10035     struct TagAlias {
10036         TagAlias(std::string const& _tag, SourceLineInfo _lineInfo);
10037 
10038         std::string tag;
10039         SourceLineInfo lineInfo;
10040     };
10041 
10042 } // end namespace Catch
10043 
10044 // end catch_tag_alias.h
10045 #include <map>
10046 
10047 namespace Catch {
10048 
10049     class TagAliasRegistry : public ITagAliasRegistry {
10050     public:
10051         ~TagAliasRegistry() override;
10052         TagAlias const* find( std::string const& alias ) const override;
10053         std::string expandAliases( std::string const& unexpandedTestSpec ) const override;
10054         void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
10055 
10056     private:
10057         std::map<std::string, TagAlias> m_registry;
10058     };
10059 
10060 } // end namespace Catch
10061 
10062 // end catch_tag_alias_registry.h
10063 // start catch_startup_exception_registry.h
10064 
10065 #include <vector>
10066 #include <exception>
10067 
10068 namespace Catch {
10069 
10070     class StartupExceptionRegistry {
10071     public:
10072         void add(std::exception_ptr const& exception) noexcept;
10073         std::vector<std::exception_ptr> const& getExceptions() const noexcept;
10074     private:
10075         std::vector<std::exception_ptr> m_exceptions;
10076     };
10077 
10078 } // end namespace Catch
10079 
10080 // end catch_startup_exception_registry.h
10081 // start catch_singletons.hpp
10082 
10083 namespace Catch {
10084 
10085     struct ISingleton {
10086         virtual ~ISingleton();
10087     };
10088 
10089     void addSingleton( ISingleton* singleton );
10090     void cleanupSingletons();
10091 
10092     template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>
10093     class Singleton : SingletonImplT, public ISingleton {
10094 
getInternal()10095         static auto getInternal() -> Singleton* {
10096             static Singleton* s_instance = nullptr;
10097             if( !s_instance ) {
10098                 s_instance = new Singleton;
10099                 addSingleton( s_instance );
10100             }
10101             return s_instance;
10102         }
10103 
10104     public:
get()10105         static auto get() -> InterfaceT const& {
10106             return *getInternal();
10107         }
getMutable()10108         static auto getMutable() -> MutableInterfaceT& {
10109             return *getInternal();
10110         }
10111     };
10112 
10113 } // namespace Catch
10114 
10115 // end catch_singletons.hpp
10116 namespace Catch {
10117 
10118     namespace {
10119 
10120         class RegistryHub : public IRegistryHub, public IMutableRegistryHub,
10121                             private NonCopyable {
10122 
10123         public: // IRegistryHub
10124             RegistryHub() = default;
getReporterRegistry() const10125             IReporterRegistry const& getReporterRegistry() const override {
10126                 return m_reporterRegistry;
10127             }
getTestCaseRegistry() const10128             ITestCaseRegistry const& getTestCaseRegistry() const override {
10129                 return m_testCaseRegistry;
10130             }
getExceptionTranslatorRegistry() const10131             IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {
10132                 return m_exceptionTranslatorRegistry;
10133             }
getTagAliasRegistry() const10134             ITagAliasRegistry const& getTagAliasRegistry() const override {
10135                 return m_tagAliasRegistry;
10136             }
getStartupExceptionRegistry() const10137             StartupExceptionRegistry const& getStartupExceptionRegistry() const override {
10138                 return m_exceptionRegistry;
10139             }
10140 
10141         public: // IMutableRegistryHub
registerReporter(std::string const & name,IReporterFactoryPtr const & factory)10142             void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override {
10143                 m_reporterRegistry.registerReporter( name, factory );
10144             }
registerListener(IReporterFactoryPtr const & factory)10145             void registerListener( IReporterFactoryPtr const& factory ) override {
10146                 m_reporterRegistry.registerListener( factory );
10147             }
registerTest(TestCase const & testInfo)10148             void registerTest( TestCase const& testInfo ) override {
10149                 m_testCaseRegistry.registerTest( testInfo );
10150             }
registerTranslator(const IExceptionTranslator * translator)10151             void registerTranslator( const IExceptionTranslator* translator ) override {
10152                 m_exceptionTranslatorRegistry.registerTranslator( translator );
10153             }
registerTagAlias(std::string const & alias,std::string const & tag,SourceLineInfo const & lineInfo)10154             void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {
10155                 m_tagAliasRegistry.add( alias, tag, lineInfo );
10156             }
registerStartupException()10157             void registerStartupException() noexcept override {
10158                 m_exceptionRegistry.add(std::current_exception());
10159             }
10160 
10161         private:
10162             TestRegistry m_testCaseRegistry;
10163             ReporterRegistry m_reporterRegistry;
10164             ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
10165             TagAliasRegistry m_tagAliasRegistry;
10166             StartupExceptionRegistry m_exceptionRegistry;
10167         };
10168     }
10169 
10170     using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
10171 
getRegistryHub()10172     IRegistryHub const& getRegistryHub() {
10173         return RegistryHubSingleton::get();
10174     }
getMutableRegistryHub()10175     IMutableRegistryHub& getMutableRegistryHub() {
10176         return RegistryHubSingleton::getMutable();
10177     }
cleanUp()10178     void cleanUp() {
10179         cleanupSingletons();
10180         cleanUpContext();
10181     }
translateActiveException()10182     std::string translateActiveException() {
10183         return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
10184     }
10185 
10186 } // end namespace Catch
10187 // end catch_registry_hub.cpp
10188 // start catch_reporter_registry.cpp
10189 
10190 namespace Catch {
10191 
10192     ReporterRegistry::~ReporterRegistry() = default;
10193 
create(std::string const & name,IConfigPtr const & config) const10194     IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const {
10195         auto it =  m_factories.find( name );
10196         if( it == m_factories.end() )
10197             return nullptr;
10198         return it->second->create( ReporterConfig( config ) );
10199     }
10200 
registerReporter(std::string const & name,IReporterFactoryPtr const & factory)10201     void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) {
10202         m_factories.emplace(name, factory);
10203     }
registerListener(IReporterFactoryPtr const & factory)10204     void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) {
10205         m_listeners.push_back( factory );
10206     }
10207 
getFactories() const10208     IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const {
10209         return m_factories;
10210     }
getListeners() const10211     IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const {
10212         return m_listeners;
10213     }
10214 
10215 }
10216 // end catch_reporter_registry.cpp
10217 // start catch_result_type.cpp
10218 
10219 namespace Catch {
10220 
isOk(ResultWas::OfType resultType)10221     bool isOk( ResultWas::OfType resultType ) {
10222         return ( resultType & ResultWas::FailureBit ) == 0;
10223     }
isJustInfo(int flags)10224     bool isJustInfo( int flags ) {
10225         return flags == ResultWas::Info;
10226     }
10227 
operator |(ResultDisposition::Flags lhs,ResultDisposition::Flags rhs)10228     ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
10229         return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
10230     }
10231 
shouldContinueOnFailure(int flags)10232     bool shouldContinueOnFailure( int flags )    { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
shouldSuppressFailure(int flags)10233     bool shouldSuppressFailure( int flags )      { return ( flags & ResultDisposition::SuppressFail ) != 0; }
10234 
10235 } // end namespace Catch
10236 // end catch_result_type.cpp
10237 // start catch_run_context.cpp
10238 
10239 #include <cassert>
10240 #include <algorithm>
10241 #include <sstream>
10242 
10243 namespace Catch {
10244 
10245     namespace Generators {
10246         struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
10247             GeneratorBasePtr m_generator;
10248 
GeneratorTrackerCatch::Generators::GeneratorTracker10249             GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
10250             :   TrackerBase( nameAndLocation, ctx, parent )
10251             {}
10252             ~GeneratorTracker();
10253 
acquireCatch::Generators::GeneratorTracker10254             static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {
10255                 std::shared_ptr<GeneratorTracker> tracker;
10256 
10257                 ITracker& currentTracker = ctx.currentTracker();
10258                 if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
10259                     assert( childTracker );
10260                     assert( childTracker->isGeneratorTracker() );
10261                     tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );
10262                 }
10263                 else {
10264                     tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );
10265                     currentTracker.addChild( tracker );
10266                 }
10267 
10268                 if( !ctx.completedCycle() && !tracker->isComplete() ) {
10269                     tracker->open();
10270                 }
10271 
10272                 return *tracker;
10273             }
10274 
10275             // TrackerBase interface
isGeneratorTrackerCatch::Generators::GeneratorTracker10276             bool isGeneratorTracker() const override { return true; }
hasGeneratorCatch::Generators::GeneratorTracker10277             auto hasGenerator() const -> bool override {
10278                 return !!m_generator;
10279             }
closeCatch::Generators::GeneratorTracker10280             void close() override {
10281                 TrackerBase::close();
10282                 // Generator interface only finds out if it has another item on atual move
10283                 if (m_runState == CompletedSuccessfully && m_generator->next()) {
10284                     m_children.clear();
10285                     m_runState = Executing;
10286                 }
10287             }
10288 
10289             // IGeneratorTracker interface
getGeneratorCatch::Generators::GeneratorTracker10290             auto getGenerator() const -> GeneratorBasePtr const& override {
10291                 return m_generator;
10292             }
setGeneratorCatch::Generators::GeneratorTracker10293             void setGenerator( GeneratorBasePtr&& generator ) override {
10294                 m_generator = std::move( generator );
10295             }
10296         };
~GeneratorTracker()10297         GeneratorTracker::~GeneratorTracker() {}
10298     }
10299 
RunContext(IConfigPtr const & _config,IStreamingReporterPtr && reporter)10300     RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
10301     :   m_runInfo(_config->name()),
10302         m_context(getCurrentMutableContext()),
10303         m_config(_config),
10304         m_reporter(std::move(reporter)),
10305         m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
10306         m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
10307     {
10308         m_context.setRunner(this);
10309         m_context.setConfig(m_config);
10310         m_context.setResultCapture(this);
10311         m_reporter->testRunStarting(m_runInfo);
10312     }
10313 
~RunContext()10314     RunContext::~RunContext() {
10315         m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
10316     }
10317 
testGroupStarting(std::string const & testSpec,std::size_t groupIndex,std::size_t groupsCount)10318     void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
10319         m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
10320     }
10321 
testGroupEnded(std::string const & testSpec,Totals const & totals,std::size_t groupIndex,std::size_t groupsCount)10322     void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {
10323         m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
10324     }
10325 
runTest(TestCase const & testCase)10326     Totals RunContext::runTest(TestCase const& testCase) {
10327         Totals prevTotals = m_totals;
10328 
10329         std::string redirectedCout;
10330         std::string redirectedCerr;
10331 
10332         auto const& testInfo = testCase.getTestCaseInfo();
10333 
10334         m_reporter->testCaseStarting(testInfo);
10335 
10336         m_activeTestCase = &testCase;
10337 
10338         ITracker& rootTracker = m_trackerContext.startRun();
10339         assert(rootTracker.isSectionTracker());
10340         static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
10341         do {
10342             m_trackerContext.startCycle();
10343             m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
10344             runCurrentTest(redirectedCout, redirectedCerr);
10345         } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
10346 
10347         Totals deltaTotals = m_totals.delta(prevTotals);
10348         if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
10349             deltaTotals.assertions.failed++;
10350             deltaTotals.testCases.passed--;
10351             deltaTotals.testCases.failed++;
10352         }
10353         m_totals.testCases += deltaTotals.testCases;
10354         m_reporter->testCaseEnded(TestCaseStats(testInfo,
10355                                   deltaTotals,
10356                                   redirectedCout,
10357                                   redirectedCerr,
10358                                   aborting()));
10359 
10360         m_activeTestCase = nullptr;
10361         m_testCaseTracker = nullptr;
10362 
10363         return deltaTotals;
10364     }
10365 
config() const10366     IConfigPtr RunContext::config() const {
10367         return m_config;
10368     }
10369 
reporter() const10370     IStreamingReporter& RunContext::reporter() const {
10371         return *m_reporter;
10372     }
10373 
assertionEnded(AssertionResult const & result)10374     void RunContext::assertionEnded(AssertionResult const & result) {
10375         if (result.getResultType() == ResultWas::Ok) {
10376             m_totals.assertions.passed++;
10377             m_lastAssertionPassed = true;
10378         } else if (!result.isOk()) {
10379             m_lastAssertionPassed = false;
10380             if( m_activeTestCase->getTestCaseInfo().okToFail() )
10381                 m_totals.assertions.failedButOk++;
10382             else
10383                 m_totals.assertions.failed++;
10384         }
10385         else {
10386             m_lastAssertionPassed = true;
10387         }
10388 
10389         // We have no use for the return value (whether messages should be cleared), because messages were made scoped
10390         // and should be let to clear themselves out.
10391         static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
10392 
10393         if (result.getResultType() != ResultWas::Warning)
10394             m_messageScopes.clear();
10395 
10396         // Reset working state
10397         resetAssertionInfo();
10398         m_lastResult = result;
10399     }
resetAssertionInfo()10400     void RunContext::resetAssertionInfo() {
10401         m_lastAssertionInfo.macroName = StringRef();
10402         m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
10403     }
10404 
sectionStarted(SectionInfo const & sectionInfo,Counts & assertions)10405     bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {
10406         ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
10407         if (!sectionTracker.isOpen())
10408             return false;
10409         m_activeSections.push_back(&sectionTracker);
10410 
10411         m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
10412 
10413         m_reporter->sectionStarting(sectionInfo);
10414 
10415         assertions = m_totals.assertions;
10416 
10417         return true;
10418     }
acquireGeneratorTracker(SourceLineInfo const & lineInfo)10419     auto RunContext::acquireGeneratorTracker( SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {
10420         using namespace Generators;
10421         GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( "generator", lineInfo ) );
10422         assert( tracker.isOpen() );
10423         m_lastAssertionInfo.lineInfo = lineInfo;
10424         return tracker;
10425     }
10426 
testForMissingAssertions(Counts & assertions)10427     bool RunContext::testForMissingAssertions(Counts& assertions) {
10428         if (assertions.total() != 0)
10429             return false;
10430         if (!m_config->warnAboutMissingAssertions())
10431             return false;
10432         if (m_trackerContext.currentTracker().hasChildren())
10433             return false;
10434         m_totals.assertions.failed++;
10435         assertions.failed++;
10436         return true;
10437     }
10438 
sectionEnded(SectionEndInfo const & endInfo)10439     void RunContext::sectionEnded(SectionEndInfo const & endInfo) {
10440         Counts assertions = m_totals.assertions - endInfo.prevAssertions;
10441         bool missingAssertions = testForMissingAssertions(assertions);
10442 
10443         if (!m_activeSections.empty()) {
10444             m_activeSections.back()->close();
10445             m_activeSections.pop_back();
10446         }
10447 
10448         m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
10449         m_messages.clear();
10450         m_messageScopes.clear();
10451     }
10452 
sectionEndedEarly(SectionEndInfo const & endInfo)10453     void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
10454         if (m_unfinishedSections.empty())
10455             m_activeSections.back()->fail();
10456         else
10457             m_activeSections.back()->close();
10458         m_activeSections.pop_back();
10459 
10460         m_unfinishedSections.push_back(endInfo);
10461     }
benchmarkStarting(BenchmarkInfo const & info)10462     void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
10463         m_reporter->benchmarkStarting( info );
10464     }
benchmarkEnded(BenchmarkStats const & stats)10465     void RunContext::benchmarkEnded( BenchmarkStats const& stats ) {
10466         m_reporter->benchmarkEnded( stats );
10467     }
10468 
pushScopedMessage(MessageInfo const & message)10469     void RunContext::pushScopedMessage(MessageInfo const & message) {
10470         m_messages.push_back(message);
10471     }
10472 
popScopedMessage(MessageInfo const & message)10473     void RunContext::popScopedMessage(MessageInfo const & message) {
10474         m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
10475     }
10476 
emplaceUnscopedMessage(MessageBuilder const & builder)10477     void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {
10478         m_messageScopes.emplace_back( builder );
10479     }
10480 
getCurrentTestName() const10481     std::string RunContext::getCurrentTestName() const {
10482         return m_activeTestCase
10483             ? m_activeTestCase->getTestCaseInfo().name
10484             : std::string();
10485     }
10486 
getLastResult() const10487     const AssertionResult * RunContext::getLastResult() const {
10488         return &(*m_lastResult);
10489     }
10490 
exceptionEarlyReported()10491     void RunContext::exceptionEarlyReported() {
10492         m_shouldReportUnexpected = false;
10493     }
10494 
handleFatalErrorCondition(StringRef message)10495     void RunContext::handleFatalErrorCondition( StringRef message ) {
10496         // First notify reporter that bad things happened
10497         m_reporter->fatalErrorEncountered(message);
10498 
10499         // Don't rebuild the result -- the stringification itself can cause more fatal errors
10500         // Instead, fake a result data.
10501         AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
10502         tempResult.message = message;
10503         AssertionResult result(m_lastAssertionInfo, tempResult);
10504 
10505         assertionEnded(result);
10506 
10507         handleUnfinishedSections();
10508 
10509         // Recreate section for test case (as we will lose the one that was in scope)
10510         auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
10511         SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
10512 
10513         Counts assertions;
10514         assertions.failed = 1;
10515         SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
10516         m_reporter->sectionEnded(testCaseSectionStats);
10517 
10518         auto const& testInfo = m_activeTestCase->getTestCaseInfo();
10519 
10520         Totals deltaTotals;
10521         deltaTotals.testCases.failed = 1;
10522         deltaTotals.assertions.failed = 1;
10523         m_reporter->testCaseEnded(TestCaseStats(testInfo,
10524                                   deltaTotals,
10525                                   std::string(),
10526                                   std::string(),
10527                                   false));
10528         m_totals.testCases.failed++;
10529         testGroupEnded(std::string(), m_totals, 1, 1);
10530         m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
10531     }
10532 
lastAssertionPassed()10533     bool RunContext::lastAssertionPassed() {
10534          return m_lastAssertionPassed;
10535     }
10536 
assertionPassed()10537     void RunContext::assertionPassed() {
10538         m_lastAssertionPassed = true;
10539         ++m_totals.assertions.passed;
10540         resetAssertionInfo();
10541         m_messageScopes.clear();
10542     }
10543 
aborting() const10544     bool RunContext::aborting() const {
10545         return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());
10546     }
10547 
runCurrentTest(std::string & redirectedCout,std::string & redirectedCerr)10548     void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
10549         auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
10550         SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
10551         m_reporter->sectionStarting(testCaseSection);
10552         Counts prevAssertions = m_totals.assertions;
10553         double duration = 0;
10554         m_shouldReportUnexpected = true;
10555         m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
10556 
10557         seedRng(*m_config);
10558 
10559         Timer timer;
10560         CATCH_TRY {
10561             if (m_reporter->getPreferences().shouldRedirectStdOut) {
10562 #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
10563                 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
10564 
10565                 timer.start();
10566                 invokeActiveTestCase();
10567 #else
10568                 OutputRedirect r(redirectedCout, redirectedCerr);
10569                 timer.start();
10570                 invokeActiveTestCase();
10571 #endif
10572             } else {
10573                 timer.start();
10574                 invokeActiveTestCase();
10575             }
10576             duration = timer.getElapsedSeconds();
10577         } CATCH_CATCH_ANON (TestFailureException&) {
10578             // This just means the test was aborted due to failure
10579         } CATCH_CATCH_ALL {
10580             // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
10581             // are reported without translation at the point of origin.
10582             if( m_shouldReportUnexpected ) {
10583                 AssertionReaction dummyReaction;
10584                 handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
10585             }
10586         }
10587         Counts assertions = m_totals.assertions - prevAssertions;
10588         bool missingAssertions = testForMissingAssertions(assertions);
10589 
10590         m_testCaseTracker->close();
10591         handleUnfinishedSections();
10592         m_messages.clear();
10593         m_messageScopes.clear();
10594 
10595         SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
10596         m_reporter->sectionEnded(testCaseSectionStats);
10597     }
10598 
invokeActiveTestCase()10599     void RunContext::invokeActiveTestCase() {
10600         FatalConditionHandler fatalConditionHandler; // Handle signals
10601         m_activeTestCase->invoke();
10602         fatalConditionHandler.reset();
10603     }
10604 
handleUnfinishedSections()10605     void RunContext::handleUnfinishedSections() {
10606         // If sections ended prematurely due to an exception we stored their
10607         // infos here so we can tear them down outside the unwind process.
10608         for (auto it = m_unfinishedSections.rbegin(),
10609              itEnd = m_unfinishedSections.rend();
10610              it != itEnd;
10611              ++it)
10612             sectionEnded(*it);
10613         m_unfinishedSections.clear();
10614     }
10615 
handleExpr(AssertionInfo const & info,ITransientExpression const & expr,AssertionReaction & reaction)10616     void RunContext::handleExpr(
10617         AssertionInfo const& info,
10618         ITransientExpression const& expr,
10619         AssertionReaction& reaction
10620     ) {
10621         m_reporter->assertionStarting( info );
10622 
10623         bool negated = isFalseTest( info.resultDisposition );
10624         bool result = expr.getResult() != negated;
10625 
10626         if( result ) {
10627             if (!m_includeSuccessfulResults) {
10628                 assertionPassed();
10629             }
10630             else {
10631                 reportExpr(info, ResultWas::Ok, &expr, negated);
10632             }
10633         }
10634         else {
10635             reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
10636             populateReaction( reaction );
10637         }
10638     }
reportExpr(AssertionInfo const & info,ResultWas::OfType resultType,ITransientExpression const * expr,bool negated)10639     void RunContext::reportExpr(
10640             AssertionInfo const &info,
10641             ResultWas::OfType resultType,
10642             ITransientExpression const *expr,
10643             bool negated ) {
10644 
10645         m_lastAssertionInfo = info;
10646         AssertionResultData data( resultType, LazyExpression( negated ) );
10647 
10648         AssertionResult assertionResult{ info, data };
10649         assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
10650 
10651         assertionEnded( assertionResult );
10652     }
10653 
handleMessage(AssertionInfo const & info,ResultWas::OfType resultType,StringRef const & message,AssertionReaction & reaction)10654     void RunContext::handleMessage(
10655             AssertionInfo const& info,
10656             ResultWas::OfType resultType,
10657             StringRef const& message,
10658             AssertionReaction& reaction
10659     ) {
10660         m_reporter->assertionStarting( info );
10661 
10662         m_lastAssertionInfo = info;
10663 
10664         AssertionResultData data( resultType, LazyExpression( false ) );
10665         data.message = message;
10666         AssertionResult assertionResult{ m_lastAssertionInfo, data };
10667         assertionEnded( assertionResult );
10668         if( !assertionResult.isOk() )
10669             populateReaction( reaction );
10670     }
handleUnexpectedExceptionNotThrown(AssertionInfo const & info,AssertionReaction & reaction)10671     void RunContext::handleUnexpectedExceptionNotThrown(
10672             AssertionInfo const& info,
10673             AssertionReaction& reaction
10674     ) {
10675         handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
10676     }
10677 
handleUnexpectedInflightException(AssertionInfo const & info,std::string const & message,AssertionReaction & reaction)10678     void RunContext::handleUnexpectedInflightException(
10679             AssertionInfo const& info,
10680             std::string const& message,
10681             AssertionReaction& reaction
10682     ) {
10683         m_lastAssertionInfo = info;
10684 
10685         AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
10686         data.message = message;
10687         AssertionResult assertionResult{ info, data };
10688         assertionEnded( assertionResult );
10689         populateReaction( reaction );
10690     }
10691 
populateReaction(AssertionReaction & reaction)10692     void RunContext::populateReaction( AssertionReaction& reaction ) {
10693         reaction.shouldDebugBreak = m_config->shouldDebugBreak();
10694         reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
10695     }
10696 
handleIncomplete(AssertionInfo const & info)10697     void RunContext::handleIncomplete(
10698             AssertionInfo const& info
10699     ) {
10700         m_lastAssertionInfo = info;
10701 
10702         AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
10703         data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
10704         AssertionResult assertionResult{ info, data };
10705         assertionEnded( assertionResult );
10706     }
handleNonExpr(AssertionInfo const & info,ResultWas::OfType resultType,AssertionReaction & reaction)10707     void RunContext::handleNonExpr(
10708             AssertionInfo const &info,
10709             ResultWas::OfType resultType,
10710             AssertionReaction &reaction
10711     ) {
10712         m_lastAssertionInfo = info;
10713 
10714         AssertionResultData data( resultType, LazyExpression( false ) );
10715         AssertionResult assertionResult{ info, data };
10716         assertionEnded( assertionResult );
10717 
10718         if( !assertionResult.isOk() )
10719             populateReaction( reaction );
10720     }
10721 
getResultCapture()10722     IResultCapture& getResultCapture() {
10723         if (auto* capture = getCurrentContext().getResultCapture())
10724             return *capture;
10725         else
10726             CATCH_INTERNAL_ERROR("No result capture instance");
10727     }
10728 }
10729 // end catch_run_context.cpp
10730 // start catch_section.cpp
10731 
10732 namespace Catch {
10733 
Section(SectionInfo const & info)10734     Section::Section( SectionInfo const& info )
10735     :   m_info( info ),
10736         m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
10737     {
10738         m_timer.start();
10739     }
10740 
~Section()10741     Section::~Section() {
10742         if( m_sectionIncluded ) {
10743             SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };
10744             if( uncaught_exceptions() )
10745                 getResultCapture().sectionEndedEarly( endInfo );
10746             else
10747                 getResultCapture().sectionEnded( endInfo );
10748         }
10749     }
10750 
10751     // This indicates whether the section should be executed or not
operator bool() const10752     Section::operator bool() const {
10753         return m_sectionIncluded;
10754     }
10755 
10756 } // end namespace Catch
10757 // end catch_section.cpp
10758 // start catch_section_info.cpp
10759 
10760 namespace Catch {
10761 
SectionInfo(SourceLineInfo const & _lineInfo,std::string const & _name)10762     SectionInfo::SectionInfo
10763         (   SourceLineInfo const& _lineInfo,
10764             std::string const& _name )
10765     :   name( _name ),
10766         lineInfo( _lineInfo )
10767     {}
10768 
10769 } // end namespace Catch
10770 // end catch_section_info.cpp
10771 // start catch_session.cpp
10772 
10773 // start catch_session.h
10774 
10775 #include <memory>
10776 
10777 namespace Catch {
10778 
10779     class Session : NonCopyable {
10780     public:
10781 
10782         Session();
10783         ~Session() override;
10784 
10785         void showHelp() const;
10786         void libIdentify();
10787 
10788         int applyCommandLine( int argc, char const * const * argv );
10789     #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
10790         int applyCommandLine( int argc, wchar_t const * const * argv );
10791     #endif
10792 
10793         void useConfigData( ConfigData const& configData );
10794 
10795         template<typename CharT>
run(int argc,CharT const * const argv[])10796         int run(int argc, CharT const * const argv[]) {
10797             if (m_startupExceptions)
10798                 return 1;
10799             int returnCode = applyCommandLine(argc, argv);
10800             if (returnCode == 0)
10801                 returnCode = run();
10802             return returnCode;
10803         }
10804 
10805         int run();
10806 
10807         clara::Parser const& cli() const;
10808         void cli( clara::Parser const& newParser );
10809         ConfigData& configData();
10810         Config& config();
10811     private:
10812         int runInternal();
10813 
10814         clara::Parser m_cli;
10815         ConfigData m_configData;
10816         std::shared_ptr<Config> m_config;
10817         bool m_startupExceptions = false;
10818     };
10819 
10820 } // end namespace Catch
10821 
10822 // end catch_session.h
10823 // start catch_version.h
10824 
10825 #include <iosfwd>
10826 
10827 namespace Catch {
10828 
10829     // Versioning information
10830     struct Version {
10831         Version( Version const& ) = delete;
10832         Version& operator=( Version const& ) = delete;
10833         Version(    unsigned int _majorVersion,
10834                     unsigned int _minorVersion,
10835                     unsigned int _patchNumber,
10836                     char const * const _branchName,
10837                     unsigned int _buildNumber );
10838 
10839         unsigned int const majorVersion;
10840         unsigned int const minorVersion;
10841         unsigned int const patchNumber;
10842 
10843         // buildNumber is only used if branchName is not null
10844         char const * const branchName;
10845         unsigned int const buildNumber;
10846 
10847         friend std::ostream& operator << ( std::ostream& os, Version const& version );
10848     };
10849 
10850     Version const& libraryVersion();
10851 }
10852 
10853 // end catch_version.h
10854 #include <cstdlib>
10855 #include <iomanip>
10856 
10857 namespace Catch {
10858 
10859     namespace {
10860         const int MaxExitCode = 255;
10861 
createReporter(std::string const & reporterName,IConfigPtr const & config)10862         IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) {
10863             auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);
10864             CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'");
10865 
10866             return reporter;
10867         }
10868 
makeReporter(std::shared_ptr<Config> const & config)10869         IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
10870             if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
10871                 return createReporter(config->getReporterName(), config);
10872             }
10873 
10874             // On older platforms, returning std::unique_ptr<ListeningReporter>
10875             // when the return type is std::unique_ptr<IStreamingReporter>
10876             // doesn't compile without a std::move call. However, this causes
10877             // a warning on newer platforms. Thus, we have to work around
10878             // it a bit and downcast the pointer manually.
10879             auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter);
10880             auto& multi = static_cast<ListeningReporter&>(*ret);
10881             auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
10882             for (auto const& listener : listeners) {
10883                 multi.addListener(listener->create(Catch::ReporterConfig(config)));
10884             }
10885             multi.addReporter(createReporter(config->getReporterName(), config));
10886             return ret;
10887         }
10888 
runTests(std::shared_ptr<Config> const & config)10889         Catch::Totals runTests(std::shared_ptr<Config> const& config) {
10890             auto reporter = makeReporter(config);
10891 
10892             RunContext context(config, std::move(reporter));
10893 
10894             Totals totals;
10895 
10896             context.testGroupStarting(config->name(), 1, 1);
10897 
10898             TestSpec testSpec = config->testSpec();
10899 
10900             auto const& allTestCases = getAllTestCasesSorted(*config);
10901             for (auto const& testCase : allTestCases) {
10902                 if (!context.aborting() && matchTest(testCase, testSpec, *config))
10903                     totals += context.runTest(testCase);
10904                 else
10905                     context.reporter().skipTest(testCase);
10906             }
10907 
10908             if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
10909                 ReusableStringStream testConfig;
10910 
10911                 bool first = true;
10912                 for (const auto& input : config->getTestsOrTags()) {
10913                     if (!first) { testConfig << ' '; }
10914                     first = false;
10915                     testConfig << input;
10916                 }
10917 
10918                 context.reporter().noMatchingTestCases(testConfig.str());
10919                 totals.error = -1;
10920             }
10921 
10922             context.testGroupEnded(config->name(), totals, 1, 1);
10923             return totals;
10924         }
10925 
applyFilenamesAsTags(Catch::IConfig const & config)10926         void applyFilenamesAsTags(Catch::IConfig const& config) {
10927             auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
10928             for (auto& testCase : tests) {
10929                 auto tags = testCase.tags;
10930 
10931                 std::string filename = testCase.lineInfo.file;
10932                 auto lastSlash = filename.find_last_of("\\/");
10933                 if (lastSlash != std::string::npos) {
10934                     filename.erase(0, lastSlash);
10935                     filename[0] = '#';
10936                 }
10937 
10938                 auto lastDot = filename.find_last_of('.');
10939                 if (lastDot != std::string::npos) {
10940                     filename.erase(lastDot);
10941                 }
10942 
10943                 tags.push_back(std::move(filename));
10944                 setTags(testCase, tags);
10945             }
10946         }
10947 
10948     } // anon namespace
10949 
Session()10950     Session::Session() {
10951         static bool alreadyInstantiated = false;
10952         if( alreadyInstantiated ) {
10953             CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
10954             CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }
10955         }
10956 
10957         // There cannot be exceptions at startup in no-exception mode.
10958 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
10959         const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
10960         if ( !exceptions.empty() ) {
10961             m_startupExceptions = true;
10962             Colour colourGuard( Colour::Red );
10963             Catch::cerr() << "Errors occurred during startup!" << '\n';
10964             // iterate over all exceptions and notify user
10965             for ( const auto& ex_ptr : exceptions ) {
10966                 try {
10967                     std::rethrow_exception(ex_ptr);
10968                 } catch ( std::exception const& ex ) {
10969                     Catch::cerr() << Column( ex.what() ).indent(2) << '\n';
10970                 }
10971             }
10972         }
10973 #endif
10974 
10975         alreadyInstantiated = true;
10976         m_cli = makeCommandLineParser( m_configData );
10977     }
~Session()10978     Session::~Session() {
10979         Catch::cleanUp();
10980     }
10981 
showHelp() const10982     void Session::showHelp() const {
10983         Catch::cout()
10984                 << "\nCatch v" << libraryVersion() << "\n"
10985                 << m_cli << std::endl
10986                 << "For more detailed usage please see the project docs\n" << std::endl;
10987     }
libIdentify()10988     void Session::libIdentify() {
10989         Catch::cout()
10990                 << std::left << std::setw(16) << "description: " << "A Catch test executable\n"
10991                 << std::left << std::setw(16) << "category: " << "testframework\n"
10992                 << std::left << std::setw(16) << "framework: " << "Catch Test\n"
10993                 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
10994     }
10995 
applyCommandLine(int argc,char const * const * argv)10996     int Session::applyCommandLine( int argc, char const * const * argv ) {
10997         if( m_startupExceptions )
10998             return 1;
10999 
11000         auto result = m_cli.parse( clara::Args( argc, argv ) );
11001         if( !result ) {
11002             config();
11003             getCurrentMutableContext().setConfig(m_config);
11004             Catch::cerr()
11005                 << Colour( Colour::Red )
11006                 << "\nError(s) in input:\n"
11007                 << Column( result.errorMessage() ).indent( 2 )
11008                 << "\n\n";
11009             Catch::cerr() << "Run with -? for usage\n" << std::endl;
11010             return MaxExitCode;
11011         }
11012 
11013         if( m_configData.showHelp )
11014             showHelp();
11015         if( m_configData.libIdentify )
11016             libIdentify();
11017         m_config.reset();
11018         return 0;
11019     }
11020 
11021 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
applyCommandLine(int argc,wchar_t const * const * argv)11022     int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {
11023 
11024         char **utf8Argv = new char *[ argc ];
11025 
11026         for ( int i = 0; i < argc; ++i ) {
11027             int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
11028 
11029             utf8Argv[ i ] = new char[ bufSize ];
11030 
11031             WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
11032         }
11033 
11034         int returnCode = applyCommandLine( argc, utf8Argv );
11035 
11036         for ( int i = 0; i < argc; ++i )
11037             delete [] utf8Argv[ i ];
11038 
11039         delete [] utf8Argv;
11040 
11041         return returnCode;
11042     }
11043 #endif
11044 
useConfigData(ConfigData const & configData)11045     void Session::useConfigData( ConfigData const& configData ) {
11046         m_configData = configData;
11047         m_config.reset();
11048     }
11049 
run()11050     int Session::run() {
11051         if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
11052             Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
11053             static_cast<void>(std::getchar());
11054         }
11055         int exitCode = runInternal();
11056         if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
11057             Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
11058             static_cast<void>(std::getchar());
11059         }
11060         return exitCode;
11061     }
11062 
cli() const11063     clara::Parser const& Session::cli() const {
11064         return m_cli;
11065     }
cli(clara::Parser const & newParser)11066     void Session::cli( clara::Parser const& newParser ) {
11067         m_cli = newParser;
11068     }
configData()11069     ConfigData& Session::configData() {
11070         return m_configData;
11071     }
config()11072     Config& Session::config() {
11073         if( !m_config )
11074             m_config = std::make_shared<Config>( m_configData );
11075         return *m_config;
11076     }
11077 
runInternal()11078     int Session::runInternal() {
11079         if( m_startupExceptions )
11080             return 1;
11081 
11082         if (m_configData.showHelp || m_configData.libIdentify) {
11083             return 0;
11084         }
11085 
11086         CATCH_TRY {
11087             config(); // Force config to be constructed
11088 
11089             seedRng( *m_config );
11090 
11091             if( m_configData.filenamesAsTags )
11092                 applyFilenamesAsTags( *m_config );
11093 
11094             // Handle list request
11095             if( Option<std::size_t> listed = list( m_config ) )
11096                 return static_cast<int>( *listed );
11097 
11098             auto totals = runTests( m_config );
11099             // Note that on unices only the lower 8 bits are usually used, clamping
11100             // the return value to 255 prevents false negative when some multiple
11101             // of 256 tests has failed
11102             return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
11103         }
11104 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
11105         catch( std::exception& ex ) {
11106             Catch::cerr() << ex.what() << std::endl;
11107             return MaxExitCode;
11108         }
11109 #endif
11110     }
11111 
11112 } // end namespace Catch
11113 // end catch_session.cpp
11114 // start catch_singletons.cpp
11115 
11116 #include <vector>
11117 
11118 namespace Catch {
11119 
11120     namespace {
getSingletons()11121         static auto getSingletons() -> std::vector<ISingleton*>*& {
11122             static std::vector<ISingleton*>* g_singletons = nullptr;
11123             if( !g_singletons )
11124                 g_singletons = new std::vector<ISingleton*>();
11125             return g_singletons;
11126         }
11127     }
11128 
~ISingleton()11129     ISingleton::~ISingleton() {}
11130 
addSingleton(ISingleton * singleton)11131     void addSingleton(ISingleton* singleton ) {
11132         getSingletons()->push_back( singleton );
11133     }
cleanupSingletons()11134     void cleanupSingletons() {
11135         auto& singletons = getSingletons();
11136         for( auto singleton : *singletons )
11137             delete singleton;
11138         delete singletons;
11139         singletons = nullptr;
11140     }
11141 
11142 } // namespace Catch
11143 // end catch_singletons.cpp
11144 // start catch_startup_exception_registry.cpp
11145 
11146 namespace Catch {
add(std::exception_ptr const & exception)11147 void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
11148         CATCH_TRY {
11149             m_exceptions.push_back(exception);
11150         } CATCH_CATCH_ALL {
11151             // If we run out of memory during start-up there's really not a lot more we can do about it
11152             std::terminate();
11153         }
11154     }
11155 
getExceptions() const11156     std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept {
11157         return m_exceptions;
11158     }
11159 
11160 } // end namespace Catch
11161 // end catch_startup_exception_registry.cpp
11162 // start catch_stream.cpp
11163 
11164 #include <cstdio>
11165 #include <iostream>
11166 #include <fstream>
11167 #include <sstream>
11168 #include <vector>
11169 #include <memory>
11170 
11171 namespace Catch {
11172 
11173     Catch::IStream::~IStream() = default;
11174 
11175     namespace detail { namespace {
11176         template<typename WriterF, std::size_t bufferSize=256>
11177         class StreamBufImpl : public std::streambuf {
11178             char data[bufferSize];
11179             WriterF m_writer;
11180 
11181         public:
StreamBufImpl()11182             StreamBufImpl() {
11183                 setp( data, data + sizeof(data) );
11184             }
11185 
~StreamBufImpl()11186             ~StreamBufImpl() noexcept {
11187                 StreamBufImpl::sync();
11188             }
11189 
11190         private:
overflow(int c)11191             int overflow( int c ) override {
11192                 sync();
11193 
11194                 if( c != EOF ) {
11195                     if( pbase() == epptr() )
11196                         m_writer( std::string( 1, static_cast<char>( c ) ) );
11197                     else
11198                         sputc( static_cast<char>( c ) );
11199                 }
11200                 return 0;
11201             }
11202 
sync()11203             int sync() override {
11204                 if( pbase() != pptr() ) {
11205                     m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
11206                     setp( pbase(), epptr() );
11207                 }
11208                 return 0;
11209             }
11210         };
11211 
11212         ///////////////////////////////////////////////////////////////////////////
11213 
11214         struct OutputDebugWriter {
11215 
operator ()Catch::detail::__anonc5acfb671c11::OutputDebugWriter11216             void operator()( std::string const&str ) {
11217                 writeToDebugConsole( str );
11218             }
11219         };
11220 
11221         ///////////////////////////////////////////////////////////////////////////
11222 
11223         class FileStream : public IStream {
11224             mutable std::ofstream m_ofs;
11225         public:
FileStream(StringRef filename)11226             FileStream( StringRef filename ) {
11227                 m_ofs.open( filename.c_str() );
11228                 CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" );
11229             }
11230             ~FileStream() override = default;
11231         public: // IStream
stream() const11232             std::ostream& stream() const override {
11233                 return m_ofs;
11234             }
11235         };
11236 
11237         ///////////////////////////////////////////////////////////////////////////
11238 
11239         class CoutStream : public IStream {
11240             mutable std::ostream m_os;
11241         public:
11242             // Store the streambuf from cout up-front because
11243             // cout may get redirected when running tests
CoutStream()11244             CoutStream() : m_os( Catch::cout().rdbuf() ) {}
11245             ~CoutStream() override = default;
11246 
11247         public: // IStream
stream() const11248             std::ostream& stream() const override { return m_os; }
11249         };
11250 
11251         ///////////////////////////////////////////////////////////////////////////
11252 
11253         class DebugOutStream : public IStream {
11254             std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
11255             mutable std::ostream m_os;
11256         public:
DebugOutStream()11257             DebugOutStream()
11258             :   m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
11259                 m_os( m_streamBuf.get() )
11260             {}
11261 
11262             ~DebugOutStream() override = default;
11263 
11264         public: // IStream
stream() const11265             std::ostream& stream() const override { return m_os; }
11266         };
11267 
11268     }} // namespace anon::detail
11269 
11270     ///////////////////////////////////////////////////////////////////////////
11271 
makeStream(StringRef const & filename)11272     auto makeStream( StringRef const &filename ) -> IStream const* {
11273         if( filename.empty() )
11274             return new detail::CoutStream();
11275         else if( filename[0] == '%' ) {
11276             if( filename == "%debug" )
11277                 return new detail::DebugOutStream();
11278             else
11279                 CATCH_ERROR( "Unrecognised stream: '" << filename << "'" );
11280         }
11281         else
11282             return new detail::FileStream( filename );
11283     }
11284 
11285     // This class encapsulates the idea of a pool of ostringstreams that can be reused.
11286     struct StringStreams {
11287         std::vector<std::unique_ptr<std::ostringstream>> m_streams;
11288         std::vector<std::size_t> m_unused;
11289         std::ostringstream m_referenceStream; // Used for copy state/ flags from
11290 
addCatch::StringStreams11291         auto add() -> std::size_t {
11292             if( m_unused.empty() ) {
11293                 m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) );
11294                 return m_streams.size()-1;
11295             }
11296             else {
11297                 auto index = m_unused.back();
11298                 m_unused.pop_back();
11299                 return index;
11300             }
11301         }
11302 
releaseCatch::StringStreams11303         void release( std::size_t index ) {
11304             m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
11305             m_unused.push_back(index);
11306         }
11307     };
11308 
ReusableStringStream()11309     ReusableStringStream::ReusableStringStream()
11310     :   m_index( Singleton<StringStreams>::getMutable().add() ),
11311         m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )
11312     {}
11313 
~ReusableStringStream()11314     ReusableStringStream::~ReusableStringStream() {
11315         static_cast<std::ostringstream*>( m_oss )->str("");
11316         m_oss->clear();
11317         Singleton<StringStreams>::getMutable().release( m_index );
11318     }
11319 
str() const11320     auto ReusableStringStream::str() const -> std::string {
11321         return static_cast<std::ostringstream*>( m_oss )->str();
11322     }
11323 
11324     ///////////////////////////////////////////////////////////////////////////
11325 
11326 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
cout()11327     std::ostream& cout() { return std::cout; }
cerr()11328     std::ostream& cerr() { return std::cerr; }
clog()11329     std::ostream& clog() { return std::clog; }
11330 #endif
11331 }
11332 // end catch_stream.cpp
11333 // start catch_string_manip.cpp
11334 
11335 #include <algorithm>
11336 #include <ostream>
11337 #include <cstring>
11338 #include <cctype>
11339 
11340 namespace Catch {
11341 
11342     namespace {
toLowerCh(char c)11343         char toLowerCh(char c) {
11344             return static_cast<char>( std::tolower( c ) );
11345         }
11346     }
11347 
startsWith(std::string const & s,std::string const & prefix)11348     bool startsWith( std::string const& s, std::string const& prefix ) {
11349         return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
11350     }
startsWith(std::string const & s,char prefix)11351     bool startsWith( std::string const& s, char prefix ) {
11352         return !s.empty() && s[0] == prefix;
11353     }
endsWith(std::string const & s,std::string const & suffix)11354     bool endsWith( std::string const& s, std::string const& suffix ) {
11355         return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
11356     }
endsWith(std::string const & s,char suffix)11357     bool endsWith( std::string const& s, char suffix ) {
11358         return !s.empty() && s[s.size()-1] == suffix;
11359     }
contains(std::string const & s,std::string const & infix)11360     bool contains( std::string const& s, std::string const& infix ) {
11361         return s.find( infix ) != std::string::npos;
11362     }
toLowerInPlace(std::string & s)11363     void toLowerInPlace( std::string& s ) {
11364         std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
11365     }
toLower(std::string const & s)11366     std::string toLower( std::string const& s ) {
11367         std::string lc = s;
11368         toLowerInPlace( lc );
11369         return lc;
11370     }
trim(std::string const & str)11371     std::string trim( std::string const& str ) {
11372         static char const* whitespaceChars = "\n\r\t ";
11373         std::string::size_type start = str.find_first_not_of( whitespaceChars );
11374         std::string::size_type end = str.find_last_not_of( whitespaceChars );
11375 
11376         return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
11377     }
11378 
replaceInPlace(std::string & str,std::string const & replaceThis,std::string const & withThis)11379     bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
11380         bool replaced = false;
11381         std::size_t i = str.find( replaceThis );
11382         while( i != std::string::npos ) {
11383             replaced = true;
11384             str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
11385             if( i < str.size()-withThis.size() )
11386                 i = str.find( replaceThis, i+withThis.size() );
11387             else
11388                 i = std::string::npos;
11389         }
11390         return replaced;
11391     }
11392 
pluralise(std::size_t count,std::string const & label)11393     pluralise::pluralise( std::size_t count, std::string const& label )
11394     :   m_count( count ),
11395         m_label( label )
11396     {}
11397 
operator <<(std::ostream & os,pluralise const & pluraliser)11398     std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
11399         os << pluraliser.m_count << ' ' << pluraliser.m_label;
11400         if( pluraliser.m_count != 1 )
11401             os << 's';
11402         return os;
11403     }
11404 
11405 }
11406 // end catch_string_manip.cpp
11407 // start catch_stringref.cpp
11408 
11409 #if defined(__clang__)
11410 #    pragma clang diagnostic push
11411 #    pragma clang diagnostic ignored "-Wexit-time-destructors"
11412 #endif
11413 
11414 #include <ostream>
11415 #include <cstring>
11416 #include <cstdint>
11417 
11418 namespace {
11419     const uint32_t byte_2_lead = 0xC0;
11420     const uint32_t byte_3_lead = 0xE0;
11421     const uint32_t byte_4_lead = 0xF0;
11422 }
11423 
11424 namespace Catch {
StringRef(char const * rawChars)11425     StringRef::StringRef( char const* rawChars ) noexcept
11426     : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
11427     {}
11428 
operator std::string() const11429     StringRef::operator std::string() const {
11430         return std::string( m_start, m_size );
11431     }
11432 
swap(StringRef & other)11433     void StringRef::swap( StringRef& other ) noexcept {
11434         std::swap( m_start, other.m_start );
11435         std::swap( m_size, other.m_size );
11436         std::swap( m_data, other.m_data );
11437     }
11438 
c_str() const11439     auto StringRef::c_str() const -> char const* {
11440         if( isSubstring() )
11441            const_cast<StringRef*>( this )->takeOwnership();
11442         return m_start;
11443     }
currentData() const11444     auto StringRef::currentData() const noexcept -> char const* {
11445         return m_start;
11446     }
11447 
isOwned() const11448     auto StringRef::isOwned() const noexcept -> bool {
11449         return m_data != nullptr;
11450     }
isSubstring() const11451     auto StringRef::isSubstring() const noexcept -> bool {
11452         return m_start[m_size] != '\0';
11453     }
11454 
takeOwnership()11455     void StringRef::takeOwnership() {
11456         if( !isOwned() ) {
11457             m_data = new char[m_size+1];
11458             memcpy( m_data, m_start, m_size );
11459             m_data[m_size] = '\0';
11460             m_start = m_data;
11461         }
11462     }
substr(size_type start,size_type size) const11463     auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {
11464         if( start < m_size )
11465             return StringRef( m_start+start, size );
11466         else
11467             return StringRef();
11468     }
operator ==(StringRef const & other) const11469     auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {
11470         return
11471             size() == other.size() &&
11472             (std::strncmp( m_start, other.m_start, size() ) == 0);
11473     }
operator !=(StringRef const & other) const11474     auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool {
11475         return !operator==( other );
11476     }
11477 
operator [](size_type index) const11478     auto StringRef::operator[](size_type index) const noexcept -> char {
11479         return m_start[index];
11480     }
11481 
numberOfCharacters() const11482     auto StringRef::numberOfCharacters() const noexcept -> size_type {
11483         size_type noChars = m_size;
11484         // Make adjustments for uft encodings
11485         for( size_type i=0; i < m_size; ++i ) {
11486             char c = m_start[i];
11487             if( ( c & byte_2_lead ) == byte_2_lead ) {
11488                 noChars--;
11489                 if (( c & byte_3_lead ) == byte_3_lead )
11490                     noChars--;
11491                 if( ( c & byte_4_lead ) == byte_4_lead )
11492                     noChars--;
11493             }
11494         }
11495         return noChars;
11496     }
11497 
operator +(StringRef const & lhs,StringRef const & rhs)11498     auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string {
11499         std::string str;
11500         str.reserve( lhs.size() + rhs.size() );
11501         str += lhs;
11502         str += rhs;
11503         return str;
11504     }
operator +(StringRef const & lhs,const char * rhs)11505     auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string {
11506         return std::string( lhs ) + std::string( rhs );
11507     }
operator +(char const * lhs,StringRef const & rhs)11508     auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string {
11509         return std::string( lhs ) + std::string( rhs );
11510     }
11511 
operator <<(std::ostream & os,StringRef const & str)11512     auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
11513         return os.write(str.currentData(), str.size());
11514     }
11515 
operator +=(std::string & lhs,StringRef const & rhs)11516     auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
11517         lhs.append(rhs.currentData(), rhs.size());
11518         return lhs;
11519     }
11520 
11521 } // namespace Catch
11522 
11523 #if defined(__clang__)
11524 #    pragma clang diagnostic pop
11525 #endif
11526 // end catch_stringref.cpp
11527 // start catch_tag_alias.cpp
11528 
11529 namespace Catch {
TagAlias(std::string const & _tag,SourceLineInfo _lineInfo)11530     TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
11531 }
11532 // end catch_tag_alias.cpp
11533 // start catch_tag_alias_autoregistrar.cpp
11534 
11535 namespace Catch {
11536 
RegistrarForTagAliases(char const * alias,char const * tag,SourceLineInfo const & lineInfo)11537     RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
11538         CATCH_TRY {
11539             getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
11540         } CATCH_CATCH_ALL {
11541             // Do not throw when constructing global objects, instead register the exception to be processed later
11542             getMutableRegistryHub().registerStartupException();
11543         }
11544     }
11545 
11546 }
11547 // end catch_tag_alias_autoregistrar.cpp
11548 // start catch_tag_alias_registry.cpp
11549 
11550 #include <sstream>
11551 
11552 namespace Catch {
11553 
~TagAliasRegistry()11554     TagAliasRegistry::~TagAliasRegistry() {}
11555 
find(std::string const & alias) const11556     TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {
11557         auto it = m_registry.find( alias );
11558         if( it != m_registry.end() )
11559             return &(it->second);
11560         else
11561             return nullptr;
11562     }
11563 
expandAliases(std::string const & unexpandedTestSpec) const11564     std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
11565         std::string expandedTestSpec = unexpandedTestSpec;
11566         for( auto const& registryKvp : m_registry ) {
11567             std::size_t pos = expandedTestSpec.find( registryKvp.first );
11568             if( pos != std::string::npos ) {
11569                 expandedTestSpec =  expandedTestSpec.substr( 0, pos ) +
11570                                     registryKvp.second.tag +
11571                                     expandedTestSpec.substr( pos + registryKvp.first.size() );
11572             }
11573         }
11574         return expandedTestSpec;
11575     }
11576 
add(std::string const & alias,std::string const & tag,SourceLineInfo const & lineInfo)11577     void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
11578         CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'),
11579                       "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo );
11580 
11581         CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
11582                       "error: tag alias, '" << alias << "' already registered.\n"
11583                       << "\tFirst seen at: " << find(alias)->lineInfo << "\n"
11584                       << "\tRedefined at: " << lineInfo );
11585     }
11586 
~ITagAliasRegistry()11587     ITagAliasRegistry::~ITagAliasRegistry() {}
11588 
get()11589     ITagAliasRegistry const& ITagAliasRegistry::get() {
11590         return getRegistryHub().getTagAliasRegistry();
11591     }
11592 
11593 } // end namespace Catch
11594 // end catch_tag_alias_registry.cpp
11595 // start catch_test_case_info.cpp
11596 
11597 #include <cctype>
11598 #include <exception>
11599 #include <algorithm>
11600 #include <sstream>
11601 
11602 namespace Catch {
11603 
11604     namespace {
parseSpecialTag(std::string const & tag)11605         TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
11606             if( startsWith( tag, '.' ) ||
11607                 tag == "!hide" )
11608                 return TestCaseInfo::IsHidden;
11609             else if( tag == "!throws" )
11610                 return TestCaseInfo::Throws;
11611             else if( tag == "!shouldfail" )
11612                 return TestCaseInfo::ShouldFail;
11613             else if( tag == "!mayfail" )
11614                 return TestCaseInfo::MayFail;
11615             else if( tag == "!nonportable" )
11616                 return TestCaseInfo::NonPortable;
11617             else if( tag == "!benchmark" )
11618                 return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );
11619             else
11620                 return TestCaseInfo::None;
11621         }
isReservedTag(std::string const & tag)11622         bool isReservedTag( std::string const& tag ) {
11623             return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
11624         }
enforceNotReservedTag(std::string const & tag,SourceLineInfo const & _lineInfo)11625         void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
11626             CATCH_ENFORCE( !isReservedTag(tag),
11627                           "Tag name: [" << tag << "] is not allowed.\n"
11628                           << "Tag names starting with non alpha-numeric characters are reserved\n"
11629                           << _lineInfo );
11630         }
11631     }
11632 
makeTestCase(ITestInvoker * _testCase,std::string const & _className,NameAndTags const & nameAndTags,SourceLineInfo const & _lineInfo)11633     TestCase makeTestCase(  ITestInvoker* _testCase,
11634                             std::string const& _className,
11635                             NameAndTags const& nameAndTags,
11636                             SourceLineInfo const& _lineInfo )
11637     {
11638         bool isHidden = false;
11639 
11640         // Parse out tags
11641         std::vector<std::string> tags;
11642         std::string desc, tag;
11643         bool inTag = false;
11644         std::string _descOrTags = nameAndTags.tags;
11645         for (char c : _descOrTags) {
11646             if( !inTag ) {
11647                 if( c == '[' )
11648                     inTag = true;
11649                 else
11650                     desc += c;
11651             }
11652             else {
11653                 if( c == ']' ) {
11654                     TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
11655                     if( ( prop & TestCaseInfo::IsHidden ) != 0 )
11656                         isHidden = true;
11657                     else if( prop == TestCaseInfo::None )
11658                         enforceNotReservedTag( tag, _lineInfo );
11659 
11660                     tags.push_back( tag );
11661                     tag.clear();
11662                     inTag = false;
11663                 }
11664                 else
11665                     tag += c;
11666             }
11667         }
11668         if( isHidden ) {
11669             tags.push_back( "." );
11670         }
11671 
11672         TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
11673         return TestCase( _testCase, std::move(info) );
11674     }
11675 
setTags(TestCaseInfo & testCaseInfo,std::vector<std::string> tags)11676     void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
11677         std::sort(begin(tags), end(tags));
11678         tags.erase(std::unique(begin(tags), end(tags)), end(tags));
11679         testCaseInfo.lcaseTags.clear();
11680 
11681         for( auto const& tag : tags ) {
11682             std::string lcaseTag = toLower( tag );
11683             testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
11684             testCaseInfo.lcaseTags.push_back( lcaseTag );
11685         }
11686         testCaseInfo.tags = std::move(tags);
11687     }
11688 
TestCaseInfo(std::string const & _name,std::string const & _className,std::string const & _description,std::vector<std::string> const & _tags,SourceLineInfo const & _lineInfo)11689     TestCaseInfo::TestCaseInfo( std::string const& _name,
11690                                 std::string const& _className,
11691                                 std::string const& _description,
11692                                 std::vector<std::string> const& _tags,
11693                                 SourceLineInfo const& _lineInfo )
11694     :   name( _name ),
11695         className( _className ),
11696         description( _description ),
11697         lineInfo( _lineInfo ),
11698         properties( None )
11699     {
11700         setTags( *this, _tags );
11701     }
11702 
isHidden() const11703     bool TestCaseInfo::isHidden() const {
11704         return ( properties & IsHidden ) != 0;
11705     }
throws() const11706     bool TestCaseInfo::throws() const {
11707         return ( properties & Throws ) != 0;
11708     }
okToFail() const11709     bool TestCaseInfo::okToFail() const {
11710         return ( properties & (ShouldFail | MayFail ) ) != 0;
11711     }
expectedToFail() const11712     bool TestCaseInfo::expectedToFail() const {
11713         return ( properties & (ShouldFail ) ) != 0;
11714     }
11715 
tagsAsString() const11716     std::string TestCaseInfo::tagsAsString() const {
11717         std::string ret;
11718         // '[' and ']' per tag
11719         std::size_t full_size = 2 * tags.size();
11720         for (const auto& tag : tags) {
11721             full_size += tag.size();
11722         }
11723         ret.reserve(full_size);
11724         for (const auto& tag : tags) {
11725             ret.push_back('[');
11726             ret.append(tag);
11727             ret.push_back(']');
11728         }
11729 
11730         return ret;
11731     }
11732 
TestCase(ITestInvoker * testCase,TestCaseInfo && info)11733     TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}
11734 
withName(std::string const & _newName) const11735     TestCase TestCase::withName( std::string const& _newName ) const {
11736         TestCase other( *this );
11737         other.name = _newName;
11738         return other;
11739     }
11740 
invoke() const11741     void TestCase::invoke() const {
11742         test->invoke();
11743     }
11744 
operator ==(TestCase const & other) const11745     bool TestCase::operator == ( TestCase const& other ) const {
11746         return  test.get() == other.test.get() &&
11747                 name == other.name &&
11748                 className == other.className;
11749     }
11750 
operator <(TestCase const & other) const11751     bool TestCase::operator < ( TestCase const& other ) const {
11752         return name < other.name;
11753     }
11754 
getTestCaseInfo() const11755     TestCaseInfo const& TestCase::getTestCaseInfo() const
11756     {
11757         return *this;
11758     }
11759 
11760 } // end namespace Catch
11761 // end catch_test_case_info.cpp
11762 // start catch_test_case_registry_impl.cpp
11763 
11764 #include <sstream>
11765 
11766 namespace Catch {
11767 
sortTests(IConfig const & config,std::vector<TestCase> const & unsortedTestCases)11768     std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
11769 
11770         std::vector<TestCase> sorted = unsortedTestCases;
11771 
11772         switch( config.runOrder() ) {
11773             case RunTests::InLexicographicalOrder:
11774                 std::sort( sorted.begin(), sorted.end() );
11775                 break;
11776             case RunTests::InRandomOrder:
11777                 seedRng( config );
11778                 std::shuffle( sorted.begin(), sorted.end(), rng() );
11779                 break;
11780             case RunTests::InDeclarationOrder:
11781                 // already in declaration order
11782                 break;
11783         }
11784         return sorted;
11785     }
matchTest(TestCase const & testCase,TestSpec const & testSpec,IConfig const & config)11786     bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
11787         return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
11788     }
11789 
enforceNoDuplicateTestCases(std::vector<TestCase> const & functions)11790     void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
11791         std::set<TestCase> seenFunctions;
11792         for( auto const& function : functions ) {
11793             auto prev = seenFunctions.insert( function );
11794             CATCH_ENFORCE( prev.second,
11795                     "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n"
11796                     << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
11797                     << "\tRedefined at " << function.getTestCaseInfo().lineInfo );
11798         }
11799     }
11800 
filterTests(std::vector<TestCase> const & testCases,TestSpec const & testSpec,IConfig const & config)11801     std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
11802         std::vector<TestCase> filtered;
11803         filtered.reserve( testCases.size() );
11804         for( auto const& testCase : testCases )
11805             if( matchTest( testCase, testSpec, config ) )
11806                 filtered.push_back( testCase );
11807         return filtered;
11808     }
getAllTestCasesSorted(IConfig const & config)11809     std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
11810         return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
11811     }
11812 
registerTest(TestCase const & testCase)11813     void TestRegistry::registerTest( TestCase const& testCase ) {
11814         std::string name = testCase.getTestCaseInfo().name;
11815         if( name.empty() ) {
11816             ReusableStringStream rss;
11817             rss << "Anonymous test case " << ++m_unnamedCount;
11818             return registerTest( testCase.withName( rss.str() ) );
11819         }
11820         m_functions.push_back( testCase );
11821     }
11822 
getAllTests() const11823     std::vector<TestCase> const& TestRegistry::getAllTests() const {
11824         return m_functions;
11825     }
getAllTestsSorted(IConfig const & config) const11826     std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
11827         if( m_sortedFunctions.empty() )
11828             enforceNoDuplicateTestCases( m_functions );
11829 
11830         if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
11831             m_sortedFunctions = sortTests( config, m_functions );
11832             m_currentSortOrder = config.runOrder();
11833         }
11834         return m_sortedFunctions;
11835     }
11836 
11837     ///////////////////////////////////////////////////////////////////////////
TestInvokerAsFunction(void (* testAsFunction)())11838     TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
11839 
invoke() const11840     void TestInvokerAsFunction::invoke() const {
11841         m_testAsFunction();
11842     }
11843 
extractClassName(StringRef const & classOrQualifiedMethodName)11844     std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
11845         std::string className = classOrQualifiedMethodName;
11846         if( startsWith( className, '&' ) )
11847         {
11848             std::size_t lastColons = className.rfind( "::" );
11849             std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
11850             if( penultimateColons == std::string::npos )
11851                 penultimateColons = 1;
11852             className = className.substr( penultimateColons, lastColons-penultimateColons );
11853         }
11854         return className;
11855     }
11856 
11857 } // end namespace Catch
11858 // end catch_test_case_registry_impl.cpp
11859 // start catch_test_case_tracker.cpp
11860 
11861 #include <algorithm>
11862 #include <cassert>
11863 #include <stdexcept>
11864 #include <memory>
11865 #include <sstream>
11866 
11867 #if defined(__clang__)
11868 #    pragma clang diagnostic push
11869 #    pragma clang diagnostic ignored "-Wexit-time-destructors"
11870 #endif
11871 
11872 namespace Catch {
11873 namespace TestCaseTracking {
11874 
NameAndLocation(std::string const & _name,SourceLineInfo const & _location)11875     NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
11876     :   name( _name ),
11877         location( _location )
11878     {}
11879 
11880     ITracker::~ITracker() = default;
11881 
instance()11882     TrackerContext& TrackerContext::instance() {
11883         static TrackerContext s_instance;
11884         return s_instance;
11885     }
11886 
startRun()11887     ITracker& TrackerContext::startRun() {
11888         m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr );
11889         m_currentTracker = nullptr;
11890         m_runState = Executing;
11891         return *m_rootTracker;
11892     }
11893 
endRun()11894     void TrackerContext::endRun() {
11895         m_rootTracker.reset();
11896         m_currentTracker = nullptr;
11897         m_runState = NotStarted;
11898     }
11899 
startCycle()11900     void TrackerContext::startCycle() {
11901         m_currentTracker = m_rootTracker.get();
11902         m_runState = Executing;
11903     }
completeCycle()11904     void TrackerContext::completeCycle() {
11905         m_runState = CompletedCycle;
11906     }
11907 
completedCycle() const11908     bool TrackerContext::completedCycle() const {
11909         return m_runState == CompletedCycle;
11910     }
currentTracker()11911     ITracker& TrackerContext::currentTracker() {
11912         return *m_currentTracker;
11913     }
setCurrentTracker(ITracker * tracker)11914     void TrackerContext::setCurrentTracker( ITracker* tracker ) {
11915         m_currentTracker = tracker;
11916     }
11917 
TrackerBase(NameAndLocation const & nameAndLocation,TrackerContext & ctx,ITracker * parent)11918     TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
11919     :   m_nameAndLocation( nameAndLocation ),
11920         m_ctx( ctx ),
11921         m_parent( parent )
11922     {}
11923 
nameAndLocation() const11924     NameAndLocation const& TrackerBase::nameAndLocation() const {
11925         return m_nameAndLocation;
11926     }
isComplete() const11927     bool TrackerBase::isComplete() const {
11928         return m_runState == CompletedSuccessfully || m_runState == Failed;
11929     }
isSuccessfullyCompleted() const11930     bool TrackerBase::isSuccessfullyCompleted() const {
11931         return m_runState == CompletedSuccessfully;
11932     }
isOpen() const11933     bool TrackerBase::isOpen() const {
11934         return m_runState != NotStarted && !isComplete();
11935     }
hasChildren() const11936     bool TrackerBase::hasChildren() const {
11937         return !m_children.empty();
11938     }
11939 
addChild(ITrackerPtr const & child)11940     void TrackerBase::addChild( ITrackerPtr const& child ) {
11941         m_children.push_back( child );
11942     }
11943 
findChild(NameAndLocation const & nameAndLocation)11944     ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) {
11945         auto it = std::find_if( m_children.begin(), m_children.end(),
11946             [&nameAndLocation]( ITrackerPtr const& tracker ){
11947                 return
11948                     tracker->nameAndLocation().location == nameAndLocation.location &&
11949                     tracker->nameAndLocation().name == nameAndLocation.name;
11950             } );
11951         return( it != m_children.end() )
11952             ? *it
11953             : nullptr;
11954     }
parent()11955     ITracker& TrackerBase::parent() {
11956         assert( m_parent ); // Should always be non-null except for root
11957         return *m_parent;
11958     }
11959 
openChild()11960     void TrackerBase::openChild() {
11961         if( m_runState != ExecutingChildren ) {
11962             m_runState = ExecutingChildren;
11963             if( m_parent )
11964                 m_parent->openChild();
11965         }
11966     }
11967 
isSectionTracker() const11968     bool TrackerBase::isSectionTracker() const { return false; }
isGeneratorTracker() const11969     bool TrackerBase::isGeneratorTracker() const { return false; }
11970 
open()11971     void TrackerBase::open() {
11972         m_runState = Executing;
11973         moveToThis();
11974         if( m_parent )
11975             m_parent->openChild();
11976     }
11977 
close()11978     void TrackerBase::close() {
11979 
11980         // Close any still open children (e.g. generators)
11981         while( &m_ctx.currentTracker() != this )
11982             m_ctx.currentTracker().close();
11983 
11984         switch( m_runState ) {
11985             case NeedsAnotherRun:
11986                 break;
11987 
11988             case Executing:
11989                 m_runState = CompletedSuccessfully;
11990                 break;
11991             case ExecutingChildren:
11992                 if( m_children.empty() || m_children.back()->isComplete() )
11993                     m_runState = CompletedSuccessfully;
11994                 break;
11995 
11996             case NotStarted:
11997             case CompletedSuccessfully:
11998             case Failed:
11999                 CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState );
12000 
12001             default:
12002                 CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState );
12003         }
12004         moveToParent();
12005         m_ctx.completeCycle();
12006     }
fail()12007     void TrackerBase::fail() {
12008         m_runState = Failed;
12009         if( m_parent )
12010             m_parent->markAsNeedingAnotherRun();
12011         moveToParent();
12012         m_ctx.completeCycle();
12013     }
markAsNeedingAnotherRun()12014     void TrackerBase::markAsNeedingAnotherRun() {
12015         m_runState = NeedsAnotherRun;
12016     }
12017 
moveToParent()12018     void TrackerBase::moveToParent() {
12019         assert( m_parent );
12020         m_ctx.setCurrentTracker( m_parent );
12021     }
moveToThis()12022     void TrackerBase::moveToThis() {
12023         m_ctx.setCurrentTracker( this );
12024     }
12025 
SectionTracker(NameAndLocation const & nameAndLocation,TrackerContext & ctx,ITracker * parent)12026     SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
12027     :   TrackerBase( nameAndLocation, ctx, parent )
12028     {
12029         if( parent ) {
12030             while( !parent->isSectionTracker() )
12031                 parent = &parent->parent();
12032 
12033             SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
12034             addNextFilters( parentSection.m_filters );
12035         }
12036     }
12037 
isComplete() const12038     bool SectionTracker::isComplete() const {
12039         bool complete = true;
12040 
12041         if ((m_filters.empty() || m_filters[0] == "") ||
12042              std::find(m_filters.begin(), m_filters.end(),
12043                        m_nameAndLocation.name) != m_filters.end())
12044             complete = TrackerBase::isComplete();
12045         return complete;
12046 
12047     }
12048 
isSectionTracker() const12049     bool SectionTracker::isSectionTracker() const { return true; }
12050 
acquire(TrackerContext & ctx,NameAndLocation const & nameAndLocation)12051     SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
12052         std::shared_ptr<SectionTracker> section;
12053 
12054         ITracker& currentTracker = ctx.currentTracker();
12055         if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
12056             assert( childTracker );
12057             assert( childTracker->isSectionTracker() );
12058             section = std::static_pointer_cast<SectionTracker>( childTracker );
12059         }
12060         else {
12061             section = std::make_shared<SectionTracker>( nameAndLocation, ctx, &currentTracker );
12062             currentTracker.addChild( section );
12063         }
12064         if( !ctx.completedCycle() )
12065             section->tryOpen();
12066         return *section;
12067     }
12068 
tryOpen()12069     void SectionTracker::tryOpen() {
12070         if( !isComplete() && (m_filters.empty() || m_filters[0].empty() ||  m_filters[0] == m_nameAndLocation.name ) )
12071             open();
12072     }
12073 
addInitialFilters(std::vector<std::string> const & filters)12074     void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
12075         if( !filters.empty() ) {
12076             m_filters.push_back(""); // Root - should never be consulted
12077             m_filters.push_back(""); // Test Case - not a section filter
12078             m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
12079         }
12080     }
addNextFilters(std::vector<std::string> const & filters)12081     void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) {
12082         if( filters.size() > 1 )
12083             m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
12084     }
12085 
12086 } // namespace TestCaseTracking
12087 
12088 using TestCaseTracking::ITracker;
12089 using TestCaseTracking::TrackerContext;
12090 using TestCaseTracking::SectionTracker;
12091 
12092 } // namespace Catch
12093 
12094 #if defined(__clang__)
12095 #    pragma clang diagnostic pop
12096 #endif
12097 // end catch_test_case_tracker.cpp
12098 // start catch_test_registry.cpp
12099 
12100 namespace Catch {
12101 
makeTestInvoker(void (* testAsFunction)())12102     auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* {
12103         return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
12104     }
12105 
NameAndTags(StringRef const & name_,StringRef const & tags_)12106     NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
12107 
AutoReg(ITestInvoker * invoker,SourceLineInfo const & lineInfo,StringRef const & classOrMethod,NameAndTags const & nameAndTags)12108     AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
12109         CATCH_TRY {
12110             getMutableRegistryHub()
12111                     .registerTest(
12112                         makeTestCase(
12113                             invoker,
12114                             extractClassName( classOrMethod ),
12115                             nameAndTags,
12116                             lineInfo));
12117         } CATCH_CATCH_ALL {
12118             // Do not throw when constructing global objects, instead register the exception to be processed later
12119             getMutableRegistryHub().registerStartupException();
12120         }
12121     }
12122 
12123     AutoReg::~AutoReg() = default;
12124 }
12125 // end catch_test_registry.cpp
12126 // start catch_test_spec.cpp
12127 
12128 #include <algorithm>
12129 #include <string>
12130 #include <vector>
12131 #include <memory>
12132 
12133 namespace Catch {
12134 
12135     TestSpec::Pattern::~Pattern() = default;
12136     TestSpec::NamePattern::~NamePattern() = default;
12137     TestSpec::TagPattern::~TagPattern() = default;
12138     TestSpec::ExcludedPattern::~ExcludedPattern() = default;
12139 
NamePattern(std::string const & name)12140     TestSpec::NamePattern::NamePattern( std::string const& name )
12141     : m_wildcardPattern( toLower( name ), CaseSensitive::No )
12142     {}
matches(TestCaseInfo const & testCase) const12143     bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
12144         return m_wildcardPattern.matches( toLower( testCase.name ) );
12145     }
12146 
TagPattern(std::string const & tag)12147     TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
matches(TestCaseInfo const & testCase) const12148     bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
12149         return std::find(begin(testCase.lcaseTags),
12150                          end(testCase.lcaseTags),
12151                          m_tag) != end(testCase.lcaseTags);
12152     }
12153 
ExcludedPattern(PatternPtr const & underlyingPattern)12154     TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
matches(TestCaseInfo const & testCase) const12155     bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
12156 
matches(TestCaseInfo const & testCase) const12157     bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
12158         // All patterns in a filter must match for the filter to be a match
12159         for( auto const& pattern : m_patterns ) {
12160             if( !pattern->matches( testCase ) )
12161                 return false;
12162         }
12163         return true;
12164     }
12165 
hasFilters() const12166     bool TestSpec::hasFilters() const {
12167         return !m_filters.empty();
12168     }
matches(TestCaseInfo const & testCase) const12169     bool TestSpec::matches( TestCaseInfo const& testCase ) const {
12170         // A TestSpec matches if any filter matches
12171         for( auto const& filter : m_filters )
12172             if( filter.matches( testCase ) )
12173                 return true;
12174         return false;
12175     }
12176 }
12177 // end catch_test_spec.cpp
12178 // start catch_test_spec_parser.cpp
12179 
12180 namespace Catch {
12181 
TestSpecParser(ITagAliasRegistry const & tagAliases)12182     TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
12183 
parse(std::string const & arg)12184     TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
12185         m_mode = None;
12186         m_exclusion = false;
12187         m_start = std::string::npos;
12188         m_arg = m_tagAliases->expandAliases( arg );
12189         m_escapeChars.clear();
12190         for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
12191             visitChar( m_arg[m_pos] );
12192         if( m_mode == Name )
12193             addPattern<TestSpec::NamePattern>();
12194         return *this;
12195     }
testSpec()12196     TestSpec TestSpecParser::testSpec() {
12197         addFilter();
12198         return m_testSpec;
12199     }
12200 
visitChar(char c)12201     void TestSpecParser::visitChar( char c ) {
12202         if( m_mode == None ) {
12203             switch( c ) {
12204             case ' ': return;
12205             case '~': m_exclusion = true; return;
12206             case '[': return startNewMode( Tag, ++m_pos );
12207             case '"': return startNewMode( QuotedName, ++m_pos );
12208             case '\\': return escape();
12209             default: startNewMode( Name, m_pos ); break;
12210             }
12211         }
12212         if( m_mode == Name ) {
12213             if( c == ',' ) {
12214                 addPattern<TestSpec::NamePattern>();
12215                 addFilter();
12216             }
12217             else if( c == '[' ) {
12218                 if( subString() == "exclude:" )
12219                     m_exclusion = true;
12220                 else
12221                     addPattern<TestSpec::NamePattern>();
12222                 startNewMode( Tag, ++m_pos );
12223             }
12224             else if( c == '\\' )
12225                 escape();
12226         }
12227         else if( m_mode == EscapedName )
12228             m_mode = Name;
12229         else if( m_mode == QuotedName && c == '"' )
12230             addPattern<TestSpec::NamePattern>();
12231         else if( m_mode == Tag && c == ']' )
12232             addPattern<TestSpec::TagPattern>();
12233     }
startNewMode(Mode mode,std::size_t start)12234     void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
12235         m_mode = mode;
12236         m_start = start;
12237     }
escape()12238     void TestSpecParser::escape() {
12239         if( m_mode == None )
12240             m_start = m_pos;
12241         m_mode = EscapedName;
12242         m_escapeChars.push_back( m_pos );
12243     }
subString() const12244     std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
12245 
addFilter()12246     void TestSpecParser::addFilter() {
12247         if( !m_currentFilter.m_patterns.empty() ) {
12248             m_testSpec.m_filters.push_back( m_currentFilter );
12249             m_currentFilter = TestSpec::Filter();
12250         }
12251     }
12252 
parseTestSpec(std::string const & arg)12253     TestSpec parseTestSpec( std::string const& arg ) {
12254         return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
12255     }
12256 
12257 } // namespace Catch
12258 // end catch_test_spec_parser.cpp
12259 // start catch_timer.cpp
12260 
12261 #include <chrono>
12262 
12263 static const uint64_t nanosecondsInSecond = 1000000000;
12264 
12265 namespace Catch {
12266 
getCurrentNanosecondsSinceEpoch()12267     auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
12268         return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
12269     }
12270 
12271     namespace {
estimateClockResolution()12272         auto estimateClockResolution() -> uint64_t {
12273             uint64_t sum = 0;
12274             static const uint64_t iterations = 1000000;
12275 
12276             auto startTime = getCurrentNanosecondsSinceEpoch();
12277 
12278             for( std::size_t i = 0; i < iterations; ++i ) {
12279 
12280                 uint64_t ticks;
12281                 uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
12282                 do {
12283                     ticks = getCurrentNanosecondsSinceEpoch();
12284                 } while( ticks == baseTicks );
12285 
12286                 auto delta = ticks - baseTicks;
12287                 sum += delta;
12288 
12289                 // If we have been calibrating for over 3 seconds -- the clock
12290                 // is terrible and we should move on.
12291                 // TBD: How to signal that the measured resolution is probably wrong?
12292                 if (ticks > startTime + 3 * nanosecondsInSecond) {
12293                     return sum / ( i + 1u );
12294                 }
12295             }
12296 
12297             // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers
12298             // - and potentially do more iterations if there's a high variance.
12299             return sum/iterations;
12300         }
12301     }
getEstimatedClockResolution()12302     auto getEstimatedClockResolution() -> uint64_t {
12303         static auto s_resolution = estimateClockResolution();
12304         return s_resolution;
12305     }
12306 
start()12307     void Timer::start() {
12308        m_nanoseconds = getCurrentNanosecondsSinceEpoch();
12309     }
getElapsedNanoseconds() const12310     auto Timer::getElapsedNanoseconds() const -> uint64_t {
12311         return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;
12312     }
getElapsedMicroseconds() const12313     auto Timer::getElapsedMicroseconds() const -> uint64_t {
12314         return getElapsedNanoseconds()/1000;
12315     }
getElapsedMilliseconds() const12316     auto Timer::getElapsedMilliseconds() const -> unsigned int {
12317         return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
12318     }
getElapsedSeconds() const12319     auto Timer::getElapsedSeconds() const -> double {
12320         return getElapsedMicroseconds()/1000000.0;
12321     }
12322 
12323 } // namespace Catch
12324 // end catch_timer.cpp
12325 // start catch_tostring.cpp
12326 
12327 #if defined(__clang__)
12328 #    pragma clang diagnostic push
12329 #    pragma clang diagnostic ignored "-Wexit-time-destructors"
12330 #    pragma clang diagnostic ignored "-Wglobal-constructors"
12331 #endif
12332 
12333 // Enable specific decls locally
12334 #if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
12335 #define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
12336 #endif
12337 
12338 #include <cmath>
12339 #include <iomanip>
12340 
12341 namespace Catch {
12342 
12343 namespace Detail {
12344 
12345     const std::string unprintableString = "{?}";
12346 
12347     namespace {
12348         const int hexThreshold = 255;
12349 
12350         struct Endianness {
12351             enum Arch { Big, Little };
12352 
whichCatch::Detail::__anonc5acfb672211::Endianness12353             static Arch which() {
12354                 union _{
12355                     int asInt;
12356                     char asChar[sizeof (int)];
12357                 } u;
12358 
12359                 u.asInt = 1;
12360                 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
12361             }
12362         };
12363     }
12364 
rawMemoryToString(const void * object,std::size_t size)12365     std::string rawMemoryToString( const void *object, std::size_t size ) {
12366         // Reverse order for little endian architectures
12367         int i = 0, end = static_cast<int>( size ), inc = 1;
12368         if( Endianness::which() == Endianness::Little ) {
12369             i = end-1;
12370             end = inc = -1;
12371         }
12372 
12373         unsigned char const *bytes = static_cast<unsigned char const *>(object);
12374         ReusableStringStream rss;
12375         rss << "0x" << std::setfill('0') << std::hex;
12376         for( ; i != end; i += inc )
12377              rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
12378        return rss.str();
12379     }
12380 }
12381 
12382 template<typename T>
fpToString(T value,int precision)12383 std::string fpToString( T value, int precision ) {
12384     if (Catch::isnan(value)) {
12385         return "nan";
12386     }
12387 
12388     ReusableStringStream rss;
12389     rss << std::setprecision( precision )
12390         << std::fixed
12391         << value;
12392     std::string d = rss.str();
12393     std::size_t i = d.find_last_not_of( '0' );
12394     if( i != std::string::npos && i != d.size()-1 ) {
12395         if( d[i] == '.' )
12396             i++;
12397         d = d.substr( 0, i+1 );
12398     }
12399     return d;
12400 }
12401 
12402 //// ======================================================= ////
12403 //
12404 //   Out-of-line defs for full specialization of StringMaker
12405 //
12406 //// ======================================================= ////
12407 
convert(const std::string & str)12408 std::string StringMaker<std::string>::convert(const std::string& str) {
12409     if (!getCurrentContext().getConfig()->showInvisibles()) {
12410         return '"' + str + '"';
12411     }
12412 
12413     std::string s("\"");
12414     for (char c : str) {
12415         switch (c) {
12416         case '\n':
12417             s.append("\\n");
12418             break;
12419         case '\t':
12420             s.append("\\t");
12421             break;
12422         default:
12423             s.push_back(c);
12424             break;
12425         }
12426     }
12427     s.append("\"");
12428     return s;
12429 }
12430 
12431 #ifdef CATCH_CONFIG_CPP17_STRING_VIEW
convert(std::string_view str)12432 std::string StringMaker<std::string_view>::convert(std::string_view str) {
12433     return ::Catch::Detail::stringify(std::string{ str });
12434 }
12435 #endif
12436 
convert(char const * str)12437 std::string StringMaker<char const*>::convert(char const* str) {
12438     if (str) {
12439         return ::Catch::Detail::stringify(std::string{ str });
12440     } else {
12441         return{ "{null string}" };
12442     }
12443 }
convert(char * str)12444 std::string StringMaker<char*>::convert(char* str) {
12445     if (str) {
12446         return ::Catch::Detail::stringify(std::string{ str });
12447     } else {
12448         return{ "{null string}" };
12449     }
12450 }
12451 
12452 #ifdef CATCH_CONFIG_WCHAR
convert(const std::wstring & wstr)12453 std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
12454     std::string s;
12455     s.reserve(wstr.size());
12456     for (auto c : wstr) {
12457         s += (c <= 0xff) ? static_cast<char>(c) : '?';
12458     }
12459     return ::Catch::Detail::stringify(s);
12460 }
12461 
12462 # ifdef CATCH_CONFIG_CPP17_STRING_VIEW
convert(std::wstring_view str)12463 std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {
12464     return StringMaker<std::wstring>::convert(std::wstring(str));
12465 }
12466 # endif
12467 
convert(wchar_t const * str)12468 std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {
12469     if (str) {
12470         return ::Catch::Detail::stringify(std::wstring{ str });
12471     } else {
12472         return{ "{null string}" };
12473     }
12474 }
convert(wchar_t * str)12475 std::string StringMaker<wchar_t *>::convert(wchar_t * str) {
12476     if (str) {
12477         return ::Catch::Detail::stringify(std::wstring{ str });
12478     } else {
12479         return{ "{null string}" };
12480     }
12481 }
12482 #endif
12483 
convert(int value)12484 std::string StringMaker<int>::convert(int value) {
12485     return ::Catch::Detail::stringify(static_cast<long long>(value));
12486 }
convert(long value)12487 std::string StringMaker<long>::convert(long value) {
12488     return ::Catch::Detail::stringify(static_cast<long long>(value));
12489 }
convert(long long value)12490 std::string StringMaker<long long>::convert(long long value) {
12491     ReusableStringStream rss;
12492     rss << value;
12493     if (value > Detail::hexThreshold) {
12494         rss << " (0x" << std::hex << value << ')';
12495     }
12496     return rss.str();
12497 }
12498 
convert(unsigned int value)12499 std::string StringMaker<unsigned int>::convert(unsigned int value) {
12500     return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
12501 }
convert(unsigned long value)12502 std::string StringMaker<unsigned long>::convert(unsigned long value) {
12503     return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
12504 }
convert(unsigned long long value)12505 std::string StringMaker<unsigned long long>::convert(unsigned long long value) {
12506     ReusableStringStream rss;
12507     rss << value;
12508     if (value > Detail::hexThreshold) {
12509         rss << " (0x" << std::hex << value << ')';
12510     }
12511     return rss.str();
12512 }
12513 
convert(bool b)12514 std::string StringMaker<bool>::convert(bool b) {
12515     return b ? "true" : "false";
12516 }
12517 
convert(signed char value)12518 std::string StringMaker<signed char>::convert(signed char value) {
12519     if (value == '\r') {
12520         return "'\\r'";
12521     } else if (value == '\f') {
12522         return "'\\f'";
12523     } else if (value == '\n') {
12524         return "'\\n'";
12525     } else if (value == '\t') {
12526         return "'\\t'";
12527     } else if ('\0' <= value && value < ' ') {
12528         return ::Catch::Detail::stringify(static_cast<unsigned int>(value));
12529     } else {
12530         char chstr[] = "' '";
12531         chstr[1] = value;
12532         return chstr;
12533     }
12534 }
convert(char c)12535 std::string StringMaker<char>::convert(char c) {
12536     return ::Catch::Detail::stringify(static_cast<signed char>(c));
12537 }
convert(unsigned char c)12538 std::string StringMaker<unsigned char>::convert(unsigned char c) {
12539     return ::Catch::Detail::stringify(static_cast<char>(c));
12540 }
12541 
convert(std::nullptr_t)12542 std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) {
12543     return "nullptr";
12544 }
12545 
convert(float value)12546 std::string StringMaker<float>::convert(float value) {
12547     return fpToString(value, 5) + 'f';
12548 }
convert(double value)12549 std::string StringMaker<double>::convert(double value) {
12550     return fpToString(value, 10);
12551 }
12552 
symbol()12553 std::string ratio_string<std::atto>::symbol() { return "a"; }
symbol()12554 std::string ratio_string<std::femto>::symbol() { return "f"; }
symbol()12555 std::string ratio_string<std::pico>::symbol() { return "p"; }
symbol()12556 std::string ratio_string<std::nano>::symbol() { return "n"; }
symbol()12557 std::string ratio_string<std::micro>::symbol() { return "u"; }
symbol()12558 std::string ratio_string<std::milli>::symbol() { return "m"; }
12559 
12560 } // end namespace Catch
12561 
12562 #if defined(__clang__)
12563 #    pragma clang diagnostic pop
12564 #endif
12565 
12566 // end catch_tostring.cpp
12567 // start catch_totals.cpp
12568 
12569 namespace Catch {
12570 
operator -(Counts const & other) const12571     Counts Counts::operator - ( Counts const& other ) const {
12572         Counts diff;
12573         diff.passed = passed - other.passed;
12574         diff.failed = failed - other.failed;
12575         diff.failedButOk = failedButOk - other.failedButOk;
12576         return diff;
12577     }
12578 
operator +=(Counts const & other)12579     Counts& Counts::operator += ( Counts const& other ) {
12580         passed += other.passed;
12581         failed += other.failed;
12582         failedButOk += other.failedButOk;
12583         return *this;
12584     }
12585 
total() const12586     std::size_t Counts::total() const {
12587         return passed + failed + failedButOk;
12588     }
allPassed() const12589     bool Counts::allPassed() const {
12590         return failed == 0 && failedButOk == 0;
12591     }
allOk() const12592     bool Counts::allOk() const {
12593         return failed == 0;
12594     }
12595 
operator -(Totals const & other) const12596     Totals Totals::operator - ( Totals const& other ) const {
12597         Totals diff;
12598         diff.assertions = assertions - other.assertions;
12599         diff.testCases = testCases - other.testCases;
12600         return diff;
12601     }
12602 
operator +=(Totals const & other)12603     Totals& Totals::operator += ( Totals const& other ) {
12604         assertions += other.assertions;
12605         testCases += other.testCases;
12606         return *this;
12607     }
12608 
delta(Totals const & prevTotals) const12609     Totals Totals::delta( Totals const& prevTotals ) const {
12610         Totals diff = *this - prevTotals;
12611         if( diff.assertions.failed > 0 )
12612             ++diff.testCases.failed;
12613         else if( diff.assertions.failedButOk > 0 )
12614             ++diff.testCases.failedButOk;
12615         else
12616             ++diff.testCases.passed;
12617         return diff;
12618     }
12619 
12620 }
12621 // end catch_totals.cpp
12622 // start catch_uncaught_exceptions.cpp
12623 
12624 #include <exception>
12625 
12626 namespace Catch {
uncaught_exceptions()12627     bool uncaught_exceptions() {
12628 #if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
12629         return std::uncaught_exceptions() > 0;
12630 #else
12631         return std::uncaught_exception();
12632 #endif
12633   }
12634 } // end namespace Catch
12635 // end catch_uncaught_exceptions.cpp
12636 // start catch_version.cpp
12637 
12638 #include <ostream>
12639 
12640 namespace Catch {
12641 
Version(unsigned int _majorVersion,unsigned int _minorVersion,unsigned int _patchNumber,char const * const _branchName,unsigned int _buildNumber)12642     Version::Version
12643         (   unsigned int _majorVersion,
12644             unsigned int _minorVersion,
12645             unsigned int _patchNumber,
12646             char const * const _branchName,
12647             unsigned int _buildNumber )
12648     :   majorVersion( _majorVersion ),
12649         minorVersion( _minorVersion ),
12650         patchNumber( _patchNumber ),
12651         branchName( _branchName ),
12652         buildNumber( _buildNumber )
12653     {}
12654 
operator <<(std::ostream & os,Version const & version)12655     std::ostream& operator << ( std::ostream& os, Version const& version ) {
12656         os  << version.majorVersion << '.'
12657             << version.minorVersion << '.'
12658             << version.patchNumber;
12659         // branchName is never null -> 0th char is \0 if it is empty
12660         if (version.branchName[0]) {
12661             os << '-' << version.branchName
12662                << '.' << version.buildNumber;
12663         }
12664         return os;
12665     }
12666 
libraryVersion()12667     Version const& libraryVersion() {
12668         static Version version( 2, 7, 0, "", 0 );
12669         return version;
12670     }
12671 
12672 }
12673 // end catch_version.cpp
12674 // start catch_wildcard_pattern.cpp
12675 
12676 #include <sstream>
12677 
12678 namespace Catch {
12679 
WildcardPattern(std::string const & pattern,CaseSensitive::Choice caseSensitivity)12680     WildcardPattern::WildcardPattern( std::string const& pattern,
12681                                       CaseSensitive::Choice caseSensitivity )
12682     :   m_caseSensitivity( caseSensitivity ),
12683         m_pattern( adjustCase( pattern ) )
12684     {
12685         if( startsWith( m_pattern, '*' ) ) {
12686             m_pattern = m_pattern.substr( 1 );
12687             m_wildcard = WildcardAtStart;
12688         }
12689         if( endsWith( m_pattern, '*' ) ) {
12690             m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
12691             m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
12692         }
12693     }
12694 
matches(std::string const & str) const12695     bool WildcardPattern::matches( std::string const& str ) const {
12696         switch( m_wildcard ) {
12697             case NoWildcard:
12698                 return m_pattern == adjustCase( str );
12699             case WildcardAtStart:
12700                 return endsWith( adjustCase( str ), m_pattern );
12701             case WildcardAtEnd:
12702                 return startsWith( adjustCase( str ), m_pattern );
12703             case WildcardAtBothEnds:
12704                 return contains( adjustCase( str ), m_pattern );
12705             default:
12706                 CATCH_INTERNAL_ERROR( "Unknown enum" );
12707         }
12708     }
12709 
adjustCase(std::string const & str) const12710     std::string WildcardPattern::adjustCase( std::string const& str ) const {
12711         return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
12712     }
12713 }
12714 // end catch_wildcard_pattern.cpp
12715 // start catch_xmlwriter.cpp
12716 
12717 #include <iomanip>
12718 
12719 using uchar = unsigned char;
12720 
12721 namespace Catch {
12722 
12723 namespace {
12724 
trailingBytes(unsigned char c)12725     size_t trailingBytes(unsigned char c) {
12726         if ((c & 0xE0) == 0xC0) {
12727             return 2;
12728         }
12729         if ((c & 0xF0) == 0xE0) {
12730             return 3;
12731         }
12732         if ((c & 0xF8) == 0xF0) {
12733             return 4;
12734         }
12735         CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
12736     }
12737 
headerValue(unsigned char c)12738     uint32_t headerValue(unsigned char c) {
12739         if ((c & 0xE0) == 0xC0) {
12740             return c & 0x1F;
12741         }
12742         if ((c & 0xF0) == 0xE0) {
12743             return c & 0x0F;
12744         }
12745         if ((c & 0xF8) == 0xF0) {
12746             return c & 0x07;
12747         }
12748         CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
12749     }
12750 
hexEscapeChar(std::ostream & os,unsigned char c)12751     void hexEscapeChar(std::ostream& os, unsigned char c) {
12752         std::ios_base::fmtflags f(os.flags());
12753         os << "\\x"
12754             << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
12755             << static_cast<int>(c);
12756         os.flags(f);
12757     }
12758 
12759 } // anonymous namespace
12760 
XmlEncode(std::string const & str,ForWhat forWhat)12761     XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
12762     :   m_str( str ),
12763         m_forWhat( forWhat )
12764     {}
12765 
encodeTo(std::ostream & os) const12766     void XmlEncode::encodeTo( std::ostream& os ) const {
12767         // Apostrophe escaping not necessary if we always use " to write attributes
12768         // (see: http://www.w3.org/TR/xml/#syntax)
12769 
12770         for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
12771             uchar c = m_str[idx];
12772             switch (c) {
12773             case '<':   os << "&lt;"; break;
12774             case '&':   os << "&amp;"; break;
12775 
12776             case '>':
12777                 // See: http://www.w3.org/TR/xml/#syntax
12778                 if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
12779                     os << "&gt;";
12780                 else
12781                     os << c;
12782                 break;
12783 
12784             case '\"':
12785                 if (m_forWhat == ForAttributes)
12786                     os << "&quot;";
12787                 else
12788                     os << c;
12789                 break;
12790 
12791             default:
12792                 // Check for control characters and invalid utf-8
12793 
12794                 // Escape control characters in standard ascii
12795                 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
12796                 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
12797                     hexEscapeChar(os, c);
12798                     break;
12799                 }
12800 
12801                 // Plain ASCII: Write it to stream
12802                 if (c < 0x7F) {
12803                     os << c;
12804                     break;
12805                 }
12806 
12807                 // UTF-8 territory
12808                 // Check if the encoding is valid and if it is not, hex escape bytes.
12809                 // Important: We do not check the exact decoded values for validity, only the encoding format
12810                 // First check that this bytes is a valid lead byte:
12811                 // This means that it is not encoded as 1111 1XXX
12812                 // Or as 10XX XXXX
12813                 if (c <  0xC0 ||
12814                     c >= 0xF8) {
12815                     hexEscapeChar(os, c);
12816                     break;
12817                 }
12818 
12819                 auto encBytes = trailingBytes(c);
12820                 // Are there enough bytes left to avoid accessing out-of-bounds memory?
12821                 if (idx + encBytes - 1 >= m_str.size()) {
12822                     hexEscapeChar(os, c);
12823                     break;
12824                 }
12825                 // The header is valid, check data
12826                 // The next encBytes bytes must together be a valid utf-8
12827                 // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
12828                 bool valid = true;
12829                 uint32_t value = headerValue(c);
12830                 for (std::size_t n = 1; n < encBytes; ++n) {
12831                     uchar nc = m_str[idx + n];
12832                     valid &= ((nc & 0xC0) == 0x80);
12833                     value = (value << 6) | (nc & 0x3F);
12834                 }
12835 
12836                 if (
12837                     // Wrong bit pattern of following bytes
12838                     (!valid) ||
12839                     // Overlong encodings
12840                     (value < 0x80) ||
12841                     (0x80 <= value && value < 0x800   && encBytes > 2) ||
12842                     (0x800 < value && value < 0x10000 && encBytes > 3) ||
12843                     // Encoded value out of range
12844                     (value >= 0x110000)
12845                     ) {
12846                     hexEscapeChar(os, c);
12847                     break;
12848                 }
12849 
12850                 // If we got here, this is in fact a valid(ish) utf-8 sequence
12851                 for (std::size_t n = 0; n < encBytes; ++n) {
12852                     os << m_str[idx + n];
12853                 }
12854                 idx += encBytes - 1;
12855                 break;
12856             }
12857         }
12858     }
12859 
operator <<(std::ostream & os,XmlEncode const & xmlEncode)12860     std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
12861         xmlEncode.encodeTo( os );
12862         return os;
12863     }
12864 
ScopedElement(XmlWriter * writer)12865     XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
12866     :   m_writer( writer )
12867     {}
12868 
ScopedElement(ScopedElement && other)12869     XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
12870     :   m_writer( other.m_writer ){
12871         other.m_writer = nullptr;
12872     }
operator =(ScopedElement && other)12873     XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
12874         if ( m_writer ) {
12875             m_writer->endElement();
12876         }
12877         m_writer = other.m_writer;
12878         other.m_writer = nullptr;
12879         return *this;
12880     }
12881 
~ScopedElement()12882     XmlWriter::ScopedElement::~ScopedElement() {
12883         if( m_writer )
12884             m_writer->endElement();
12885     }
12886 
writeText(std::string const & text,bool indent)12887     XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
12888         m_writer->writeText( text, indent );
12889         return *this;
12890     }
12891 
XmlWriter(std::ostream & os)12892     XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
12893     {
12894         writeDeclaration();
12895     }
12896 
~XmlWriter()12897     XmlWriter::~XmlWriter() {
12898         while( !m_tags.empty() )
12899             endElement();
12900     }
12901 
startElement(std::string const & name)12902     XmlWriter& XmlWriter::startElement( std::string const& name ) {
12903         ensureTagClosed();
12904         newlineIfNecessary();
12905         m_os << m_indent << '<' << name;
12906         m_tags.push_back( name );
12907         m_indent += "  ";
12908         m_tagIsOpen = true;
12909         return *this;
12910     }
12911 
scopedElement(std::string const & name)12912     XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
12913         ScopedElement scoped( this );
12914         startElement( name );
12915         return scoped;
12916     }
12917 
endElement()12918     XmlWriter& XmlWriter::endElement() {
12919         newlineIfNecessary();
12920         m_indent = m_indent.substr( 0, m_indent.size()-2 );
12921         if( m_tagIsOpen ) {
12922             m_os << "/>";
12923             m_tagIsOpen = false;
12924         }
12925         else {
12926             m_os << m_indent << "</" << m_tags.back() << ">";
12927         }
12928         m_os << std::endl;
12929         m_tags.pop_back();
12930         return *this;
12931     }
12932 
writeAttribute(std::string const & name,std::string const & attribute)12933     XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {
12934         if( !name.empty() && !attribute.empty() )
12935             m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
12936         return *this;
12937     }
12938 
writeAttribute(std::string const & name,bool attribute)12939     XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {
12940         m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
12941         return *this;
12942     }
12943 
writeText(std::string const & text,bool indent)12944     XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
12945         if( !text.empty() ){
12946             bool tagWasOpen = m_tagIsOpen;
12947             ensureTagClosed();
12948             if( tagWasOpen && indent )
12949                 m_os << m_indent;
12950             m_os << XmlEncode( text );
12951             m_needsNewline = true;
12952         }
12953         return *this;
12954     }
12955 
writeComment(std::string const & text)12956     XmlWriter& XmlWriter::writeComment( std::string const& text ) {
12957         ensureTagClosed();
12958         m_os << m_indent << "<!--" << text << "-->";
12959         m_needsNewline = true;
12960         return *this;
12961     }
12962 
writeStylesheetRef(std::string const & url)12963     void XmlWriter::writeStylesheetRef( std::string const& url ) {
12964         m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
12965     }
12966 
writeBlankLine()12967     XmlWriter& XmlWriter::writeBlankLine() {
12968         ensureTagClosed();
12969         m_os << '\n';
12970         return *this;
12971     }
12972 
ensureTagClosed()12973     void XmlWriter::ensureTagClosed() {
12974         if( m_tagIsOpen ) {
12975             m_os << ">" << std::endl;
12976             m_tagIsOpen = false;
12977         }
12978     }
12979 
writeDeclaration()12980     void XmlWriter::writeDeclaration() {
12981         m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
12982     }
12983 
newlineIfNecessary()12984     void XmlWriter::newlineIfNecessary() {
12985         if( m_needsNewline ) {
12986             m_os << std::endl;
12987             m_needsNewline = false;
12988         }
12989     }
12990 }
12991 // end catch_xmlwriter.cpp
12992 // start catch_reporter_bases.cpp
12993 
12994 #include <cstring>
12995 #include <cfloat>
12996 #include <cstdio>
12997 #include <cassert>
12998 #include <memory>
12999 
13000 namespace Catch {
prepareExpandedExpression(AssertionResult & result)13001     void prepareExpandedExpression(AssertionResult& result) {
13002         result.getExpandedExpression();
13003     }
13004 
13005     // Because formatting using c++ streams is stateful, drop down to C is required
13006     // Alternatively we could use stringstream, but its performance is... not good.
getFormattedDuration(double duration)13007     std::string getFormattedDuration( double duration ) {
13008         // Max exponent + 1 is required to represent the whole part
13009         // + 1 for decimal point
13010         // + 3 for the 3 decimal places
13011         // + 1 for null terminator
13012         const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
13013         char buffer[maxDoubleSize];
13014 
13015         // Save previous errno, to prevent sprintf from overwriting it
13016         ErrnoGuard guard;
13017 #ifdef _MSC_VER
13018         sprintf_s(buffer, "%.3f", duration);
13019 #else
13020         std::sprintf(buffer, "%.3f", duration);
13021 #endif
13022         return std::string(buffer);
13023     }
13024 
TestEventListenerBase(ReporterConfig const & _config)13025     TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
13026         :StreamingReporterBase(_config) {}
13027 
getSupportedVerbosities()13028     std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() {
13029         return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High };
13030     }
13031 
assertionStarting(AssertionInfo const &)13032     void TestEventListenerBase::assertionStarting(AssertionInfo const &) {}
13033 
assertionEnded(AssertionStats const &)13034     bool TestEventListenerBase::assertionEnded(AssertionStats const &) {
13035         return false;
13036     }
13037 
13038 } // end namespace Catch
13039 // end catch_reporter_bases.cpp
13040 // start catch_reporter_compact.cpp
13041 
13042 namespace {
13043 
13044 #ifdef CATCH_PLATFORM_MAC
failedString()13045     const char* failedString() { return "FAILED"; }
passedString()13046     const char* passedString() { return "PASSED"; }
13047 #else
13048     const char* failedString() { return "failed"; }
13049     const char* passedString() { return "passed"; }
13050 #endif
13051 
13052     // Colour::LightGrey
dimColour()13053     Catch::Colour::Code dimColour() { return Catch::Colour::FileName; }
13054 
bothOrAll(std::size_t count)13055     std::string bothOrAll( std::size_t count ) {
13056         return count == 1 ? std::string() :
13057                count == 2 ? "both " : "all " ;
13058     }
13059 
13060 } // anon namespace
13061 
13062 namespace Catch {
13063 namespace {
13064 // Colour, message variants:
13065 // - white: No tests ran.
13066 // -   red: Failed [both/all] N test cases, failed [both/all] M assertions.
13067 // - white: Passed [both/all] N test cases (no assertions).
13068 // -   red: Failed N tests cases, failed M assertions.
13069 // - green: Passed [both/all] N tests cases with M assertions.
printTotals(std::ostream & out,const Totals & totals)13070 void printTotals(std::ostream& out, const Totals& totals) {
13071     if (totals.testCases.total() == 0) {
13072         out << "No tests ran.";
13073     } else if (totals.testCases.failed == totals.testCases.total()) {
13074         Colour colour(Colour::ResultError);
13075         const std::string qualify_assertions_failed =
13076             totals.assertions.failed == totals.assertions.total() ?
13077             bothOrAll(totals.assertions.failed) : std::string();
13078         out <<
13079             "Failed " << bothOrAll(totals.testCases.failed)
13080             << pluralise(totals.testCases.failed, "test case") << ", "
13081             "failed " << qualify_assertions_failed <<
13082             pluralise(totals.assertions.failed, "assertion") << '.';
13083     } else if (totals.assertions.total() == 0) {
13084         out <<
13085             "Passed " << bothOrAll(totals.testCases.total())
13086             << pluralise(totals.testCases.total(), "test case")
13087             << " (no assertions).";
13088     } else if (totals.assertions.failed) {
13089         Colour colour(Colour::ResultError);
13090         out <<
13091             "Failed " << pluralise(totals.testCases.failed, "test case") << ", "
13092             "failed " << pluralise(totals.assertions.failed, "assertion") << '.';
13093     } else {
13094         Colour colour(Colour::ResultSuccess);
13095         out <<
13096             "Passed " << bothOrAll(totals.testCases.passed)
13097             << pluralise(totals.testCases.passed, "test case") <<
13098             " with " << pluralise(totals.assertions.passed, "assertion") << '.';
13099     }
13100 }
13101 
13102 // Implementation of CompactReporter formatting
13103 class AssertionPrinter {
13104 public:
13105     AssertionPrinter& operator= (AssertionPrinter const&) = delete;
13106     AssertionPrinter(AssertionPrinter const&) = delete;
AssertionPrinter(std::ostream & _stream,AssertionStats const & _stats,bool _printInfoMessages)13107     AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
13108         : stream(_stream)
13109         , result(_stats.assertionResult)
13110         , messages(_stats.infoMessages)
13111         , itMessage(_stats.infoMessages.begin())
13112         , printInfoMessages(_printInfoMessages) {}
13113 
print()13114     void print() {
13115         printSourceInfo();
13116 
13117         itMessage = messages.begin();
13118 
13119         switch (result.getResultType()) {
13120         case ResultWas::Ok:
13121             printResultType(Colour::ResultSuccess, passedString());
13122             printOriginalExpression();
13123             printReconstructedExpression();
13124             if (!result.hasExpression())
13125                 printRemainingMessages(Colour::None);
13126             else
13127                 printRemainingMessages();
13128             break;
13129         case ResultWas::ExpressionFailed:
13130             if (result.isOk())
13131                 printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok"));
13132             else
13133                 printResultType(Colour::Error, failedString());
13134             printOriginalExpression();
13135             printReconstructedExpression();
13136             printRemainingMessages();
13137             break;
13138         case ResultWas::ThrewException:
13139             printResultType(Colour::Error, failedString());
13140             printIssue("unexpected exception with message:");
13141             printMessage();
13142             printExpressionWas();
13143             printRemainingMessages();
13144             break;
13145         case ResultWas::FatalErrorCondition:
13146             printResultType(Colour::Error, failedString());
13147             printIssue("fatal error condition with message:");
13148             printMessage();
13149             printExpressionWas();
13150             printRemainingMessages();
13151             break;
13152         case ResultWas::DidntThrowException:
13153             printResultType(Colour::Error, failedString());
13154             printIssue("expected exception, got none");
13155             printExpressionWas();
13156             printRemainingMessages();
13157             break;
13158         case ResultWas::Info:
13159             printResultType(Colour::None, "info");
13160             printMessage();
13161             printRemainingMessages();
13162             break;
13163         case ResultWas::Warning:
13164             printResultType(Colour::None, "warning");
13165             printMessage();
13166             printRemainingMessages();
13167             break;
13168         case ResultWas::ExplicitFailure:
13169             printResultType(Colour::Error, failedString());
13170             printIssue("explicitly");
13171             printRemainingMessages(Colour::None);
13172             break;
13173             // These cases are here to prevent compiler warnings
13174         case ResultWas::Unknown:
13175         case ResultWas::FailureBit:
13176         case ResultWas::Exception:
13177             printResultType(Colour::Error, "** internal error **");
13178             break;
13179         }
13180     }
13181 
13182 private:
printSourceInfo() const13183     void printSourceInfo() const {
13184         Colour colourGuard(Colour::FileName);
13185         stream << result.getSourceInfo() << ':';
13186     }
13187 
printResultType(Colour::Code colour,std::string const & passOrFail) const13188     void printResultType(Colour::Code colour, std::string const& passOrFail) const {
13189         if (!passOrFail.empty()) {
13190             {
13191                 Colour colourGuard(colour);
13192                 stream << ' ' << passOrFail;
13193             }
13194             stream << ':';
13195         }
13196     }
13197 
printIssue(std::string const & issue) const13198     void printIssue(std::string const& issue) const {
13199         stream << ' ' << issue;
13200     }
13201 
printExpressionWas()13202     void printExpressionWas() {
13203         if (result.hasExpression()) {
13204             stream << ';';
13205             {
13206                 Colour colour(dimColour());
13207                 stream << " expression was:";
13208             }
13209             printOriginalExpression();
13210         }
13211     }
13212 
printOriginalExpression() const13213     void printOriginalExpression() const {
13214         if (result.hasExpression()) {
13215             stream << ' ' << result.getExpression();
13216         }
13217     }
13218 
printReconstructedExpression() const13219     void printReconstructedExpression() const {
13220         if (result.hasExpandedExpression()) {
13221             {
13222                 Colour colour(dimColour());
13223                 stream << " for: ";
13224             }
13225             stream << result.getExpandedExpression();
13226         }
13227     }
13228 
printMessage()13229     void printMessage() {
13230         if (itMessage != messages.end()) {
13231             stream << " '" << itMessage->message << '\'';
13232             ++itMessage;
13233         }
13234     }
13235 
printRemainingMessages(Colour::Code colour=dimColour ())13236     void printRemainingMessages(Colour::Code colour = dimColour()) {
13237         if (itMessage == messages.end())
13238             return;
13239 
13240         // using messages.end() directly yields (or auto) compilation error:
13241         std::vector<MessageInfo>::const_iterator itEnd = messages.end();
13242         const std::size_t N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
13243 
13244         {
13245             Colour colourGuard(colour);
13246             stream << " with " << pluralise(N, "message") << ':';
13247         }
13248 
13249         for (; itMessage != itEnd; ) {
13250             // If this assertion is a warning ignore any INFO messages
13251             if (printInfoMessages || itMessage->type != ResultWas::Info) {
13252                 stream << " '" << itMessage->message << '\'';
13253                 if (++itMessage != itEnd) {
13254                     Colour colourGuard(dimColour());
13255                     stream << " and";
13256                 }
13257             }
13258         }
13259     }
13260 
13261 private:
13262     std::ostream& stream;
13263     AssertionResult const& result;
13264     std::vector<MessageInfo> messages;
13265     std::vector<MessageInfo>::const_iterator itMessage;
13266     bool printInfoMessages;
13267 };
13268 
13269 } // anon namespace
13270 
getDescription()13271         std::string CompactReporter::getDescription() {
13272             return "Reports test results on a single line, suitable for IDEs";
13273         }
13274 
getPreferences() const13275         ReporterPreferences CompactReporter::getPreferences() const {
13276             return m_reporterPrefs;
13277         }
13278 
noMatchingTestCases(std::string const & spec)13279         void CompactReporter::noMatchingTestCases( std::string const& spec ) {
13280             stream << "No test cases matched '" << spec << '\'' << std::endl;
13281         }
13282 
assertionStarting(AssertionInfo const &)13283         void CompactReporter::assertionStarting( AssertionInfo const& ) {}
13284 
assertionEnded(AssertionStats const & _assertionStats)13285         bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {
13286             AssertionResult const& result = _assertionStats.assertionResult;
13287 
13288             bool printInfoMessages = true;
13289 
13290             // Drop out if result was successful and we're not printing those
13291             if( !m_config->includeSuccessfulResults() && result.isOk() ) {
13292                 if( result.getResultType() != ResultWas::Warning )
13293                     return false;
13294                 printInfoMessages = false;
13295             }
13296 
13297             AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
13298             printer.print();
13299 
13300             stream << std::endl;
13301             return true;
13302         }
13303 
sectionEnded(SectionStats const & _sectionStats)13304         void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
13305             if (m_config->showDurations() == ShowDurations::Always) {
13306                 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
13307             }
13308         }
13309 
testRunEnded(TestRunStats const & _testRunStats)13310         void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) {
13311             printTotals( stream, _testRunStats.totals );
13312             stream << '\n' << std::endl;
13313             StreamingReporterBase::testRunEnded( _testRunStats );
13314         }
13315 
~CompactReporter()13316         CompactReporter::~CompactReporter() {}
13317 
13318     CATCH_REGISTER_REPORTER( "compact", CompactReporter )
13319 
13320 } // end namespace Catch
13321 // end catch_reporter_compact.cpp
13322 // start catch_reporter_console.cpp
13323 
13324 #include <cfloat>
13325 #include <cstdio>
13326 
13327 #if defined(_MSC_VER)
13328 #pragma warning(push)
13329 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
13330  // Note that 4062 (not all labels are handled
13331  // and default is missing) is enabled
13332 #endif
13333 
13334 namespace Catch {
13335 
13336 namespace {
13337 
13338 // Formatter impl for ConsoleReporter
13339 class ConsoleAssertionPrinter {
13340 public:
13341     ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete;
13342     ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete;
ConsoleAssertionPrinter(std::ostream & _stream,AssertionStats const & _stats,bool _printInfoMessages)13343     ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
13344         : stream(_stream),
13345         stats(_stats),
13346         result(_stats.assertionResult),
13347         colour(Colour::None),
13348         message(result.getMessage()),
13349         messages(_stats.infoMessages),
13350         printInfoMessages(_printInfoMessages) {
13351         switch (result.getResultType()) {
13352         case ResultWas::Ok:
13353             colour = Colour::Success;
13354             passOrFail = "PASSED";
13355             //if( result.hasMessage() )
13356             if (_stats.infoMessages.size() == 1)
13357                 messageLabel = "with message";
13358             if (_stats.infoMessages.size() > 1)
13359                 messageLabel = "with messages";
13360             break;
13361         case ResultWas::ExpressionFailed:
13362             if (result.isOk()) {
13363                 colour = Colour::Success;
13364                 passOrFail = "FAILED - but was ok";
13365             } else {
13366                 colour = Colour::Error;
13367                 passOrFail = "FAILED";
13368             }
13369             if (_stats.infoMessages.size() == 1)
13370                 messageLabel = "with message";
13371             if (_stats.infoMessages.size() > 1)
13372                 messageLabel = "with messages";
13373             break;
13374         case ResultWas::ThrewException:
13375             colour = Colour::Error;
13376             passOrFail = "FAILED";
13377             messageLabel = "due to unexpected exception with ";
13378             if (_stats.infoMessages.size() == 1)
13379                 messageLabel += "message";
13380             if (_stats.infoMessages.size() > 1)
13381                 messageLabel += "messages";
13382             break;
13383         case ResultWas::FatalErrorCondition:
13384             colour = Colour::Error;
13385             passOrFail = "FAILED";
13386             messageLabel = "due to a fatal error condition";
13387             break;
13388         case ResultWas::DidntThrowException:
13389             colour = Colour::Error;
13390             passOrFail = "FAILED";
13391             messageLabel = "because no exception was thrown where one was expected";
13392             break;
13393         case ResultWas::Info:
13394             messageLabel = "info";
13395             break;
13396         case ResultWas::Warning:
13397             messageLabel = "warning";
13398             break;
13399         case ResultWas::ExplicitFailure:
13400             passOrFail = "FAILED";
13401             colour = Colour::Error;
13402             if (_stats.infoMessages.size() == 1)
13403                 messageLabel = "explicitly with message";
13404             if (_stats.infoMessages.size() > 1)
13405                 messageLabel = "explicitly with messages";
13406             break;
13407             // These cases are here to prevent compiler warnings
13408         case ResultWas::Unknown:
13409         case ResultWas::FailureBit:
13410         case ResultWas::Exception:
13411             passOrFail = "** internal error **";
13412             colour = Colour::Error;
13413             break;
13414         }
13415     }
13416 
print() const13417     void print() const {
13418         printSourceInfo();
13419         if (stats.totals.assertions.total() > 0) {
13420             printResultType();
13421             printOriginalExpression();
13422             printReconstructedExpression();
13423         } else {
13424             stream << '\n';
13425         }
13426         printMessage();
13427     }
13428 
13429 private:
printResultType() const13430     void printResultType() const {
13431         if (!passOrFail.empty()) {
13432             Colour colourGuard(colour);
13433             stream << passOrFail << ":\n";
13434         }
13435     }
printOriginalExpression() const13436     void printOriginalExpression() const {
13437         if (result.hasExpression()) {
13438             Colour colourGuard(Colour::OriginalExpression);
13439             stream << "  ";
13440             stream << result.getExpressionInMacro();
13441             stream << '\n';
13442         }
13443     }
printReconstructedExpression() const13444     void printReconstructedExpression() const {
13445         if (result.hasExpandedExpression()) {
13446             stream << "with expansion:\n";
13447             Colour colourGuard(Colour::ReconstructedExpression);
13448             stream << Column(result.getExpandedExpression()).indent(2) << '\n';
13449         }
13450     }
printMessage() const13451     void printMessage() const {
13452         if (!messageLabel.empty())
13453             stream << messageLabel << ':' << '\n';
13454         for (auto const& msg : messages) {
13455             // If this assertion is a warning ignore any INFO messages
13456             if (printInfoMessages || msg.type != ResultWas::Info)
13457                 stream << Column(msg.message).indent(2) << '\n';
13458         }
13459     }
printSourceInfo() const13460     void printSourceInfo() const {
13461         Colour colourGuard(Colour::FileName);
13462         stream << result.getSourceInfo() << ": ";
13463     }
13464 
13465     std::ostream& stream;
13466     AssertionStats const& stats;
13467     AssertionResult const& result;
13468     Colour::Code colour;
13469     std::string passOrFail;
13470     std::string messageLabel;
13471     std::string message;
13472     std::vector<MessageInfo> messages;
13473     bool printInfoMessages;
13474 };
13475 
makeRatio(std::size_t number,std::size_t total)13476 std::size_t makeRatio(std::size_t number, std::size_t total) {
13477     std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
13478     return (ratio == 0 && number > 0) ? 1 : ratio;
13479 }
13480 
findMax(std::size_t & i,std::size_t & j,std::size_t & k)13481 std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {
13482     if (i > j && i > k)
13483         return i;
13484     else if (j > k)
13485         return j;
13486     else
13487         return k;
13488 }
13489 
13490 struct ColumnInfo {
13491     enum Justification { Left, Right };
13492     std::string name;
13493     int width;
13494     Justification justification;
13495 };
13496 struct ColumnBreak {};
13497 struct RowBreak {};
13498 
13499 class Duration {
13500     enum class Unit {
13501         Auto,
13502         Nanoseconds,
13503         Microseconds,
13504         Milliseconds,
13505         Seconds,
13506         Minutes
13507     };
13508     static const uint64_t s_nanosecondsInAMicrosecond = 1000;
13509     static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
13510     static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
13511     static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
13512 
13513     uint64_t m_inNanoseconds;
13514     Unit m_units;
13515 
13516 public:
Duration(uint64_t inNanoseconds,Unit units=Unit::Auto)13517     explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
13518         : m_inNanoseconds(inNanoseconds),
13519         m_units(units) {
13520         if (m_units == Unit::Auto) {
13521             if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
13522                 m_units = Unit::Nanoseconds;
13523             else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
13524                 m_units = Unit::Microseconds;
13525             else if (m_inNanoseconds < s_nanosecondsInASecond)
13526                 m_units = Unit::Milliseconds;
13527             else if (m_inNanoseconds < s_nanosecondsInAMinute)
13528                 m_units = Unit::Seconds;
13529             else
13530                 m_units = Unit::Minutes;
13531         }
13532 
13533     }
13534 
value() const13535     auto value() const -> double {
13536         switch (m_units) {
13537         case Unit::Microseconds:
13538             return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond);
13539         case Unit::Milliseconds:
13540             return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond);
13541         case Unit::Seconds:
13542             return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond);
13543         case Unit::Minutes:
13544             return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
13545         default:
13546             return static_cast<double>(m_inNanoseconds);
13547         }
13548     }
unitsAsString() const13549     auto unitsAsString() const -> std::string {
13550         switch (m_units) {
13551         case Unit::Nanoseconds:
13552             return "ns";
13553         case Unit::Microseconds:
13554             return "us";
13555         case Unit::Milliseconds:
13556             return "ms";
13557         case Unit::Seconds:
13558             return "s";
13559         case Unit::Minutes:
13560             return "m";
13561         default:
13562             return "** internal error **";
13563         }
13564 
13565     }
operator <<(std::ostream & os,Duration const & duration)13566     friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {
13567         return os << duration.value() << " " << duration.unitsAsString();
13568     }
13569 };
13570 } // end anon namespace
13571 
13572 class TablePrinter {
13573     std::ostream& m_os;
13574     std::vector<ColumnInfo> m_columnInfos;
13575     std::ostringstream m_oss;
13576     int m_currentColumn = -1;
13577     bool m_isOpen = false;
13578 
13579 public:
TablePrinter(std::ostream & os,std::vector<ColumnInfo> columnInfos)13580     TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
13581     :   m_os( os ),
13582         m_columnInfos( std::move( columnInfos ) ) {}
13583 
columnInfos() const13584     auto columnInfos() const -> std::vector<ColumnInfo> const& {
13585         return m_columnInfos;
13586     }
13587 
open()13588     void open() {
13589         if (!m_isOpen) {
13590             m_isOpen = true;
13591             *this << RowBreak();
13592             for (auto const& info : m_columnInfos)
13593                 *this << info.name << ColumnBreak();
13594             *this << RowBreak();
13595             m_os << Catch::getLineOfChars<'-'>() << "\n";
13596         }
13597     }
close()13598     void close() {
13599         if (m_isOpen) {
13600             *this << RowBreak();
13601             m_os << std::endl;
13602             m_isOpen = false;
13603         }
13604     }
13605 
13606     template<typename T>
operator <<(TablePrinter & tp,T const & value)13607     friend TablePrinter& operator << (TablePrinter& tp, T const& value) {
13608         tp.m_oss << value;
13609         return tp;
13610     }
13611 
operator <<(TablePrinter & tp,ColumnBreak)13612     friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) {
13613         auto colStr = tp.m_oss.str();
13614         // This takes account of utf8 encodings
13615         auto strSize = Catch::StringRef(colStr).numberOfCharacters();
13616         tp.m_oss.str("");
13617         tp.open();
13618         if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
13619             tp.m_currentColumn = -1;
13620             tp.m_os << "\n";
13621         }
13622         tp.m_currentColumn++;
13623 
13624         auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
13625         auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width))
13626             ? std::string(colInfo.width - (strSize + 2), ' ')
13627             : std::string();
13628         if (colInfo.justification == ColumnInfo::Left)
13629             tp.m_os << colStr << padding << " ";
13630         else
13631             tp.m_os << padding << colStr << " ";
13632         return tp;
13633     }
13634 
operator <<(TablePrinter & tp,RowBreak)13635     friend TablePrinter& operator << (TablePrinter& tp, RowBreak) {
13636         if (tp.m_currentColumn > 0) {
13637             tp.m_os << "\n";
13638             tp.m_currentColumn = -1;
13639         }
13640         return tp;
13641     }
13642 };
13643 
ConsoleReporter(ReporterConfig const & config)13644 ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
13645     : StreamingReporterBase(config),
13646     m_tablePrinter(new TablePrinter(config.stream(),
13647     {
13648         { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
13649         { "iters", 8, ColumnInfo::Right },
13650         { "elapsed ns", 14, ColumnInfo::Right },
13651         { "average", 14, ColumnInfo::Right }
13652     })) {}
13653 ConsoleReporter::~ConsoleReporter() = default;
13654 
getDescription()13655 std::string ConsoleReporter::getDescription() {
13656     return "Reports test results as plain lines of text";
13657 }
13658 
noMatchingTestCases(std::string const & spec)13659 void ConsoleReporter::noMatchingTestCases(std::string const& spec) {
13660     stream << "No test cases matched '" << spec << '\'' << std::endl;
13661 }
13662 
assertionStarting(AssertionInfo const &)13663 void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
13664 
assertionEnded(AssertionStats const & _assertionStats)13665 bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
13666     AssertionResult const& result = _assertionStats.assertionResult;
13667 
13668     bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
13669 
13670     // Drop out if result was successful but we're not printing them.
13671     if (!includeResults && result.getResultType() != ResultWas::Warning)
13672         return false;
13673 
13674     lazyPrint();
13675 
13676     ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
13677     printer.print();
13678     stream << std::endl;
13679     return true;
13680 }
13681 
sectionStarting(SectionInfo const & _sectionInfo)13682 void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) {
13683     m_headerPrinted = false;
13684     StreamingReporterBase::sectionStarting(_sectionInfo);
13685 }
sectionEnded(SectionStats const & _sectionStats)13686 void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
13687     m_tablePrinter->close();
13688     if (_sectionStats.missingAssertions) {
13689         lazyPrint();
13690         Colour colour(Colour::ResultError);
13691         if (m_sectionStack.size() > 1)
13692             stream << "\nNo assertions in section";
13693         else
13694             stream << "\nNo assertions in test case";
13695         stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
13696     }
13697     if (m_config->showDurations() == ShowDurations::Always) {
13698         stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
13699     }
13700     if (m_headerPrinted) {
13701         m_headerPrinted = false;
13702     }
13703     StreamingReporterBase::sectionEnded(_sectionStats);
13704 }
13705 
benchmarkStarting(BenchmarkInfo const & info)13706 void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
13707     lazyPrintWithoutClosingBenchmarkTable();
13708 
13709     auto nameCol = Column( info.name ).width( static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) );
13710 
13711     bool firstLine = true;
13712     for (auto line : nameCol) {
13713         if (!firstLine)
13714             (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
13715         else
13716             firstLine = false;
13717 
13718         (*m_tablePrinter) << line << ColumnBreak();
13719     }
13720 }
benchmarkEnded(BenchmarkStats const & stats)13721 void ConsoleReporter::benchmarkEnded(BenchmarkStats const& stats) {
13722     Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
13723     (*m_tablePrinter)
13724         << stats.iterations << ColumnBreak()
13725         << stats.elapsedTimeInNanoseconds << ColumnBreak()
13726         << average << ColumnBreak();
13727 }
13728 
testCaseEnded(TestCaseStats const & _testCaseStats)13729 void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
13730     m_tablePrinter->close();
13731     StreamingReporterBase::testCaseEnded(_testCaseStats);
13732     m_headerPrinted = false;
13733 }
testGroupEnded(TestGroupStats const & _testGroupStats)13734 void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) {
13735     if (currentGroupInfo.used) {
13736         printSummaryDivider();
13737         stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
13738         printTotals(_testGroupStats.totals);
13739         stream << '\n' << std::endl;
13740     }
13741     StreamingReporterBase::testGroupEnded(_testGroupStats);
13742 }
testRunEnded(TestRunStats const & _testRunStats)13743 void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
13744     printTotalsDivider(_testRunStats.totals);
13745     printTotals(_testRunStats.totals);
13746     stream << std::endl;
13747     StreamingReporterBase::testRunEnded(_testRunStats);
13748 }
13749 
lazyPrint()13750 void ConsoleReporter::lazyPrint() {
13751 
13752     m_tablePrinter->close();
13753     lazyPrintWithoutClosingBenchmarkTable();
13754 }
13755 
lazyPrintWithoutClosingBenchmarkTable()13756 void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
13757 
13758     if (!currentTestRunInfo.used)
13759         lazyPrintRunInfo();
13760     if (!currentGroupInfo.used)
13761         lazyPrintGroupInfo();
13762 
13763     if (!m_headerPrinted) {
13764         printTestCaseAndSectionHeader();
13765         m_headerPrinted = true;
13766     }
13767 }
lazyPrintRunInfo()13768 void ConsoleReporter::lazyPrintRunInfo() {
13769     stream << '\n' << getLineOfChars<'~'>() << '\n';
13770     Colour colour(Colour::SecondaryText);
13771     stream << currentTestRunInfo->name
13772         << " is a Catch v" << libraryVersion() << " host application.\n"
13773         << "Run with -? for options\n\n";
13774 
13775     if (m_config->rngSeed() != 0)
13776         stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
13777 
13778     currentTestRunInfo.used = true;
13779 }
lazyPrintGroupInfo()13780 void ConsoleReporter::lazyPrintGroupInfo() {
13781     if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
13782         printClosedHeader("Group: " + currentGroupInfo->name);
13783         currentGroupInfo.used = true;
13784     }
13785 }
printTestCaseAndSectionHeader()13786 void ConsoleReporter::printTestCaseAndSectionHeader() {
13787     assert(!m_sectionStack.empty());
13788     printOpenHeader(currentTestCaseInfo->name);
13789 
13790     if (m_sectionStack.size() > 1) {
13791         Colour colourGuard(Colour::Headers);
13792 
13793         auto
13794             it = m_sectionStack.begin() + 1, // Skip first section (test case)
13795             itEnd = m_sectionStack.end();
13796         for (; it != itEnd; ++it)
13797             printHeaderString(it->name, 2);
13798     }
13799 
13800     SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
13801 
13802     if (!lineInfo.empty()) {
13803         stream << getLineOfChars<'-'>() << '\n';
13804         Colour colourGuard(Colour::FileName);
13805         stream << lineInfo << '\n';
13806     }
13807     stream << getLineOfChars<'.'>() << '\n' << std::endl;
13808 }
13809 
printClosedHeader(std::string const & _name)13810 void ConsoleReporter::printClosedHeader(std::string const& _name) {
13811     printOpenHeader(_name);
13812     stream << getLineOfChars<'.'>() << '\n';
13813 }
printOpenHeader(std::string const & _name)13814 void ConsoleReporter::printOpenHeader(std::string const& _name) {
13815     stream << getLineOfChars<'-'>() << '\n';
13816     {
13817         Colour colourGuard(Colour::Headers);
13818         printHeaderString(_name);
13819     }
13820 }
13821 
13822 // if string has a : in first line will set indent to follow it on
13823 // subsequent lines
printHeaderString(std::string const & _string,std::size_t indent)13824 void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) {
13825     std::size_t i = _string.find(": ");
13826     if (i != std::string::npos)
13827         i += 2;
13828     else
13829         i = 0;
13830     stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n';
13831 }
13832 
13833 struct SummaryColumn {
13834 
SummaryColumnCatch::SummaryColumn13835     SummaryColumn( std::string _label, Colour::Code _colour )
13836     :   label( std::move( _label ) ),
13837         colour( _colour ) {}
addRowCatch::SummaryColumn13838     SummaryColumn addRow( std::size_t count ) {
13839         ReusableStringStream rss;
13840         rss << count;
13841         std::string row = rss.str();
13842         for (auto& oldRow : rows) {
13843             while (oldRow.size() < row.size())
13844                 oldRow = ' ' + oldRow;
13845             while (oldRow.size() > row.size())
13846                 row = ' ' + row;
13847         }
13848         rows.push_back(row);
13849         return *this;
13850     }
13851 
13852     std::string label;
13853     Colour::Code colour;
13854     std::vector<std::string> rows;
13855 
13856 };
13857 
printTotals(Totals const & totals)13858 void ConsoleReporter::printTotals( Totals const& totals ) {
13859     if (totals.testCases.total() == 0) {
13860         stream << Colour(Colour::Warning) << "No tests ran\n";
13861     } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {
13862         stream << Colour(Colour::ResultSuccess) << "All tests passed";
13863         stream << " ("
13864             << pluralise(totals.assertions.passed, "assertion") << " in "
13865             << pluralise(totals.testCases.passed, "test case") << ')'
13866             << '\n';
13867     } else {
13868 
13869         std::vector<SummaryColumn> columns;
13870         columns.push_back(SummaryColumn("", Colour::None)
13871                           .addRow(totals.testCases.total())
13872                           .addRow(totals.assertions.total()));
13873         columns.push_back(SummaryColumn("passed", Colour::Success)
13874                           .addRow(totals.testCases.passed)
13875                           .addRow(totals.assertions.passed));
13876         columns.push_back(SummaryColumn("failed", Colour::ResultError)
13877                           .addRow(totals.testCases.failed)
13878                           .addRow(totals.assertions.failed));
13879         columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure)
13880                           .addRow(totals.testCases.failedButOk)
13881                           .addRow(totals.assertions.failedButOk));
13882 
13883         printSummaryRow("test cases", columns, 0);
13884         printSummaryRow("assertions", columns, 1);
13885     }
13886 }
printSummaryRow(std::string const & label,std::vector<SummaryColumn> const & cols,std::size_t row)13887 void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) {
13888     for (auto col : cols) {
13889         std::string value = col.rows[row];
13890         if (col.label.empty()) {
13891             stream << label << ": ";
13892             if (value != "0")
13893                 stream << value;
13894             else
13895                 stream << Colour(Colour::Warning) << "- none -";
13896         } else if (value != "0") {
13897             stream << Colour(Colour::LightGrey) << " | ";
13898             stream << Colour(col.colour)
13899                 << value << ' ' << col.label;
13900         }
13901     }
13902     stream << '\n';
13903 }
13904 
printTotalsDivider(Totals const & totals)13905 void ConsoleReporter::printTotalsDivider(Totals const& totals) {
13906     if (totals.testCases.total() > 0) {
13907         std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
13908         std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
13909         std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
13910         while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
13911             findMax(failedRatio, failedButOkRatio, passedRatio)++;
13912         while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
13913             findMax(failedRatio, failedButOkRatio, passedRatio)--;
13914 
13915         stream << Colour(Colour::Error) << std::string(failedRatio, '=');
13916         stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '=');
13917         if (totals.testCases.allPassed())
13918             stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '=');
13919         else
13920             stream << Colour(Colour::Success) << std::string(passedRatio, '=');
13921     } else {
13922         stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '=');
13923     }
13924     stream << '\n';
13925 }
printSummaryDivider()13926 void ConsoleReporter::printSummaryDivider() {
13927     stream << getLineOfChars<'-'>() << '\n';
13928 }
13929 
13930 CATCH_REGISTER_REPORTER("console", ConsoleReporter)
13931 
13932 } // end namespace Catch
13933 
13934 #if defined(_MSC_VER)
13935 #pragma warning(pop)
13936 #endif
13937 // end catch_reporter_console.cpp
13938 // start catch_reporter_junit.cpp
13939 
13940 #include <cassert>
13941 #include <sstream>
13942 #include <ctime>
13943 #include <algorithm>
13944 
13945 namespace Catch {
13946 
13947     namespace {
getCurrentTimestamp()13948         std::string getCurrentTimestamp() {
13949             // Beware, this is not reentrant because of backward compatibility issues
13950             // Also, UTC only, again because of backward compatibility (%z is C++11)
13951             time_t rawtime;
13952             std::time(&rawtime);
13953             auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
13954 
13955 #ifdef _MSC_VER
13956             std::tm timeInfo = {};
13957             gmtime_s(&timeInfo, &rawtime);
13958 #else
13959             std::tm* timeInfo;
13960             timeInfo = std::gmtime(&rawtime);
13961 #endif
13962 
13963             char timeStamp[timeStampSize];
13964             const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
13965 
13966 #ifdef _MSC_VER
13967             std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
13968 #else
13969             std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
13970 #endif
13971             return std::string(timeStamp);
13972         }
13973 
fileNameTag(const std::vector<std::string> & tags)13974         std::string fileNameTag(const std::vector<std::string> &tags) {
13975             auto it = std::find_if(begin(tags),
13976                                    end(tags),
13977                                    [] (std::string const& tag) {return tag.front() == '#'; });
13978             if (it != tags.end())
13979                 return it->substr(1);
13980             return std::string();
13981         }
13982     } // anonymous namespace
13983 
JunitReporter(ReporterConfig const & _config)13984     JunitReporter::JunitReporter( ReporterConfig const& _config )
13985         :   CumulativeReporterBase( _config ),
13986             xml( _config.stream() )
13987         {
13988             m_reporterPrefs.shouldRedirectStdOut = true;
13989             m_reporterPrefs.shouldReportAllAssertions = true;
13990         }
13991 
~JunitReporter()13992     JunitReporter::~JunitReporter() {}
13993 
getDescription()13994     std::string JunitReporter::getDescription() {
13995         return "Reports test results in an XML format that looks like Ant's junitreport target";
13996     }
13997 
noMatchingTestCases(std::string const &)13998     void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {}
13999 
testRunStarting(TestRunInfo const & runInfo)14000     void JunitReporter::testRunStarting( TestRunInfo const& runInfo )  {
14001         CumulativeReporterBase::testRunStarting( runInfo );
14002         xml.startElement( "testsuites" );
14003         if( m_config->rngSeed() != 0 ) {
14004             xml.startElement( "properties" );
14005             xml.scopedElement( "property" )
14006                 .writeAttribute( "name", "random-seed" )
14007                 .writeAttribute( "value", m_config->rngSeed() );
14008             xml.endElement();
14009         }
14010     }
14011 
testGroupStarting(GroupInfo const & groupInfo)14012     void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
14013         suiteTimer.start();
14014         stdOutForSuite.clear();
14015         stdErrForSuite.clear();
14016         unexpectedExceptions = 0;
14017         CumulativeReporterBase::testGroupStarting( groupInfo );
14018     }
14019 
testCaseStarting(TestCaseInfo const & testCaseInfo)14020     void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) {
14021         m_okToFail = testCaseInfo.okToFail();
14022     }
14023 
assertionEnded(AssertionStats const & assertionStats)14024     bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) {
14025         if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
14026             unexpectedExceptions++;
14027         return CumulativeReporterBase::assertionEnded( assertionStats );
14028     }
14029 
testCaseEnded(TestCaseStats const & testCaseStats)14030     void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
14031         stdOutForSuite += testCaseStats.stdOut;
14032         stdErrForSuite += testCaseStats.stdErr;
14033         CumulativeReporterBase::testCaseEnded( testCaseStats );
14034     }
14035 
testGroupEnded(TestGroupStats const & testGroupStats)14036     void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
14037         double suiteTime = suiteTimer.getElapsedSeconds();
14038         CumulativeReporterBase::testGroupEnded( testGroupStats );
14039         writeGroup( *m_testGroups.back(), suiteTime );
14040     }
14041 
testRunEndedCumulative()14042     void JunitReporter::testRunEndedCumulative() {
14043         xml.endElement();
14044     }
14045 
writeGroup(TestGroupNode const & groupNode,double suiteTime)14046     void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
14047         XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
14048         TestGroupStats const& stats = groupNode.value;
14049         xml.writeAttribute( "name", stats.groupInfo.name );
14050         xml.writeAttribute( "errors", unexpectedExceptions );
14051         xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
14052         xml.writeAttribute( "tests", stats.totals.assertions.total() );
14053         xml.writeAttribute( "hostname", "tbd" ); // !TBD
14054         if( m_config->showDurations() == ShowDurations::Never )
14055             xml.writeAttribute( "time", "" );
14056         else
14057             xml.writeAttribute( "time", suiteTime );
14058         xml.writeAttribute( "timestamp", getCurrentTimestamp() );
14059 
14060         // Write test cases
14061         for( auto const& child : groupNode.children )
14062             writeTestCase( *child );
14063 
14064         xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), false );
14065         xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), false );
14066     }
14067 
writeTestCase(TestCaseNode const & testCaseNode)14068     void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
14069         TestCaseStats const& stats = testCaseNode.value;
14070 
14071         // All test cases have exactly one section - which represents the
14072         // test case itself. That section may have 0-n nested sections
14073         assert( testCaseNode.children.size() == 1 );
14074         SectionNode const& rootSection = *testCaseNode.children.front();
14075 
14076         std::string className = stats.testInfo.className;
14077 
14078         if( className.empty() ) {
14079             className = fileNameTag(stats.testInfo.tags);
14080             if ( className.empty() )
14081                 className = "global";
14082         }
14083 
14084         if ( !m_config->name().empty() )
14085             className = m_config->name() + "." + className;
14086 
14087         writeSection( className, "", rootSection );
14088     }
14089 
writeSection(std::string const & className,std::string const & rootName,SectionNode const & sectionNode)14090     void JunitReporter::writeSection(  std::string const& className,
14091                         std::string const& rootName,
14092                         SectionNode const& sectionNode ) {
14093         std::string name = trim( sectionNode.stats.sectionInfo.name );
14094         if( !rootName.empty() )
14095             name = rootName + '/' + name;
14096 
14097         if( !sectionNode.assertions.empty() ||
14098             !sectionNode.stdOut.empty() ||
14099             !sectionNode.stdErr.empty() ) {
14100             XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
14101             if( className.empty() ) {
14102                 xml.writeAttribute( "classname", name );
14103                 xml.writeAttribute( "name", "root" );
14104             }
14105             else {
14106                 xml.writeAttribute( "classname", className );
14107                 xml.writeAttribute( "name", name );
14108             }
14109             xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) );
14110 
14111             writeAssertions( sectionNode );
14112 
14113             if( !sectionNode.stdOut.empty() )
14114                 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
14115             if( !sectionNode.stdErr.empty() )
14116                 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
14117         }
14118         for( auto const& childNode : sectionNode.childSections )
14119             if( className.empty() )
14120                 writeSection( name, "", *childNode );
14121             else
14122                 writeSection( className, name, *childNode );
14123     }
14124 
writeAssertions(SectionNode const & sectionNode)14125     void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
14126         for( auto const& assertion : sectionNode.assertions )
14127             writeAssertion( assertion );
14128     }
14129 
writeAssertion(AssertionStats const & stats)14130     void JunitReporter::writeAssertion( AssertionStats const& stats ) {
14131         AssertionResult const& result = stats.assertionResult;
14132         if( !result.isOk() ) {
14133             std::string elementName;
14134             switch( result.getResultType() ) {
14135                 case ResultWas::ThrewException:
14136                 case ResultWas::FatalErrorCondition:
14137                     elementName = "error";
14138                     break;
14139                 case ResultWas::ExplicitFailure:
14140                     elementName = "failure";
14141                     break;
14142                 case ResultWas::ExpressionFailed:
14143                     elementName = "failure";
14144                     break;
14145                 case ResultWas::DidntThrowException:
14146                     elementName = "failure";
14147                     break;
14148 
14149                 // We should never see these here:
14150                 case ResultWas::Info:
14151                 case ResultWas::Warning:
14152                 case ResultWas::Ok:
14153                 case ResultWas::Unknown:
14154                 case ResultWas::FailureBit:
14155                 case ResultWas::Exception:
14156                     elementName = "internalError";
14157                     break;
14158             }
14159 
14160             XmlWriter::ScopedElement e = xml.scopedElement( elementName );
14161 
14162             xml.writeAttribute( "message", result.getExpandedExpression() );
14163             xml.writeAttribute( "type", result.getTestMacroName() );
14164 
14165             ReusableStringStream rss;
14166             if( !result.getMessage().empty() )
14167                 rss << result.getMessage() << '\n';
14168             for( auto const& msg : stats.infoMessages )
14169                 if( msg.type == ResultWas::Info )
14170                     rss << msg.message << '\n';
14171 
14172             rss << "at " << result.getSourceInfo();
14173             xml.writeText( rss.str(), false );
14174         }
14175     }
14176 
14177     CATCH_REGISTER_REPORTER( "junit", JunitReporter )
14178 
14179 } // end namespace Catch
14180 // end catch_reporter_junit.cpp
14181 // start catch_reporter_listening.cpp
14182 
14183 #include <cassert>
14184 
14185 namespace Catch {
14186 
ListeningReporter()14187     ListeningReporter::ListeningReporter() {
14188         // We will assume that listeners will always want all assertions
14189         m_preferences.shouldReportAllAssertions = true;
14190     }
14191 
addListener(IStreamingReporterPtr && listener)14192     void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
14193         m_listeners.push_back( std::move( listener ) );
14194     }
14195 
addReporter(IStreamingReporterPtr && reporter)14196     void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
14197         assert(!m_reporter && "Listening reporter can wrap only 1 real reporter");
14198         m_reporter = std::move( reporter );
14199         m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;
14200     }
14201 
getPreferences() const14202     ReporterPreferences ListeningReporter::getPreferences() const {
14203         return m_preferences;
14204     }
14205 
getSupportedVerbosities()14206     std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
14207         return std::set<Verbosity>{ };
14208     }
14209 
noMatchingTestCases(std::string const & spec)14210     void ListeningReporter::noMatchingTestCases( std::string const& spec ) {
14211         for ( auto const& listener : m_listeners ) {
14212             listener->noMatchingTestCases( spec );
14213         }
14214         m_reporter->noMatchingTestCases( spec );
14215     }
14216 
benchmarkStarting(BenchmarkInfo const & benchmarkInfo)14217     void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
14218         for ( auto const& listener : m_listeners ) {
14219             listener->benchmarkStarting( benchmarkInfo );
14220         }
14221         m_reporter->benchmarkStarting( benchmarkInfo );
14222     }
benchmarkEnded(BenchmarkStats const & benchmarkStats)14223     void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
14224         for ( auto const& listener : m_listeners ) {
14225             listener->benchmarkEnded( benchmarkStats );
14226         }
14227         m_reporter->benchmarkEnded( benchmarkStats );
14228     }
14229 
testRunStarting(TestRunInfo const & testRunInfo)14230     void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
14231         for ( auto const& listener : m_listeners ) {
14232             listener->testRunStarting( testRunInfo );
14233         }
14234         m_reporter->testRunStarting( testRunInfo );
14235     }
14236 
testGroupStarting(GroupInfo const & groupInfo)14237     void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) {
14238         for ( auto const& listener : m_listeners ) {
14239             listener->testGroupStarting( groupInfo );
14240         }
14241         m_reporter->testGroupStarting( groupInfo );
14242     }
14243 
testCaseStarting(TestCaseInfo const & testInfo)14244     void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
14245         for ( auto const& listener : m_listeners ) {
14246             listener->testCaseStarting( testInfo );
14247         }
14248         m_reporter->testCaseStarting( testInfo );
14249     }
14250 
sectionStarting(SectionInfo const & sectionInfo)14251     void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) {
14252         for ( auto const& listener : m_listeners ) {
14253             listener->sectionStarting( sectionInfo );
14254         }
14255         m_reporter->sectionStarting( sectionInfo );
14256     }
14257 
assertionStarting(AssertionInfo const & assertionInfo)14258     void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) {
14259         for ( auto const& listener : m_listeners ) {
14260             listener->assertionStarting( assertionInfo );
14261         }
14262         m_reporter->assertionStarting( assertionInfo );
14263     }
14264 
14265     // The return value indicates if the messages buffer should be cleared:
assertionEnded(AssertionStats const & assertionStats)14266     bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) {
14267         for( auto const& listener : m_listeners ) {
14268             static_cast<void>( listener->assertionEnded( assertionStats ) );
14269         }
14270         return m_reporter->assertionEnded( assertionStats );
14271     }
14272 
sectionEnded(SectionStats const & sectionStats)14273     void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) {
14274         for ( auto const& listener : m_listeners ) {
14275             listener->sectionEnded( sectionStats );
14276         }
14277         m_reporter->sectionEnded( sectionStats );
14278     }
14279 
testCaseEnded(TestCaseStats const & testCaseStats)14280     void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
14281         for ( auto const& listener : m_listeners ) {
14282             listener->testCaseEnded( testCaseStats );
14283         }
14284         m_reporter->testCaseEnded( testCaseStats );
14285     }
14286 
testGroupEnded(TestGroupStats const & testGroupStats)14287     void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
14288         for ( auto const& listener : m_listeners ) {
14289             listener->testGroupEnded( testGroupStats );
14290         }
14291         m_reporter->testGroupEnded( testGroupStats );
14292     }
14293 
testRunEnded(TestRunStats const & testRunStats)14294     void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) {
14295         for ( auto const& listener : m_listeners ) {
14296             listener->testRunEnded( testRunStats );
14297         }
14298         m_reporter->testRunEnded( testRunStats );
14299     }
14300 
skipTest(TestCaseInfo const & testInfo)14301     void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) {
14302         for ( auto const& listener : m_listeners ) {
14303             listener->skipTest( testInfo );
14304         }
14305         m_reporter->skipTest( testInfo );
14306     }
14307 
isMulti() const14308     bool ListeningReporter::isMulti() const {
14309         return true;
14310     }
14311 
14312 } // end namespace Catch
14313 // end catch_reporter_listening.cpp
14314 // start catch_reporter_xml.cpp
14315 
14316 #if defined(_MSC_VER)
14317 #pragma warning(push)
14318 #pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
14319                               // Note that 4062 (not all labels are handled
14320                               // and default is missing) is enabled
14321 #endif
14322 
14323 namespace Catch {
XmlReporter(ReporterConfig const & _config)14324     XmlReporter::XmlReporter( ReporterConfig const& _config )
14325     :   StreamingReporterBase( _config ),
14326         m_xml(_config.stream())
14327     {
14328         m_reporterPrefs.shouldRedirectStdOut = true;
14329         m_reporterPrefs.shouldReportAllAssertions = true;
14330     }
14331 
14332     XmlReporter::~XmlReporter() = default;
14333 
getDescription()14334     std::string XmlReporter::getDescription() {
14335         return "Reports test results as an XML document";
14336     }
14337 
getStylesheetRef() const14338     std::string XmlReporter::getStylesheetRef() const {
14339         return std::string();
14340     }
14341 
writeSourceInfo(SourceLineInfo const & sourceInfo)14342     void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) {
14343         m_xml
14344             .writeAttribute( "filename", sourceInfo.file )
14345             .writeAttribute( "line", sourceInfo.line );
14346     }
14347 
noMatchingTestCases(std::string const & s)14348     void XmlReporter::noMatchingTestCases( std::string const& s ) {
14349         StreamingReporterBase::noMatchingTestCases( s );
14350     }
14351 
testRunStarting(TestRunInfo const & testInfo)14352     void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) {
14353         StreamingReporterBase::testRunStarting( testInfo );
14354         std::string stylesheetRef = getStylesheetRef();
14355         if( !stylesheetRef.empty() )
14356             m_xml.writeStylesheetRef( stylesheetRef );
14357         m_xml.startElement( "Catch" );
14358         if( !m_config->name().empty() )
14359             m_xml.writeAttribute( "name", m_config->name() );
14360         if( m_config->rngSeed() != 0 )
14361             m_xml.scopedElement( "Randomness" )
14362                 .writeAttribute( "seed", m_config->rngSeed() );
14363     }
14364 
testGroupStarting(GroupInfo const & groupInfo)14365     void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) {
14366         StreamingReporterBase::testGroupStarting( groupInfo );
14367         m_xml.startElement( "Group" )
14368             .writeAttribute( "name", groupInfo.name );
14369     }
14370 
testCaseStarting(TestCaseInfo const & testInfo)14371     void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
14372         StreamingReporterBase::testCaseStarting(testInfo);
14373         m_xml.startElement( "TestCase" )
14374             .writeAttribute( "name", trim( testInfo.name ) )
14375             .writeAttribute( "description", testInfo.description )
14376             .writeAttribute( "tags", testInfo.tagsAsString() );
14377 
14378         writeSourceInfo( testInfo.lineInfo );
14379 
14380         if ( m_config->showDurations() == ShowDurations::Always )
14381             m_testCaseTimer.start();
14382         m_xml.ensureTagClosed();
14383     }
14384 
sectionStarting(SectionInfo const & sectionInfo)14385     void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) {
14386         StreamingReporterBase::sectionStarting( sectionInfo );
14387         if( m_sectionDepth++ > 0 ) {
14388             m_xml.startElement( "Section" )
14389                 .writeAttribute( "name", trim( sectionInfo.name ) );
14390             writeSourceInfo( sectionInfo.lineInfo );
14391             m_xml.ensureTagClosed();
14392         }
14393     }
14394 
assertionStarting(AssertionInfo const &)14395     void XmlReporter::assertionStarting( AssertionInfo const& ) { }
14396 
assertionEnded(AssertionStats const & assertionStats)14397     bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {
14398 
14399         AssertionResult const& result = assertionStats.assertionResult;
14400 
14401         bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
14402 
14403         if( includeResults || result.getResultType() == ResultWas::Warning ) {
14404             // Print any info messages in <Info> tags.
14405             for( auto const& msg : assertionStats.infoMessages ) {
14406                 if( msg.type == ResultWas::Info && includeResults ) {
14407                     m_xml.scopedElement( "Info" )
14408                             .writeText( msg.message );
14409                 } else if ( msg.type == ResultWas::Warning ) {
14410                     m_xml.scopedElement( "Warning" )
14411                             .writeText( msg.message );
14412                 }
14413             }
14414         }
14415 
14416         // Drop out if result was successful but we're not printing them.
14417         if( !includeResults && result.getResultType() != ResultWas::Warning )
14418             return true;
14419 
14420         // Print the expression if there is one.
14421         if( result.hasExpression() ) {
14422             m_xml.startElement( "Expression" )
14423                 .writeAttribute( "success", result.succeeded() )
14424                 .writeAttribute( "type", result.getTestMacroName() );
14425 
14426             writeSourceInfo( result.getSourceInfo() );
14427 
14428             m_xml.scopedElement( "Original" )
14429                 .writeText( result.getExpression() );
14430             m_xml.scopedElement( "Expanded" )
14431                 .writeText( result.getExpandedExpression() );
14432         }
14433 
14434         // And... Print a result applicable to each result type.
14435         switch( result.getResultType() ) {
14436             case ResultWas::ThrewException:
14437                 m_xml.startElement( "Exception" );
14438                 writeSourceInfo( result.getSourceInfo() );
14439                 m_xml.writeText( result.getMessage() );
14440                 m_xml.endElement();
14441                 break;
14442             case ResultWas::FatalErrorCondition:
14443                 m_xml.startElement( "FatalErrorCondition" );
14444                 writeSourceInfo( result.getSourceInfo() );
14445                 m_xml.writeText( result.getMessage() );
14446                 m_xml.endElement();
14447                 break;
14448             case ResultWas::Info:
14449                 m_xml.scopedElement( "Info" )
14450                     .writeText( result.getMessage() );
14451                 break;
14452             case ResultWas::Warning:
14453                 // Warning will already have been written
14454                 break;
14455             case ResultWas::ExplicitFailure:
14456                 m_xml.startElement( "Failure" );
14457                 writeSourceInfo( result.getSourceInfo() );
14458                 m_xml.writeText( result.getMessage() );
14459                 m_xml.endElement();
14460                 break;
14461             default:
14462                 break;
14463         }
14464 
14465         if( result.hasExpression() )
14466             m_xml.endElement();
14467 
14468         return true;
14469     }
14470 
sectionEnded(SectionStats const & sectionStats)14471     void XmlReporter::sectionEnded( SectionStats const& sectionStats ) {
14472         StreamingReporterBase::sectionEnded( sectionStats );
14473         if( --m_sectionDepth > 0 ) {
14474             XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
14475             e.writeAttribute( "successes", sectionStats.assertions.passed );
14476             e.writeAttribute( "failures", sectionStats.assertions.failed );
14477             e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
14478 
14479             if ( m_config->showDurations() == ShowDurations::Always )
14480                 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
14481 
14482             m_xml.endElement();
14483         }
14484     }
14485 
testCaseEnded(TestCaseStats const & testCaseStats)14486     void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
14487         StreamingReporterBase::testCaseEnded( testCaseStats );
14488         XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
14489         e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
14490 
14491         if ( m_config->showDurations() == ShowDurations::Always )
14492             e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
14493 
14494         if( !testCaseStats.stdOut.empty() )
14495             m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
14496         if( !testCaseStats.stdErr.empty() )
14497             m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
14498 
14499         m_xml.endElement();
14500     }
14501 
testGroupEnded(TestGroupStats const & testGroupStats)14502     void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
14503         StreamingReporterBase::testGroupEnded( testGroupStats );
14504         // TODO: Check testGroupStats.aborting and act accordingly.
14505         m_xml.scopedElement( "OverallResults" )
14506             .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
14507             .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
14508             .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
14509         m_xml.endElement();
14510     }
14511 
testRunEnded(TestRunStats const & testRunStats)14512     void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) {
14513         StreamingReporterBase::testRunEnded( testRunStats );
14514         m_xml.scopedElement( "OverallResults" )
14515             .writeAttribute( "successes", testRunStats.totals.assertions.passed )
14516             .writeAttribute( "failures", testRunStats.totals.assertions.failed )
14517             .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
14518         m_xml.endElement();
14519     }
14520 
14521     CATCH_REGISTER_REPORTER( "xml", XmlReporter )
14522 
14523 } // end namespace Catch
14524 
14525 #if defined(_MSC_VER)
14526 #pragma warning(pop)
14527 #endif
14528 // end catch_reporter_xml.cpp
14529 
14530 namespace Catch {
14531     LeakDetector leakDetector;
14532 }
14533 
14534 #ifdef __clang__
14535 #pragma clang diagnostic pop
14536 #endif
14537 
14538 // end catch_impl.hpp
14539 #endif
14540 
14541 #ifdef CATCH_CONFIG_MAIN
14542 // start catch_default_main.hpp
14543 
14544 #ifndef __OBJC__
14545 
14546 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
14547 // Standard C/C++ Win32 Unicode wmain entry point
wmain(int argc,wchar_t * argv[],wchar_t * [])14548 extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
14549 #else
14550 // Standard C/C++ main entry point
14551 int main (int argc, char * argv[]) {
14552 #endif
14553 
14554     return Catch::Session().run( argc, argv );
14555 }
14556 
14557 #else // __OBJC__
14558 
14559 // Objective-C entry point
14560 int main (int argc, char * const argv[]) {
14561 #if !CATCH_ARC_ENABLED
14562     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
14563 #endif
14564 
14565     Catch::registerTestMethods();
14566     int result = Catch::Session().run( argc, (char**)argv );
14567 
14568 #if !CATCH_ARC_ENABLED
14569     [pool drain];
14570 #endif
14571 
14572     return result;
14573 }
14574 
14575 #endif // __OBJC__
14576 
14577 // end catch_default_main.hpp
14578 #endif
14579 
14580 #if !defined(CATCH_CONFIG_IMPL_ONLY)
14581 
14582 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
14583 #  undef CLARA_CONFIG_MAIN
14584 #endif
14585 
14586 #if !defined(CATCH_CONFIG_DISABLE)
14587 //////
14588 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
14589 #ifdef CATCH_CONFIG_PREFIX_ALL
14590 
14591 #define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14592 #define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
14593 
14594 #define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14595 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
14596 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
14597 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14598 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
14599 #endif// CATCH_CONFIG_DISABLE_MATCHERS
14600 #define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14601 
14602 #define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14603 #define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
14604 #define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14605 #define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14606 #define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
14607 
14608 #define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14609 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
14610 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
14611 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14612 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
14613 #endif // CATCH_CONFIG_DISABLE_MATCHERS
14614 #define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14615 
14616 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14617 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
14618 
14619 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
14620 #endif // CATCH_CONFIG_DISABLE_MATCHERS
14621 
14622 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
14623 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
14624 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )
14625 
14626 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
14627 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
14628 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
14629 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
14630 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
14631 #define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
14632 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
14633 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14634 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14635 
14636 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
14637 
14638 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
14639 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
14640 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14641 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
14642 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
14643 #else
14644 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
14645 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
14646 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
14647 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
14648 #endif
14649 
14650 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
14651 #define CATCH_STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__ ,      #__VA_ARGS__ );     CATCH_SUCCEED( #__VA_ARGS__ )
14652 #define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
14653 #else
14654 #define CATCH_STATIC_REQUIRE( ... )       CATCH_REQUIRE( __VA_ARGS__ )
14655 #define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
14656 #endif
14657 
14658 // "BDD-style" convenience wrappers
14659 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
14660 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
14661 #define CATCH_GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
14662 #define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
14663 #define CATCH_WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
14664 #define CATCH_AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
14665 #define CATCH_THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
14666 #define CATCH_AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
14667 
14668 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
14669 #else
14670 
14671 #define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__  )
14672 #define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
14673 
14674 #define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14675 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
14676 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
14677 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14678 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
14679 #endif // CATCH_CONFIG_DISABLE_MATCHERS
14680 #define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14681 
14682 #define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14683 #define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
14684 #define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14685 #define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14686 #define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
14687 
14688 #define CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14689 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
14690 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
14691 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14692 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
14693 #endif // CATCH_CONFIG_DISABLE_MATCHERS
14694 #define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14695 
14696 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14697 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
14698 
14699 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
14700 #endif // CATCH_CONFIG_DISABLE_MATCHERS
14701 
14702 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
14703 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
14704 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
14705 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
14706 
14707 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
14708 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
14709 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
14710 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
14711 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
14712 #define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
14713 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
14714 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14715 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
14716 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
14717 
14718 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
14719 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
14720 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14721 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
14722 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
14723 #else
14724 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
14725 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
14726 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
14727 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
14728 #endif
14729 
14730 #if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
14731 #define STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__,  #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
14732 #define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
14733 #else
14734 #define STATIC_REQUIRE( ... )       REQUIRE( __VA_ARGS__ )
14735 #define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
14736 #endif
14737 
14738 #endif
14739 
14740 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
14741 
14742 // "BDD-style" convenience wrappers
14743 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
14744 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
14745 
14746 #define GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )
14747 #define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
14748 #define WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )
14749 #define AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
14750 #define THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )
14751 #define AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )
14752 
14753 using Catch::Detail::Approx;
14754 
14755 #else // CATCH_CONFIG_DISABLE
14756 
14757 //////
14758 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
14759 #ifdef CATCH_CONFIG_PREFIX_ALL
14760 
14761 #define CATCH_REQUIRE( ... )        (void)(0)
14762 #define CATCH_REQUIRE_FALSE( ... )  (void)(0)
14763 
14764 #define CATCH_REQUIRE_THROWS( ... ) (void)(0)
14765 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
14766 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher )     (void)(0)
14767 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14768 #define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
14769 #endif// CATCH_CONFIG_DISABLE_MATCHERS
14770 #define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
14771 
14772 #define CATCH_CHECK( ... )         (void)(0)
14773 #define CATCH_CHECK_FALSE( ... )   (void)(0)
14774 #define CATCH_CHECKED_IF( ... )    if (__VA_ARGS__)
14775 #define CATCH_CHECKED_ELSE( ... )  if (!(__VA_ARGS__))
14776 #define CATCH_CHECK_NOFAIL( ... )  (void)(0)
14777 
14778 #define CATCH_CHECK_THROWS( ... )  (void)(0)
14779 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
14780 #define CATCH_CHECK_THROWS_WITH( expr, matcher )     (void)(0)
14781 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14782 #define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
14783 #endif // CATCH_CONFIG_DISABLE_MATCHERS
14784 #define CATCH_CHECK_NOTHROW( ... ) (void)(0)
14785 
14786 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14787 #define CATCH_CHECK_THAT( arg, matcher )   (void)(0)
14788 
14789 #define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
14790 #endif // CATCH_CONFIG_DISABLE_MATCHERS
14791 
14792 #define CATCH_INFO( msg )    (void)(0)
14793 #define CATCH_WARN( msg )    (void)(0)
14794 #define CATCH_CAPTURE( msg ) (void)(0)
14795 
14796 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14797 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14798 #define CATCH_METHOD_AS_TEST_CASE( method, ... )
14799 #define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
14800 #define CATCH_SECTION( ... )
14801 #define CATCH_DYNAMIC_SECTION( ... )
14802 #define CATCH_FAIL( ... ) (void)(0)
14803 #define CATCH_FAIL_CHECK( ... ) (void)(0)
14804 #define CATCH_SUCCEED( ... ) (void)(0)
14805 
14806 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14807 
14808 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
14809 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
14810 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
14811 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
14812 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14813 #else
14814 #define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
14815 #define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
14816 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
14817 #define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14818 #endif
14819 
14820 // "BDD-style" convenience wrappers
14821 #define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14822 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
14823 #define CATCH_GIVEN( desc )
14824 #define CATCH_AND_GIVEN( desc )
14825 #define CATCH_WHEN( desc )
14826 #define CATCH_AND_WHEN( desc )
14827 #define CATCH_THEN( desc )
14828 #define CATCH_AND_THEN( desc )
14829 
14830 #define CATCH_STATIC_REQUIRE( ... )       (void)(0)
14831 #define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
14832 
14833 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
14834 #else
14835 
14836 #define REQUIRE( ... )       (void)(0)
14837 #define REQUIRE_FALSE( ... ) (void)(0)
14838 
14839 #define REQUIRE_THROWS( ... ) (void)(0)
14840 #define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
14841 #define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
14842 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14843 #define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
14844 #endif // CATCH_CONFIG_DISABLE_MATCHERS
14845 #define REQUIRE_NOTHROW( ... ) (void)(0)
14846 
14847 #define CHECK( ... ) (void)(0)
14848 #define CHECK_FALSE( ... ) (void)(0)
14849 #define CHECKED_IF( ... ) if (__VA_ARGS__)
14850 #define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
14851 #define CHECK_NOFAIL( ... ) (void)(0)
14852 
14853 #define CHECK_THROWS( ... )  (void)(0)
14854 #define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
14855 #define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
14856 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14857 #define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
14858 #endif // CATCH_CONFIG_DISABLE_MATCHERS
14859 #define CHECK_NOTHROW( ... ) (void)(0)
14860 
14861 #if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
14862 #define CHECK_THAT( arg, matcher ) (void)(0)
14863 
14864 #define REQUIRE_THAT( arg, matcher ) (void)(0)
14865 #endif // CATCH_CONFIG_DISABLE_MATCHERS
14866 
14867 #define INFO( msg ) (void)(0)
14868 #define WARN( msg ) (void)(0)
14869 #define CAPTURE( msg ) (void)(0)
14870 
14871 #define TEST_CASE( ... )  INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14872 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14873 #define METHOD_AS_TEST_CASE( method, ... )
14874 #define REGISTER_TEST_CASE( Function, ... ) (void)(0)
14875 #define SECTION( ... )
14876 #define DYNAMIC_SECTION( ... )
14877 #define FAIL( ... ) (void)(0)
14878 #define FAIL_CHECK( ... ) (void)(0)
14879 #define SUCCEED( ... ) (void)(0)
14880 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
14881 
14882 #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
14883 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) )
14884 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className )
14885 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
14886 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14887 #else
14888 #define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) ) )
14889 #define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), className ) )
14890 #define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
14891 #define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
14892 #endif
14893 
14894 #define STATIC_REQUIRE( ... )       (void)(0)
14895 #define STATIC_REQUIRE_FALSE( ... ) (void)(0)
14896 
14897 #endif
14898 
14899 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
14900 
14901 // "BDD-style" convenience wrappers
14902 #define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )
14903 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
14904 
14905 #define GIVEN( desc )
14906 #define AND_GIVEN( desc )
14907 #define WHEN( desc )
14908 #define AND_WHEN( desc )
14909 #define THEN( desc )
14910 #define AND_THEN( desc )
14911 
14912 using Catch::Detail::Approx;
14913 
14914 #endif
14915 
14916 #endif // ! CATCH_CONFIG_IMPL_ONLY
14917 
14918 // start catch_reenable_warnings.h
14919 
14920 
14921 #ifdef __clang__
14922 #    ifdef __ICC // icpc defines the __clang__ macro
14923 #        pragma warning(pop)
14924 #    else
14925 #        pragma clang diagnostic pop
14926 #    endif
14927 #elif defined __GNUC__
14928 #    pragma GCC diagnostic pop
14929 #endif
14930 
14931 // end catch_reenable_warnings.h
14932 // end catch.hpp
14933 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
14934 
14935