catch.hpp
Go to the documentation of this file.
1/*
2 * Catch v2.2.3
3 * Generated: 2018-06-06 23:11:57.601416
4 * ----------------------------------------------------------
5 * This file has been merged from multiple headers. Please don't edit it directly
6 * Copyright (c) 2018 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 2
18#define CATCH_VERSION_PATCH 3
19
20#ifdef __clang__
21# pragma clang system_header
22#elif defined __GNUC__
23# pragma GCC system_header
24#endif
25
26// start catch_suppress_warnings.h
27
28#ifdef __clang__
29# ifdef __ICC // icpc defines the __clang__ macro
30# pragma warning(push)
31# pragma warning(disable: 161 1682)
32# else // __ICC
33# pragma clang diagnostic ignored "-Wunused-variable"
34# pragma clang diagnostic push
35# pragma clang diagnostic ignored "-Wpadded"
36# pragma clang diagnostic ignored "-Wswitch-enum"
37# pragma clang diagnostic ignored "-Wcovered-switch-default"
38# endif
39#elif defined __GNUC__
40# pragma GCC diagnostic ignored "-Wparentheses"
41# pragma GCC diagnostic push
42# pragma GCC diagnostic ignored "-Wunused-variable"
43# pragma GCC diagnostic ignored "-Wpadded"
44#endif
45// end catch_suppress_warnings.h
46#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
47# define CATCH_IMPL
48# define CATCH_CONFIG_ALL_PARTS
49#endif
50
51// In the impl file, we want to have access to all parts of the headers
52// Can also be used to sanely support PCHs
53#if defined(CATCH_CONFIG_ALL_PARTS)
54# define CATCH_CONFIG_EXTERNAL_INTERFACES
55# if defined(CATCH_CONFIG_DISABLE_MATCHERS)
56# undef CATCH_CONFIG_DISABLE_MATCHERS
57# endif
58# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
59#endif
60
61#if !defined(CATCH_CONFIG_IMPL_ONLY)
62// start catch_platform.h
63
64#ifdef __APPLE__
65# include <TargetConditionals.h>
66# if TARGET_OS_OSX == 1
67# define CATCH_PLATFORM_MAC
68# elif TARGET_OS_IPHONE == 1
69# define CATCH_PLATFORM_IPHONE
70# endif
71
72#elif defined(linux) || defined(__linux) || defined(__linux__)
73# define CATCH_PLATFORM_LINUX
74
75#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
76# define CATCH_PLATFORM_WINDOWS
77#endif
78
79// end catch_platform.h
80
81#ifdef CATCH_IMPL
82# ifndef CLARA_CONFIG_MAIN
83# define CLARA_CONFIG_MAIN_NOT_DEFINED
84# define CLARA_CONFIG_MAIN
85# endif
86#endif
87
88// start catch_user_interfaces.h
89
90namespace Catch {
91 unsigned int rngSeed();
92}
93
94// end catch_user_interfaces.h
95// start catch_tag_alias_autoregistrar.h
96
97// start catch_common.h
98
99// start catch_compiler_capabilities.h
100
101// Detect a number of compiler features - by compiler
102// The following features are defined:
103//
104// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
105// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
106// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
107// ****************
108// Note to maintainers: if new toggles are added please document them
109// in configuration.md, too
110// ****************
111
112// In general each macro has a _NO_<feature name> form
113// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.
114// Many features, at point of detection, define an _INTERNAL_ macro, so they
115// can be combined, en-mass, with the _NO_ forms later.
116
117#ifdef __cplusplus
118
119# if __cplusplus >= 201402L
120# define CATCH_CPP14_OR_GREATER
121# endif
122
123# if __cplusplus >= 201703L
124# define CATCH_CPP17_OR_GREATER
125# endif
126
127#endif
128
129#if defined(CATCH_CPP17_OR_GREATER)
130# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
131#endif
132
133#ifdef __clang__
134
135# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
136 _Pragma( "clang diagnostic push" ) \
137 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \
138 _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")
139# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
140 _Pragma( "clang diagnostic pop" )
141
142# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
143 _Pragma( "clang diagnostic push" ) \
144 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
145# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
146 _Pragma( "clang diagnostic pop" )
147
148#endif // __clang__
149
151// Assume that non-Windows platforms support posix signals by default
152#if !defined(CATCH_PLATFORM_WINDOWS)
153 #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS
154#endif
155
157// We know some environments not to support full POSIX signals
158#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)
159 #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
160#endif
161
162#ifdef __OS400__
163# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
164# define CATCH_CONFIG_COLOUR_NONE
165#endif
166
168// Android somehow still does not support std::to_string
169#if defined(__ANDROID__)
170# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING
171#endif
172
174// Not all Windows environments support SEH properly
175#if defined(__MINGW32__)
176# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH
177#endif
178
180// Cygwin
181#ifdef __CYGWIN__
182
183// Required for some versions of Cygwin to declare gettimeofday
184// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
185# define _BSD_SOURCE
186
187#endif // __CYGWIN__
188
190// Visual C++
191#ifdef _MSC_VER
192
193# if _MSC_VER >= 1900 // Visual Studio 2015 or newer
194# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
195# endif
196
197// Universal Windows platform does not support SEH
198// Or console colours (or console at all...)
199# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
200# define CATCH_CONFIG_COLOUR_NONE
201# else
202# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
203# endif
204
205#endif // _MSC_VER
206
208
209// DJGPP
210#ifdef __DJGPP__
211# define CATCH_INTERNAL_CONFIG_NO_WCHAR
212#endif // __DJGPP__
213
215
216// Use of __COUNTER__ is suppressed during code analysis in
217// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly
218// handled by it.
219// Otherwise all supported compilers support COUNTER macro,
220// but user still might want to turn it off
221#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )
222 #define CATCH_INTERNAL_CONFIG_COUNTER
223#endif
224
225#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)
226# define CATCH_CONFIG_COUNTER
227#endif
228#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)
229# define CATCH_CONFIG_WINDOWS_SEH
230#endif
231// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
232#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)
233# define CATCH_CONFIG_POSIX_SIGNALS
234#endif
235// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.
236#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)
237# define CATCH_CONFIG_WCHAR
238#endif
239
240#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)
241# define CATCH_CONFIG_CPP11_TO_STRING
242#endif
243
244#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
245# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS
246#endif
247
248#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
249# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
250# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
251#endif
252#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)
253# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
254# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
255#endif
256
257// end catch_compiler_capabilities.h
258#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
259#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
260#ifdef CATCH_CONFIG_COUNTER
261# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
262#else
263# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
264#endif
265
266#include <iosfwd>
267#include <string>
268#include <cstdint>
269
270namespace Catch {
271
272 struct CaseSensitive { enum Choice {
274 No
275 }; };
276
278 NonCopyable( NonCopyable const& ) = delete;
279 NonCopyable( NonCopyable && ) = delete;
280 NonCopyable& operator = ( NonCopyable const& ) = delete;
281 NonCopyable& operator = ( NonCopyable && ) = delete;
282
283 protected:
285 virtual ~NonCopyable();
286 };
287
289
290 SourceLineInfo() = delete;
291 SourceLineInfo( char const* _file, std::size_t _line ) noexcept
292 : file( _file ),
293 line( _line )
294 {}
295
296 SourceLineInfo( SourceLineInfo const& other ) = default;
300
301 bool empty() const noexcept;
302 bool operator == ( SourceLineInfo const& other ) const noexcept;
303 bool operator < ( SourceLineInfo const& other ) const noexcept;
304
305 char const* file;
306 std::size_t line;
307 };
308
309 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
310
311 // Use this in variadic streaming macros to allow
312 // >> +StreamEndStop
313 // as well as
314 // >> stuff +StreamEndStop
317 };
318 template<typename T>
319 T const& operator + ( T const& value, StreamEndStop ) {
320 return value;
321 }
322}
323
324#define CATCH_INTERNAL_LINEINFO \
325 ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
326
327// end catch_common.h
328namespace Catch {
329
331 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
332 };
333
334} // end namespace Catch
335
336#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \
337 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
338 namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \
339 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
340
341// end catch_tag_alias_autoregistrar.h
342// start catch_test_registry.h
343
344// start catch_interfaces_testcase.h
345
346#include <vector>
347#include <memory>
348
349namespace Catch {
350
351 class TestSpec;
352
354 virtual void invoke () const = 0;
355 virtual ~ITestInvoker();
356 };
357
358 using ITestCasePtr = std::shared_ptr<ITestInvoker>;
359
360 class TestCase;
361 struct IConfig;
362
365 virtual std::vector<TestCase> const& getAllTests() const = 0;
366 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
367 };
368
369 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
370 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
371 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
372
373}
374
375// end catch_interfaces_testcase.h
376// start catch_stringref.h
377
378#include <cstddef>
379#include <string>
380#include <iosfwd>
381
382namespace Catch {
383
384 class StringData;
385
393 class StringRef {
394 public:
395 using size_type = std::size_t;
396
397 private:
398 friend struct StringRefTestAccess;
399
400 char const* m_start;
401 size_type m_size;
402
403 char* m_data = nullptr;
404
405 void takeOwnership();
406
407 static constexpr char const* const s_empty = "";
408
409 public: // construction/ assignment
410 StringRef() noexcept
411 : StringRef( s_empty, 0 )
412 {}
413
414 StringRef( StringRef const& other ) noexcept
415 : m_start( other.m_start ),
416 m_size( other.m_size )
417 {}
418
419 StringRef( StringRef&& other ) noexcept
420 : m_start( other.m_start ),
421 m_size( other.m_size ),
422 m_data( other.m_data )
423 {
424 other.m_data = nullptr;
425 }
426
427 StringRef( char const* rawChars ) noexcept;
428
429 StringRef( char const* rawChars, size_type size ) noexcept
430 : m_start( rawChars ),
431 m_size( size )
432 {}
433
434 StringRef( std::string const& stdString ) noexcept
435 : m_start( stdString.c_str() ),
436 m_size( stdString.size() )
437 {}
438
439 ~StringRef() noexcept {
440 delete[] m_data;
441 }
442
443 auto operator = ( StringRef const &other ) noexcept -> StringRef& {
444 delete[] m_data;
445 m_data = nullptr;
446 m_start = other.m_start;
447 m_size = other.m_size;
448 return *this;
449 }
450
451 operator std::string() const;
452
453 void swap( StringRef& other ) noexcept;
454
455 public: // operators
456 auto operator == ( StringRef const& other ) const noexcept -> bool;
457 auto operator != ( StringRef const& other ) const noexcept -> bool;
458
459 auto operator[] ( size_type index ) const noexcept -> char;
460
461 public: // named queries
462 auto empty() const noexcept -> bool {
463 return m_size == 0;
464 }
465 auto size() const noexcept -> size_type {
466 return m_size;
467 }
468
469 auto numberOfCharacters() const noexcept -> size_type;
470 auto c_str() const -> char const*;
471
472 public: // substrings and searches
473 auto substr( size_type start, size_type size ) const noexcept -> StringRef;
474
475 // Returns the current start pointer.
476 // Note that the pointer can change when if the StringRef is a substring
477 auto currentData() const noexcept -> char const*;
478
479 private: // ownership queries - may not be consistent between calls
480 auto isOwned() const noexcept -> bool;
481 auto isSubstring() const noexcept -> bool;
482 };
483
484 auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string;
485 auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string;
486 auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string;
487
488 auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;
489 auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;
490
491 inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {
492 return StringRef( rawChars, size );
493 }
494
495} // namespace Catch
496
497// end catch_stringref.h
498namespace Catch {
499
500template<typename C>
502 void (C::*m_testAsMethod)();
503public:
504 TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}
505
506 void invoke() const override {
507 C obj;
508 (obj.*m_testAsMethod)();
509 }
510};
511
512auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;
513
514template<typename C>
515auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {
516 return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod );
517}
518
520 NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;
523};
524
526 AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;
528};
529
530} // end namespace Catch
531
532#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)
533#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__
534#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__
535#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF
536
537#if defined(CATCH_CONFIG_DISABLE)
538 #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \
539 static void TestName()
540 #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \
541 namespace{ \
542 struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
543 void test(); \
544 }; \
545 } \
546 void TestName::test()
547
548#endif
549
551 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
552 static void TestName(); \
553 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
554 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
555 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
556 static void TestName()
557 #define INTERNAL_CATCH_TESTCASE( ... ) \
558 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
559
561 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
562 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
563 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \
564 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
565
567 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
568 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
569 namespace{ \
570 struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \
571 void test(); \
572 }; \
573 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
574 } \
575 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
576 void TestName::test()
577 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
578 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
579
581 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
582 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
583 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \
584 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
585
586// end catch_test_registry.h
587// start catch_capture.hpp
588
589// start catch_assertionhandler.h
590
591// start catch_assertioninfo.h
592
593// start catch_result_type.h
594
595namespace Catch {
596
597 // ResultWas::OfType enum
598 struct ResultWas { enum OfType {
600 Ok = 0,
601 Info = 1,
603
605
608
610
613
615
616 }; };
617
618 bool isOk( ResultWas::OfType resultType );
619 bool isJustInfo( int flags );
620
621 // ResultDisposition::Flags enum
622 struct ResultDisposition { enum Flags {
623 Normal = 0x01,
624
625 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
626 FalseTest = 0x04, // Prefix expression with !
627 SuppressFail = 0x08 // Failures are reported but do not fail the test
628 }; };
629
631
632 bool shouldContinueOnFailure( int flags );
633 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
634 bool shouldSuppressFailure( int flags );
635
636} // end namespace Catch
637
638// end catch_result_type.h
639namespace Catch {
640
642 {
647
648 // We want to delete this constructor but a compiler bug in 4.8 means
649 // the struct is then treated as non-aggregate
650 //AssertionInfo() = delete;
651 };
652
653} // end namespace Catch
654
655// end catch_assertioninfo.h
656// start catch_decomposer.h
657
658// start catch_tostring.h
659
660#include <vector>
661#include <cstddef>
662#include <type_traits>
663#include <string>
664// start catch_stream.h
665
666#include <iosfwd>
667#include <cstddef>
668#include <ostream>
669
670namespace Catch {
671
672 std::ostream& cout();
673 std::ostream& cerr();
674 std::ostream& clog();
675
676 class StringRef;
677
678 struct IStream {
679 virtual ~IStream();
680 virtual std::ostream& stream() const = 0;
681 };
682
683 auto makeStream( StringRef const &filename ) -> IStream const*;
684
686 std::size_t m_index;
687 std::ostream* m_oss;
688 public:
691
692 auto str() const -> std::string;
693
694 template<typename T>
695 auto operator << ( T const& value ) -> ReusableStringStream& {
696 *m_oss << value;
697 return *this;
698 }
699 auto get() -> std::ostream& { return *m_oss; }
700
701 static void cleanup();
702 };
703}
704
705// end catch_stream.h
706
707#ifdef __OBJC__
708// start catch_objc_arc.hpp
709
710#import <Foundation/Foundation.h>
711
712#ifdef __has_feature
713#define CATCH_ARC_ENABLED __has_feature(objc_arc)
714#else
715#define CATCH_ARC_ENABLED 0
716#endif
717
718void arcSafeRelease( NSObject* obj );
719id performOptionalSelector( id obj, SEL sel );
720
721#if !CATCH_ARC_ENABLED
722inline void arcSafeRelease( NSObject* obj ) {
723 [obj release];
724}
725inline id performOptionalSelector( id obj, SEL sel ) {
726 if( [obj respondsToSelector: sel] )
727 return [obj performSelector: sel];
728 return nil;
729}
730#define CATCH_UNSAFE_UNRETAINED
731#define CATCH_ARC_STRONG
732#else
733inline void arcSafeRelease( NSObject* ){}
734inline id performOptionalSelector( id obj, SEL sel ) {
735#ifdef __clang__
736#pragma clang diagnostic push
737#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
738#endif
739 if( [obj respondsToSelector: sel] )
740 return [obj performSelector: sel];
741#ifdef __clang__
742#pragma clang diagnostic pop
743#endif
744 return nil;
745}
746#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
747#define CATCH_ARC_STRONG __strong
748#endif
749
750// end catch_objc_arc.hpp
751#endif
752
753#ifdef _MSC_VER
754#pragma warning(push)
755#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless
756#endif
757
758// We need a dummy global operator<< so we can bring it into Catch namespace later
760std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);
761
762namespace Catch {
763 // Bring in operator<< from global namespace into Catch namespace
764 using ::operator<<;
765
766 namespace Detail {
767
768 extern const std::string unprintableString;
769
770 std::string rawMemoryToString( const void *object, std::size_t size );
771
772 template<typename T>
773 std::string rawMemoryToString( const T& object ) {
774 return rawMemoryToString( &object, sizeof(object) );
775 }
776
777 template<typename T>
779 template<typename SS, typename TT>
780 static auto test(int)
781 -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
782
783 template<typename, typename>
784 static auto test(...)->std::false_type;
785
786 public:
787 static const bool value = decltype(test<std::ostream, const T&>(0))::value;
788 };
789
790 template<typename E>
792
793 template<typename T>
794 typename std::enable_if<
796 std::string>::type convertUnstreamable( T const& ) {
798 }
799 template<typename T>
800 typename std::enable_if<
802 std::string>::type convertUnstreamable(T const& ex) {
803 return ex.what();
804 }
805
806 template<typename T>
807 typename std::enable_if<
809 , std::string>::type convertUnstreamable( T const& value ) {
811 }
812
813#if defined(_MANAGED)
815 template<typename T>
816 std::string clrReferenceToString( T^ ref ) {
817 if (ref == nullptr)
818 return std::string("null");
819 auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());
820 cli::pin_ptr<System::Byte> p = &bytes[0];
821 return std::string(reinterpret_cast<char const *>(p), bytes->Length);
822 }
823#endif
824
825 } // namespace Detail
826
827 // If we decide for C++14, change these to enable_if_ts
828 template <typename T, typename = void>
829 struct StringMaker {
830 template <typename Fake = T>
831 static
833 convert(const Fake& value) {
835 // NB: call using the function-like syntax to avoid ambiguity with
836 // user-defined templated operator<< under clang.
837 rss.operator<<(value);
838 return rss.str();
839 }
840
841 template <typename Fake = T>
842 static
844 convert( const Fake& value ) {
845#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)
847#else
848 return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);
849#endif
850 }
851 };
852
853 namespace Detail {
854
855 // This function dispatches all stringification requests inside of Catch.
856 // Should be preferably called fully qualified, like ::Catch::Detail::stringify
857 template <typename T>
859 return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e);
860 }
861
862 template<typename E>
864 return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));
865 }
866
867#if defined(_MANAGED)
868 template <typename T>
869 std::string stringify( T^ e ) {
870 return ::Catch::StringMaker<T^>::convert(e);
871 }
872#endif
873
874 } // namespace Detail
875
876 // Some predefined specializations
877
878 template<>
879 struct StringMaker<std::string> {
880 static std::string convert(const std::string& str);
881 };
882#ifdef CATCH_CONFIG_WCHAR
883 template<>
884 struct StringMaker<std::wstring> {
885 static std::string convert(const std::wstring& wstr);
886 };
887#endif
888
889 template<>
890 struct StringMaker<char const *> {
891 static std::string convert(char const * str);
892 };
893 template<>
894 struct StringMaker<char *> {
895 static std::string convert(char * str);
896 };
897
898#ifdef CATCH_CONFIG_WCHAR
899 template<>
900 struct StringMaker<wchar_t const *> {
901 static std::string convert(wchar_t const * str);
902 };
903 template<>
904 struct StringMaker<wchar_t *> {
905 static std::string convert(wchar_t * str);
906 };
907#endif
908
909 // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,
910 // while keeping string semantics?
911 template<int SZ>
912 struct StringMaker<char[SZ]> {
913 static std::string convert(char const* str) {
915 }
916 };
917 template<int SZ>
918 struct StringMaker<signed char[SZ]> {
919 static std::string convert(signed char const* str) {
920 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
921 }
922 };
923 template<int SZ>
924 struct StringMaker<unsigned char[SZ]> {
925 static std::string convert(unsigned char const* str) {
926 return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });
927 }
928 };
929
930 template<>
931 struct StringMaker<int> {
933 };
934 template<>
935 struct StringMaker<long> {
937 };
938 template<>
939 struct StringMaker<long long> {
940 static std::string convert(long long value);
941 };
942 template<>
943 struct StringMaker<unsigned int> {
944 static std::string convert(unsigned int value);
945 };
946 template<>
947 struct StringMaker<unsigned long> {
948 static std::string convert(unsigned long value);
949 };
950 template<>
951 struct StringMaker<unsigned long long> {
952 static std::string convert(unsigned long long value);
953 };
954
955 template<>
957 static std::string convert(bool b);
958 };
959
960 template<>
961 struct StringMaker<char> {
962 static std::string convert(char c);
963 };
964 template<>
965 struct StringMaker<signed char> {
966 static std::string convert(signed char c);
967 };
968 template<>
969 struct StringMaker<unsigned char> {
970 static std::string convert(unsigned char c);
971 };
972
973 template<>
974 struct StringMaker<std::nullptr_t> {
975 static std::string convert(std::nullptr_t);
976 };
977
978 template<>
979 struct StringMaker<float> {
980 static std::string convert(float value);
981 };
982 template<>
983 struct StringMaker<double> {
984 static std::string convert(double value);
985 };
986
987 template <typename T>
988 struct StringMaker<T*> {
989 template <typename U>
990 static std::string convert(U* p) {
991 if (p) {
993 } else {
994 return "nullptr";
995 }
996 }
997 };
998
999 template <typename R, typename C>
1000 struct StringMaker<R C::*> {
1001 static std::string convert(R C::* p) {
1002 if (p) {
1004 } else {
1005 return "nullptr";
1006 }
1007 }
1008 };
1009
1010#if defined(_MANAGED)
1011 template <typename T>
1012 struct StringMaker<T^> {
1013 static std::string convert( T^ ref ) {
1014 return ::Catch::Detail::clrReferenceToString(ref);
1015 }
1016 };
1017#endif
1018
1019 namespace Detail {
1020 template<typename InputIterator>
1021 std::string rangeToString(InputIterator first, InputIterator last) {
1023 rss << "{ ";
1024 if (first != last) {
1025 rss << ::Catch::Detail::stringify(*first);
1026 for (++first; first != last; ++first)
1027 rss << ", " << ::Catch::Detail::stringify(*first);
1028 }
1029 rss << " }";
1030 return rss.str();
1031 }
1032 }
1033
1034#ifdef __OBJC__
1035 template<>
1036 struct StringMaker<NSString*> {
1037 static std::string convert(NSString * nsstring) {
1038 if (!nsstring)
1039 return "nil";
1040 return std::string("@") + [nsstring UTF8String];
1041 }
1042 };
1043 template<>
1044 struct StringMaker<NSObject*> {
1045 static std::string convert(NSObject* nsObject) {
1046 return ::Catch::Detail::stringify([nsObject description]);
1047 }
1048
1049 };
1050 namespace Detail {
1051 inline std::string stringify( NSString* nsstring ) {
1052 return StringMaker<NSString*>::convert( nsstring );
1053 }
1054
1055 } // namespace Detail
1056#endif // __OBJC__
1057
1058} // namespace Catch
1059
1061// Separate std-lib types stringification, so it can be selectively enabled
1062// This means that we do not bring in
1063
1064#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)
1065# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
1066# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
1067# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
1068#endif
1069
1070// Separate std::pair specialization
1071#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)
1072#include <utility>
1073namespace Catch {
1074 template<typename T1, typename T2>
1075 struct StringMaker<std::pair<T1, T2> > {
1076 static std::string convert(const std::pair<T1, T2>& pair) {
1077 ReusableStringStream rss;
1078 rss << "{ "
1079 << ::Catch::Detail::stringify(pair.first)
1080 << ", "
1081 << ::Catch::Detail::stringify(pair.second)
1082 << " }";
1083 return rss.str();
1084 }
1085 };
1086}
1087#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER
1088
1089// Separate std::tuple specialization
1090#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)
1091#include <tuple>
1092namespace Catch {
1093 namespace Detail {
1094 template<
1095 typename Tuple,
1096 std::size_t N = 0,
1098 >
1099 struct TupleElementPrinter {
1100 static void print(const Tuple& tuple, std::ostream& os) {
1101 os << (N ? ", " : " ")
1102 << ::Catch::Detail::stringify(std::get<N>(tuple));
1103 TupleElementPrinter<Tuple, N + 1>::print(tuple, os);
1104 }
1105 };
1106
1107 template<
1108 typename Tuple,
1109 std::size_t N
1110 >
1111 struct TupleElementPrinter<Tuple, N, false> {
1112 static void print(const Tuple&, std::ostream&) {}
1113 };
1114
1115 }
1116
1117 template<typename ...Types>
1118 struct StringMaker<std::tuple<Types...>> {
1119 static std::string convert(const std::tuple<Types...>& tuple) {
1120 ReusableStringStream rss;
1121 rss << '{';
1122 Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());
1123 rss << " }";
1124 return rss.str();
1125 }
1126 };
1127}
1128#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER
1129
1130namespace Catch {
1131 struct not_this_one {}; // Tag type for detecting which begin/ end are being selected
1132
1133 // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace
1134 using std::begin;
1135 using std::end;
1136
1139
1140 template <typename T>
1141 struct is_range {
1142 static const bool value =
1143 !std::is_same<decltype(begin(std::declval<T>())), not_this_one>::value &&
1144 !std::is_same<decltype(end(std::declval<T>())), not_this_one>::value;
1145 };
1146
1147#if defined(_MANAGED) // Managed types are never ranges
1148 template <typename T>
1149 struct is_range<T^> {
1150 static const bool value = false;
1151 };
1152#endif
1153
1154 template<typename Range>
1156 return ::Catch::Detail::rangeToString( begin( range ), end( range ) );
1157 }
1158
1159 // Handle vector<bool> specially
1160 template<typename Allocator>
1161 std::string rangeToString( std::vector<bool, Allocator> const& v ) {
1163 rss << "{ ";
1164 bool first = true;
1165 for( bool b : v ) {
1166 if( first )
1167 first = false;
1168 else
1169 rss << ", ";
1170 rss << ::Catch::Detail::stringify( b );
1171 }
1172 rss << " }";
1173 return rss.str();
1174 }
1175
1176 template<typename R>
1177 struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {
1178 static std::string convert( R const& range ) {
1179 return rangeToString( range );
1180 }
1181 };
1182
1183 template <typename T, int SZ>
1184 struct StringMaker<T[SZ]> {
1185 static std::string convert(T const(&arr)[SZ]) {
1186 return rangeToString(arr);
1187 }
1188 };
1189
1190} // namespace Catch
1191
1192// Separate std::chrono::duration specialization
1193#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
1194#include <ctime>
1195#include <ratio>
1196#include <chrono>
1197
1198namespace Catch {
1199
1200template <class Ratio>
1201struct ratio_string {
1202 static std::string symbol();
1203};
1204
1205template <class Ratio>
1206std::string ratio_string<Ratio>::symbol() {
1208 rss << '[' << Ratio::num << '/'
1209 << Ratio::den << ']';
1210 return rss.str();
1211}
1212template <>
1213struct ratio_string<std::atto> {
1214 static std::string symbol();
1215};
1216template <>
1217struct ratio_string<std::femto> {
1218 static std::string symbol();
1219};
1220template <>
1221struct ratio_string<std::pico> {
1222 static std::string symbol();
1223};
1224template <>
1225struct ratio_string<std::nano> {
1226 static std::string symbol();
1227};
1228template <>
1229struct ratio_string<std::micro> {
1230 static std::string symbol();
1231};
1232template <>
1233struct ratio_string<std::milli> {
1234 static std::string symbol();
1235};
1236
1238 // std::chrono::duration specializations
1239 template<typename Value, typename Ratio>
1240 struct StringMaker<std::chrono::duration<Value, Ratio>> {
1241 static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {
1242 ReusableStringStream rss;
1243 rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';
1244 return rss.str();
1245 }
1246 };
1247 template<typename Value>
1248 struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {
1249 static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {
1250 ReusableStringStream rss;
1251 rss << duration.count() << " s";
1252 return rss.str();
1253 }
1254 };
1255 template<typename Value>
1256 struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {
1257 static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {
1258 ReusableStringStream rss;
1259 rss << duration.count() << " m";
1260 return rss.str();
1261 }
1262 };
1263 template<typename Value>
1264 struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {
1265 static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {
1266 ReusableStringStream rss;
1267 rss << duration.count() << " h";
1268 return rss.str();
1269 }
1270 };
1271
1273 // std::chrono::time_point specialization
1274 // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>
1275 template<typename Clock, typename Duration>
1276 struct StringMaker<std::chrono::time_point<Clock, Duration>> {
1277 static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {
1278 return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";
1279 }
1280 };
1281 // std::chrono::time_point<system_clock> specialization
1282 template<typename Duration>
1283 struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {
1284 static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {
1286
1287#ifdef _MSC_VER
1288 std::tm timeInfo = {};
1289 gmtime_s(&timeInfo, &converted);
1290#else
1291 std::tm* timeInfo = std::gmtime(&converted);
1292#endif
1293
1294 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
1295 char timeStamp[timeStampSize];
1296 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
1297
1298#ifdef _MSC_VER
1299 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
1300#else
1301 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
1302#endif
1303 return std::string(timeStamp);
1304 }
1305 };
1306}
1307#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
1308
1309#ifdef _MSC_VER
1310#pragma warning(pop)
1311#endif
1312
1313// end catch_tostring.h
1314#include <iosfwd>
1315
1316#ifdef _MSC_VER
1317#pragma warning(push)
1318#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1319#pragma warning(disable:4018) // more "signed/unsigned mismatch"
1320#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
1321#pragma warning(disable:4180) // qualifier applied to function type has no meaning
1322#endif
1323
1324namespace Catch {
1325
1327 auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }
1328 auto getResult() const -> bool { return m_result; }
1329 virtual void streamReconstructedExpression( std::ostream &os ) const = 0;
1330
1333 m_result( result )
1334 {}
1335
1336 // We don't actually need a virtual destructor, but many static analysers
1337 // complain if it's not here :-(
1339
1342
1343 };
1344
1345 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );
1346
1347 template<typename LhsT, typename RhsT>
1349 LhsT m_lhs;
1350 StringRef m_op;
1351 RhsT m_rhs;
1352
1353 void streamReconstructedExpression( std::ostream &os ) const override {
1355 ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );
1356 }
1357
1358 public:
1359 BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )
1360 : ITransientExpression{ true, comparisonResult },
1361 m_lhs( lhs ),
1362 m_op( op ),
1363 m_rhs( rhs )
1364 {}
1365 };
1366
1367 template<typename LhsT>
1369 LhsT m_lhs;
1370
1371 void streamReconstructedExpression( std::ostream &os ) const override {
1372 os << Catch::Detail::stringify( m_lhs );
1373 }
1374
1375 public:
1376 explicit UnaryExpr( LhsT lhs )
1377 : ITransientExpression{ false, lhs ? true : false },
1378 m_lhs( lhs )
1379 {}
1380 };
1381
1382 // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)
1383 template<typename LhsT, typename RhsT>
1384 auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }
1385 template<typename T>
1386 auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
1387 template<typename T>
1388 auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }
1389 template<typename T>
1390 auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
1391 template<typename T>
1392 auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }
1393
1394 template<typename LhsT, typename RhsT>
1395 auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }
1396 template<typename T>
1397 auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
1398 template<typename T>
1399 auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }
1400 template<typename T>
1401 auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
1402 template<typename T>
1403 auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }
1404
1405 template<typename LhsT>
1406 class ExprLhs {
1407 LhsT m_lhs;
1408 public:
1409 explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}
1410
1411 template<typename RhsT>
1412 auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
1413 return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs };
1414 }
1415 auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
1416 return { m_lhs == rhs, m_lhs, "==", rhs };
1417 }
1418
1419 template<typename RhsT>
1420 auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
1421 return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs };
1422 }
1423 auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {
1424 return { m_lhs != rhs, m_lhs, "!=", rhs };
1425 }
1426
1427 template<typename RhsT>
1428 auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
1429 return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };
1430 }
1431 template<typename RhsT>
1432 auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
1433 return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };
1434 }
1435 template<typename RhsT>
1436 auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
1437 return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };
1438 }
1439 template<typename RhsT>
1440 auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {
1441 return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };
1442 }
1443
1444 auto makeUnaryExpr() const -> UnaryExpr<LhsT> {
1445 return UnaryExpr<LhsT>{ m_lhs };
1446 }
1447 };
1448
1450
1451 template<typename T>
1452 void handleExpression( ExprLhs<T> const& expr ) {
1454 }
1455
1456 struct Decomposer {
1457 template<typename T>
1458 auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {
1459 return ExprLhs<T const&>{ lhs };
1460 }
1461
1463 return ExprLhs<bool>{ value };
1464 }
1465 };
1466
1467} // end namespace Catch
1468
1469#ifdef _MSC_VER
1470#pragma warning(pop)
1471#endif
1472
1473// end catch_decomposer.h
1474// start catch_interfaces_capture.h
1475
1476#include <string>
1477
1478namespace Catch {
1479
1480 class AssertionResult;
1481 struct AssertionInfo;
1482 struct SectionInfo;
1483 struct SectionEndInfo;
1484 struct MessageInfo;
1485 struct Counts;
1486 struct BenchmarkInfo;
1487 struct BenchmarkStats;
1488 struct AssertionReaction;
1489
1490 struct ITransientExpression;
1491
1493
1495
1496 virtual bool sectionStarted( SectionInfo const& sectionInfo,
1497 Counts& assertions ) = 0;
1498 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
1499 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
1500
1501 virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;
1502 virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0;
1503
1504 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1505 virtual void popScopedMessage( MessageInfo const& message ) = 0;
1506
1507 virtual void handleFatalErrorCondition( StringRef message ) = 0;
1508
1509 virtual void handleExpr
1510 ( AssertionInfo const& info,
1511 ITransientExpression const& expr,
1512 AssertionReaction& reaction ) = 0;
1513 virtual void handleMessage
1514 ( AssertionInfo const& info,
1515 ResultWas::OfType resultType,
1516 StringRef const& message,
1517 AssertionReaction& reaction ) = 0;
1519 ( AssertionInfo const& info,
1520 AssertionReaction& reaction ) = 0;
1522 ( AssertionInfo const& info,
1523 std::string const& message,
1524 AssertionReaction& reaction ) = 0;
1525 virtual void handleIncomplete
1526 ( AssertionInfo const& info ) = 0;
1527 virtual void handleNonExpr
1528 ( AssertionInfo const &info,
1529 ResultWas::OfType resultType,
1530 AssertionReaction &reaction ) = 0;
1531
1532 virtual bool lastAssertionPassed() = 0;
1533 virtual void assertionPassed() = 0;
1534
1535 // Deprecated, do not use:
1536 virtual std::string getCurrentTestName() const = 0;
1537 virtual const AssertionResult* getLastResult() const = 0;
1538 virtual void exceptionEarlyReported() = 0;
1539 };
1540
1542}
1543
1544// end catch_interfaces_capture.h
1545namespace Catch {
1546
1548 struct AssertionResultData;
1549 struct IResultCapture;
1550 class RunContext;
1551
1553 friend class AssertionHandler;
1554 friend struct AssertionStats;
1555 friend class RunContext;
1556
1557 ITransientExpression const* m_transientExpression = nullptr;
1558 bool m_isNegated;
1559 public:
1560 LazyExpression( bool isNegated );
1563
1564 explicit operator bool() const;
1565
1566 friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
1567 };
1568
1570 bool shouldDebugBreak = false;
1571 bool shouldThrow = false;
1572 };
1573
1575 AssertionInfo m_assertionInfo;
1576 AssertionReaction m_reaction;
1577 bool m_completed = false;
1578 IResultCapture& m_resultCapture;
1579
1580 public:
1582 ( StringRef macroName,
1583 SourceLineInfo const& lineInfo,
1584 StringRef capturedExpression,
1585 ResultDisposition::Flags resultDisposition );
1587 if ( !m_completed ) {
1588 m_resultCapture.handleIncomplete( m_assertionInfo );
1589 }
1590 }
1591
1592 template<typename T>
1593 void handleExpr( ExprLhs<T> const& expr ) {
1594 handleExpr( expr.makeUnaryExpr() );
1595 }
1597
1598 void handleMessage(ResultWas::OfType resultType, StringRef const& message);
1599
1605
1606 void complete();
1608
1609 // query
1610 auto allowThrows() const -> bool;
1611 };
1612
1613 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
1614
1615} // namespace Catch
1616
1617// end catch_assertionhandler.h
1618// start catch_message.h
1619
1620#include <string>
1621
1622namespace Catch {
1623
1625 MessageInfo( std::string const& _macroName,
1626 SourceLineInfo const& _lineInfo,
1627 ResultWas::OfType _type );
1628
1633 unsigned int sequence;
1634
1635 bool operator == ( MessageInfo const& other ) const;
1636 bool operator < ( MessageInfo const& other ) const;
1637 private:
1638 static unsigned int globalCount;
1639 };
1640
1642
1643 template<typename T>
1645 m_stream << value;
1646 return *this;
1647 }
1648
1650 };
1651
1653 MessageBuilder( std::string const& macroName,
1654 SourceLineInfo const& lineInfo,
1655 ResultWas::OfType type );
1656
1657 template<typename T>
1659 m_stream << value;
1660 return *this;
1661 }
1662
1664 };
1665
1667 public:
1668 explicit ScopedMessage( MessageBuilder const& builder );
1670
1672 };
1673
1674} // end namespace Catch
1675
1676// end catch_message.h
1677#if !defined(CATCH_CONFIG_DISABLE)
1678
1679#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
1680 #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
1681#else
1682 #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
1683#endif
1684
1685#if defined(CATCH_CONFIG_FAST_COMPILE)
1686
1688// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
1689// macros.
1690#define INTERNAL_CATCH_TRY
1691#define INTERNAL_CATCH_CATCH( capturer )
1692
1693#else // CATCH_CONFIG_FAST_COMPILE
1694
1695#define INTERNAL_CATCH_TRY try
1696#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
1697
1698#endif
1699
1700#define INTERNAL_CATCH_REACT( handler ) handler.complete();
1701
1703#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
1704 do { \
1705 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
1706 INTERNAL_CATCH_TRY { \
1707 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
1708 catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
1709 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
1710 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
1711 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1712 } 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
1713 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
1714
1716#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
1717 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
1718 if( Catch::getResultCapture().lastAssertionPassed() )
1719
1721#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
1722 INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
1723 if( !Catch::getResultCapture().lastAssertionPassed() )
1724
1726#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
1727 do { \
1728 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
1729 try { \
1730 static_cast<void>(__VA_ARGS__); \
1731 catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
1732 } \
1733 catch( ... ) { \
1734 catchAssertionHandler.handleUnexpectedInflightException(); \
1735 } \
1736 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1737 } while( false )
1738
1740#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
1741 do { \
1742 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
1743 if( catchAssertionHandler.allowThrows() ) \
1744 try { \
1745 static_cast<void>(__VA_ARGS__); \
1746 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
1747 } \
1748 catch( ... ) { \
1749 catchAssertionHandler.handleExceptionThrownAsExpected(); \
1750 } \
1751 else \
1752 catchAssertionHandler.handleThrowingCallSkipped(); \
1753 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1754 } while( false )
1755
1757#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
1758 do { \
1759 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
1760 if( catchAssertionHandler.allowThrows() ) \
1761 try { \
1762 static_cast<void>(expr); \
1763 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
1764 } \
1765 catch( exceptionType const& ) { \
1766 catchAssertionHandler.handleExceptionThrownAsExpected(); \
1767 } \
1768 catch( ... ) { \
1769 catchAssertionHandler.handleUnexpectedInflightException(); \
1770 } \
1771 else \
1772 catchAssertionHandler.handleThrowingCallSkipped(); \
1773 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1774 } while( false )
1775
1777#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
1778 do { \
1779 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
1780 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
1781 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1782 } while( false )
1783
1785#define INTERNAL_CATCH_INFO( macroName, log ) \
1786 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
1787
1789// Although this is matcher-based, it can be used with just a string
1790#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
1791 do { \
1792 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
1793 if( catchAssertionHandler.allowThrows() ) \
1794 try { \
1795 static_cast<void>(__VA_ARGS__); \
1796 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
1797 } \
1798 catch( ... ) { \
1799 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \
1800 } \
1801 else \
1802 catchAssertionHandler.handleThrowingCallSkipped(); \
1803 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
1804 } while( false )
1805
1806#endif // CATCH_CONFIG_DISABLE
1807
1808// end catch_capture.hpp
1809// start catch_section.h
1810
1811// start catch_section_info.h
1812
1813// start catch_totals.h
1814
1815#include <cstddef>
1816
1817namespace Catch {
1818
1819 struct Counts {
1820 Counts operator - ( Counts const& other ) const;
1821 Counts& operator += ( Counts const& other );
1822
1823 std::size_t total() const;
1824 bool allPassed() const;
1825 bool allOk() const;
1826
1827 std::size_t passed = 0;
1828 std::size_t failed = 0;
1829 std::size_t failedButOk = 0;
1830 };
1831
1832 struct Totals {
1833
1834 Totals operator - ( Totals const& other ) const;
1835 Totals& operator += ( Totals const& other );
1836
1837 Totals delta( Totals const& prevTotals ) const;
1838
1839 int error = 0;
1842 };
1843}
1844
1845// end catch_totals.h
1846#include <string>
1847
1848namespace Catch {
1849
1852 ( SourceLineInfo const& _lineInfo,
1853 std::string const& _name,
1854 std::string const& _description = std::string() );
1855
1859 };
1860
1862 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds );
1863
1867 };
1868
1869} // end namespace Catch
1870
1871// end catch_section_info.h
1872// start catch_timer.h
1873
1874#include <cstdint>
1875
1876namespace Catch {
1877
1880
1881 class Timer {
1882 uint64_t m_nanoseconds = 0;
1883 public:
1884 void start();
1885 auto getElapsedNanoseconds() const -> uint64_t;
1886 auto getElapsedMicroseconds() const -> uint64_t;
1887 auto getElapsedMilliseconds() const -> unsigned int;
1888 auto getElapsedSeconds() const -> double;
1889 };
1890
1891} // namespace Catch
1892
1893// end catch_timer.h
1894#include <string>
1895
1896namespace Catch {
1897
1899 public:
1900 Section( SectionInfo const& info );
1902
1903 // This indicates whether the section should be executed or not
1904 explicit operator bool() const;
1905
1906 private:
1907 SectionInfo m_info;
1908
1909 std::string m_name;
1910 Counts m_assertions;
1911 bool m_sectionIncluded;
1912 Timer m_timer;
1913 };
1914
1915} // end namespace Catch
1916
1917 #define INTERNAL_CATCH_SECTION( ... ) \
1918 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
1919
1920// end catch_section.h
1921// start catch_benchmark.h
1922
1923#include <cstdint>
1924#include <string>
1925
1926namespace Catch {
1927
1929
1930 std::string m_name;
1931 std::size_t m_count = 0;
1932 std::size_t m_iterationsToRun = 1;
1933 uint64_t m_resolution;
1934 Timer m_timer;
1935
1936 static auto getResolution() -> uint64_t;
1937 public:
1938 // Keep most of this inline as it's on the code path that is being timed
1940 : m_name( name ),
1941 m_resolution( getResolution() )
1942 {
1943 reportStart();
1944 m_timer.start();
1945 }
1946
1947 explicit operator bool() {
1948 if( m_count < m_iterationsToRun )
1949 return true;
1950 return needsMoreIterations();
1951 }
1952
1953 void increment() {
1954 ++m_count;
1955 }
1956
1959 };
1960
1961} // end namespace Catch
1962
1963#define BENCHMARK( name ) \
1964 for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() )
1965
1966// end catch_benchmark.h
1967// start catch_interfaces_exception.h
1968
1969// start catch_interfaces_registry_hub.h
1970
1971#include <string>
1972#include <memory>
1973
1974namespace Catch {
1975
1976 class TestCase;
1977 struct ITestCaseRegistry;
1978 struct IExceptionTranslatorRegistry;
1979 struct IExceptionTranslator;
1980 struct IReporterRegistry;
1981 struct IReporterFactory;
1982 struct ITagAliasRegistry;
1983 class StartupExceptionRegistry;
1984
1985 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
1986
1988 virtual ~IRegistryHub();
1989
1990 virtual IReporterRegistry const& getReporterRegistry() const = 0;
1991 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
1992 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
1993
1995
1996 virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;
1997 };
1998
2001 virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;
2002 virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;
2003 virtual void registerTest( TestCase const& testInfo ) = 0;
2004 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2005 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
2006 virtual void registerStartupException() noexcept = 0;
2007 };
2008
2011 void cleanUp();
2013
2014}
2015
2016// end catch_interfaces_registry_hub.h
2017#if defined(CATCH_CONFIG_DISABLE)
2018 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \
2019 static std::string translatorName( signature )
2020#endif
2021
2022#include <exception>
2023#include <string>
2024#include <vector>
2025
2026namespace Catch {
2028
2029 struct IExceptionTranslator;
2030 using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;
2031
2034 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
2035 };
2036
2039
2041 };
2042
2044 template<typename T>
2045 class ExceptionTranslator : public IExceptionTranslator {
2046 public:
2047
2048 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2049 : m_translateFunction( translateFunction )
2050 {}
2051
2052 std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {
2053 try {
2054 if( it == itEnd )
2055 std::rethrow_exception(std::current_exception());
2056 else
2057 return (*it)->translate( it+1, itEnd );
2058 }
2059 catch( T& ex ) {
2060 return m_translateFunction( ex );
2061 }
2062 }
2063
2064 protected:
2065 std::string(*m_translateFunction)( T& );
2066 };
2067
2068 public:
2069 template<typename T>
2070 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
2072 ( new ExceptionTranslator<T>( translateFunction ) );
2073 }
2074 };
2075}
2076
2078#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2079 static std::string translatorName( signature ); \
2080 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
2081 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \
2082 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \
2083 static std::string translatorName( signature )
2084
2085#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
2086
2087// end catch_interfaces_exception.h
2088// start catch_approx.h
2089
2090#include <type_traits>
2091#include <stdexcept>
2092
2093namespace Catch {
2094namespace Detail {
2095
2096 class Approx {
2097 private:
2098 bool equalityComparisonImpl(double other) const;
2099
2100 public:
2101 explicit Approx ( double value );
2102
2103 static Approx custom();
2104
2107 Approx approx( static_cast<double>(value) );
2108 approx.epsilon( m_epsilon );
2109 approx.margin( m_margin );
2110 approx.scale( m_scale );
2111 return approx;
2112 }
2113
2115 explicit Approx( T const& value ): Approx(static_cast<double>(value))
2116 {}
2117
2119 friend bool operator == ( const T& lhs, Approx const& rhs ) {
2120 auto lhs_v = static_cast<double>(lhs);
2121 return rhs.equalityComparisonImpl(lhs_v);
2122 }
2123
2125 friend bool operator == ( Approx const& lhs, const T& rhs ) {
2126 return operator==( rhs, lhs );
2127 }
2128
2130 friend bool operator != ( T const& lhs, Approx const& rhs ) {
2131 return !operator==( lhs, rhs );
2132 }
2133
2135 friend bool operator != ( Approx const& lhs, T const& rhs ) {
2136 return !operator==( rhs, lhs );
2137 }
2138
2140 friend bool operator <= ( T const& lhs, Approx const& rhs ) {
2141 return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;
2142 }
2143
2145 friend bool operator <= ( Approx const& lhs, T const& rhs ) {
2146 return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;
2147 }
2148
2150 friend bool operator >= ( T const& lhs, Approx const& rhs ) {
2151 return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;
2152 }
2153
2155 friend bool operator >= ( Approx const& lhs, T const& rhs ) {
2156 return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;
2157 }
2158
2160 Approx& epsilon( T const& newEpsilon ) {
2161 double epsilonAsDouble = static_cast<double>(newEpsilon);
2162 if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) {
2163 throw std::domain_error
2164 ( "Invalid Approx::epsilon: " +
2165 Catch::Detail::stringify( epsilonAsDouble ) +
2166 ", Approx::epsilon has to be between 0 and 1" );
2167 }
2168 m_epsilon = epsilonAsDouble;
2169 return *this;
2170 }
2171
2173 Approx& margin( T const& newMargin ) {
2174 double marginAsDouble = static_cast<double>(newMargin);
2175 if( marginAsDouble < 0 ) {
2176 throw std::domain_error
2177 ( "Invalid Approx::margin: " +
2178 Catch::Detail::stringify( marginAsDouble ) +
2179 ", Approx::Margin has to be non-negative." );
2180
2181 }
2182 m_margin = marginAsDouble;
2183 return *this;
2184 }
2185
2187 Approx& scale( T const& newScale ) {
2188 m_scale = static_cast<double>(newScale);
2189 return *this;
2190 }
2191
2193
2194 private:
2195 double m_epsilon;
2196 double m_margin;
2197 double m_scale;
2198 double m_value;
2199 };
2200}
2201
2202template<>
2205};
2206
2207} // end namespace Catch
2208
2209// end catch_approx.h
2210// start catch_string_manip.h
2211
2212#include <string>
2213#include <iosfwd>
2214
2215namespace Catch {
2216
2217 bool startsWith( std::string const& s, std::string const& prefix );
2218 bool startsWith( std::string const& s, char prefix );
2219 bool endsWith( std::string const& s, std::string const& suffix );
2220 bool endsWith( std::string const& s, char suffix );
2221 bool contains( std::string const& s, std::string const& infix );
2225 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
2226
2227 struct pluralise {
2228 pluralise( std::size_t count, std::string const& label );
2229
2230 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
2231
2232 std::size_t m_count;
2234 };
2235}
2236
2237// end catch_string_manip.h
2238#ifndef CATCH_CONFIG_DISABLE_MATCHERS
2239// start catch_capture_matchers.h
2240
2241// start catch_matchers.h
2242
2243#include <string>
2244#include <vector>
2245
2246namespace Catch {
2247namespace Matchers {
2248 namespace Impl {
2249
2250 template<typename ArgT> struct MatchAllOf;
2251 template<typename ArgT> struct MatchAnyOf;
2252 template<typename ArgT> struct MatchNotOf;
2253
2255 public:
2258 MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;
2260
2261 protected:
2263 virtual std::string describe() const = 0;
2265 };
2266
2267 template<typename ObjectT>
2269 virtual bool match( ObjectT const& arg ) const = 0;
2270 };
2271 template<typename PtrT>
2272 struct MatcherMethod<PtrT*> {
2273 virtual bool match( PtrT* arg ) const = 0;
2274 };
2275
2276 template<typename T>
2278
2279 MatchAllOf<T> operator && ( MatcherBase const& other ) const;
2280 MatchAnyOf<T> operator || ( MatcherBase const& other ) const;
2281 MatchNotOf<T> operator ! () const;
2282 };
2283
2284 template<typename ArgT>
2285 struct MatchAllOf : MatcherBase<ArgT> {
2286 bool match( ArgT const& arg ) const override {
2287 for( auto matcher : m_matchers ) {
2288 if (!matcher->match(arg))
2289 return false;
2290 }
2291 return true;
2292 }
2293 std::string describe() const override {
2294 std::string description;
2295 description.reserve( 4 + m_matchers.size()*32 );
2296 description += "( ";
2297 bool first = true;
2298 for( auto matcher : m_matchers ) {
2299 if( first )
2300 first = false;
2301 else
2302 description += " and ";
2303 description += matcher->toString();
2304 }
2305 description += " )";
2306 return description;
2307 }
2308
2309 MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
2310 m_matchers.push_back( &other );
2311 return *this;
2312 }
2313
2314 std::vector<MatcherBase<ArgT> const*> m_matchers;
2315 };
2316 template<typename ArgT>
2317 struct MatchAnyOf : MatcherBase<ArgT> {
2318
2319 bool match( ArgT const& arg ) const override {
2320 for( auto matcher : m_matchers ) {
2321 if (matcher->match(arg))
2322 return true;
2323 }
2324 return false;
2325 }
2326 std::string describe() const override {
2327 std::string description;
2328 description.reserve( 4 + m_matchers.size()*32 );
2329 description += "( ";
2330 bool first = true;
2331 for( auto matcher : m_matchers ) {
2332 if( first )
2333 first = false;
2334 else
2335 description += " or ";
2336 description += matcher->toString();
2337 }
2338 description += " )";
2339 return description;
2340 }
2341
2342 MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
2343 m_matchers.push_back( &other );
2344 return *this;
2345 }
2346
2347 std::vector<MatcherBase<ArgT> const*> m_matchers;
2348 };
2349
2350 template<typename ArgT>
2351 struct MatchNotOf : MatcherBase<ArgT> {
2352
2353 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
2354
2355 bool match( ArgT const& arg ) const override {
2356 return !m_underlyingMatcher.match( arg );
2357 }
2358
2359 std::string describe() const override {
2360 return "not " + m_underlyingMatcher.toString();
2361 }
2363 };
2364
2365 template<typename T>
2367 return MatchAllOf<T>() && *this && other;
2368 }
2369 template<typename T>
2371 return MatchAnyOf<T>() || *this || other;
2372 }
2373 template<typename T>
2375 return MatchNotOf<T>( *this );
2376 }
2377
2378 } // namespace Impl
2379
2380} // namespace Matchers
2381
2382using namespace Matchers;
2384
2385} // namespace Catch
2386
2387// end catch_matchers.h
2388// start catch_matchers_floating.h
2389
2390#include <type_traits>
2391#include <cmath>
2392
2393namespace Catch {
2394namespace Matchers {
2395
2396 namespace Floating {
2397
2398 enum class FloatingPointKind : uint8_t;
2399
2401 WithinAbsMatcher(double target, double margin);
2402 bool match(double const& matchee) const override;
2403 std::string describe() const override;
2404 private:
2405 double m_target;
2406 double m_margin;
2407 };
2408
2410 WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType);
2411 bool match(double const& matchee) const override;
2412 std::string describe() const override;
2413 private:
2414 double m_target;
2415 int m_ulps;
2416 FloatingPointKind m_type;
2417 };
2418
2419 } // namespace Floating
2420
2421 // The following functions create the actual matcher objects.
2422 // This allows the types to be inferred
2423 Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff);
2424 Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff);
2425 Floating::WithinAbsMatcher WithinAbs(double target, double margin);
2426
2427} // namespace Matchers
2428} // namespace Catch
2429
2430// end catch_matchers_floating.h
2431// start catch_matchers_generic.hpp
2432
2433#include <functional>
2434#include <string>
2435
2436namespace Catch {
2437namespace Matchers {
2438namespace Generic {
2439
2440namespace Detail {
2442}
2443
2444template <typename T>
2446 std::function<bool(T const&)> m_predicate;
2447 std::string m_description;
2448public:
2449
2450 PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)
2451 :m_predicate(std::move(elem)),
2452 m_description(Detail::finalizeDescription(descr))
2453 {}
2454
2455 bool match( T const& item ) const override {
2456 return m_predicate(item);
2457 }
2458
2459 std::string describe() const override {
2460 return m_description;
2461 }
2462};
2463
2464} // namespace Generic
2465
2466 // The following functions create the actual matcher objects.
2467 // The user has to explicitly specify type to the function, because
2468 // infering std::function<bool(T const&)> is hard (but possible) and
2469 // requires a lot of TMP.
2470 template<typename T>
2471 Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
2472 return Generic::PredicateMatcher<T>(predicate, description);
2473 }
2474
2475} // namespace Matchers
2476} // namespace Catch
2477
2478// end catch_matchers_generic.hpp
2479// start catch_matchers_string.h
2480
2481#include <string>
2482
2483namespace Catch {
2484namespace Matchers {
2485
2486 namespace StdString {
2487
2489 {
2490 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
2493
2496 };
2497
2498 struct StringMatcherBase : MatcherBase<std::string> {
2499 StringMatcherBase( std::string const& operation, CasedString const& comparator );
2500 std::string describe() const override;
2501
2504 };
2505
2507 EqualsMatcher( CasedString const& comparator );
2508 bool match( std::string const& source ) const override;
2509 };
2511 ContainsMatcher( CasedString const& comparator );
2512 bool match( std::string const& source ) const override;
2513 };
2515 StartsWithMatcher( CasedString const& comparator );
2516 bool match( std::string const& source ) const override;
2517 };
2519 EndsWithMatcher( CasedString const& comparator );
2520 bool match( std::string const& source ) const override;
2521 };
2522
2523 struct RegexMatcher : MatcherBase<std::string> {
2525 bool match( std::string const& matchee ) const override;
2526 std::string describe() const override;
2527
2528 private:
2529 std::string m_regex;
2530 CaseSensitive::Choice m_caseSensitivity;
2531 };
2532
2533 } // namespace StdString
2534
2535 // The following functions create the actual matcher objects.
2536 // This allows the types to be inferred
2537
2543
2544} // namespace Matchers
2545} // namespace Catch
2546
2547// end catch_matchers_string.h
2548// start catch_matchers_vector.h
2549
2550#include <algorithm>
2551
2552namespace Catch {
2553namespace Matchers {
2554
2555 namespace Vector {
2556 namespace Detail {
2557 template <typename InputIterator, typename T>
2558 size_t count(InputIterator first, InputIterator last, T const& item) {
2559 size_t cnt = 0;
2560 for (; first != last; ++first) {
2561 if (*first == item) {
2562 ++cnt;
2563 }
2564 }
2565 return cnt;
2566 }
2567 template <typename InputIterator, typename T>
2568 bool contains(InputIterator first, InputIterator last, T const& item) {
2569 for (; first != last; ++first) {
2570 if (*first == item) {
2571 return true;
2572 }
2573 }
2574 return false;
2575 }
2576 }
2577
2578 template<typename T>
2579 struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
2580
2581 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
2582
2583 bool match(std::vector<T> const &v) const override {
2584 for (auto const& el : v) {
2585 if (el == m_comparator) {
2586 return true;
2587 }
2588 }
2589 return false;
2590 }
2591
2592 std::string describe() const override {
2593 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
2594 }
2595
2597 };
2598
2599 template<typename T>
2600 struct ContainsMatcher : MatcherBase<std::vector<T>> {
2601
2602 ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
2603
2604 bool match(std::vector<T> const &v) const override {
2605 // !TBD: see note in EqualsMatcher
2606 if (m_comparator.size() > v.size())
2607 return false;
2608 for (auto const& comparator : m_comparator) {
2609 auto present = false;
2610 for (const auto& el : v) {
2611 if (el == comparator) {
2612 present = true;
2613 break;
2614 }
2615 }
2616 if (!present) {
2617 return false;
2618 }
2619 }
2620 return true;
2621 }
2622 std::string describe() const override {
2623 return "Contains: " + ::Catch::Detail::stringify( m_comparator );
2624 }
2625
2626 std::vector<T> const& m_comparator;
2627 };
2628
2629 template<typename T>
2630 struct EqualsMatcher : MatcherBase<std::vector<T>> {
2631
2632 EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
2633
2634 bool match(std::vector<T> const &v) const override {
2635 // !TBD: This currently works if all elements can be compared using !=
2636 // - a more general approach would be via a compare template that defaults
2637 // to using !=. but could be specialised for, e.g. std::vector<T> etc
2638 // - then just call that directly
2639 if (m_comparator.size() != v.size())
2640 return false;
2641 for (std::size_t i = 0; i < v.size(); ++i)
2642 if (m_comparator[i] != v[i])
2643 return false;
2644 return true;
2645 }
2646 std::string describe() const override {
2647 return "Equals: " + ::Catch::Detail::stringify( m_comparator );
2648 }
2649 std::vector<T> const& m_comparator;
2650 };
2651
2652 template<typename T>
2653 struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
2654 UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
2655 bool match(std::vector<T> const& vec) const override {
2656 // Note: This is a reimplementation of std::is_permutation,
2657 // because I don't want to include <algorithm> inside the common path
2658 if (m_target.size() != vec.size()) {
2659 return false;
2660 }
2661 auto lfirst = m_target.begin(), llast = m_target.end();
2662 auto rfirst = vec.begin(), rlast = vec.end();
2663 // Cut common prefix to optimize checking of permuted parts
2664 while (lfirst != llast && *lfirst != *rfirst) {
2665 ++lfirst; ++rfirst;
2666 }
2667 if (lfirst == llast) {
2668 return true;
2669 }
2670
2671 for (auto mid = lfirst; mid != llast; ++mid) {
2672 // Skip already counted items
2673 if (Detail::contains(lfirst, mid, *mid)) {
2674 continue;
2675 }
2676 size_t num_vec = Detail::count(rfirst, rlast, *mid);
2677 if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
2678 return false;
2679 }
2680 }
2681
2682 return true;
2683 }
2684
2685 std::string describe() const override {
2686 return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);
2687 }
2688 private:
2689 std::vector<T> const& m_target;
2690 };
2691
2692 } // namespace Vector
2693
2694 // The following functions create the actual matcher objects.
2695 // This allows the types to be inferred
2696
2697 template<typename T>
2698 Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
2699 return Vector::ContainsMatcher<T>( comparator );
2700 }
2701
2702 template<typename T>
2704 return Vector::ContainsElementMatcher<T>( comparator );
2705 }
2706
2707 template<typename T>
2708 Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
2709 return Vector::EqualsMatcher<T>( comparator );
2710 }
2711
2712 template<typename T>
2714 return Vector::UnorderedEqualsMatcher<T>(target);
2715 }
2716
2717} // namespace Matchers
2718} // namespace Catch
2719
2720// end catch_matchers_vector.h
2721namespace Catch {
2722
2723 template<typename ArgT, typename MatcherT>
2725 ArgT const& m_arg;
2726 MatcherT m_matcher;
2727 StringRef m_matcherString;
2728 public:
2729 MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString )
2730 : ITransientExpression{ true, matcher.match( arg ) },
2731 m_arg( arg ),
2732 m_matcher( matcher ),
2733 m_matcherString( matcherString )
2734 {}
2735
2736 void streamReconstructedExpression( std::ostream &os ) const override {
2737 auto matcherAsString = m_matcher.toString();
2738 os << Catch::Detail::stringify( m_arg ) << ' ';
2739 if( matcherAsString == Detail::unprintableString )
2740 os << m_matcherString;
2741 else
2742 os << matcherAsString;
2743 }
2744 };
2745
2747
2748 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString );
2749
2750 template<typename ArgT, typename MatcherT>
2751 auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr<ArgT, MatcherT> {
2752 return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );
2753 }
2754
2755} // namespace Catch
2756
2758#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
2759 do { \
2760 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
2761 INTERNAL_CATCH_TRY { \
2762 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \
2763 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
2764 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2765 } while( false )
2766
2768#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
2769 do { \
2770 Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
2771 if( catchAssertionHandler.allowThrows() ) \
2772 try { \
2773 static_cast<void>(__VA_ARGS__ ); \
2774 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
2775 } \
2776 catch( exceptionType const& ex ) { \
2777 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \
2778 } \
2779 catch( ... ) { \
2780 catchAssertionHandler.handleUnexpectedInflightException(); \
2781 } \
2782 else \
2783 catchAssertionHandler.handleThrowingCallSkipped(); \
2784 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
2785 } while( false )
2786
2787// end catch_capture_matchers.h
2788#endif
2789
2790// These files are included here so the single_include script doesn't put them
2791// in the conditionally compiled sections
2792// start catch_test_case_info.h
2793
2794#include <string>
2795#include <vector>
2796#include <memory>
2797
2798#ifdef __clang__
2799#pragma clang diagnostic push
2800#pragma clang diagnostic ignored "-Wpadded"
2801#endif
2802
2803namespace Catch {
2804
2805 struct ITestInvoker;
2806
2809 None = 0,
2810 IsHidden = 1 << 1,
2811 ShouldFail = 1 << 2,
2812 MayFail = 1 << 3,
2813 Throws = 1 << 4,
2814 NonPortable = 1 << 5,
2815 Benchmark = 1 << 6
2817
2819 std::string const& _className,
2820 std::string const& _description,
2821 std::vector<std::string> const& _tags,
2822 SourceLineInfo const& _lineInfo );
2823
2824 friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags );
2825
2826 bool isHidden() const;
2827 bool throws() const;
2828 bool okToFail() const;
2829 bool expectedToFail() const;
2830
2832
2836 std::vector<std::string> tags;
2837 std::vector<std::string> lcaseTags;
2840 };
2841
2842 class TestCase : public TestCaseInfo {
2843 public:
2844
2845 TestCase( ITestInvoker* testCase, TestCaseInfo&& info );
2846
2847 TestCase withName( std::string const& _newName ) const;
2848
2849 void invoke() const;
2850
2852
2853 bool operator == ( TestCase const& other ) const;
2854 bool operator < ( TestCase const& other ) const;
2855
2856 private:
2857 std::shared_ptr<ITestInvoker> test;
2858 };
2859
2861 std::string const& className,
2862 NameAndTags const& nameAndTags,
2863 SourceLineInfo const& lineInfo );
2864}
2865
2866#ifdef __clang__
2867#pragma clang diagnostic pop
2868#endif
2869
2870// end catch_test_case_info.h
2871// start catch_interfaces_runner.h
2872
2873namespace Catch {
2874
2875 struct IRunner {
2876 virtual ~IRunner();
2877 virtual bool aborting() const = 0;
2878 };
2879}
2880
2881// end catch_interfaces_runner.h
2882
2883#ifdef __OBJC__
2884// start catch_objc.hpp
2885
2886#import <objc/runtime.h>
2887
2888#include <string>
2889
2890// NB. Any general catch headers included here must be included
2891// in catch.hpp first to make sure they are included by the single
2892// header for non obj-usage
2893
2895// This protocol is really only here for (self) documenting purposes, since
2896// all its methods are optional.
2897@protocol OcFixture
2898
2899@optional
2900
2901-(void) setUp;
2902-(void) tearDown;
2903
2904@end
2905
2906namespace Catch {
2907
2908 class OcMethod : public ITestInvoker {
2909
2910 public:
2911 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2912
2913 virtual void invoke() const {
2914 id obj = [[m_cls alloc] init];
2915
2916 performOptionalSelector( obj, @selector(setUp) );
2917 performOptionalSelector( obj, m_sel );
2918 performOptionalSelector( obj, @selector(tearDown) );
2919
2920 arcSafeRelease( obj );
2921 }
2922 private:
2923 virtual ~OcMethod() {}
2924
2925 Class m_cls;
2926 SEL m_sel;
2927 };
2928
2929 namespace Detail{
2930
2931 inline std::string getAnnotation( Class cls,
2932 std::string const& annotationName,
2933 std::string const& testCaseName ) {
2934 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2935 SEL sel = NSSelectorFromString( selStr );
2936 arcSafeRelease( selStr );
2937 id value = performOptionalSelector( cls, sel );
2938 if( value )
2939 return [(NSString*)value UTF8String];
2940 return "";
2941 }
2942 }
2943
2944 inline std::size_t registerTestMethods() {
2945 std::size_t noTestMethods = 0;
2946 int noClasses = objc_getClassList( nullptr, 0 );
2947
2948 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
2949 objc_getClassList( classes, noClasses );
2950
2951 for( int c = 0; c < noClasses; c++ ) {
2952 Class cls = classes[c];
2953 {
2954 u_int count;
2955 Method* methods = class_copyMethodList( cls, &count );
2956 for( u_int m = 0; m < count ; m++ ) {
2957 SEL selector = method_getName(methods[m]);
2958 std::string methodName = sel_getName(selector);
2959 if( startsWith( methodName, "Catch_TestCase_" ) ) {
2960 std::string testCaseName = methodName.substr( 15 );
2961 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2962 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
2963 const char* className = class_getName( cls );
2964
2965 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo("",0) ) );
2966 noTestMethods++;
2967 }
2968 }
2969 free(methods);
2970 }
2971 }
2972 return noTestMethods;
2973 }
2974
2975#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
2976
2977 namespace Matchers {
2978 namespace Impl {
2979 namespace NSStringMatchers {
2980
2981 struct StringHolder : MatcherBase<NSString*>{
2982 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
2983 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
2984 StringHolder() {
2985 arcSafeRelease( m_substr );
2986 }
2987
2988 bool match( NSString* arg ) const override {
2989 return false;
2990 }
2991
2992 NSString* CATCH_ARC_STRONG m_substr;
2993 };
2994
2995 struct Equals : StringHolder {
2996 Equals( NSString* substr ) : StringHolder( substr ){}
2997
2998 bool match( NSString* str ) const override {
2999 return (str != nil || m_substr == nil ) &&
3000 [str isEqualToString:m_substr];
3001 }
3002
3003 std::string describe() const override {
3004 return "equals string: " + Catch::Detail::stringify( m_substr );
3005 }
3006 };
3007
3008 struct Contains : StringHolder {
3009 Contains( NSString* substr ) : StringHolder( substr ){}
3010
3011 bool match( NSString* str ) const {
3012 return (str != nil || m_substr == nil ) &&
3013 [str rangeOfString:m_substr].location != NSNotFound;
3014 }
3015
3016 std::string describe() const override {
3017 return "contains string: " + Catch::Detail::stringify( m_substr );
3018 }
3019 };
3020
3021 struct StartsWith : StringHolder {
3022 StartsWith( NSString* substr ) : StringHolder( substr ){}
3023
3024 bool match( NSString* str ) const override {
3025 return (str != nil || m_substr == nil ) &&
3026 [str rangeOfString:m_substr].location == 0;
3027 }
3028
3029 std::string describe() const override {
3030 return "starts with: " + Catch::Detail::stringify( m_substr );
3031 }
3032 };
3033 struct EndsWith : StringHolder {
3034 EndsWith( NSString* substr ) : StringHolder( substr ){}
3035
3036 bool match( NSString* str ) const override {
3037 return (str != nil || m_substr == nil ) &&
3038 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
3039 }
3040
3041 std::string describe() const override {
3042 return "ends with: " + Catch::Detail::stringify( m_substr );
3043 }
3044 };
3045
3046 } // namespace NSStringMatchers
3047 } // namespace Impl
3048
3050 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3051
3053 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
3054
3056 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
3057
3059 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3060
3061 } // namespace Matchers
3062
3063 using namespace Matchers;
3064
3065#endif // CATCH_CONFIG_DISABLE_MATCHERS
3066
3067} // namespace Catch
3068
3070#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix
3071#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \
3072+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \
3073{ \
3074return @ name; \
3075} \
3076+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \
3077{ \
3078return @ desc; \
3079} \
3080-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )
3081
3082#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )
3083
3084// end catch_objc.hpp
3085#endif
3086
3087#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES
3088// start catch_external_interfaces.h
3089
3090// start catch_reporter_bases.hpp
3091
3092// start catch_interfaces_reporter.h
3093
3094// start catch_config.hpp
3095
3096// start catch_test_spec_parser.h
3097
3098#ifdef __clang__
3099#pragma clang diagnostic push
3100#pragma clang diagnostic ignored "-Wpadded"
3101#endif
3102
3103// start catch_test_spec.h
3104
3105#ifdef __clang__
3106#pragma clang diagnostic push
3107#pragma clang diagnostic ignored "-Wpadded"
3108#endif
3109
3110// start catch_wildcard_pattern.h
3111
3112namespace Catch
3113{
3114 class WildcardPattern {
3115 enum WildcardPosition {
3116 NoWildcard = 0,
3117 WildcardAtStart = 1,
3118 WildcardAtEnd = 2,
3119 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3120 };
3121
3122 public:
3123
3124 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity );
3125 virtual ~WildcardPattern() = default;
3126 virtual bool matches( std::string const& str ) const;
3127
3128 private:
3129 std::string adjustCase( std::string const& str ) const;
3130 CaseSensitive::Choice m_caseSensitivity;
3131 WildcardPosition m_wildcard = NoWildcard;
3132 std::string m_pattern;
3133 };
3134}
3135
3136// end catch_wildcard_pattern.h
3137#include <string>
3138#include <vector>
3139#include <memory>
3140
3141namespace Catch {
3142
3143 class TestSpec {
3144 struct Pattern {
3145 virtual ~Pattern();
3146 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3147 };
3148 using PatternPtr = std::shared_ptr<Pattern>;
3149
3150 class NamePattern : public Pattern {
3151 public:
3152 NamePattern( std::string const& name );
3153 virtual ~NamePattern();
3154 virtual bool matches( TestCaseInfo const& testCase ) const override;
3155 private:
3156 WildcardPattern m_wildcardPattern;
3157 };
3158
3159 class TagPattern : public Pattern {
3160 public:
3161 TagPattern( std::string const& tag );
3162 virtual ~TagPattern();
3163 virtual bool matches( TestCaseInfo const& testCase ) const override;
3164 private:
3165 std::string m_tag;
3166 };
3167
3168 class ExcludedPattern : public Pattern {
3169 public:
3170 ExcludedPattern( PatternPtr const& underlyingPattern );
3171 virtual ~ExcludedPattern();
3172 virtual bool matches( TestCaseInfo const& testCase ) const override;
3173 private:
3174 PatternPtr m_underlyingPattern;
3175 };
3176
3177 struct Filter {
3178 std::vector<PatternPtr> m_patterns;
3179
3180 bool matches( TestCaseInfo const& testCase ) const;
3181 };
3182
3183 public:
3184 bool hasFilters() const;
3185 bool matches( TestCaseInfo const& testCase ) const;
3186
3187 private:
3188 std::vector<Filter> m_filters;
3189
3190 friend class TestSpecParser;
3191 };
3192}
3193
3194#ifdef __clang__
3195#pragma clang diagnostic pop
3196#endif
3197
3198// end catch_test_spec.h
3199// start catch_interfaces_tag_alias_registry.h
3200
3201#include <string>
3202
3203namespace Catch {
3204
3205 struct TagAlias;
3206
3207 struct ITagAliasRegistry {
3208 virtual ~ITagAliasRegistry();
3209 // Nullptr if not present
3210 virtual TagAlias const* find( std::string const& alias ) const = 0;
3211 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
3212
3213 static ITagAliasRegistry const& get();
3214 };
3215
3216} // end namespace Catch
3217
3218// end catch_interfaces_tag_alias_registry.h
3219namespace Catch {
3220
3221 class TestSpecParser {
3222 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
3223 Mode m_mode = None;
3224 bool m_exclusion = false;
3225 std::size_t m_start = std::string::npos, m_pos = 0;
3226 std::string m_arg;
3227 std::vector<std::size_t> m_escapeChars;
3228 TestSpec::Filter m_currentFilter;
3229 TestSpec m_testSpec;
3230 ITagAliasRegistry const* m_tagAliases = nullptr;
3231
3232 public:
3233 TestSpecParser( ITagAliasRegistry const& tagAliases );
3234
3235 TestSpecParser& parse( std::string const& arg );
3236 TestSpec testSpec();
3237
3238 private:
3239 void visitChar( char c );
3240 void startNewMode( Mode mode, std::size_t start );
3241 void escape();
3242 std::string subString() const;
3243
3244 template<typename T>
3245 void addPattern() {
3246 std::string token = subString();
3247 for( std::size_t i = 0; i < m_escapeChars.size(); ++i )
3248 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
3249 m_escapeChars.clear();
3250 if( startsWith( token, "exclude:" ) ) {
3251 m_exclusion = true;
3252 token = token.substr( 8 );
3253 }
3254 if( !token.empty() ) {
3255 TestSpec::PatternPtr pattern = std::make_shared<T>( token );
3256 if( m_exclusion )
3257 pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
3258 m_currentFilter.m_patterns.push_back( pattern );
3259 }
3260 m_exclusion = false;
3261 m_mode = None;
3262 }
3263
3264 void addFilter();
3265 };
3266 TestSpec parseTestSpec( std::string const& arg );
3267
3268} // namespace Catch
3269
3270#ifdef __clang__
3271#pragma clang diagnostic pop
3272#endif
3273
3274// end catch_test_spec_parser.h
3275// start catch_interfaces_config.h
3276
3277#include <iosfwd>
3278#include <string>
3279#include <vector>
3280#include <memory>
3281
3282namespace Catch {
3283
3284 enum class Verbosity {
3285 Quiet = 0,
3286 Normal,
3287 High
3288 };
3289
3290 struct WarnAbout { enum What {
3291 Nothing = 0x00,
3292 NoAssertions = 0x01,
3293 NoTests = 0x02
3294 }; };
3295
3296 struct ShowDurations { enum OrNot {
3297 DefaultForReporter,
3298 Always,
3299 Never
3300 }; };
3301 struct RunTests { enum InWhatOrder {
3302 InDeclarationOrder,
3303 InLexicographicalOrder,
3304 InRandomOrder
3305 }; };
3306 struct UseColour { enum YesOrNo {
3307 Auto,
3308 Yes,
3309 No
3310 }; };
3311 struct WaitForKeypress { enum When {
3312 Never,
3313 BeforeStart = 1,
3314 BeforeExit = 2,
3315 BeforeStartAndExit = BeforeStart | BeforeExit
3316 }; };
3317
3318 class TestSpec;
3319
3320 struct IConfig : NonCopyable {
3321
3322 virtual ~IConfig();
3323
3324 virtual bool allowThrows() const = 0;
3325 virtual std::ostream& stream() const = 0;
3326 virtual std::string name() const = 0;
3327 virtual bool includeSuccessfulResults() const = 0;
3328 virtual bool shouldDebugBreak() const = 0;
3329 virtual bool warnAboutMissingAssertions() const = 0;
3330 virtual bool warnAboutNoTests() const = 0;
3331 virtual int abortAfter() const = 0;
3332 virtual bool showInvisibles() const = 0;
3333 virtual ShowDurations::OrNot showDurations() const = 0;
3334 virtual TestSpec const& testSpec() const = 0;
3335 virtual bool hasTestFilters() const = 0;
3336 virtual RunTests::InWhatOrder runOrder() const = 0;
3337 virtual unsigned int rngSeed() const = 0;
3338 virtual int benchmarkResolutionMultiple() const = 0;
3339 virtual UseColour::YesOrNo useColour() const = 0;
3340 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
3341 virtual Verbosity verbosity() const = 0;
3342 };
3343
3344 using IConfigPtr = std::shared_ptr<IConfig const>;
3345}
3346
3347// end catch_interfaces_config.h
3348// Libstdc++ doesn't like incomplete classes for unique_ptr
3349
3350#include <memory>
3351#include <vector>
3352#include <string>
3353
3354#ifndef CATCH_CONFIG_CONSOLE_WIDTH
3355#define CATCH_CONFIG_CONSOLE_WIDTH 80
3356#endif
3357
3358namespace Catch {
3359
3360 struct IStream;
3361
3362 struct ConfigData {
3363 bool listTests = false;
3364 bool listTags = false;
3365 bool listReporters = false;
3366 bool listTestNamesOnly = false;
3367
3368 bool showSuccessfulTests = false;
3369 bool shouldDebugBreak = false;
3370 bool noThrow = false;
3371 bool showHelp = false;
3372 bool showInvisibles = false;
3373 bool filenamesAsTags = false;
3374 bool libIdentify = false;
3375
3376 int abortAfter = -1;
3377 unsigned int rngSeed = 0;
3378 int benchmarkResolutionMultiple = 100;
3379
3380 Verbosity verbosity = Verbosity::Normal;
3381 WarnAbout::What warnings = WarnAbout::Nothing;
3382 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
3383 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
3384 UseColour::YesOrNo useColour = UseColour::Auto;
3385 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
3386
3387 std::string outputFilename;
3389 std::string processName;
3390#ifndef CATCH_CONFIG_DEFAULT_REPORTER
3391#define CATCH_CONFIG_DEFAULT_REPORTER "console"
3392#endif
3393 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
3394#undef CATCH_CONFIG_DEFAULT_REPORTER
3395
3396 std::vector<std::string> testsOrTags;
3397 std::vector<std::string> sectionsToRun;
3398 };
3399
3400 class Config : public IConfig {
3401 public:
3402
3403 Config() = default;
3404 Config( ConfigData const& data );
3405 virtual ~Config() = default;
3406
3407 std::string const& getFilename() const;
3408
3409 bool listTests() const;
3410 bool listTestNamesOnly() const;
3411 bool listTags() const;
3412 bool listReporters() const;
3413
3414 std::string getProcessName() const;
3415 std::string const& getReporterName() const;
3416
3417 std::vector<std::string> const& getTestsOrTags() const;
3418 std::vector<std::string> const& getSectionsToRun() const override;
3419
3420 virtual TestSpec const& testSpec() const override;
3421 bool hasTestFilters() const override;
3422
3423 bool showHelp() const;
3424
3425 // IConfig interface
3426 bool allowThrows() const override;
3427 std::ostream& stream() const override;
3428 std::string name() const override;
3429 bool includeSuccessfulResults() const override;
3430 bool warnAboutMissingAssertions() const override;
3431 bool warnAboutNoTests() const override;
3432 ShowDurations::OrNot showDurations() const override;
3433 RunTests::InWhatOrder runOrder() const override;
3434 unsigned int rngSeed() const override;
3435 int benchmarkResolutionMultiple() const override;
3436 UseColour::YesOrNo useColour() const override;
3437 bool shouldDebugBreak() const override;
3438 int abortAfter() const override;
3439 bool showInvisibles() const override;
3440 Verbosity verbosity() const override;
3441
3442 private:
3443
3444 IStream const* openStream();
3445 ConfigData m_data;
3446
3447 std::unique_ptr<IStream const> m_stream;
3448 TestSpec m_testSpec;
3449 bool m_hasTestFilters = false;
3450 };
3451
3452} // end namespace Catch
3453
3454// end catch_config.hpp
3455// start catch_assertionresult.h
3456
3457#include <string>
3458
3459namespace Catch {
3460
3461 struct AssertionResultData
3462 {
3463 AssertionResultData() = delete;
3464
3465 AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );
3466
3467 std::string message;
3468 mutable std::string reconstructedExpression;
3469 LazyExpression lazyExpression;
3470 ResultWas::OfType resultType;
3471
3472 std::string reconstructExpression() const;
3473 };
3474
3475 class AssertionResult {
3476 public:
3477 AssertionResult() = delete;
3478 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
3479
3480 bool isOk() const;
3481 bool succeeded() const;
3482 ResultWas::OfType getResultType() const;
3483 bool hasExpression() const;
3484 bool hasMessage() const;
3485 std::string getExpression() const;
3486 std::string getExpressionInMacro() const;
3487 bool hasExpandedExpression() const;
3488 std::string getExpandedExpression() const;
3489 std::string getMessage() const;
3490 SourceLineInfo getSourceInfo() const;
3491 StringRef getTestMacroName() const;
3492
3493 //protected:
3494 AssertionInfo m_info;
3495 AssertionResultData m_resultData;
3496 };
3497
3498} // end namespace Catch
3499
3500// end catch_assertionresult.h
3501// start catch_option.hpp
3502
3503namespace Catch {
3504
3505 // An optional type
3506 template<typename T>
3507 class Option {
3508 public:
3509 Option() : nullableValue( nullptr ) {}
3510 Option( T const& _value )
3511 : nullableValue( new( storage ) T( _value ) )
3512 {}
3513 Option( Option const& _other )
3514 : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )
3515 {}
3516
3517 ~Option() {
3518 reset();
3519 }
3520
3521 Option& operator= ( Option const& _other ) {
3522 if( &_other != this ) {
3523 reset();
3524 if( _other )
3525 nullableValue = new( storage ) T( *_other );
3526 }
3527 return *this;
3528 }
3529 Option& operator = ( T const& _value ) {
3530 reset();
3531 nullableValue = new( storage ) T( _value );
3532 return *this;
3533 }
3534
3535 void reset() {
3536 if( nullableValue )
3537 nullableValue->~T();
3538 nullableValue = nullptr;
3539 }
3540
3541 T& operator*() { return *nullableValue; }
3542 T const& operator*() const { return *nullableValue; }
3543 T* operator->() { return nullableValue; }
3544 const T* operator->() const { return nullableValue; }
3545
3546 T valueOr( T const& defaultValue ) const {
3547 return nullableValue ? *nullableValue : defaultValue;
3548 }
3549
3550 bool some() const { return nullableValue != nullptr; }
3551 bool none() const { return nullableValue == nullptr; }
3552
3553 bool operator !() const { return nullableValue == nullptr; }
3554 explicit operator bool() const {
3555 return some();
3556 }
3557
3558 private:
3559 T *nullableValue;
3560 alignas(alignof(T)) char storage[sizeof(T)];
3561 };
3562
3563} // end namespace Catch
3564
3565// end catch_option.hpp
3566#include <string>
3567#include <iosfwd>
3568#include <map>
3569#include <set>
3570#include <memory>
3571
3572namespace Catch {
3573
3574 struct ReporterConfig {
3575 explicit ReporterConfig( IConfigPtr const& _fullConfig );
3576
3577 ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream );
3578
3579 std::ostream& stream() const;
3580 IConfigPtr fullConfig() const;
3581
3582 private:
3583 std::ostream* m_stream;
3584 IConfigPtr m_fullConfig;
3585 };
3586
3587 struct ReporterPreferences {
3588 bool shouldRedirectStdOut = false;
3589 };
3590
3591 template<typename T>
3592 struct LazyStat : Option<T> {
3593 LazyStat& operator=( T const& _value ) {
3594 Option<T>::operator=( _value );
3595 used = false;
3596 return *this;
3597 }
3598 void reset() {
3599 Option<T>::reset();
3600 used = false;
3601 }
3602 bool used = false;
3603 };
3604
3605 struct TestRunInfo {
3606 TestRunInfo( std::string const& _name );
3608 };
3609 struct GroupInfo {
3610 GroupInfo( std::string const& _name,
3611 std::size_t _groupIndex,
3612 std::size_t _groupsCount );
3613
3615 std::size_t groupIndex;
3616 std::size_t groupsCounts;
3617 };
3618
3619 struct AssertionStats {
3620 AssertionStats( AssertionResult const& _assertionResult,
3621 std::vector<MessageInfo> const& _infoMessages,
3622 Totals const& _totals );
3623
3624 AssertionStats( AssertionStats const& ) = default;
3625 AssertionStats( AssertionStats && ) = default;
3626 AssertionStats& operator = ( AssertionStats const& ) = default;
3627 AssertionStats& operator = ( AssertionStats && ) = default;
3628 virtual ~AssertionStats();
3629
3630 AssertionResult assertionResult;
3631 std::vector<MessageInfo> infoMessages;
3632 Totals totals;
3633 };
3634
3635 struct SectionStats {
3636 SectionStats( SectionInfo const& _sectionInfo,
3637 Counts const& _assertions,
3638 double _durationInSeconds,
3639 bool _missingAssertions );
3640 SectionStats( SectionStats const& ) = default;
3641 SectionStats( SectionStats && ) = default;
3642 SectionStats& operator = ( SectionStats const& ) = default;
3643 SectionStats& operator = ( SectionStats && ) = default;
3644 virtual ~SectionStats();
3645
3646 SectionInfo sectionInfo;
3647 Counts assertions;
3648 double durationInSeconds;
3649 bool missingAssertions;
3650 };
3651
3652 struct TestCaseStats {
3653 TestCaseStats( TestCaseInfo const& _testInfo,
3654 Totals const& _totals,
3655 std::string const& _stdOut,
3656 std::string const& _stdErr,
3657 bool _aborting );
3658
3659 TestCaseStats( TestCaseStats const& ) = default;
3660 TestCaseStats( TestCaseStats && ) = default;
3661 TestCaseStats& operator = ( TestCaseStats const& ) = default;
3662 TestCaseStats& operator = ( TestCaseStats && ) = default;
3663 virtual ~TestCaseStats();
3664
3665 TestCaseInfo testInfo;
3666 Totals totals;
3667 std::string stdOut;
3668 std::string stdErr;
3669 bool aborting;
3670 };
3671
3672 struct TestGroupStats {
3673 TestGroupStats( GroupInfo const& _groupInfo,
3674 Totals const& _totals,
3675 bool _aborting );
3676 TestGroupStats( GroupInfo const& _groupInfo );
3677
3678 TestGroupStats( TestGroupStats const& ) = default;
3679 TestGroupStats( TestGroupStats && ) = default;
3680 TestGroupStats& operator = ( TestGroupStats const& ) = default;
3681 TestGroupStats& operator = ( TestGroupStats && ) = default;
3682 virtual ~TestGroupStats();
3683
3684 GroupInfo groupInfo;
3685 Totals totals;
3686 bool aborting;
3687 };
3688
3689 struct TestRunStats {
3690 TestRunStats( TestRunInfo const& _runInfo,
3691 Totals const& _totals,
3692 bool _aborting );
3693
3694 TestRunStats( TestRunStats const& ) = default;
3695 TestRunStats( TestRunStats && ) = default;
3696 TestRunStats& operator = ( TestRunStats const& ) = default;
3697 TestRunStats& operator = ( TestRunStats && ) = default;
3698 virtual ~TestRunStats();
3699
3700 TestRunInfo runInfo;
3701 Totals totals;
3702 bool aborting;
3703 };
3704
3705 struct BenchmarkInfo {
3707 };
3708 struct BenchmarkStats {
3709 BenchmarkInfo info;
3710 std::size_t iterations;
3711 uint64_t elapsedTimeInNanoseconds;
3712 };
3713
3714 struct IStreamingReporter {
3715 virtual ~IStreamingReporter() = default;
3716
3717 // Implementing class must also provide the following static methods:
3718 // static std::string getDescription();
3719 // static std::set<Verbosity> getSupportedVerbosities()
3720
3721 virtual ReporterPreferences getPreferences() const = 0;
3722
3723 virtual void noMatchingTestCases( std::string const& spec ) = 0;
3724
3725 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
3726 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
3727
3728 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
3729 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
3730
3731 // *** experimental ***
3732 virtual void benchmarkStarting( BenchmarkInfo const& ) {}
3733
3734 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
3735
3736 // The return value indicates if the messages buffer should be cleared:
3737 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
3738
3739 // *** experimental ***
3740 virtual void benchmarkEnded( BenchmarkStats const& ) {}
3741
3742 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
3743 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
3744 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
3745 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
3746
3747 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
3748
3749 // Default empty implementation provided
3750 virtual void fatalErrorEncountered( StringRef name );
3751
3752 virtual bool isMulti() const;
3753 };
3754 using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;
3755
3756 struct IReporterFactory {
3757 virtual ~IReporterFactory();
3758 virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0;
3759 virtual std::string getDescription() const = 0;
3760 };
3761 using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;
3762
3763 struct IReporterRegistry {
3764 using FactoryMap = std::map<std::string, IReporterFactoryPtr>;
3765 using Listeners = std::vector<IReporterFactoryPtr>;
3766
3767 virtual ~IReporterRegistry();
3768 virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0;
3769 virtual FactoryMap const& getFactories() const = 0;
3770 virtual Listeners const& getListeners() const = 0;
3771 };
3772
3773} // end namespace Catch
3774
3775// end catch_interfaces_reporter.h
3776#include <algorithm>
3777#include <cstring>
3778#include <cfloat>
3779#include <cstdio>
3780#include <cassert>
3781#include <memory>
3782#include <ostream>
3783
3784namespace Catch {
3785 void prepareExpandedExpression(AssertionResult& result);
3786
3787 // Returns double formatted as %.3f (format expected on output)
3788 std::string getFormattedDuration( double duration );
3789
3790 template<typename DerivedT>
3791 struct StreamingReporterBase : IStreamingReporter {
3792
3793 StreamingReporterBase( ReporterConfig const& _config )
3794 : m_config( _config.fullConfig() ),
3795 stream( _config.stream() )
3796 {
3797 m_reporterPrefs.shouldRedirectStdOut = false;
3798 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
3799 throw std::domain_error( "Verbosity level not supported by this reporter" );
3800 }
3801
3802 ReporterPreferences getPreferences() const override {
3803 return m_reporterPrefs;
3804 }
3805
3806 static std::set<Verbosity> getSupportedVerbosities() {
3807 return { Verbosity::Normal };
3808 }
3809
3810 ~StreamingReporterBase() override = default;
3811
3812 void noMatchingTestCases(std::string const&) override {}
3813
3814 void testRunStarting(TestRunInfo const& _testRunInfo) override {
3815 currentTestRunInfo = _testRunInfo;
3816 }
3817 void testGroupStarting(GroupInfo const& _groupInfo) override {
3818 currentGroupInfo = _groupInfo;
3819 }
3820
3821 void testCaseStarting(TestCaseInfo const& _testInfo) override {
3822 currentTestCaseInfo = _testInfo;
3823 }
3824 void sectionStarting(SectionInfo const& _sectionInfo) override {
3825 m_sectionStack.push_back(_sectionInfo);
3826 }
3827
3828 void sectionEnded(SectionStats const& /* _sectionStats */) override {
3829 m_sectionStack.pop_back();
3830 }
3831 void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
3832 currentTestCaseInfo.reset();
3833 }
3834 void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override {
3835 currentGroupInfo.reset();
3836 }
3837 void testRunEnded(TestRunStats const& /* _testRunStats */) override {
3838 currentTestCaseInfo.reset();
3839 currentGroupInfo.reset();
3840 currentTestRunInfo.reset();
3841 }
3842
3843 void skipTest(TestCaseInfo const&) override {
3844 // Don't do anything with this by default.
3845 // It can optionally be overridden in the derived class.
3846 }
3847
3848 IConfigPtr m_config;
3849 std::ostream& stream;
3850
3851 LazyStat<TestRunInfo> currentTestRunInfo;
3852 LazyStat<GroupInfo> currentGroupInfo;
3853 LazyStat<TestCaseInfo> currentTestCaseInfo;
3854
3855 std::vector<SectionInfo> m_sectionStack;
3856 ReporterPreferences m_reporterPrefs;
3857 };
3858
3859 template<typename DerivedT>
3860 struct CumulativeReporterBase : IStreamingReporter {
3861 template<typename T, typename ChildNodeT>
3862 struct Node {
3863 explicit Node( T const& _value ) : value( _value ) {}
3864 virtual ~Node() {}
3865
3866 using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;
3867 T value;
3868 ChildNodes children;
3869 };
3870 struct SectionNode {
3871 explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}
3872 virtual ~SectionNode() = default;
3873
3874 bool operator == (SectionNode const& other) const {
3875 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
3876 }
3877 bool operator == (std::shared_ptr<SectionNode> const& other) const {
3878 return operator==(*other);
3879 }
3880
3881 SectionStats stats;
3882 using ChildSections = std::vector<std::shared_ptr<SectionNode>>;
3883 using Assertions = std::vector<AssertionStats>;
3884 ChildSections childSections;
3885 Assertions assertions;
3886 std::string stdOut;
3887 std::string stdErr;
3888 };
3889
3890 struct BySectionInfo {
3891 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
3892 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
3893 bool operator() (std::shared_ptr<SectionNode> const& node) const {
3894 return ((node->stats.sectionInfo.name == m_other.name) &&
3895 (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
3896 }
3897 void operator=(BySectionInfo const&) = delete;
3898
3899 private:
3900 SectionInfo const& m_other;
3901 };
3902
3903 using TestCaseNode = Node<TestCaseStats, SectionNode>;
3904 using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
3905 using TestRunNode = Node<TestRunStats, TestGroupNode>;
3906
3907 CumulativeReporterBase( ReporterConfig const& _config )
3908 : m_config( _config.fullConfig() ),
3909 stream( _config.stream() )
3910 {
3911 m_reporterPrefs.shouldRedirectStdOut = false;
3912 if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )
3913 throw std::domain_error( "Verbosity level not supported by this reporter" );
3914 }
3915 ~CumulativeReporterBase() override = default;
3916
3917 ReporterPreferences getPreferences() const override {
3918 return m_reporterPrefs;
3919 }
3920
3921 static std::set<Verbosity> getSupportedVerbosities() {
3922 return { Verbosity::Normal };
3923 }
3924
3925 void testRunStarting( TestRunInfo const& ) override {}
3926 void testGroupStarting( GroupInfo const& ) override {}
3927
3928 void testCaseStarting( TestCaseInfo const& ) override {}
3929
3930 void sectionStarting( SectionInfo const& sectionInfo ) override {
3931 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
3932 std::shared_ptr<SectionNode> node;
3933 if( m_sectionStack.empty() ) {
3934 if( !m_rootSection )
3935 m_rootSection = std::make_shared<SectionNode>( incompleteStats );
3936 node = m_rootSection;
3937 }
3938 else {
3939 SectionNode& parentNode = *m_sectionStack.back();
3940 auto it =
3941 std::find_if( parentNode.childSections.begin(),
3942 parentNode.childSections.end(),
3943 BySectionInfo( sectionInfo ) );
3944 if( it == parentNode.childSections.end() ) {
3945 node = std::make_shared<SectionNode>( incompleteStats );
3946 parentNode.childSections.push_back( node );
3947 }
3948 else
3949 node = *it;
3950 }
3951 m_sectionStack.push_back( node );
3952 m_deepestSection = std::move(node);
3953 }
3954
3955 void assertionStarting(AssertionInfo const&) override {}
3956
3957 bool assertionEnded(AssertionStats const& assertionStats) override {
3958 assert(!m_sectionStack.empty());
3959 // AssertionResult holds a pointer to a temporary DecomposedExpression,
3960 // which getExpandedExpression() calls to build the expression string.
3961 // Our section stack copy of the assertionResult will likely outlive the
3962 // temporary, so it must be expanded or discarded now to avoid calling
3963 // a destroyed object later.
3964 prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );
3965 SectionNode& sectionNode = *m_sectionStack.back();
3966 sectionNode.assertions.push_back(assertionStats);
3967 return true;
3968 }
3969 void sectionEnded(SectionStats const& sectionStats) override {
3970 assert(!m_sectionStack.empty());
3971 SectionNode& node = *m_sectionStack.back();
3972 node.stats = sectionStats;
3973 m_sectionStack.pop_back();
3974 }
3975 void testCaseEnded(TestCaseStats const& testCaseStats) override {
3976 auto node = std::make_shared<TestCaseNode>(testCaseStats);
3977 assert(m_sectionStack.size() == 0);
3978 node->children.push_back(m_rootSection);
3979 m_testCases.push_back(node);
3980 m_rootSection.reset();
3981
3982 assert(m_deepestSection);
3983 m_deepestSection->stdOut = testCaseStats.stdOut;
3984 m_deepestSection->stdErr = testCaseStats.stdErr;
3985 }
3986 void testGroupEnded(TestGroupStats const& testGroupStats) override {
3987 auto node = std::make_shared<TestGroupNode>(testGroupStats);
3988 node->children.swap(m_testCases);
3989 m_testGroups.push_back(node);
3990 }
3991 void testRunEnded(TestRunStats const& testRunStats) override {
3992 auto node = std::make_shared<TestRunNode>(testRunStats);
3993 node->children.swap(m_testGroups);
3994 m_testRuns.push_back(node);
3995 testRunEndedCumulative();
3996 }
3997 virtual void testRunEndedCumulative() = 0;
3998
3999 void skipTest(TestCaseInfo const&) override {}
4000
4001 IConfigPtr m_config;
4002 std::ostream& stream;
4003 std::vector<AssertionStats> m_assertions;
4004 std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;
4005 std::vector<std::shared_ptr<TestCaseNode>> m_testCases;
4006 std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;
4007
4008 std::vector<std::shared_ptr<TestRunNode>> m_testRuns;
4009
4010 std::shared_ptr<SectionNode> m_rootSection;
4011 std::shared_ptr<SectionNode> m_deepestSection;
4012 std::vector<std::shared_ptr<SectionNode>> m_sectionStack;
4013 ReporterPreferences m_reporterPrefs;
4014 };
4015
4016 template<char C>
4017 char const* getLineOfChars() {
4018 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
4019 if( !*line ) {
4020 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
4021 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
4022 }
4023 return line;
4024 }
4025
4026 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
4027 TestEventListenerBase( ReporterConfig const& _config );
4028
4029 void assertionStarting(AssertionInfo const&) override;
4030 bool assertionEnded(AssertionStats const&) override;
4031 };
4032
4033} // end namespace Catch
4034
4035// end catch_reporter_bases.hpp
4036// start catch_console_colour.h
4037
4038namespace Catch {
4039
4040 struct Colour {
4041 enum Code {
4042 None = 0,
4043
4044 White,
4045 Red,
4046 Green,
4047 Blue,
4048 Cyan,
4049 Yellow,
4050 Grey,
4051
4052 Bright = 0x10,
4053
4054 BrightRed = Bright | Red,
4055 BrightGreen = Bright | Green,
4056 LightGrey = Bright | Grey,
4057 BrightWhite = Bright | White,
4058 BrightYellow = Bright | Yellow,
4059
4060 // By intention
4061 FileName = LightGrey,
4062 Warning = BrightYellow,
4063 ResultError = BrightRed,
4064 ResultSuccess = BrightGreen,
4065 ResultExpectedFailure = Warning,
4066
4067 Error = BrightRed,
4068 Success = Green,
4069
4070 OriginalExpression = Cyan,
4071 ReconstructedExpression = BrightYellow,
4072
4073 SecondaryText = LightGrey,
4074 Headers = White
4075 };
4076
4077 // Use constructed object for RAII guard
4078 Colour( Code _colourCode );
4079 Colour( Colour&& other ) noexcept;
4080 Colour& operator=( Colour&& other ) noexcept;
4081 ~Colour();
4082
4083 // Use static method for one-shot changes
4084 static void use( Code _colourCode );
4085
4086 private:
4087 bool m_moved = false;
4088 };
4089
4090 std::ostream& operator << ( std::ostream& os, Colour const& );
4091
4092} // end namespace Catch
4093
4094// end catch_console_colour.h
4095// start catch_reporter_registrars.hpp
4096
4097
4098namespace Catch {
4099
4100 template<typename T>
4101 class ReporterRegistrar {
4102
4103 class ReporterFactory : public IReporterFactory {
4104
4105 virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
4106 return std::unique_ptr<T>( new T( config ) );
4107 }
4108
4109 virtual std::string getDescription() const override {
4110 return T::getDescription();
4111 }
4112 };
4113
4114 public:
4115
4116 explicit ReporterRegistrar( std::string const& name ) {
4117 getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() );
4118 }
4119 };
4120
4121 template<typename T>
4122 class ListenerRegistrar {
4123
4124 class ListenerFactory : public IReporterFactory {
4125
4126 virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
4127 return std::unique_ptr<T>( new T( config ) );
4128 }
4129 virtual std::string getDescription() const override {
4130 return std::string();
4131 }
4132 };
4133
4134 public:
4135
4136 ListenerRegistrar() {
4137 getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() );
4138 }
4139 };
4140}
4141
4142#if !defined(CATCH_CONFIG_DISABLE)
4143
4144#define CATCH_REGISTER_REPORTER( name, reporterType ) \
4145 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
4146 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
4147 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
4148
4149#define CATCH_REGISTER_LISTENER( listenerType ) \
4150 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
4151 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
4152 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
4153#else // CATCH_CONFIG_DISABLE
4154
4155#define CATCH_REGISTER_REPORTER(name, reporterType)
4156#define CATCH_REGISTER_LISTENER(listenerType)
4157
4158#endif // CATCH_CONFIG_DISABLE
4159
4160// end catch_reporter_registrars.hpp
4161// Allow users to base their work off existing reporters
4162// start catch_reporter_compact.h
4163
4164namespace Catch {
4165
4166 struct CompactReporter : StreamingReporterBase<CompactReporter> {
4167
4168 using StreamingReporterBase::StreamingReporterBase;
4169
4170 ~CompactReporter() override;
4171
4172 static std::string getDescription();
4173
4174 ReporterPreferences getPreferences() const override;
4175
4176 void noMatchingTestCases(std::string const& spec) override;
4177
4178 void assertionStarting(AssertionInfo const&) override;
4179
4180 bool assertionEnded(AssertionStats const& _assertionStats) override;
4181
4182 void sectionEnded(SectionStats const& _sectionStats) override;
4183
4184 void testRunEnded(TestRunStats const& _testRunStats) override;
4185
4186 };
4187
4188} // end namespace Catch
4189
4190// end catch_reporter_compact.h
4191// start catch_reporter_console.h
4192
4193#if defined(_MSC_VER)
4194#pragma warning(push)
4195#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
4196 // Note that 4062 (not all labels are handled
4197 // and default is missing) is enabled
4198#endif
4199
4200namespace Catch {
4201 // Fwd decls
4202 struct SummaryColumn;
4203 class TablePrinter;
4204
4205 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
4206 std::unique_ptr<TablePrinter> m_tablePrinter;
4207
4208 ConsoleReporter(ReporterConfig const& config);
4209 ~ConsoleReporter() override;
4210 static std::string getDescription();
4211
4212 void noMatchingTestCases(std::string const& spec) override;
4213
4214 void assertionStarting(AssertionInfo const&) override;
4215
4216 bool assertionEnded(AssertionStats const& _assertionStats) override;
4217
4218 void sectionStarting(SectionInfo const& _sectionInfo) override;
4219 void sectionEnded(SectionStats const& _sectionStats) override;
4220
4221 void benchmarkStarting(BenchmarkInfo const& info) override;
4222 void benchmarkEnded(BenchmarkStats const& stats) override;
4223
4224 void testCaseEnded(TestCaseStats const& _testCaseStats) override;
4225 void testGroupEnded(TestGroupStats const& _testGroupStats) override;
4226 void testRunEnded(TestRunStats const& _testRunStats) override;
4227
4228 private:
4229
4230 void lazyPrint();
4231
4232 void lazyPrintWithoutClosingBenchmarkTable();
4233 void lazyPrintRunInfo();
4234 void lazyPrintGroupInfo();
4235 void printTestCaseAndSectionHeader();
4236
4237 void printClosedHeader(std::string const& _name);
4238 void printOpenHeader(std::string const& _name);
4239
4240 // if string has a : in first line will set indent to follow it on
4241 // subsequent lines
4242 void printHeaderString(std::string const& _string, std::size_t indent = 0);
4243
4244 void printTotals(Totals const& totals);
4245 void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row);
4246
4247 void printTotalsDivider(Totals const& totals);
4248 void printSummaryDivider();
4249
4250 private:
4251 bool m_headerPrinted = false;
4252 };
4253
4254} // end namespace Catch
4255
4256#if defined(_MSC_VER)
4257#pragma warning(pop)
4258#endif
4259
4260// end catch_reporter_console.h
4261// start catch_reporter_junit.h
4262
4263// start catch_xmlwriter.h
4264
4265#include <vector>
4266
4267namespace Catch {
4268
4269 class XmlEncode {
4270 public:
4271 enum ForWhat { ForTextNodes, ForAttributes };
4272
4273 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes );
4274
4275 void encodeTo( std::ostream& os ) const;
4276
4277 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );
4278
4279 private:
4280 std::string m_str;
4281 ForWhat m_forWhat;
4282 };
4283
4284 class XmlWriter {
4285 public:
4286
4287 class ScopedElement {
4288 public:
4289 ScopedElement( XmlWriter* writer );
4290
4291 ScopedElement( ScopedElement&& other ) noexcept;
4292 ScopedElement& operator=( ScopedElement&& other ) noexcept;
4293
4294 ~ScopedElement();
4295
4296 ScopedElement& writeText( std::string const& text, bool indent = true );
4297
4298 template<typename T>
4299 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
4300 m_writer->writeAttribute( name, attribute );
4301 return *this;
4302 }
4303
4304 private:
4305 mutable XmlWriter* m_writer = nullptr;
4306 };
4307
4308 XmlWriter( std::ostream& os = Catch::cout() );
4309 ~XmlWriter();
4310
4311 XmlWriter( XmlWriter const& ) = delete;
4312 XmlWriter& operator=( XmlWriter const& ) = delete;
4313
4314 XmlWriter& startElement( std::string const& name );
4315
4316 ScopedElement scopedElement( std::string const& name );
4317
4318 XmlWriter& endElement();
4319
4320 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );
4321
4322 XmlWriter& writeAttribute( std::string const& name, bool attribute );
4323
4324 template<typename T>
4325 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
4326 ReusableStringStream rss;
4327 rss << attribute;
4328 return writeAttribute( name, rss.str() );
4329 }
4330
4331 XmlWriter& writeText( std::string const& text, bool indent = true );
4332
4333 XmlWriter& writeComment( std::string const& text );
4334
4335 void writeStylesheetRef( std::string const& url );
4336
4337 XmlWriter& writeBlankLine();
4338
4339 void ensureTagClosed();
4340
4341 private:
4342
4343 void writeDeclaration();
4344
4345 void newlineIfNecessary();
4346
4347 bool m_tagIsOpen = false;
4348 bool m_needsNewline = false;
4349 std::vector<std::string> m_tags;
4350 std::string m_indent;
4351 std::ostream& m_os;
4352 };
4353
4354}
4355
4356// end catch_xmlwriter.h
4357namespace Catch {
4358
4359 class JunitReporter : public CumulativeReporterBase<JunitReporter> {
4360 public:
4361 JunitReporter(ReporterConfig const& _config);
4362
4363 ~JunitReporter() override;
4364
4365 static std::string getDescription();
4366
4367 void noMatchingTestCases(std::string const& /*spec*/) override;
4368
4369 void testRunStarting(TestRunInfo const& runInfo) override;
4370
4371 void testGroupStarting(GroupInfo const& groupInfo) override;
4372
4373 void testCaseStarting(TestCaseInfo const& testCaseInfo) override;
4374 bool assertionEnded(AssertionStats const& assertionStats) override;
4375
4376 void testCaseEnded(TestCaseStats const& testCaseStats) override;
4377
4378 void testGroupEnded(TestGroupStats const& testGroupStats) override;
4379
4380 void testRunEndedCumulative() override;
4381
4382 void writeGroup(TestGroupNode const& groupNode, double suiteTime);
4383
4384 void writeTestCase(TestCaseNode const& testCaseNode);
4385
4386 void writeSection(std::string const& className,
4387 std::string const& rootName,
4388 SectionNode const& sectionNode);
4389
4390 void writeAssertions(SectionNode const& sectionNode);
4391 void writeAssertion(AssertionStats const& stats);
4392
4393 XmlWriter xml;
4394 Timer suiteTimer;
4395 std::string stdOutForSuite;
4396 std::string stdErrForSuite;
4397 unsigned int unexpectedExceptions = 0;
4398 bool m_okToFail = false;
4399 };
4400
4401} // end namespace Catch
4402
4403// end catch_reporter_junit.h
4404// start catch_reporter_xml.h
4405
4406namespace Catch {
4407 class XmlReporter : public StreamingReporterBase<XmlReporter> {
4408 public:
4409 XmlReporter(ReporterConfig const& _config);
4410
4411 ~XmlReporter() override;
4412
4413 static std::string getDescription();
4414
4415 virtual std::string getStylesheetRef() const;
4416
4417 void writeSourceInfo(SourceLineInfo const& sourceInfo);
4418
4419 public: // StreamingReporterBase
4420
4421 void noMatchingTestCases(std::string const& s) override;
4422
4423 void testRunStarting(TestRunInfo const& testInfo) override;
4424
4425 void testGroupStarting(GroupInfo const& groupInfo) override;
4426
4427 void testCaseStarting(TestCaseInfo const& testInfo) override;
4428
4429 void sectionStarting(SectionInfo const& sectionInfo) override;
4430
4431 void assertionStarting(AssertionInfo const&) override;
4432
4433 bool assertionEnded(AssertionStats const& assertionStats) override;
4434
4435 void sectionEnded(SectionStats const& sectionStats) override;
4436
4437 void testCaseEnded(TestCaseStats const& testCaseStats) override;
4438
4439 void testGroupEnded(TestGroupStats const& testGroupStats) override;
4440
4441 void testRunEnded(TestRunStats const& testRunStats) override;
4442
4443 private:
4444 Timer m_testCaseTimer;
4445 XmlWriter m_xml;
4446 int m_sectionDepth = 0;
4447 };
4448
4449} // end namespace Catch
4450
4451// end catch_reporter_xml.h
4452
4453// end catch_external_interfaces.h
4454#endif
4455
4456#endif // ! CATCH_CONFIG_IMPL_ONLY
4457
4458#ifdef CATCH_IMPL
4459// start catch_impl.hpp
4460
4461#ifdef __clang__
4462#pragma clang diagnostic push
4463#pragma clang diagnostic ignored "-Wweak-vtables"
4464#endif
4465
4466// Keep these here for external reporters
4467// start catch_test_case_tracker.h
4468
4469#include <string>
4470#include <vector>
4471#include <memory>
4472
4473namespace Catch {
4474namespace TestCaseTracking {
4475
4476 struct NameAndLocation {
4478 SourceLineInfo location;
4479
4480 NameAndLocation( std::string const& _name, SourceLineInfo const& _location );
4481 };
4482
4483 struct ITracker;
4484
4485 using ITrackerPtr = std::shared_ptr<ITracker>;
4486
4487 struct ITracker {
4488 virtual ~ITracker();
4489
4490 // static queries
4491 virtual NameAndLocation const& nameAndLocation() const = 0;
4492
4493 // dynamic queries
4494 virtual bool isComplete() const = 0; // Successfully completed or failed
4495 virtual bool isSuccessfullyCompleted() const = 0;
4496 virtual bool isOpen() const = 0; // Started but not complete
4497 virtual bool hasChildren() const = 0;
4498
4499 virtual ITracker& parent() = 0;
4500
4501 // actions
4502 virtual void close() = 0; // Successfully complete
4503 virtual void fail() = 0;
4504 virtual void markAsNeedingAnotherRun() = 0;
4505
4506 virtual void addChild( ITrackerPtr const& child ) = 0;
4507 virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0;
4508 virtual void openChild() = 0;
4509
4510 // Debug/ checking
4511 virtual bool isSectionTracker() const = 0;
4512 virtual bool isIndexTracker() const = 0;
4513 };
4514
4515 class TrackerContext {
4516
4517 enum RunState {
4518 NotStarted,
4519 Executing,
4520 CompletedCycle
4521 };
4522
4523 ITrackerPtr m_rootTracker;
4524 ITracker* m_currentTracker = nullptr;
4525 RunState m_runState = NotStarted;
4526
4527 public:
4528
4529 static TrackerContext& instance();
4530
4531 ITracker& startRun();
4532 void endRun();
4533
4534 void startCycle();
4535 void completeCycle();
4536
4537 bool completedCycle() const;
4538 ITracker& currentTracker();
4539 void setCurrentTracker( ITracker* tracker );
4540 };
4541
4542 class TrackerBase : public ITracker {
4543 protected:
4544 enum CycleState {
4545 NotStarted,
4546 Executing,
4547 ExecutingChildren,
4548 NeedsAnotherRun,
4549 CompletedSuccessfully,
4550 Failed
4551 };
4552
4553 class TrackerHasName {
4554 NameAndLocation m_nameAndLocation;
4555 public:
4556 TrackerHasName( NameAndLocation const& nameAndLocation );
4557 bool operator ()( ITrackerPtr const& tracker ) const;
4558 };
4559
4560 using Children = std::vector<ITrackerPtr>;
4561 NameAndLocation m_nameAndLocation;
4562 TrackerContext& m_ctx;
4563 ITracker* m_parent;
4564 Children m_children;
4565 CycleState m_runState = NotStarted;
4566
4567 public:
4568 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
4569
4570 NameAndLocation const& nameAndLocation() const override;
4571 bool isComplete() const override;
4572 bool isSuccessfullyCompleted() const override;
4573 bool isOpen() const override;
4574 bool hasChildren() const override;
4575
4576 void addChild( ITrackerPtr const& child ) override;
4577
4578 ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override;
4579 ITracker& parent() override;
4580
4581 void openChild() override;
4582
4583 bool isSectionTracker() const override;
4584 bool isIndexTracker() const override;
4585
4586 void open();
4587
4588 void close() override;
4589 void fail() override;
4590 void markAsNeedingAnotherRun() override;
4591
4592 private:
4593 void moveToParent();
4594 void moveToThis();
4595 };
4596
4597 class SectionTracker : public TrackerBase {
4598 std::vector<std::string> m_filters;
4599 public:
4600 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
4601
4602 bool isSectionTracker() const override;
4603
4604 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );
4605
4606 void tryOpen();
4607
4608 void addInitialFilters( std::vector<std::string> const& filters );
4609 void addNextFilters( std::vector<std::string> const& filters );
4610 };
4611
4612 class IndexTracker : public TrackerBase {
4613 int m_size;
4614 int m_index = -1;
4615 public:
4616 IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size );
4617
4618 bool isIndexTracker() const override;
4619 void close() override;
4620
4621 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size );
4622
4623 int index() const;
4624
4625 void moveNext();
4626 };
4627
4628} // namespace TestCaseTracking
4629
4630using TestCaseTracking::ITracker;
4631using TestCaseTracking::TrackerContext;
4632using TestCaseTracking::SectionTracker;
4633using TestCaseTracking::IndexTracker;
4634
4635} // namespace Catch
4636
4637// end catch_test_case_tracker.h
4638
4639// start catch_leak_detector.h
4640
4641namespace Catch {
4642
4643 struct LeakDetector {
4644 LeakDetector();
4645 };
4646
4647}
4648// end catch_leak_detector.h
4649// Cpp files will be included in the single-header file here
4650// start catch_approx.cpp
4651
4652#include <cmath>
4653#include <limits>
4654
4655namespace {
4656
4657// Performs equivalent check of std::fabs(lhs - rhs) <= margin
4658// But without the subtraction to allow for INFINITY in comparison
4659bool marginComparison(double lhs, double rhs, double margin) {
4660 return (lhs + margin >= rhs) && (rhs + margin >= lhs);
4661}
4662
4663}
4664
4665namespace Catch {
4666namespace Detail {
4667
4668 Approx::Approx ( double value )
4669 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
4670 m_margin( 0.0 ),
4671 m_scale( 0.0 ),
4672 m_value( value )
4673 {}
4674
4675 Approx Approx::custom() {
4676 return Approx( 0 );
4677 }
4678
4679 std::string Approx::toString() const {
4680 ReusableStringStream rss;
4681 rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";
4682 return rss.str();
4683 }
4684
4685 bool Approx::equalityComparisonImpl(const double other) const {
4686 // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value
4687 // Thanks to Richard Harris for his help refining the scaled margin value
4688 return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
4689 }
4690
4691} // end namespace Detail
4692
4693std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {
4694 return value.toString();
4695}
4696
4697} // end namespace Catch
4698// end catch_approx.cpp
4699// start catch_assertionhandler.cpp
4700
4701// start catch_context.h
4702
4703#include <memory>
4704
4705namespace Catch {
4706
4707 struct IResultCapture;
4708 struct IRunner;
4709 struct IConfig;
4710 struct IMutableContext;
4711
4712 using IConfigPtr = std::shared_ptr<IConfig const>;
4713
4714 struct IContext
4715 {
4716 virtual ~IContext();
4717
4718 virtual IResultCapture* getResultCapture() = 0;
4719 virtual IRunner* getRunner() = 0;
4720 virtual IConfigPtr const& getConfig() const = 0;
4721 };
4722
4723 struct IMutableContext : IContext
4724 {
4725 virtual ~IMutableContext();
4726 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
4727 virtual void setRunner( IRunner* runner ) = 0;
4728 virtual void setConfig( IConfigPtr const& config ) = 0;
4729
4730 private:
4731 static IMutableContext *currentContext;
4732 friend IMutableContext& getCurrentMutableContext();
4733 friend void cleanUpContext();
4734 static void createContext();
4735 };
4736
4737 inline IMutableContext& getCurrentMutableContext()
4738 {
4739 if( !IMutableContext::currentContext )
4740 IMutableContext::createContext();
4741 return *IMutableContext::currentContext;
4742 }
4743
4744 inline IContext& getCurrentContext()
4745 {
4746 return getCurrentMutableContext();
4747 }
4748
4749 void cleanUpContext();
4750}
4751
4752// end catch_context.h
4753// start catch_debugger.h
4754
4755namespace Catch {
4756 bool isDebuggerActive();
4757}
4758
4759#ifdef CATCH_PLATFORM_MAC
4760
4761 #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */
4762
4763#elif defined(CATCH_PLATFORM_LINUX)
4764 // If we can use inline assembler, do it because this allows us to break
4765 // directly at the location of the failing check instead of breaking inside
4766 // raise() called from it, i.e. one stack frame below.
4767 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
4768 #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */
4769 #else // Fall back to the generic way.
4770 #include <signal.h>
4771
4772 #define CATCH_TRAP() raise(SIGTRAP)
4773 #endif
4774#elif defined(_MSC_VER)
4775 #define CATCH_TRAP() __debugbreak()
4776#elif defined(__MINGW32__)
4777 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
4778 #define CATCH_TRAP() DebugBreak()
4779#endif
4780
4781#ifdef CATCH_TRAP
4782 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
4783#else
4784 namespace Catch {
4785 inline void doNothing() {}
4786 }
4787 #define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing()
4788#endif
4789
4790// end catch_debugger.h
4791// start catch_run_context.h
4792
4793// start catch_fatal_condition.h
4794
4795// start catch_windows_h_proxy.h
4796
4797
4798#if defined(CATCH_PLATFORM_WINDOWS)
4799
4800#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
4801# define CATCH_DEFINED_NOMINMAX
4802# define NOMINMAX
4803#endif
4804#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
4805# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
4806# define WIN32_LEAN_AND_MEAN
4807#endif
4808
4809#ifdef __AFXDLL
4810#include <AfxWin.h>
4811#else
4812#include <windows.h>
4813#endif
4814
4815#ifdef CATCH_DEFINED_NOMINMAX
4816# undef NOMINMAX
4817#endif
4818#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
4819# undef WIN32_LEAN_AND_MEAN
4820#endif
4821
4822#endif // defined(CATCH_PLATFORM_WINDOWS)
4823
4824// end catch_windows_h_proxy.h
4825#if defined( CATCH_CONFIG_WINDOWS_SEH )
4826
4827namespace Catch {
4828
4829 struct FatalConditionHandler {
4830
4831 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
4832 FatalConditionHandler();
4833 static void reset();
4834 ~FatalConditionHandler();
4835
4836 private:
4837 static bool isSet;
4838 static ULONG guaranteeSize;
4839 static PVOID exceptionHandlerHandle;
4840 };
4841
4842} // namespace Catch
4843
4844#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
4845
4846#include <signal.h>
4847
4848namespace Catch {
4849
4850 struct FatalConditionHandler {
4851
4852 static bool isSet;
4853 static struct sigaction oldSigActions[];
4854 static stack_t oldSigStack;
4855 static char altStackMem[];
4856
4857 static void handleSignal( int sig );
4858
4859 FatalConditionHandler();
4860 ~FatalConditionHandler();
4861 static void reset();
4862 };
4863
4864} // namespace Catch
4865
4866#else
4867
4868namespace Catch {
4869 struct FatalConditionHandler {
4870 void reset();
4871 };
4872}
4873
4874#endif
4875
4876// end catch_fatal_condition.h
4877#include <string>
4878
4879namespace Catch {
4880
4881 struct IMutableContext;
4882
4884
4885 class RunContext : public IResultCapture, public IRunner {
4886
4887 public:
4888 RunContext( RunContext const& ) = delete;
4889 RunContext& operator =( RunContext const& ) = delete;
4890
4891 explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter );
4892
4893 ~RunContext() override;
4894
4895 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );
4896 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );
4897
4898 Totals runTest(TestCase const& testCase);
4899
4900 IConfigPtr config() const;
4901 IStreamingReporter& reporter() const;
4902
4903 public: // IResultCapture
4904
4905 // Assertion handlers
4906 void handleExpr
4907 ( AssertionInfo const& info,
4908 ITransientExpression const& expr,
4909 AssertionReaction& reaction ) override;
4910 void handleMessage
4911 ( AssertionInfo const& info,
4912 ResultWas::OfType resultType,
4913 StringRef const& message,
4914 AssertionReaction& reaction ) override;
4915 void handleUnexpectedExceptionNotThrown
4916 ( AssertionInfo const& info,
4917 AssertionReaction& reaction ) override;
4918 void handleUnexpectedInflightException
4919 ( AssertionInfo const& info,
4920 std::string const& message,
4921 AssertionReaction& reaction ) override;
4922 void handleIncomplete
4923 ( AssertionInfo const& info ) override;
4924 void handleNonExpr
4925 ( AssertionInfo const &info,
4926 ResultWas::OfType resultType,
4927 AssertionReaction &reaction ) override;
4928
4929 bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;
4930
4931 void sectionEnded( SectionEndInfo const& endInfo ) override;
4932 void sectionEndedEarly( SectionEndInfo const& endInfo ) override;
4933
4934 void benchmarkStarting( BenchmarkInfo const& info ) override;
4935 void benchmarkEnded( BenchmarkStats const& stats ) override;
4936
4937 void pushScopedMessage( MessageInfo const& message ) override;
4938 void popScopedMessage( MessageInfo const& message ) override;
4939
4940 std::string getCurrentTestName() const override;
4941
4942 const AssertionResult* getLastResult() const override;
4943
4944 void exceptionEarlyReported() override;
4945
4946 void handleFatalErrorCondition( StringRef message ) override;
4947
4948 bool lastAssertionPassed() override;
4949
4950 void assertionPassed() override;
4951
4952 public:
4953 // !TBD We need to do this another way!
4954 bool aborting() const final;
4955
4956 private:
4957
4958 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );
4959 void invokeActiveTestCase();
4960
4961 void resetAssertionInfo();
4962 bool testForMissingAssertions( Counts& assertions );
4963
4964 void assertionEnded( AssertionResult const& result );
4965 void reportExpr
4966 ( AssertionInfo const &info,
4967 ResultWas::OfType resultType,
4968 ITransientExpression const *expr,
4969 bool negated );
4970
4971 void populateReaction( AssertionReaction& reaction );
4972
4973 private:
4974
4975 void handleUnfinishedSections();
4976
4977 TestRunInfo m_runInfo;
4978 IMutableContext& m_context;
4979 TestCase const* m_activeTestCase = nullptr;
4980 ITracker* m_testCaseTracker;
4981 Option<AssertionResult> m_lastResult;
4982
4983 IConfigPtr m_config;
4984 Totals m_totals;
4985 IStreamingReporterPtr m_reporter;
4986 std::vector<MessageInfo> m_messages;
4987 AssertionInfo m_lastAssertionInfo;
4988 std::vector<SectionEndInfo> m_unfinishedSections;
4989 std::vector<ITracker*> m_activeSections;
4990 TrackerContext m_trackerContext;
4991 bool m_lastAssertionPassed = false;
4992 bool m_shouldReportUnexpected = true;
4993 bool m_includeSuccessfulResults;
4994 };
4995
4996} // end namespace Catch
4997
4998// end catch_run_context.h
4999namespace Catch {
5000
5001 auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
5002 expr.streamReconstructedExpression( os );
5003 return os;
5004 }
5005
5006 LazyExpression::LazyExpression( bool isNegated )
5007 : m_isNegated( isNegated )
5008 {}
5009
5010 LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {}
5011
5012 LazyExpression::operator bool() const {
5013 return m_transientExpression != nullptr;
5014 }
5015
5016 auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& {
5017 if( lazyExpr.m_isNegated )
5018 os << "!";
5019
5020 if( lazyExpr ) {
5021 if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
5022 os << "(" << *lazyExpr.m_transientExpression << ")";
5023 else
5024 os << *lazyExpr.m_transientExpression;
5025 }
5026 else {
5027 os << "{** error - unchecked empty expression requested **}";
5028 }
5029 return os;
5030 }
5031
5033 ( StringRef macroName,
5034 SourceLineInfo const& lineInfo,
5035 StringRef capturedExpression,
5036 ResultDisposition::Flags resultDisposition )
5037 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
5038 m_resultCapture( getResultCapture() )
5039 {}
5040
5041 void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
5042 m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
5043 }
5044 void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) {
5045 m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
5046 }
5047
5048 auto AssertionHandler::allowThrows() const -> bool {
5049 return getCurrentContext().getConfig()->allowThrows();
5050 }
5051
5053 setCompleted();
5054 if( m_reaction.shouldDebugBreak ) {
5055
5056 // If you find your debugger stopping you here then go one level up on the
5057 // call-stack for the code that caused it (typically a failed assertion)
5058
5059 // (To go back to the test and change execution, jump over the throw, next)
5060 CATCH_BREAK_INTO_DEBUGGER();
5061 }
5062 if( m_reaction.shouldThrow )
5064 }
5066 m_completed = true;
5067 }
5068
5070 m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
5071 }
5072
5074 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
5075 }
5077 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
5078 }
5079
5081 m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
5082 }
5083
5085 m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
5086 }
5087
5088 // This is the overload that takes a string and infers the Equals matcher from it
5089 // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
5090 void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ) {
5091 handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
5092 }
5093
5094} // namespace Catch
5095// end catch_assertionhandler.cpp
5096// start catch_assertionresult.cpp
5097
5098namespace Catch {
5099 AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):
5100 lazyExpression(_lazyExpression),
5101 resultType(_resultType) {}
5102
5103 std::string AssertionResultData::reconstructExpression() const {
5104
5105 if( reconstructedExpression.empty() ) {
5106 if( lazyExpression ) {
5107 ReusableStringStream rss;
5108 rss << lazyExpression;
5109 reconstructedExpression = rss.str();
5110 }
5111 }
5112 return reconstructedExpression;
5113 }
5114
5115 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
5116 : m_info( info ),
5117 m_resultData( data )
5118 {}
5119
5120 // Result was a success
5121 bool AssertionResult::succeeded() const {
5122 return Catch::isOk( m_resultData.resultType );
5123 }
5124
5125 // Result was a success, or failure is suppressed
5126 bool AssertionResult::isOk() const {
5127 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
5128 }
5129
5130 ResultWas::OfType AssertionResult::getResultType() const {
5131 return m_resultData.resultType;
5132 }
5133
5134 bool AssertionResult::hasExpression() const {
5135 return m_info.capturedExpression[0] != 0;
5136 }
5137
5138 bool AssertionResult::hasMessage() const {
5139 return !m_resultData.message.empty();
5140 }
5141
5142 std::string AssertionResult::getExpression() const {
5143 if( isFalseTest( m_info.resultDisposition ) )
5144 return "!(" + m_info.capturedExpression + ")";
5145 else
5146 return m_info.capturedExpression;
5147 }
5148
5149 std::string AssertionResult::getExpressionInMacro() const {
5150 std::string expr;
5151 if( m_info.macroName[0] == 0 )
5152 expr = m_info.capturedExpression;
5153 else {
5154 expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
5155 expr += m_info.macroName;
5156 expr += "( ";
5157 expr += m_info.capturedExpression;
5158 expr += " )";
5159 }
5160 return expr;
5161 }
5162
5163 bool AssertionResult::hasExpandedExpression() const {
5164 return hasExpression() && getExpandedExpression() != getExpression();
5165 }
5166
5167 std::string AssertionResult::getExpandedExpression() const {
5168 std::string expr = m_resultData.reconstructExpression();
5169 return expr.empty()
5170 ? getExpression()
5171 : expr;
5172 }
5173
5174 std::string AssertionResult::getMessage() const {
5175 return m_resultData.message;
5176 }
5177 SourceLineInfo AssertionResult::getSourceInfo() const {
5178 return m_info.lineInfo;
5179 }
5180
5181 StringRef AssertionResult::getTestMacroName() const {
5182 return m_info.macroName;
5183 }
5184
5185} // end namespace Catch
5186// end catch_assertionresult.cpp
5187// start catch_benchmark.cpp
5188
5189namespace Catch {
5190
5191 auto BenchmarkLooper::getResolution() -> uint64_t {
5192 return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple();
5193 }
5194
5196 getResultCapture().benchmarkStarting( { m_name } );
5197 }
5199 auto elapsed = m_timer.getElapsedNanoseconds();
5200
5201 // Exponentially increasing iterations until we're confident in our timer resolution
5202 if( elapsed < m_resolution ) {
5203 m_iterationsToRun *= 10;
5204 return true;
5205 }
5206
5207 getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } );
5208 return false;
5209 }
5210
5211} // end namespace Catch
5212// end catch_benchmark.cpp
5213// start catch_capture_matchers.cpp
5214
5215namespace Catch {
5216
5217 using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
5218
5219 // This is the general overload that takes a any string matcher
5220 // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers
5221 // the Equals matcher (so the header does not mention matchers)
5222 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) {
5223 std::string exceptionMessage = Catch::translateActiveException();
5224 MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
5225 handler.handleExpr( expr );
5226 }
5227
5228} // namespace Catch
5229// end catch_capture_matchers.cpp
5230// start catch_commandline.cpp
5231
5232// start catch_commandline.h
5233
5234// start catch_clara.h
5235
5236// Use Catch's value for console width (store Clara's off to the side, if present)
5237#ifdef CLARA_CONFIG_CONSOLE_WIDTH
5238#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
5239#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
5240#endif
5241#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
5242
5243#ifdef __clang__
5244#pragma clang diagnostic push
5245#pragma clang diagnostic ignored "-Wweak-vtables"
5246#pragma clang diagnostic ignored "-Wexit-time-destructors"
5247#pragma clang diagnostic ignored "-Wshadow"
5248#endif
5249
5250// start clara.hpp
5251// Copyright 2017 Two Blue Cubes Ltd. All rights reserved.
5252//
5253// Distributed under the Boost Software License, Version 1.0. (See accompanying
5254// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5255//
5256// See https://github.com/philsquared/Clara for more details
5257
5258// Clara v1.1.4
5259
5260
5261#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
5262#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
5263#endif
5264
5265#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
5266#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
5267#endif
5268
5269#ifndef CLARA_CONFIG_OPTIONAL_TYPE
5270#ifdef __has_include
5271#if __has_include(<optional>) && __cplusplus >= 201703L
5272#include <optional>
5273#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
5274#endif
5275#endif
5276#endif
5277
5278// ----------- #included from clara_textflow.hpp -----------
5279
5280// TextFlowCpp
5281//
5282// A single-header library for wrapping and laying out basic text, by Phil Nash
5283//
5284// This work is licensed under the BSD 2-Clause license.
5285// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause
5286//
5287// This project is hosted at https://github.com/philsquared/textflowcpp
5288
5289
5290#include <cassert>
5291#include <ostream>
5292#include <sstream>
5293#include <vector>
5294
5295#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
5296#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
5297#endif
5298
5299namespace Catch { namespace clara { namespace TextFlow {
5300
5301 inline auto isWhitespace( char c ) -> bool {
5302 static std::string chars = " \t\n\r";
5303 return chars.find( c ) != std::string::npos;
5304 }
5305 inline auto isBreakableBefore( char c ) -> bool {
5306 static std::string chars = "[({<|";
5307 return chars.find( c ) != std::string::npos;
5308 }
5309 inline auto isBreakableAfter( char c ) -> bool {
5310 static std::string chars = "])}>.,:;*+-=&/\\";
5311 return chars.find( c ) != std::string::npos;
5312 }
5313
5314 class Columns;
5315
5316 class Column {
5317 std::vector<std::string> m_strings;
5318 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
5319 size_t m_indent = 0;
5320 size_t m_initialIndent = std::string::npos;
5321
5322 public:
5323 class iterator {
5324 friend Column;
5325
5326 Column const& m_column;
5327 size_t m_stringIndex = 0;
5328 size_t m_pos = 0;
5329
5330 size_t m_len = 0;
5331 size_t m_end = 0;
5332 bool m_suffix = false;
5333
5334 iterator( Column const& column, size_t stringIndex )
5335 : m_column( column ),
5336 m_stringIndex( stringIndex )
5337 {}
5338
5339 auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
5340
5341 auto isBoundary( size_t at ) const -> bool {
5342 assert( at > 0 );
5343 assert( at <= line().size() );
5344
5345 return at == line().size() ||
5346 ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) ||
5347 isBreakableBefore( line()[at] ) ||
5348 isBreakableAfter( line()[at-1] );
5349 }
5350
5351 void calcLength() {
5352 assert( m_stringIndex < m_column.m_strings.size() );
5353
5354 m_suffix = false;
5355 auto width = m_column.m_width-indent();
5356 m_end = m_pos;
5357 while( m_end < line().size() && line()[m_end] != '\n' )
5358 ++m_end;
5359
5360 if( m_end < m_pos + width ) {
5361 m_len = m_end - m_pos;
5362 }
5363 else {
5364 size_t len = width;
5365 while (len > 0 && !isBoundary(m_pos + len))
5366 --len;
5367 while (len > 0 && isWhitespace( line()[m_pos + len - 1] ))
5368 --len;
5369
5370 if (len > 0) {
5371 m_len = len;
5372 } else {
5373 m_suffix = true;
5374 m_len = width - 1;
5375 }
5376 }
5377 }
5378
5379 auto indent() const -> size_t {
5380 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
5381 return initial == std::string::npos ? m_column.m_indent : initial;
5382 }
5383
5384 auto addIndentAndSuffix(std::string const &plain) const -> std::string {
5385 return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain);
5386 }
5387
5388 public:
5389 explicit iterator( Column const& column ) : m_column( column ) {
5390 assert( m_column.m_width > m_column.m_indent );
5391 assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent );
5392 calcLength();
5393 if( m_len == 0 )
5394 m_stringIndex++; // Empty string
5395 }
5396
5397 auto operator *() const -> std::string {
5398 assert( m_stringIndex < m_column.m_strings.size() );
5399 assert( m_pos <= m_end );
5400 if( m_pos + m_column.m_width < m_end )
5401 return addIndentAndSuffix(line().substr(m_pos, m_len));
5402 else
5403 return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos));
5404 }
5405
5406 auto operator ++() -> iterator& {
5407 m_pos += m_len;
5408 if( m_pos < line().size() && line()[m_pos] == '\n' )
5409 m_pos += 1;
5410 else
5411 while( m_pos < line().size() && isWhitespace( line()[m_pos] ) )
5412 ++m_pos;
5413
5414 if( m_pos == line().size() ) {
5415 m_pos = 0;
5416 ++m_stringIndex;
5417 }
5418 if( m_stringIndex < m_column.m_strings.size() )
5419 calcLength();
5420 return *this;
5421 }
5422 auto operator ++(int) -> iterator {
5423 iterator prev( *this );
5424 operator++();
5425 return prev;
5426 }
5427
5428 auto operator ==( iterator const& other ) const -> bool {
5429 return
5430 m_pos == other.m_pos &&
5431 m_stringIndex == other.m_stringIndex &&
5432 &m_column == &other.m_column;
5433 }
5434 auto operator !=( iterator const& other ) const -> bool {
5435 return !operator==( other );
5436 }
5437 };
5438 using const_iterator = iterator;
5439
5440 explicit Column( std::string const& text ) { m_strings.push_back( text ); }
5441
5442 auto width( size_t newWidth ) -> Column& {
5443 assert( newWidth > 0 );
5444 m_width = newWidth;
5445 return *this;
5446 }
5447 auto indent( size_t newIndent ) -> Column& {
5448 m_indent = newIndent;
5449 return *this;
5450 }
5451 auto initialIndent( size_t newIndent ) -> Column& {
5452 m_initialIndent = newIndent;
5453 return *this;
5454 }
5455
5456 auto width() const -> size_t { return m_width; }
5457 auto begin() const -> iterator { return iterator( *this ); }
5458 auto end() const -> iterator { return { *this, m_strings.size() }; }
5459
5460 inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) {
5461 bool first = true;
5462 for( auto line : col ) {
5463 if( first )
5464 first = false;
5465 else
5466 os << "\n";
5467 os << line;
5468 }
5469 return os;
5470 }
5471
5472 auto operator + ( Column const& other ) -> Columns;
5473
5474 auto toString() const -> std::string {
5475 std::ostringstream oss;
5476 oss << *this;
5477 return oss.str();
5478 }
5479 };
5480
5481 class Spacer : public Column {
5482
5483 public:
5484 explicit Spacer( size_t spaceWidth ) : Column( "" ) {
5485 width( spaceWidth );
5486 }
5487 };
5488
5489 class Columns {
5490 std::vector<Column> m_columns;
5491
5492 public:
5493
5494 class iterator {
5495 friend Columns;
5496 struct EndTag {};
5497
5498 std::vector<Column> const& m_columns;
5499 std::vector<Column::iterator> m_iterators;
5500 size_t m_activeIterators;
5501
5502 iterator( Columns const& columns, EndTag )
5503 : m_columns( columns.m_columns ),
5504 m_activeIterators( 0 )
5505 {
5506 m_iterators.reserve( m_columns.size() );
5507
5508 for( auto const& col : m_columns )
5509 m_iterators.push_back( col.end() );
5510 }
5511
5512 public:
5513 explicit iterator( Columns const& columns )
5514 : m_columns( columns.m_columns ),
5515 m_activeIterators( m_columns.size() )
5516 {
5517 m_iterators.reserve( m_columns.size() );
5518
5519 for( auto const& col : m_columns )
5520 m_iterators.push_back( col.begin() );
5521 }
5522
5523 auto operator ==( iterator const& other ) const -> bool {
5524 return m_iterators == other.m_iterators;
5525 }
5526 auto operator !=( iterator const& other ) const -> bool {
5527 return m_iterators != other.m_iterators;
5528 }
5529 auto operator *() const -> std::string {
5530 std::string row, padding;
5531
5532 for( size_t i = 0; i < m_columns.size(); ++i ) {
5533 auto width = m_columns[i].width();
5534 if( m_iterators[i] != m_columns[i].end() ) {
5535 std::string col = *m_iterators[i];
5536 row += padding + col;
5537 if( col.size() < width )
5538 padding = std::string( width - col.size(), ' ' );
5539 else
5540 padding = "";
5541 }
5542 else {
5543 padding += std::string( width, ' ' );
5544 }
5545 }
5546 return row;
5547 }
5548 auto operator ++() -> iterator& {
5549 for( size_t i = 0; i < m_columns.size(); ++i ) {
5550 if (m_iterators[i] != m_columns[i].end())
5551 ++m_iterators[i];
5552 }
5553 return *this;
5554 }
5555 auto operator ++(int) -> iterator {
5556 iterator prev( *this );
5557 operator++();
5558 return prev;
5559 }
5560 };
5561 using const_iterator = iterator;
5562
5563 auto begin() const -> iterator { return iterator( *this ); }
5564 auto end() const -> iterator { return { *this, iterator::EndTag() }; }
5565
5566 auto operator += ( Column const& col ) -> Columns& {
5567 m_columns.push_back( col );
5568 return *this;
5569 }
5570 auto operator + ( Column const& col ) -> Columns {
5571 Columns combined = *this;
5572 combined += col;
5573 return combined;
5574 }
5575
5576 inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) {
5577
5578 bool first = true;
5579 for( auto line : cols ) {
5580 if( first )
5581 first = false;
5582 else
5583 os << "\n";
5584 os << line;
5585 }
5586 return os;
5587 }
5588
5589 auto toString() const -> std::string {
5590 std::ostringstream oss;
5591 oss << *this;
5592 return oss.str();
5593 }
5594 };
5595
5596 inline auto Column::operator + ( Column const& other ) -> Columns {
5597 Columns cols;
5598 cols += *this;
5599 cols += other;
5600 return cols;
5601 }
5602}}} // namespace Catch::clara::TextFlow
5603
5604// ----------- end of #include from clara_textflow.hpp -----------
5605// ........... back in clara.hpp
5606
5607#include <memory>
5608#include <set>
5609#include <algorithm>
5610
5611#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
5612#define CATCH_PLATFORM_WINDOWS
5613#endif
5614
5615namespace Catch { namespace clara {
5616namespace detail {
5617
5618 // Traits for extracting arg and return type of lambdas (for single argument lambdas)
5619 template<typename L>
5620 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
5621
5622 template<typename ClassT, typename ReturnT, typename... Args>
5623 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
5624 static const bool isValid = false;
5625 };
5626
5627 template<typename ClassT, typename ReturnT, typename ArgT>
5628 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
5629 static const bool isValid = true;
5630 using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;
5631 using ReturnType = ReturnT;
5632 };
5633
5634 class TokenStream;
5635
5636 // Transport for raw args (copied from main args, or supplied via init list for testing)
5637 class Args {
5638 friend TokenStream;
5639 std::string m_exeName;
5640 std::vector<std::string> m_args;
5641
5642 public:
5643 Args( int argc, char const* const* argv )
5644 : m_exeName(argv[0]),
5645 m_args(argv + 1, argv + argc) {}
5646
5647 Args( std::initializer_list<std::string> args )
5648 : m_exeName( *args.begin() ),
5649 m_args( args.begin()+1, args.end() )
5650 {}
5651
5652 auto exeName() const -> std::string {
5653 return m_exeName;
5654 }
5655 };
5656
5657 // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string
5658 // may encode an option + its argument if the : or = form is used
5659 enum class TokenType {
5660 Option, Argument
5661 };
5662 struct Token {
5663 TokenType type;
5664 std::string token;
5665 };
5666
5667 inline auto isOptPrefix( char c ) -> bool {
5668 return c == '-'
5669#ifdef CATCH_PLATFORM_WINDOWS
5670 || c == '/'
5671#endif
5672 ;
5673 }
5674
5675 // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled
5676 class TokenStream {
5677 using Iterator = std::vector<std::string>::const_iterator;
5678 Iterator it;
5679 Iterator itEnd;
5680 std::vector<Token> m_tokenBuffer;
5681
5682 void loadBuffer() {
5683 m_tokenBuffer.resize( 0 );
5684
5685 // Skip any empty strings
5686 while( it != itEnd && it->empty() )
5687 ++it;
5688
5689 if( it != itEnd ) {
5690 auto const &next = *it;
5691 if( isOptPrefix( next[0] ) ) {
5692 auto delimiterPos = next.find_first_of( " :=" );
5693 if( delimiterPos != std::string::npos ) {
5694 m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );
5695 m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );
5696 } else {
5697 if( next[1] != '-' && next.size() > 2 ) {
5698 std::string opt = "- ";
5699 for( size_t i = 1; i < next.size(); ++i ) {
5700 opt[1] = next[i];
5701 m_tokenBuffer.push_back( { TokenType::Option, opt } );
5702 }
5703 } else {
5704 m_tokenBuffer.push_back( { TokenType::Option, next } );
5705 }
5706 }
5707 } else {
5708 m_tokenBuffer.push_back( { TokenType::Argument, next } );
5709 }
5710 }
5711 }
5712
5713 public:
5714 explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}
5715
5716 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
5717 loadBuffer();
5718 }
5719
5720 explicit operator bool() const {
5721 return !m_tokenBuffer.empty() || it != itEnd;
5722 }
5723
5724 auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }
5725
5726 auto operator*() const -> Token {
5727 assert( !m_tokenBuffer.empty() );
5728 return m_tokenBuffer.front();
5729 }
5730
5731 auto operator->() const -> Token const * {
5732 assert( !m_tokenBuffer.empty() );
5733 return &m_tokenBuffer.front();
5734 }
5735
5736 auto operator++() -> TokenStream & {
5737 if( m_tokenBuffer.size() >= 2 ) {
5738 m_tokenBuffer.erase( m_tokenBuffer.begin() );
5739 } else {
5740 if( it != itEnd )
5741 ++it;
5742 loadBuffer();
5743 }
5744 return *this;
5745 }
5746 };
5747
5748 class ResultBase {
5749 public:
5750 enum Type {
5751 Ok, LogicError, RuntimeError
5752 };
5753
5754 protected:
5755 ResultBase( Type type ) : m_type( type ) {}
5756 virtual ~ResultBase() = default;
5757
5758 virtual void enforceOk() const = 0;
5759
5760 Type m_type;
5761 };
5762
5763 template<typename T>
5764 class ResultValueBase : public ResultBase {
5765 public:
5766 auto value() const -> T const & {
5767 enforceOk();
5768 return m_value;
5769 }
5770
5771 protected:
5772 ResultValueBase( Type type ) : ResultBase( type ) {}
5773
5774 ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) {
5775 if( m_type == ResultBase::Ok )
5776 new( &m_value ) T( other.m_value );
5777 }
5778
5779 ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {
5780 new( &m_value ) T( value );
5781 }
5782
5783 auto operator=( ResultValueBase const &other ) -> ResultValueBase & {
5784 if( m_type == ResultBase::Ok )
5785 m_value.~T();
5786 ResultBase::operator=(other);
5787 if( m_type == ResultBase::Ok )
5788 new( &m_value ) T( other.m_value );
5789 return *this;
5790 }
5791
5792 ~ResultValueBase() override {
5793 if( m_type == Ok )
5794 m_value.~T();
5795 }
5796
5797 union {
5798 T m_value;
5799 };
5800 };
5801
5802 template<>
5803 class ResultValueBase<void> : public ResultBase {
5804 protected:
5805 using ResultBase::ResultBase;
5806 };
5807
5808 template<typename T = void>
5809 class BasicResult : public ResultValueBase<T> {
5810 public:
5811 template<typename U>
5812 explicit BasicResult( BasicResult<U> const &other )
5813 : ResultValueBase<T>( other.type() ),
5814 m_errorMessage( other.errorMessage() )
5815 {
5816 assert( type() != ResultBase::Ok );
5817 }
5818
5819 template<typename U>
5820 static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; }
5821 static auto ok() -> BasicResult { return { ResultBase::Ok }; }
5822 static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; }
5823 static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; }
5824
5825 explicit operator bool() const { return m_type == ResultBase::Ok; }
5826 auto type() const -> ResultBase::Type { return m_type; }
5827 auto errorMessage() const -> std::string { return m_errorMessage; }
5828
5829 protected:
5830 void enforceOk() const override {
5831
5832 // Errors shouldn't reach this point, but if they do
5833 // the actual error message will be in m_errorMessage
5834 assert( m_type != ResultBase::LogicError );
5835 assert( m_type != ResultBase::RuntimeError );
5836 if( m_type != ResultBase::Ok )
5837 std::abort();
5838 }
5839
5840 std::string m_errorMessage; // Only populated if resultType is an error
5841
5842 BasicResult( ResultBase::Type type, std::string const &message )
5843 : ResultValueBase<T>(type),
5844 m_errorMessage(message)
5845 {
5846 assert( m_type != ResultBase::Ok );
5847 }
5848
5849 using ResultValueBase<T>::ResultValueBase;
5850 using ResultBase::m_type;
5851 };
5852
5853 enum class ParseResultType {
5854 Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
5855 };
5856
5857 class ParseState {
5858 public:
5859
5860 ParseState( ParseResultType type, TokenStream const &remainingTokens )
5861 : m_type(type),
5862 m_remainingTokens( remainingTokens )
5863 {}
5864
5865 auto type() const -> ParseResultType { return m_type; }
5866 auto remainingTokens() const -> TokenStream { return m_remainingTokens; }
5867
5868 private:
5869 ParseResultType m_type;
5870 TokenStream m_remainingTokens;
5871 };
5872
5873 using Result = BasicResult<void>;
5874 using ParserResult = BasicResult<ParseResultType>;
5875 using InternalParseResult = BasicResult<ParseState>;
5876
5877 struct HelpColumns {
5878 std::string left;
5879 std::string right;
5880 };
5881
5882 template<typename T>
5883 inline auto convertInto( std::string const &source, T& target ) -> ParserResult {
5884 std::stringstream ss;
5885 ss << source;
5886 ss >> target;
5887 if( ss.fail() )
5888 return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" );
5889 else
5890 return ParserResult::ok( ParseResultType::Matched );
5891 }
5892 inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult {
5893 target = source;
5894 return ParserResult::ok( ParseResultType::Matched );
5895 }
5896 inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {
5897 std::string srcLC = source;
5898 std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast<char>( ::tolower(c) ); } );
5899 if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")
5900 target = true;
5901 else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")
5902 target = false;
5903 else
5904 return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );
5905 return ParserResult::ok( ParseResultType::Matched );
5906 }
5907#ifdef CLARA_CONFIG_OPTIONAL_TYPE
5908 template<typename T>
5909 inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
5910 T temp;
5911 auto result = convertInto( source, temp );
5912 if( result )
5913 target = std::move(temp);
5914 return result;
5915 }
5916#endif // CLARA_CONFIG_OPTIONAL_TYPE
5917
5918 struct NonCopyable {
5919 NonCopyable() = default;
5920 NonCopyable( NonCopyable const & ) = delete;
5921 NonCopyable( NonCopyable && ) = delete;
5922 NonCopyable &operator=( NonCopyable const & ) = delete;
5923 NonCopyable &operator=( NonCopyable && ) = delete;
5924 };
5925
5926 struct BoundRef : NonCopyable {
5927 virtual ~BoundRef() = default;
5928 virtual auto isContainer() const -> bool { return false; }
5929 virtual auto isFlag() const -> bool { return false; }
5930 };
5931 struct BoundValueRefBase : BoundRef {
5932 virtual auto setValue( std::string const &arg ) -> ParserResult = 0;
5933 };
5934 struct BoundFlagRefBase : BoundRef {
5935 virtual auto setFlag( bool flag ) -> ParserResult = 0;
5936 virtual auto isFlag() const -> bool { return true; }
5937 };
5938
5939 template<typename T>
5940 struct BoundValueRef : BoundValueRefBase {
5941 T &m_ref;
5942
5943 explicit BoundValueRef( T &ref ) : m_ref( ref ) {}
5944
5945 auto setValue( std::string const &arg ) -> ParserResult override {
5946 return convertInto( arg, m_ref );
5947 }
5948 };
5949
5950 template<typename T>
5951 struct BoundValueRef<std::vector<T>> : BoundValueRefBase {
5952 std::vector<T> &m_ref;
5953
5954 explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}
5955
5956 auto isContainer() const -> bool override { return true; }
5957
5958 auto setValue( std::string const &arg ) -> ParserResult override {
5959 T temp;
5960 auto result = convertInto( arg, temp );
5961 if( result )
5962 m_ref.push_back( temp );
5963 return result;
5964 }
5965 };
5966
5967 struct BoundFlagRef : BoundFlagRefBase {
5968 bool &m_ref;
5969
5970 explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}
5971
5972 auto setFlag( bool flag ) -> ParserResult override {
5973 m_ref = flag;
5974 return ParserResult::ok( ParseResultType::Matched );
5975 }
5976 };
5977
5978 template<typename ReturnType>
5979 struct LambdaInvoker {
5980 static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" );
5981
5982 template<typename L, typename ArgType>
5983 static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
5984 return lambda( arg );
5985 }
5986 };
5987
5988 template<>
5989 struct LambdaInvoker<void> {
5990 template<typename L, typename ArgType>
5991 static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {
5992 lambda( arg );
5993 return ParserResult::ok( ParseResultType::Matched );
5994 }
5995 };
5996
5997 template<typename ArgType, typename L>
5998 inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {
5999 ArgType temp{};
6000 auto result = convertInto( arg, temp );
6001 return !result
6002 ? result
6003 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
6004 }
6005
6006 template<typename L>
6007 struct BoundLambda : BoundValueRefBase {
6008 L m_lambda;
6009
6010 static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
6011 explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}
6012
6013 auto setValue( std::string const &arg ) -> ParserResult override {
6014 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );
6015 }
6016 };
6017
6018 template<typename L>
6019 struct BoundFlagLambda : BoundFlagRefBase {
6020 L m_lambda;
6021
6022 static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );
6023 static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" );
6024
6025 explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}
6026
6027 auto setFlag( bool flag ) -> ParserResult override {
6028 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
6029 }
6030 };
6031
6032 enum class Optionality { Optional, Required };
6033
6034 struct Parser;
6035
6036 class ParserBase {
6037 public:
6038 virtual ~ParserBase() = default;
6039 virtual auto validate() const -> Result { return Result::ok(); }
6040 virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0;
6041 virtual auto cardinality() const -> size_t { return 1; }
6042
6043 auto parse( Args const &args ) const -> InternalParseResult {
6044 return parse( args.exeName(), TokenStream( args ) );
6045 }
6046 };
6047
6048 template<typename DerivedT>
6049 class ComposableParserImpl : public ParserBase {
6050 public:
6051 template<typename T>
6052 auto operator|( T const &other ) const -> Parser;
6053
6054 template<typename T>
6055 auto operator+( T const &other ) const -> Parser;
6056 };
6057
6058 // Common code and state for Args and Opts
6059 template<typename DerivedT>
6060 class ParserRefImpl : public ComposableParserImpl<DerivedT> {
6061 protected:
6062 Optionality m_optionality = Optionality::Optional;
6063 std::shared_ptr<BoundRef> m_ref;
6064 std::string m_hint;
6065 std::string m_description;
6066
6067 explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}
6068
6069 public:
6070 template<typename T>
6071 ParserRefImpl( T &ref, std::string const &hint )
6072 : m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),
6073 m_hint( hint )
6074 {}
6075
6076 template<typename LambdaT>
6077 ParserRefImpl( LambdaT const &ref, std::string const &hint )
6078 : m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),
6079 m_hint(hint)
6080 {}
6081
6082 auto operator()( std::string const &description ) -> DerivedT & {
6083 m_description = description;
6084 return static_cast<DerivedT &>( *this );
6085 }
6086
6087 auto optional() -> DerivedT & {
6088 m_optionality = Optionality::Optional;
6089 return static_cast<DerivedT &>( *this );
6090 };
6091
6092 auto required() -> DerivedT & {
6093 m_optionality = Optionality::Required;
6094 return static_cast<DerivedT &>( *this );
6095 };
6096
6097 auto isOptional() const -> bool {
6098 return m_optionality == Optionality::Optional;
6099 }
6100
6101 auto cardinality() const -> size_t override {
6102 if( m_ref->isContainer() )
6103 return 0;
6104 else
6105 return 1;
6106 }
6107
6108 auto hint() const -> std::string { return m_hint; }
6109 };
6110
6111 class ExeName : public ComposableParserImpl<ExeName> {
6112 std::shared_ptr<std::string> m_name;
6113 std::shared_ptr<BoundValueRefBase> m_ref;
6114
6115 template<typename LambdaT>
6116 static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {
6117 return std::make_shared<BoundLambda<LambdaT>>( lambda) ;
6118 }
6119
6120 public:
6121 ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}
6122
6123 explicit ExeName( std::string &ref ) : ExeName() {
6124 m_ref = std::make_shared<BoundValueRef<std::string>>( ref );
6125 }
6126
6127 template<typename LambdaT>
6128 explicit ExeName( LambdaT const& lambda ) : ExeName() {
6129 m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );
6130 }
6131
6132 // The exe name is not parsed out of the normal tokens, but is handled specially
6133 auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
6134 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
6135 }
6136
6137 auto name() const -> std::string { return *m_name; }
6138 auto set( std::string const& newName ) -> ParserResult {
6139
6140 auto lastSlash = newName.find_last_of( "\\/" );
6141 auto filename = ( lastSlash == std::string::npos )
6142 ? newName
6143 : newName.substr( lastSlash+1 );
6144
6145 *m_name = filename;
6146 if( m_ref )
6147 return m_ref->setValue( filename );
6148 else
6149 return ParserResult::ok( ParseResultType::Matched );
6150 }
6151 };
6152
6153 class Arg : public ParserRefImpl<Arg> {
6154 public:
6155 using ParserRefImpl::ParserRefImpl;
6156
6157 auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override {
6158 auto validationResult = validate();
6159 if( !validationResult )
6160 return InternalParseResult( validationResult );
6161
6162 auto remainingTokens = tokens;
6163 auto const &token = *remainingTokens;
6164 if( token.type != TokenType::Argument )
6165 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
6166
6167 assert( !m_ref->isFlag() );
6168 auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
6169
6170 auto result = valueRef->setValue( remainingTokens->token );
6171 if( !result )
6172 return InternalParseResult( result );
6173 else
6174 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
6175 }
6176 };
6177
6178 inline auto normaliseOpt( std::string const &optName ) -> std::string {
6179#ifdef CATCH_PLATFORM_WINDOWS
6180 if( optName[0] == '/' )
6181 return "-" + optName.substr( 1 );
6182 else
6183#endif
6184 return optName;
6185 }
6186
6187 class Opt : public ParserRefImpl<Opt> {
6188 protected:
6189 std::vector<std::string> m_optNames;
6190
6191 public:
6192 template<typename LambdaT>
6193 explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}
6194
6195 explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}
6196
6197 template<typename LambdaT>
6198 Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
6199
6200 template<typename T>
6201 Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}
6202
6203 auto operator[]( std::string const &optName ) -> Opt & {
6204 m_optNames.push_back( optName );
6205 return *this;
6206 }
6207
6208 auto getHelpColumns() const -> std::vector<HelpColumns> {
6209 std::ostringstream oss;
6210 bool first = true;
6211 for( auto const &opt : m_optNames ) {
6212 if (first)
6213 first = false;
6214 else
6215 oss << ", ";
6216 oss << opt;
6217 }
6218 if( !m_hint.empty() )
6219 oss << " <" << m_hint << ">";
6220 return { { oss.str(), m_description } };
6221 }
6222
6223 auto isMatch( std::string const &optToken ) const -> bool {
6224 auto normalisedToken = normaliseOpt( optToken );
6225 for( auto const &name : m_optNames ) {
6226 if( normaliseOpt( name ) == normalisedToken )
6227 return true;
6228 }
6229 return false;
6230 }
6231
6232 using ParserBase::parse;
6233
6234 auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {
6235 auto validationResult = validate();
6236 if( !validationResult )
6237 return InternalParseResult( validationResult );
6238
6239 auto remainingTokens = tokens;
6240 if( remainingTokens && remainingTokens->type == TokenType::Option ) {
6241 auto const &token = *remainingTokens;
6242 if( isMatch(token.token ) ) {
6243 if( m_ref->isFlag() ) {
6244 auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );
6245 auto result = flagRef->setFlag( true );
6246 if( !result )
6247 return InternalParseResult( result );
6248 if( result.value() == ParseResultType::ShortCircuitAll )
6249 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
6250 } else {
6251 auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );
6252 ++remainingTokens;
6253 if( !remainingTokens )
6254 return InternalParseResult::runtimeError( "Expected argument following " + token.token );
6255 auto const &argToken = *remainingTokens;
6256 if( argToken.type != TokenType::Argument )
6257 return InternalParseResult::runtimeError( "Expected argument following " + token.token );
6258 auto result = valueRef->setValue( argToken.token );
6259 if( !result )
6260 return InternalParseResult( result );
6261 if( result.value() == ParseResultType::ShortCircuitAll )
6262 return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );
6263 }
6264 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
6265 }
6266 }
6267 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
6268 }
6269
6270 auto validate() const -> Result override {
6271 if( m_optNames.empty() )
6272 return Result::logicError( "No options supplied to Opt" );
6273 for( auto const &name : m_optNames ) {
6274 if( name.empty() )
6275 return Result::logicError( "Option name cannot be empty" );
6276#ifdef CATCH_PLATFORM_WINDOWS
6277 if( name[0] != '-' && name[0] != '/' )
6278 return Result::logicError( "Option name must begin with '-' or '/'" );
6279#else
6280 if( name[0] != '-' )
6281 return Result::logicError( "Option name must begin with '-'" );
6282#endif
6283 }
6284 return ParserRefImpl::validate();
6285 }
6286 };
6287
6288 struct Help : Opt {
6289 Help( bool &showHelpFlag )
6290 : Opt([&]( bool flag ) {
6291 showHelpFlag = flag;
6292 return ParserResult::ok( ParseResultType::ShortCircuitAll );
6293 })
6294 {
6295 static_cast<Opt &>( *this )
6296 ("display usage information")
6297 ["-?"]["-h"]["--help"]
6298 .optional();
6299 }
6300 };
6301
6302 struct Parser : ParserBase {
6303
6304 mutable ExeName m_exeName;
6305 std::vector<Opt> m_options;
6306 std::vector<Arg> m_args;
6307
6308 auto operator|=( ExeName const &exeName ) -> Parser & {
6309 m_exeName = exeName;
6310 return *this;
6311 }
6312
6313 auto operator|=( Arg const &arg ) -> Parser & {
6314 m_args.push_back(arg);
6315 return *this;
6316 }
6317
6318 auto operator|=( Opt const &opt ) -> Parser & {
6319 m_options.push_back(opt);
6320 return *this;
6321 }
6322
6323 auto operator|=( Parser const &other ) -> Parser & {
6324 m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());
6325 m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());
6326 return *this;
6327 }
6328
6329 template<typename T>
6330 auto operator|( T const &other ) const -> Parser {
6331 return Parser( *this ) |= other;
6332 }
6333
6334 // Forward deprecated interface with '+' instead of '|'
6335 template<typename T>
6336 auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }
6337 template<typename T>
6338 auto operator+( T const &other ) const -> Parser { return operator|( other ); }
6339
6340 auto getHelpColumns() const -> std::vector<HelpColumns> {
6341 std::vector<HelpColumns> cols;
6342 for (auto const &o : m_options) {
6343 auto childCols = o.getHelpColumns();
6344 cols.insert( cols.end(), childCols.begin(), childCols.end() );
6345 }
6346 return cols;
6347 }
6348
6349 void writeToStream( std::ostream &os ) const {
6350 if (!m_exeName.name().empty()) {
6351 os << "usage:\n" << " " << m_exeName.name() << " ";
6352 bool required = true, first = true;
6353 for( auto const &arg : m_args ) {
6354 if (first)
6355 first = false;
6356 else
6357 os << " ";
6358 if( arg.isOptional() && required ) {
6359 os << "[";
6360 required = false;
6361 }
6362 os << "<" << arg.hint() << ">";
6363 if( arg.cardinality() == 0 )
6364 os << " ... ";
6365 }
6366 if( !required )
6367 os << "]";
6368 if( !m_options.empty() )
6369 os << " options";
6370 os << "\n\nwhere options are:" << std::endl;
6371 }
6372
6373 auto rows = getHelpColumns();
6374 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
6375 size_t optWidth = 0;
6376 for( auto const &cols : rows )
6377 optWidth = (std::max)(optWidth, cols.left.size() + 2);
6378
6379 optWidth = (std::min)(optWidth, consoleWidth/2);
6380
6381 for( auto const &cols : rows ) {
6382 auto row =
6383 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
6384 TextFlow::Spacer(4) +
6385 TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );
6386 os << row << std::endl;
6387 }
6388 }
6389
6390 friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& {
6391 parser.writeToStream( os );
6392 return os;
6393 }
6394
6395 auto validate() const -> Result override {
6396 for( auto const &opt : m_options ) {
6397 auto result = opt.validate();
6398 if( !result )
6399 return result;
6400 }
6401 for( auto const &arg : m_args ) {
6402 auto result = arg.validate();
6403 if( !result )
6404 return result;
6405 }
6406 return Result::ok();
6407 }
6408
6409 using ParserBase::parse;
6410
6411 auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override {
6412
6413 struct ParserInfo {
6414 ParserBase const* parser = nullptr;
6415 size_t count = 0;
6416 };
6417 const size_t totalParsers = m_options.size() + m_args.size();
6418 assert( totalParsers < 512 );
6419 // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do
6420 ParserInfo parseInfos[512];
6421
6422 {
6423 size_t i = 0;
6424 for (auto const &opt : m_options) parseInfos[i++].parser = &opt;
6425 for (auto const &arg : m_args) parseInfos[i++].parser = &arg;
6426 }
6427
6428 m_exeName.set( exeName );
6429
6430 auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
6431 while( result.value().remainingTokens() ) {
6432 bool tokenParsed = false;
6433
6434 for( size_t i = 0; i < totalParsers; ++i ) {
6435 auto& parseInfo = parseInfos[i];
6436 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
6437 result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
6438 if (!result)
6439 return result;
6440 if (result.value().type() != ParseResultType::NoMatch) {
6441 tokenParsed = true;
6442 ++parseInfo.count;
6443 break;
6444 }
6445 }
6446 }
6447
6448 if( result.value().type() == ParseResultType::ShortCircuitAll )
6449 return result;
6450 if( !tokenParsed )
6451 return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token );
6452 }
6453 // !TBD Check missing required options
6454 return result;
6455 }
6456 };
6457
6458 template<typename DerivedT>
6459 template<typename T>
6460 auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser {
6461 return Parser() | static_cast<DerivedT const &>( *this ) | other;
6462 }
6463} // namespace detail
6464
6465// A Combined parser
6466using detail::Parser;
6467
6468// A parser for options
6469using detail::Opt;
6470
6471// A parser for arguments
6472using detail::Arg;
6473
6474// Wrapper for argc, argv from main()
6475using detail::Args;
6476
6477// Specifies the name of the executable
6478using detail::ExeName;
6479
6480// Convenience wrapper for option parser that specifies the help option
6481using detail::Help;
6482
6483// enum of result types from a parse
6484using detail::ParseResultType;
6485
6486// Result type for parser operation
6487using detail::ParserResult;
6488
6489}} // namespace Catch::clara
6490
6491// end clara.hpp
6492#ifdef __clang__
6493#pragma clang diagnostic pop
6494#endif
6495
6496// Restore Clara's value for console width, if present
6497#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
6498#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
6499#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
6500#endif
6501
6502// end catch_clara.h
6503namespace Catch {
6504
6505 clara::Parser makeCommandLineParser( ConfigData& config );
6506
6507} // end namespace Catch
6508
6509// end catch_commandline.h
6510#include <fstream>
6511#include <ctime>
6512
6513namespace Catch {
6514
6515 clara::Parser makeCommandLineParser( ConfigData& config ) {
6516
6517 using namespace clara;
6518
6519 auto const setWarning = [&]( std::string const& warning ) {
6520 auto warningSet = [&]() {
6521 if( warning == "NoAssertions" )
6522 return WarnAbout::NoAssertions;
6523
6524 if ( warning == "NoTests" )
6525 return WarnAbout::NoTests;
6526
6527 return WarnAbout::Nothing;
6528 }();
6529
6530 if (warningSet == WarnAbout::Nothing)
6531 return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );
6532 config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );
6533 return ParserResult::ok( ParseResultType::Matched );
6534 };
6535 auto const loadTestNamesFromFile = [&]( std::string const& filename ) {
6536 std::ifstream f( filename.c_str() );
6537 if( !f.is_open() )
6538 return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" );
6539
6540 std::string line;
6541 while( std::getline( f, line ) ) {
6542 line = trim(line);
6543 if( !line.empty() && !startsWith( line, '#' ) ) {
6544 if( !startsWith( line, '"' ) )
6545 line = '"' + line + '"';
6546 config.testsOrTags.push_back( line + ',' );
6547 }
6548 }
6549 return ParserResult::ok( ParseResultType::Matched );
6550 };
6551 auto const setTestOrder = [&]( std::string const& order ) {
6552 if( startsWith( "declared", order ) )
6553 config.runOrder = RunTests::InDeclarationOrder;
6554 else if( startsWith( "lexical", order ) )
6555 config.runOrder = RunTests::InLexicographicalOrder;
6556 else if( startsWith( "random", order ) )
6557 config.runOrder = RunTests::InRandomOrder;
6558 else
6559 return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" );
6560 return ParserResult::ok( ParseResultType::Matched );
6561 };
6562 auto const setRngSeed = [&]( std::string const& seed ) {
6563 if( seed != "time" )
6564 return clara::detail::convertInto( seed, config.rngSeed );
6565 config.rngSeed = static_cast<unsigned int>( std::time(nullptr) );
6566 return ParserResult::ok( ParseResultType::Matched );
6567 };
6568 auto const setColourUsage = [&]( std::string const& useColour ) {
6569 auto mode = toLower( useColour );
6570
6571 if( mode == "yes" )
6572 config.useColour = UseColour::Yes;
6573 else if( mode == "no" )
6574 config.useColour = UseColour::No;
6575 else if( mode == "auto" )
6576 config.useColour = UseColour::Auto;
6577 else
6578 return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" );
6579 return ParserResult::ok( ParseResultType::Matched );
6580 };
6581 auto const setWaitForKeypress = [&]( std::string const& keypress ) {
6582 auto keypressLc = toLower( keypress );
6583 if( keypressLc == "start" )
6584 config.waitForKeypress = WaitForKeypress::BeforeStart;
6585 else if( keypressLc == "exit" )
6586 config.waitForKeypress = WaitForKeypress::BeforeExit;
6587 else if( keypressLc == "both" )
6588 config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;
6589 else
6590 return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" );
6591 return ParserResult::ok( ParseResultType::Matched );
6592 };
6593 auto const setVerbosity = [&]( std::string const& verbosity ) {
6594 auto lcVerbosity = toLower( verbosity );
6595 if( lcVerbosity == "quiet" )
6596 config.verbosity = Verbosity::Quiet;
6597 else if( lcVerbosity == "normal" )
6598 config.verbosity = Verbosity::Normal;
6599 else if( lcVerbosity == "high" )
6600 config.verbosity = Verbosity::High;
6601 else
6602 return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" );
6603 return ParserResult::ok( ParseResultType::Matched );
6604 };
6605
6606 auto cli
6607 = ExeName( config.processName )
6608 | Help( config.showHelp )
6609 | Opt( config.listTests )
6610 ["-l"]["--list-tests"]
6611 ( "list all/matching test cases" )
6612 | Opt( config.listTags )
6613 ["-t"]["--list-tags"]
6614 ( "list all/matching tags" )
6615 | Opt( config.showSuccessfulTests )
6616 ["-s"]["--success"]
6617 ( "include successful tests in output" )
6618 | Opt( config.shouldDebugBreak )
6619 ["-b"]["--break"]
6620 ( "break into debugger on failure" )
6621 | Opt( config.noThrow )
6622 ["-e"]["--nothrow"]
6623 ( "skip exception tests" )
6624 | Opt( config.showInvisibles )
6625 ["-i"]["--invisibles"]
6626 ( "show invisibles (tabs, newlines)" )
6627 | Opt( config.outputFilename, "filename" )
6628 ["-o"]["--out"]
6629 ( "output filename" )
6630 | Opt( config.reporterName, "name" )
6631 ["-r"]["--reporter"]
6632 ( "reporter to use (defaults to console)" )
6633 | Opt( config.name, "name" )
6634 ["-n"]["--name"]
6635 ( "suite name" )
6636 | Opt( [&]( bool ){ config.abortAfter = 1; } )
6637 ["-a"]["--abort"]
6638 ( "abort at first failure" )
6639 | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )
6640 ["-x"]["--abortx"]
6641 ( "abort after x failures" )
6642 | Opt( setWarning, "warning name" )
6643 ["-w"]["--warn"]
6644 ( "enable warnings" )
6645 | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )
6646 ["-d"]["--durations"]
6647 ( "show test durations" )
6648 | Opt( loadTestNamesFromFile, "filename" )
6649 ["-f"]["--input-file"]
6650 ( "load test names to run from a file" )
6651 | Opt( config.filenamesAsTags )
6652 ["-#"]["--filenames-as-tags"]
6653 ( "adds a tag for the filename" )
6654 | Opt( config.sectionsToRun, "section name" )
6655 ["-c"]["--section"]
6656 ( "specify section to run" )
6657 | Opt( setVerbosity, "quiet|normal|high" )
6658 ["-v"]["--verbosity"]
6659 ( "set output verbosity" )
6660 | Opt( config.listTestNamesOnly )
6661 ["--list-test-names-only"]
6662 ( "list all/matching test cases names only" )
6663 | Opt( config.listReporters )
6664 ["--list-reporters"]
6665 ( "list all reporters" )
6666 | Opt( setTestOrder, "decl|lex|rand" )
6667 ["--order"]
6668 ( "test case order (defaults to decl)" )
6669 | Opt( setRngSeed, "'time'|number" )
6670 ["--rng-seed"]
6671 ( "set a specific seed for random numbers" )
6672 | Opt( setColourUsage, "yes|no" )
6673 ["--use-colour"]
6674 ( "should output be colourised" )
6675 | Opt( config.libIdentify )
6676 ["--libidentify"]
6677 ( "report name and version according to libidentify standard" )
6678 | Opt( setWaitForKeypress, "start|exit|both" )
6679 ["--wait-for-keypress"]
6680 ( "waits for a keypress before exiting" )
6681 | Opt( config.benchmarkResolutionMultiple, "multiplier" )
6682 ["--benchmark-resolution-multiple"]
6683 ( "multiple of clock resolution to run benchmarks" )
6684
6685 | Arg( config.testsOrTags, "test name|pattern|tags" )
6686 ( "which test or tests to use" );
6687
6688 return cli;
6689 }
6690
6691} // end namespace Catch
6692// end catch_commandline.cpp
6693// start catch_common.cpp
6694
6695#include <cstring>
6696#include <ostream>
6697
6698namespace Catch {
6699
6700 bool SourceLineInfo::empty() const noexcept {
6701 return file[0] == '\0';
6702 }
6703 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {
6704 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
6705 }
6706 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {
6707 return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
6708 }
6709
6710 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
6711#ifndef __GNUG__
6712 os << info.file << '(' << info.line << ')';
6713#else
6714 os << info.file << ':' << info.line;
6715#endif
6716 return os;
6717 }
6718
6720 return std::string();
6721 }
6722
6723 NonCopyable::NonCopyable() = default;
6724 NonCopyable::~NonCopyable() = default;
6725
6726}
6727// end catch_common.cpp
6728// start catch_config.cpp
6729
6730// start catch_enforce.h
6731
6732#include <stdexcept>
6733
6734#define CATCH_PREPARE_EXCEPTION( type, msg ) \
6735 type( ( Catch::ReusableStringStream() << msg ).str() )
6736#define CATCH_INTERNAL_ERROR( msg ) \
6737 throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg);
6738#define CATCH_ERROR( msg ) \
6739 throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg )
6740#define CATCH_ENFORCE( condition, msg ) \
6741 do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
6742
6743// end catch_enforce.h
6744namespace Catch {
6745
6746 Config::Config( ConfigData const& data )
6747 : m_data( data ),
6748 m_stream( openStream() )
6749 {
6750 TestSpecParser parser(ITagAliasRegistry::get());
6751 if (data.testsOrTags.empty()) {
6752 parser.parse("~[.]"); // All not hidden tests
6753 }
6754 else {
6755 m_hasTestFilters = true;
6756 for( auto const& testOrTags : data.testsOrTags )
6757 parser.parse( testOrTags );
6758 }
6759 m_testSpec = parser.testSpec();
6760 }
6761
6762 std::string const& Config::getFilename() const {
6763 return m_data.outputFilename ;
6764 }
6765
6766 bool Config::listTests() const { return m_data.listTests; }
6767 bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; }
6768 bool Config::listTags() const { return m_data.listTags; }
6769 bool Config::listReporters() const { return m_data.listReporters; }
6770
6771 std::string Config::getProcessName() const { return m_data.processName; }
6772 std::string const& Config::getReporterName() const { return m_data.reporterName; }
6773
6774 std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }
6775 std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }
6776
6777 TestSpec const& Config::testSpec() const { return m_testSpec; }
6778 bool Config::hasTestFilters() const { return m_hasTestFilters; }
6779
6780 bool Config::showHelp() const { return m_data.showHelp; }
6781
6782 // IConfig interface
6783 bool Config::allowThrows() const { return !m_data.noThrow; }
6784 std::ostream& Config::stream() const { return m_stream->stream(); }
6785 std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
6786 bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
6787 bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); }
6788 bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); }
6789 ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }
6790 RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; }
6791 unsigned int Config::rngSeed() const { return m_data.rngSeed; }
6792 int Config::benchmarkResolutionMultiple() const { return m_data.benchmarkResolutionMultiple; }
6793 UseColour::YesOrNo Config::useColour() const { return m_data.useColour; }
6794 bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; }
6795 int Config::abortAfter() const { return m_data.abortAfter; }
6796 bool Config::showInvisibles() const { return m_data.showInvisibles; }
6797 Verbosity Config::verbosity() const { return m_data.verbosity; }
6798
6799 IStream const* Config::openStream() {
6800 return Catch::makeStream(m_data.outputFilename);
6801 }
6802
6803} // end namespace Catch
6804// end catch_config.cpp
6805// start catch_console_colour.cpp
6806
6807#if defined(__clang__)
6808# pragma clang diagnostic push
6809# pragma clang diagnostic ignored "-Wexit-time-destructors"
6810#endif
6811
6812// start catch_errno_guard.h
6813
6814namespace Catch {
6815
6816 class ErrnoGuard {
6817 public:
6818 ErrnoGuard();
6819 ~ErrnoGuard();
6820 private:
6821 int m_oldErrno;
6822 };
6823
6824}
6825
6826// end catch_errno_guard.h
6827#include <sstream>
6828
6829namespace Catch {
6830 namespace {
6831
6832 struct IColourImpl {
6833 virtual ~IColourImpl() = default;
6834 virtual void use( Colour::Code _colourCode ) = 0;
6835 };
6836
6837 struct NoColourImpl : IColourImpl {
6838 void use( Colour::Code ) {}
6839
6840 static IColourImpl* instance() {
6841 static NoColourImpl s_instance;
6842 return &s_instance;
6843 }
6844 };
6845
6846 } // anon namespace
6847} // namespace Catch
6848
6849#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
6850# ifdef CATCH_PLATFORM_WINDOWS
6851# define CATCH_CONFIG_COLOUR_WINDOWS
6852# else
6853# define CATCH_CONFIG_COLOUR_ANSI
6854# endif
6855#endif
6856
6857#if defined ( CATCH_CONFIG_COLOUR_WINDOWS )
6858
6859namespace Catch {
6860namespace {
6861
6862 class Win32ColourImpl : public IColourImpl {
6863 public:
6864 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
6865 {
6866 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
6867 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
6868 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
6869 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
6870 }
6871
6872 virtual void use( Colour::Code _colourCode ) override {
6873 switch( _colourCode ) {
6874 case Colour::None: return setTextAttribute( originalForegroundAttributes );
6875 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6876 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
6877 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
6878 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
6879 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
6880 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
6881 case Colour::Grey: return setTextAttribute( 0 );
6882
6883 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
6884 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
6885 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
6886 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6887 case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
6888
6889 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
6890
6891 default:
6892 CATCH_ERROR( "Unknown colour requested" );
6893 }
6894 }
6895
6896 private:
6897 void setTextAttribute( WORD _textAttribute ) {
6898 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
6899 }
6900 HANDLE stdoutHandle;
6901 WORD originalForegroundAttributes;
6902 WORD originalBackgroundAttributes;
6903 };
6904
6905 IColourImpl* platformColourInstance() {
6906 static Win32ColourImpl s_instance;
6907
6908 IConfigPtr config = getCurrentContext().getConfig();
6909 UseColour::YesOrNo colourMode = config
6910 ? config->useColour()
6911 : UseColour::Auto;
6912 if( colourMode == UseColour::Auto )
6913 colourMode = UseColour::Yes;
6914 return colourMode == UseColour::Yes
6915 ? &s_instance
6916 : NoColourImpl::instance();
6917 }
6918
6919} // end anon namespace
6920} // end namespace Catch
6921
6922#elif defined( CATCH_CONFIG_COLOUR_ANSI )
6923
6924#include <unistd.h>
6925
6926namespace Catch {
6927namespace {
6928
6929 // use POSIX/ ANSI console terminal codes
6930 // Thanks to Adam Strzelecki for original contribution
6931 // (http://github.com/nanoant)
6932 // https://github.com/philsquared/Catch/pull/131
6933 class PosixColourImpl : public IColourImpl {
6934 public:
6935 virtual void use( Colour::Code _colourCode ) override {
6936 switch( _colourCode ) {
6937 case Colour::None:
6938 case Colour::White: return setColour( "[0m" );
6939 case Colour::Red: return setColour( "[0;31m" );
6940 case Colour::Green: return setColour( "[0;32m" );
6941 case Colour::Blue: return setColour( "[0;34m" );
6942 case Colour::Cyan: return setColour( "[0;36m" );
6943 case Colour::Yellow: return setColour( "[0;33m" );
6944 case Colour::Grey: return setColour( "[1;30m" );
6945
6946 case Colour::LightGrey: return setColour( "[0;37m" );
6947 case Colour::BrightRed: return setColour( "[1;31m" );
6948 case Colour::BrightGreen: return setColour( "[1;32m" );
6949 case Colour::BrightWhite: return setColour( "[1;37m" );
6950 case Colour::BrightYellow: return setColour( "[1;33m" );
6951
6952 case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );
6953 default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );
6954 }
6955 }
6956 static IColourImpl* instance() {
6957 static PosixColourImpl s_instance;
6958 return &s_instance;
6959 }
6960
6961 private:
6962 void setColour( const char* _escapeCode ) {
6963 Catch::cout() << '\033' << _escapeCode;
6964 }
6965 };
6966
6967 bool useColourOnPlatform() {
6968 return
6969#ifdef CATCH_PLATFORM_MAC
6970 !isDebuggerActive() &&
6971#endif
6972#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
6973 isatty(STDOUT_FILENO)
6974#else
6975 false
6976#endif
6977 ;
6978 }
6979 IColourImpl* platformColourInstance() {
6980 ErrnoGuard guard;
6981 IConfigPtr config = getCurrentContext().getConfig();
6982 UseColour::YesOrNo colourMode = config
6983 ? config->useColour()
6984 : UseColour::Auto;
6985 if( colourMode == UseColour::Auto )
6986 colourMode = useColourOnPlatform()
6987 ? UseColour::Yes
6988 : UseColour::No;
6989 return colourMode == UseColour::Yes
6990 ? PosixColourImpl::instance()
6991 : NoColourImpl::instance();
6992 }
6993
6994} // end anon namespace
6995} // end namespace Catch
6996
6997#else // not Windows or ANSI ///////////////////////////////////////////////
6998
6999namespace Catch {
7000
7001 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
7002
7003} // end namespace Catch
7004
7005#endif // Windows/ ANSI/ None
7006
7007namespace Catch {
7008
7009 Colour::Colour( Code _colourCode ) { use( _colourCode ); }
7010 Colour::Colour( Colour&& rhs ) noexcept {
7011 m_moved = rhs.m_moved;
7012 rhs.m_moved = true;
7013 }
7014 Colour& Colour::operator=( Colour&& rhs ) noexcept {
7015 m_moved = rhs.m_moved;
7016 rhs.m_moved = true;
7017 return *this;
7018 }
7019
7020 Colour::~Colour(){ if( !m_moved ) use( None ); }
7021
7022 void Colour::use( Code _colourCode ) {
7023 static IColourImpl* impl = platformColourInstance();
7024 impl->use( _colourCode );
7025 }
7026
7027 std::ostream& operator << ( std::ostream& os, Colour const& ) {
7028 return os;
7029 }
7030
7031} // end namespace Catch
7032
7033#if defined(__clang__)
7034# pragma clang diagnostic pop
7035#endif
7036
7037// end catch_console_colour.cpp
7038// start catch_context.cpp
7039
7040namespace Catch {
7041
7042 class Context : public IMutableContext, NonCopyable {
7043
7044 public: // IContext
7045 virtual IResultCapture* getResultCapture() override {
7046 return m_resultCapture;
7047 }
7048 virtual IRunner* getRunner() override {
7049 return m_runner;
7050 }
7051
7052 virtual IConfigPtr const& getConfig() const override {
7053 return m_config;
7054 }
7055
7056 virtual ~Context() override;
7057
7058 public: // IMutableContext
7059 virtual void setResultCapture( IResultCapture* resultCapture ) override {
7060 m_resultCapture = resultCapture;
7061 }
7062 virtual void setRunner( IRunner* runner ) override {
7063 m_runner = runner;
7064 }
7065 virtual void setConfig( IConfigPtr const& config ) override {
7066 m_config = config;
7067 }
7068
7069 friend IMutableContext& getCurrentMutableContext();
7070
7071 private:
7072 IConfigPtr m_config;
7073 IRunner* m_runner = nullptr;
7074 IResultCapture* m_resultCapture = nullptr;
7075 };
7076
7077 IMutableContext *IMutableContext::currentContext = nullptr;
7078
7079 void IMutableContext::createContext()
7080 {
7081 currentContext = new Context();
7082 }
7083
7084 void cleanUpContext() {
7085 delete IMutableContext::currentContext;
7086 IMutableContext::currentContext = nullptr;
7087 }
7088 IContext::~IContext() = default;
7089 IMutableContext::~IMutableContext() = default;
7090 Context::~Context() = default;
7091}
7092// end catch_context.cpp
7093// start catch_debug_console.cpp
7094
7095// start catch_debug_console.h
7096
7097#include <string>
7098
7099namespace Catch {
7100 void writeToDebugConsole( std::string const& text );
7101}
7102
7103// end catch_debug_console.h
7104#ifdef CATCH_PLATFORM_WINDOWS
7105
7106 namespace Catch {
7107 void writeToDebugConsole( std::string const& text ) {
7108 ::OutputDebugStringA( text.c_str() );
7109 }
7110 }
7111
7112#else
7113
7114 namespace Catch {
7115 void writeToDebugConsole( std::string const& text ) {
7116 // !TBD: Need a version for Mac/ XCode and other IDEs
7117 Catch::cout() << text;
7118 }
7119 }
7120
7121#endif // Platform
7122// end catch_debug_console.cpp
7123// start catch_debugger.cpp
7124
7125#ifdef CATCH_PLATFORM_MAC
7126
7127# include <assert.h>
7128# include <stdbool.h>
7129# include <sys/types.h>
7130# include <unistd.h>
7131# include <sys/sysctl.h>
7132# include <cstddef>
7133# include <ostream>
7134
7135namespace Catch {
7136
7137 // The following function is taken directly from the following technical note:
7138 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
7139
7140 // Returns true if the current process is being debugged (either
7141 // running under the debugger or has a debugger attached post facto).
7142 bool isDebuggerActive(){
7143
7144 int mib[4];
7145 struct kinfo_proc info;
7146 std::size_t size;
7147
7148 // Initialize the flags so that, if sysctl fails for some bizarre
7149 // reason, we get a predictable result.
7150
7151 info.kp_proc.p_flag = 0;
7152
7153 // Initialize mib, which tells sysctl the info we want, in this case
7154 // we're looking for information about a specific process ID.
7155
7156 mib[0] = CTL_KERN;
7157 mib[1] = KERN_PROC;
7158 mib[2] = KERN_PROC_PID;
7159 mib[3] = getpid();
7160
7161 // Call sysctl.
7162
7163 size = sizeof(info);
7164 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {
7165 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
7166 return false;
7167 }
7168
7169 // We're being debugged if the P_TRACED flag is set.
7170
7171 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
7172 }
7173 } // namespace Catch
7174
7175#elif defined(CATCH_PLATFORM_LINUX)
7176 #include <fstream>
7177 #include <string>
7178
7179 namespace Catch{
7180 // The standard POSIX way of detecting a debugger is to attempt to
7181 // ptrace() the process, but this needs to be done from a child and not
7182 // this process itself to still allow attaching to this process later
7183 // if wanted, so is rather heavy. Under Linux we have the PID of the
7184 // "debugger" (which doesn't need to be gdb, of course, it could also
7185 // be strace, for example) in /proc/$PID/status, so just get it from
7186 // there instead.
7187 bool isDebuggerActive(){
7188 // Libstdc++ has a bug, where std::ifstream sets errno to 0
7189 // This way our users can properly assert over errno values
7190 ErrnoGuard guard;
7191 std::ifstream in("/proc/self/status");
7192 for( std::string line; std::getline(in, line); ) {
7193 static const int PREFIX_LEN = 11;
7194 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
7195 // We're traced if the PID is not 0 and no other PID starts
7196 // with 0 digit, so it's enough to check for just a single
7197 // character.
7198 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
7199 }
7200 }
7201
7202 return false;
7203 }
7204 } // namespace Catch
7205#elif defined(_MSC_VER)
7206 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
7207 namespace Catch {
7208 bool isDebuggerActive() {
7209 return IsDebuggerPresent() != 0;
7210 }
7211 }
7212#elif defined(__MINGW32__)
7213 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
7214 namespace Catch {
7215 bool isDebuggerActive() {
7216 return IsDebuggerPresent() != 0;
7217 }
7218 }
7219#else
7220 namespace Catch {
7221 bool isDebuggerActive() { return false; }
7222 }
7223#endif // Platform
7224// end catch_debugger.cpp
7225// start catch_decomposer.cpp
7226
7227namespace Catch {
7228
7230
7231 void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {
7232 if( lhs.size() + rhs.size() < 40 &&
7233 lhs.find('\n') == std::string::npos &&
7234 rhs.find('\n') == std::string::npos )
7235 os << lhs << " " << op << " " << rhs;
7236 else
7237 os << lhs << "\n" << op << "\n" << rhs;
7238 }
7239}
7240// end catch_decomposer.cpp
7241// start catch_errno_guard.cpp
7242
7243#include <cerrno>
7244
7245namespace Catch {
7246 ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
7247 ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
7248}
7249// end catch_errno_guard.cpp
7250// start catch_exception_translator_registry.cpp
7251
7252// start catch_exception_translator_registry.h
7253
7254#include <vector>
7255#include <string>
7256#include <memory>
7257
7258namespace Catch {
7259
7260 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
7261 public:
7262 ~ExceptionTranslatorRegistry();
7263 virtual void registerTranslator( const IExceptionTranslator* translator );
7264 virtual std::string translateActiveException() const override;
7265 std::string tryTranslators() const;
7266
7267 private:
7268 std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;
7269 };
7270}
7271
7272// end catch_exception_translator_registry.h
7273#ifdef __OBJC__
7274#import "Foundation/Foundation.h"
7275#endif
7276
7277namespace Catch {
7278
7279 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
7280 }
7281
7282 void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) {
7283 m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );
7284 }
7285
7287 try {
7288#ifdef __OBJC__
7289 // In Objective-C try objective-c exceptions first
7290 @try {
7291 return tryTranslators();
7292 }
7293 @catch (NSException *exception) {
7294 return Catch::Detail::stringify( [exception description] );
7295 }
7296#else
7297 // Compiling a mixed mode project with MSVC means that CLR
7298 // exceptions will be caught in (...) as well. However, these
7299 // do not fill-in std::current_exception and thus lead to crash
7300 // when attempting rethrow.
7301 // /EHa switch also causes structured exceptions to be caught
7302 // here, but they fill-in current_exception properly, so
7303 // at worst the output should be a little weird, instead of
7304 // causing a crash.
7305 if (std::current_exception() == nullptr) {
7306 return "Non C++ exception. Possibly a CLR exception.";
7307 }
7308 return tryTranslators();
7309#endif
7310 }
7311 catch( TestFailureException& ) {
7312 std::rethrow_exception(std::current_exception());
7313 }
7314 catch( std::exception& ex ) {
7315 return ex.what();
7316 }
7317 catch( std::string& msg ) {
7318 return msg;
7319 }
7320 catch( const char* msg ) {
7321 return msg;
7322 }
7323 catch(...) {
7324 return "Unknown exception";
7325 }
7326 }
7327
7328 std::string ExceptionTranslatorRegistry::tryTranslators() const {
7329 if( m_translators.empty() )
7330 std::rethrow_exception(std::current_exception());
7331 else
7332 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
7333 }
7334}
7335// end catch_exception_translator_registry.cpp
7336// start catch_fatal_condition.cpp
7337
7338#if defined(__GNUC__)
7339# pragma GCC diagnostic push
7340# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
7341#endif
7342
7343#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
7344
7345namespace {
7346 // Report the error condition
7347 void reportFatal( char const * const message ) {
7348 Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );
7349 }
7350}
7351
7352#endif // signals/SEH handling
7353
7354#if defined( CATCH_CONFIG_WINDOWS_SEH )
7355
7356namespace Catch {
7357 struct SignalDefs { DWORD id; const char* name; };
7358
7359 // There is no 1-1 mapping between signals and windows exceptions.
7360 // Windows can easily distinguish between SO and SigSegV,
7361 // but SigInt, SigTerm, etc are handled differently.
7362 static SignalDefs signalDefs[] = {
7363 { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
7364 { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
7365 { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
7366 { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
7367 };
7368
7369 LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
7370 for (auto const& def : signalDefs) {
7371 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
7372 reportFatal(def.name);
7373 }
7374 }
7375 // If its not an exception we care about, pass it along.
7376 // This stops us from eating debugger breaks etc.
7377 return EXCEPTION_CONTINUE_SEARCH;
7378 }
7379
7380 FatalConditionHandler::FatalConditionHandler() {
7381 isSet = true;
7382 // 32k seems enough for Catch to handle stack overflow,
7383 // but the value was found experimentally, so there is no strong guarantee
7384 guaranteeSize = 32 * 1024;
7385 exceptionHandlerHandle = nullptr;
7386 // Register as first handler in current chain
7387 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
7388 // Pass in guarantee size to be filled
7389 SetThreadStackGuarantee(&guaranteeSize);
7390 }
7391
7392 void FatalConditionHandler::reset() {
7393 if (isSet) {
7394 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
7395 SetThreadStackGuarantee(&guaranteeSize);
7396 exceptionHandlerHandle = nullptr;
7397 isSet = false;
7398 }
7399 }
7400
7401 FatalConditionHandler::~FatalConditionHandler() {
7402 reset();
7403 }
7404
7405bool FatalConditionHandler::isSet = false;
7406ULONG FatalConditionHandler::guaranteeSize = 0;
7407PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr;
7408
7409} // namespace Catch
7410
7411#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
7412
7413namespace Catch {
7414
7415 struct SignalDefs {
7416 int id;
7417 const char* name;
7418 };
7419
7420 // 32kb for the alternate stack seems to be sufficient. However, this value
7421 // is experimentally determined, so that's not guaranteed.
7422 constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
7423
7424 static SignalDefs signalDefs[] = {
7425 { SIGINT, "SIGINT - Terminal interrupt signal" },
7426 { SIGILL, "SIGILL - Illegal instruction signal" },
7427 { SIGFPE, "SIGFPE - Floating point error signal" },
7428 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
7429 { SIGTERM, "SIGTERM - Termination request signal" },
7430 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
7431 };
7432
7433 void FatalConditionHandler::handleSignal( int sig ) {
7434 char const * name = "<unknown signal>";
7435 for (auto const& def : signalDefs) {
7436 if (sig == def.id) {
7437 name = def.name;
7438 break;
7439 }
7440 }
7441 reset();
7442 reportFatal(name);
7443 raise( sig );
7444 }
7445
7446 FatalConditionHandler::FatalConditionHandler() {
7447 isSet = true;
7448 stack_t sigStack;
7449 sigStack.ss_sp = altStackMem;
7450 sigStack.ss_size = sigStackSize;
7451 sigStack.ss_flags = 0;
7452 sigaltstack(&sigStack, &oldSigStack);
7453 struct sigaction sa = { };
7454
7455 sa.sa_handler = handleSignal;
7456 sa.sa_flags = SA_ONSTACK;
7457 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
7458 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
7459 }
7460 }
7461
7462 FatalConditionHandler::~FatalConditionHandler() {
7463 reset();
7464 }
7465
7466 void FatalConditionHandler::reset() {
7467 if( isSet ) {
7468 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
7469 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
7470 sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);
7471 }
7472 // Return the old stack
7473 sigaltstack(&oldSigStack, nullptr);
7474 isSet = false;
7475 }
7476 }
7477
7478 bool FatalConditionHandler::isSet = false;
7479 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
7480 stack_t FatalConditionHandler::oldSigStack = {};
7481 char FatalConditionHandler::altStackMem[sigStackSize] = {};
7482
7483} // namespace Catch
7484
7485#else
7486
7487namespace Catch {
7488 void FatalConditionHandler::reset() {}
7489}
7490
7491#endif // signals/SEH handling
7492
7493#if defined(__GNUC__)
7494# pragma GCC diagnostic pop
7495#endif
7496// end catch_fatal_condition.cpp
7497// start catch_interfaces_capture.cpp
7498
7499namespace Catch {
7501}
7502// end catch_interfaces_capture.cpp
7503// start catch_interfaces_config.cpp
7504
7505namespace Catch {
7506 IConfig::~IConfig() = default;
7507}
7508// end catch_interfaces_config.cpp
7509// start catch_interfaces_exception.cpp
7510
7511namespace Catch {
7514}
7515// end catch_interfaces_exception.cpp
7516// start catch_interfaces_registry_hub.cpp
7517
7518namespace Catch {
7519 IRegistryHub::~IRegistryHub() = default;
7521}
7522// end catch_interfaces_registry_hub.cpp
7523// start catch_interfaces_reporter.cpp
7524
7525// start catch_reporter_listening.h
7526
7527namespace Catch {
7528
7529 class ListeningReporter : public IStreamingReporter {
7530 using Reporters = std::vector<IStreamingReporterPtr>;
7531 Reporters m_listeners;
7532 IStreamingReporterPtr m_reporter = nullptr;
7533
7534 public:
7535 void addListener( IStreamingReporterPtr&& listener );
7536 void addReporter( IStreamingReporterPtr&& reporter );
7537
7538 public: // IStreamingReporter
7539
7540 ReporterPreferences getPreferences() const override;
7541
7542 void noMatchingTestCases( std::string const& spec ) override;
7543
7544 static std::set<Verbosity> getSupportedVerbosities();
7545
7546 void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;
7547 void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override;
7548
7549 void testRunStarting( TestRunInfo const& testRunInfo ) override;
7550 void testGroupStarting( GroupInfo const& groupInfo ) override;
7551 void testCaseStarting( TestCaseInfo const& testInfo ) override;
7552 void sectionStarting( SectionInfo const& sectionInfo ) override;
7553 void assertionStarting( AssertionInfo const& assertionInfo ) override;
7554
7555 // The return value indicates if the messages buffer should be cleared:
7556 bool assertionEnded( AssertionStats const& assertionStats ) override;
7557 void sectionEnded( SectionStats const& sectionStats ) override;
7558 void testCaseEnded( TestCaseStats const& testCaseStats ) override;
7559 void testGroupEnded( TestGroupStats const& testGroupStats ) override;
7560 void testRunEnded( TestRunStats const& testRunStats ) override;
7561
7562 void skipTest( TestCaseInfo const& testInfo ) override;
7563 bool isMulti() const override;
7564
7565 };
7566
7567} // end namespace Catch
7568
7569// end catch_reporter_listening.h
7570namespace Catch {
7571
7572 ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig )
7573 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
7574
7575 ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream )
7576 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
7577
7578 std::ostream& ReporterConfig::stream() const { return *m_stream; }
7579 IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; }
7580
7581 TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {}
7582
7583 GroupInfo::GroupInfo( std::string const& _name,
7584 std::size_t _groupIndex,
7585 std::size_t _groupsCount )
7586 : name( _name ),
7587 groupIndex( _groupIndex ),
7588 groupsCounts( _groupsCount )
7589 {}
7590
7591 AssertionStats::AssertionStats( AssertionResult const& _assertionResult,
7592 std::vector<MessageInfo> const& _infoMessages,
7593 Totals const& _totals )
7594 : assertionResult( _assertionResult ),
7595 infoMessages( _infoMessages ),
7596 totals( _totals )
7597 {
7598 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
7599
7600 if( assertionResult.hasMessage() ) {
7601 // Copy message into messages list.
7602 // !TBD This should have been done earlier, somewhere
7603 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
7604 builder << assertionResult.getMessage();
7605 builder.m_info.message = builder.m_stream.str();
7606
7607 infoMessages.push_back( builder.m_info );
7608 }
7609 }
7610
7611 AssertionStats::~AssertionStats() = default;
7612
7613 SectionStats::SectionStats( SectionInfo const& _sectionInfo,
7614 Counts const& _assertions,
7615 double _durationInSeconds,
7616 bool _missingAssertions )
7617 : sectionInfo( _sectionInfo ),
7618 assertions( _assertions ),
7619 durationInSeconds( _durationInSeconds ),
7620 missingAssertions( _missingAssertions )
7621 {}
7622
7623 SectionStats::~SectionStats() = default;
7624
7625 TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo,
7626 Totals const& _totals,
7627 std::string const& _stdOut,
7628 std::string const& _stdErr,
7629 bool _aborting )
7630 : testInfo( _testInfo ),
7631 totals( _totals ),
7632 stdOut( _stdOut ),
7633 stdErr( _stdErr ),
7634 aborting( _aborting )
7635 {}
7636
7637 TestCaseStats::~TestCaseStats() = default;
7638
7639 TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo,
7640 Totals const& _totals,
7641 bool _aborting )
7642 : groupInfo( _groupInfo ),
7643 totals( _totals ),
7644 aborting( _aborting )
7645 {}
7646
7647 TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo )
7648 : groupInfo( _groupInfo ),
7649 aborting( false )
7650 {}
7651
7652 TestGroupStats::~TestGroupStats() = default;
7653
7654 TestRunStats::TestRunStats( TestRunInfo const& _runInfo,
7655 Totals const& _totals,
7656 bool _aborting )
7657 : runInfo( _runInfo ),
7658 totals( _totals ),
7659 aborting( _aborting )
7660 {}
7661
7662 TestRunStats::~TestRunStats() = default;
7663
7664 void IStreamingReporter::fatalErrorEncountered( StringRef ) {}
7665 bool IStreamingReporter::isMulti() const { return false; }
7666
7667 IReporterFactory::~IReporterFactory() = default;
7668 IReporterRegistry::~IReporterRegistry() = default;
7669
7670} // end namespace Catch
7671// end catch_interfaces_reporter.cpp
7672// start catch_interfaces_runner.cpp
7673
7674namespace Catch {
7675 IRunner::~IRunner() = default;
7676}
7677// end catch_interfaces_runner.cpp
7678// start catch_interfaces_testcase.cpp
7679
7680namespace Catch {
7681 ITestInvoker::~ITestInvoker() = default;
7683}
7684// end catch_interfaces_testcase.cpp
7685// start catch_leak_detector.cpp
7686
7687#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
7688#include <crtdbg.h>
7689
7690namespace Catch {
7691
7692 LeakDetector::LeakDetector() {
7693 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
7694 flag |= _CRTDBG_LEAK_CHECK_DF;
7695 flag |= _CRTDBG_ALLOC_MEM_DF;
7696 _CrtSetDbgFlag(flag);
7697 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
7698 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
7699 // Change this to leaking allocation's number to break there
7700 _CrtSetBreakAlloc(-1);
7701 }
7702}
7703
7704#else
7705
7706 Catch::LeakDetector::LeakDetector() {}
7707
7708#endif
7709// end catch_leak_detector.cpp
7710// start catch_list.cpp
7711
7712// start catch_list.h
7713
7714#include <set>
7715
7716namespace Catch {
7717
7718 std::size_t listTests( Config const& config );
7719
7720 std::size_t listTestsNamesOnly( Config const& config );
7721
7722 struct TagInfo {
7723 void add( std::string const& spelling );
7724 std::string all() const;
7725
7726 std::set<std::string> spellings;
7727 std::size_t count = 0;
7728 };
7729
7730 std::size_t listTags( Config const& config );
7731
7732 std::size_t listReporters( Config const& /*config*/ );
7733
7734 Option<std::size_t> list( Config const& config );
7735
7736} // end namespace Catch
7737
7738// end catch_list.h
7739// start catch_text.h
7740
7741namespace Catch {
7742 using namespace clara::TextFlow;
7743}
7744
7745// end catch_text.h
7746#include <limits>
7747#include <algorithm>
7748#include <iomanip>
7749
7750namespace Catch {
7751
7752 std::size_t listTests( Config const& config ) {
7753 TestSpec testSpec = config.testSpec();
7754 if( config.hasTestFilters() )
7755 Catch::cout() << "Matching test cases:\n";
7756 else {
7757 Catch::cout() << "All available test cases:\n";
7758 }
7759
7760 auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
7761 for( auto const& testCaseInfo : matchedTestCases ) {
7762 Colour::Code colour = testCaseInfo.isHidden()
7763 ? Colour::SecondaryText
7764 : Colour::None;
7765 Colour colourGuard( colour );
7766
7767 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n";
7768 if( config.verbosity() >= Verbosity::High ) {
7769 Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl;
7770 std::string description = testCaseInfo.description;
7771 if( description.empty() )
7772 description = "(NO DESCRIPTION)";
7773 Catch::cout() << Column( description ).indent(4) << std::endl;
7774 }
7775 if( !testCaseInfo.tags.empty() )
7776 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";
7777 }
7778
7779 if( !config.hasTestFilters() )
7780 Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl;
7781 else
7782 Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;
7783 return matchedTestCases.size();
7784 }
7785
7786 std::size_t listTestsNamesOnly( Config const& config ) {
7787 TestSpec testSpec = config.testSpec();
7788 std::size_t matchedTests = 0;
7789 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
7790 for( auto const& testCaseInfo : matchedTestCases ) {
7791 matchedTests++;
7792 if( startsWith( testCaseInfo.name, '#' ) )
7793 Catch::cout() << '"' << testCaseInfo.name << '"';
7794 else
7795 Catch::cout() << testCaseInfo.name;
7796 if ( config.verbosity() >= Verbosity::High )
7797 Catch::cout() << "\t@" << testCaseInfo.lineInfo;
7798 Catch::cout() << std::endl;
7799 }
7800 return matchedTests;
7801 }
7802
7803 void TagInfo::add( std::string const& spelling ) {
7804 ++count;
7805 spellings.insert( spelling );
7806 }
7807
7808 std::string TagInfo::all() const {
7809 std::string out;
7810 for( auto const& spelling : spellings )
7811 out += "[" + spelling + "]";
7812 return out;
7813 }
7814
7815 std::size_t listTags( Config const& config ) {
7816 TestSpec testSpec = config.testSpec();
7817 if( config.hasTestFilters() )
7818 Catch::cout() << "Tags for matching test cases:\n";
7819 else {
7820 Catch::cout() << "All available tags:\n";
7821 }
7822
7823 std::map<std::string, TagInfo> tagCounts;
7824
7825 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
7826 for( auto const& testCase : matchedTestCases ) {
7827 for( auto const& tagName : testCase.getTestCaseInfo().tags ) {
7828 std::string lcaseTagName = toLower( tagName );
7829 auto countIt = tagCounts.find( lcaseTagName );
7830 if( countIt == tagCounts.end() )
7831 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
7832 countIt->second.add( tagName );
7833 }
7834 }
7835
7836 for( auto const& tagCount : tagCounts ) {
7837 ReusableStringStream rss;
7838 rss << " " << std::setw(2) << tagCount.second.count << " ";
7839 auto str = rss.str();
7840 auto wrapper = Column( tagCount.second.all() )
7841 .initialIndent( 0 )
7842 .indent( str.size() )
7843 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
7844 Catch::cout() << str << wrapper << '\n';
7845 }
7846 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
7847 return tagCounts.size();
7848 }
7849
7850 std::size_t listReporters( Config const& /*config*/ ) {
7851 Catch::cout() << "Available reporters:\n";
7852 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
7853 std::size_t maxNameLen = 0;
7854 for( auto const& factoryKvp : factories )
7855 maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );
7856
7857 for( auto const& factoryKvp : factories ) {
7858 Catch::cout()
7859 << Column( factoryKvp.first + ":" )
7860 .indent(2)
7861 .width( 5+maxNameLen )
7862 + Column( factoryKvp.second->getDescription() )
7863 .initialIndent(0)
7864 .indent(2)
7865 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
7866 << "\n";
7867 }
7868 Catch::cout() << std::endl;
7869 return factories.size();
7870 }
7871
7872 Option<std::size_t> list( Config const& config ) {
7873 Option<std::size_t> listedCount;
7874 if( config.listTests() )
7875 listedCount = listedCount.valueOr(0) + listTests( config );
7876 if( config.listTestNamesOnly() )
7877 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
7878 if( config.listTags() )
7879 listedCount = listedCount.valueOr(0) + listTags( config );
7880 if( config.listReporters() )
7881 listedCount = listedCount.valueOr(0) + listReporters( config );
7882 return listedCount;
7883 }
7884
7885} // end namespace Catch
7886// end catch_list.cpp
7887// start catch_matchers.cpp
7888
7889namespace Catch {
7890namespace Matchers {
7891 namespace Impl {
7892
7894 if( m_cachedToString.empty() )
7896 return m_cachedToString;
7897 }
7898
7900
7901 } // namespace Impl
7902} // namespace Matchers
7903
7904using namespace Matchers;
7905using Matchers::Impl::MatcherBase;
7906
7907} // namespace Catch
7908// end catch_matchers.cpp
7909// start catch_matchers_floating.cpp
7910
7911// start catch_to_string.hpp
7912
7913#include <string>
7914
7915namespace Catch {
7916 template <typename T>
7917 std::string to_string(T const& t) {
7918#if defined(CATCH_CONFIG_CPP11_TO_STRING)
7919 return std::to_string(t);
7920#else
7921 ReusableStringStream rss;
7922 rss << t;
7923 return rss.str();
7924#endif
7925 }
7926} // end namespace Catch
7927
7928// end catch_to_string.hpp
7929#include <cstdlib>
7930#include <cstdint>
7931#include <cstring>
7932#include <stdexcept>
7933
7934namespace Catch {
7935namespace Matchers {
7936namespace Floating {
7937enum class FloatingPointKind : uint8_t {
7938 Float,
7939 Double
7940};
7941}
7942}
7943}
7944
7945namespace {
7946
7947template <typename T>
7948struct Converter;
7949
7950template <>
7951struct Converter<float> {
7952 static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");
7953 Converter(float f) {
7954 std::memcpy(&i, &f, sizeof(f));
7955 }
7956 int32_t i;
7957};
7958
7959template <>
7960struct Converter<double> {
7961 static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");
7962 Converter(double d) {
7963 std::memcpy(&i, &d, sizeof(d));
7964 }
7965 int64_t i;
7966};
7967
7968template <typename T>
7969auto convert(T t) -> Converter<T> {
7970 return Converter<T>(t);
7971}
7972
7973template <typename FP>
7974bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) {
7975 // Comparison with NaN should always be false.
7976 // This way we can rule it out before getting into the ugly details
7977 if (std::isnan(lhs) || std::isnan(rhs)) {
7978 return false;
7979 }
7980
7981 auto lc = convert(lhs);
7982 auto rc = convert(rhs);
7983
7984 if ((lc.i < 0) != (rc.i < 0)) {
7985 // Potentially we can have +0 and -0
7986 return lhs == rhs;
7987 }
7988
7989 auto ulpDiff = std::abs(lc.i - rc.i);
7990 return ulpDiff <= maxUlpDiff;
7991}
7992
7993}
7994
7995namespace Catch {
7996namespace Matchers {
7997namespace Floating {
7998 WithinAbsMatcher::WithinAbsMatcher(double target, double margin)
7999 :m_target{ target }, m_margin{ margin } {
8000 if (m_margin < 0) {
8001 throw std::domain_error("Allowed margin difference has to be >= 0");
8002 }
8003 }
8004
8005 // Performs equivalent check of std::fabs(lhs - rhs) <= margin
8006 // But without the subtraction to allow for INFINITY in comparison
8007 bool WithinAbsMatcher::match(double const& matchee) const {
8008 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
8009 }
8010
8011 std::string WithinAbsMatcher::describe() const {
8012 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
8013 }
8014
8015 WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
8016 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
8017 if (m_ulps < 0) {
8018 throw std::domain_error("Allowed ulp difference has to be >= 0");
8019 }
8020 }
8021
8022 bool WithinUlpsMatcher::match(double const& matchee) const {
8023 switch (m_type) {
8025 return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);
8027 return almostEqualUlps<double>(matchee, m_target, m_ulps);
8028 default:
8029 throw std::domain_error("Unknown FloatingPointKind value");
8030 }
8031 }
8032
8033 std::string WithinUlpsMatcher::describe() const {
8034 return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
8035 }
8036
8037}// namespace Floating
8038
8039Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) {
8040 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
8041}
8042
8043Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) {
8044 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
8045}
8046
8047Floating::WithinAbsMatcher WithinAbs(double target, double margin) {
8048 return Floating::WithinAbsMatcher(target, margin);
8049}
8050
8051} // namespace Matchers
8052} // namespace Catch
8053
8054// end catch_matchers_floating.cpp
8055// start catch_matchers_generic.cpp
8056
8058 if (desc.empty()) {
8059 return "matches undescribed predicate";
8060 } else {
8061 return "matches predicate: \"" + desc + '"';
8062 }
8063}
8064// end catch_matchers_generic.cpp
8065// start catch_matchers_string.cpp
8066
8067#include <regex>
8068
8069namespace Catch {
8070namespace Matchers {
8071
8072 namespace StdString {
8073
8074 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
8075 : m_caseSensitivity( caseSensitivity ),
8076 m_str( adjustString( str ) )
8077 {}
8078 std::string CasedString::adjustString( std::string const& str ) const {
8079 return m_caseSensitivity == CaseSensitive::No
8080 ? toLower( str )
8081 : str;
8082 }
8083 std::string CasedString::caseSensitivitySuffix() const {
8084 return m_caseSensitivity == CaseSensitive::No
8085 ? " (case insensitive)"
8086 : std::string();
8087 }
8088
8089 StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
8090 : m_comparator( comparator ),
8091 m_operation( operation ) {
8092 }
8093
8094 std::string StringMatcherBase::describe() const {
8095 std::string description;
8096 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
8097 m_comparator.caseSensitivitySuffix().size());
8098 description += m_operation;
8099 description += ": \"";
8100 description += m_comparator.m_str;
8101 description += "\"";
8102 description += m_comparator.caseSensitivitySuffix();
8103 return description;
8104 }
8105
8106 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
8107
8108 bool EqualsMatcher::match( std::string const& source ) const {
8109 return m_comparator.adjustString( source ) == m_comparator.m_str;
8110 }
8111
8112 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
8113
8114 bool ContainsMatcher::match( std::string const& source ) const {
8115 return contains( m_comparator.adjustString( source ), m_comparator.m_str );
8116 }
8117
8118 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
8119
8120 bool StartsWithMatcher::match( std::string const& source ) const {
8121 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8122 }
8123
8124 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
8125
8126 bool EndsWithMatcher::match( std::string const& source ) const {
8127 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
8128 }
8129
8130 RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}
8131
8132 bool RegexMatcher::match(std::string const& matchee) const {
8133 auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway
8134 if (m_caseSensitivity == CaseSensitive::Choice::No) {
8135 flags |= std::regex::icase;
8136 }
8137 auto reg = std::regex(m_regex, flags);
8138 return std::regex_match(matchee, reg);
8139 }
8140
8141 std::string RegexMatcher::describe() const {
8142 return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");
8143 }
8144
8145 } // namespace StdString
8146
8147 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
8148 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
8149 }
8150 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
8151 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
8152 }
8153 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
8154 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
8155 }
8156 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
8157 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
8158 }
8159
8160 StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) {
8161 return StdString::RegexMatcher(regex, caseSensitivity);
8162 }
8163
8164} // namespace Matchers
8165} // namespace Catch
8166// end catch_matchers_string.cpp
8167// start catch_message.cpp
8168
8169// start catch_uncaught_exceptions.h
8170
8171namespace Catch {
8172 bool uncaught_exceptions();
8173} // end namespace Catch
8174
8175// end catch_uncaught_exceptions.h
8176namespace Catch {
8177
8178 MessageInfo::MessageInfo( std::string const& _macroName,
8179 SourceLineInfo const& _lineInfo,
8180 ResultWas::OfType _type )
8181 : macroName( _macroName ),
8182 lineInfo( _lineInfo ),
8183 type( _type ),
8184 sequence( ++globalCount )
8185 {}
8186
8187 bool MessageInfo::operator==( MessageInfo const& other ) const {
8188 return sequence == other.sequence;
8189 }
8190
8191 bool MessageInfo::operator<( MessageInfo const& other ) const {
8192 return sequence < other.sequence;
8193 }
8194
8195 // This may need protecting if threading support is added
8196 unsigned int MessageInfo::globalCount = 0;
8197
8199
8201 SourceLineInfo const& lineInfo,
8202 ResultWas::OfType type )
8203 :m_info(macroName, lineInfo, type) {}
8204
8206
8207 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
8208 : m_info( builder.m_info )
8209 {
8210 m_info.message = builder.m_stream.str();
8212 }
8213
8215 if ( !uncaught_exceptions() ){
8217 }
8218 }
8219} // end namespace Catch
8220// end catch_message.cpp
8221// start catch_output_redirect.cpp
8222
8223// start catch_output_redirect.h
8224#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
8225#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
8226
8227#include <cstdio>
8228#include <iosfwd>
8229#include <string>
8230
8231namespace Catch {
8232
8233 class RedirectedStream {
8234 std::ostream& m_originalStream;
8235 std::ostream& m_redirectionStream;
8236 std::streambuf* m_prevBuf;
8237
8238 public:
8239 RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );
8240 ~RedirectedStream();
8241 };
8242
8243 class RedirectedStdOut {
8244 ReusableStringStream m_rss;
8245 RedirectedStream m_cout;
8246 public:
8247 RedirectedStdOut();
8248 auto str() const -> std::string;
8249 };
8250
8251 // StdErr has two constituent streams in C++, std::cerr and std::clog
8252 // This means that we need to redirect 2 streams into 1 to keep proper
8253 // order of writes
8254 class RedirectedStdErr {
8255 ReusableStringStream m_rss;
8256 RedirectedStream m_cerr;
8257 RedirectedStream m_clog;
8258 public:
8259 RedirectedStdErr();
8260 auto str() const -> std::string;
8261 };
8262
8263 // Windows's implementation of std::tmpfile is terrible (it tries
8264 // to create a file inside system folder, thus requiring elevated
8265 // privileges for the binary), so we have to use tmpnam(_s) and
8266 // create the file ourselves there.
8267 class TempFile {
8268 public:
8269 TempFile(TempFile const&) = delete;
8270 TempFile& operator=(TempFile const&) = delete;
8271 TempFile(TempFile&&) = delete;
8272 TempFile& operator=(TempFile&&) = delete;
8273
8274 TempFile();
8275 ~TempFile();
8276
8277 std::FILE* getFile();
8278 std::string getContents();
8279
8280 private:
8281 std::FILE* m_file = nullptr;
8282 #if defined(_MSC_VER)
8283 char m_buffer[L_tmpnam] = { 0 };
8284 #endif
8285 };
8286
8287 class OutputRedirect {
8288 public:
8289 OutputRedirect(OutputRedirect const&) = delete;
8290 OutputRedirect& operator=(OutputRedirect const&) = delete;
8291 OutputRedirect(OutputRedirect&&) = delete;
8292 OutputRedirect& operator=(OutputRedirect&&) = delete;
8293
8294 OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);
8295 ~OutputRedirect();
8296
8297 private:
8298 int m_originalStdout = -1;
8299 int m_originalStderr = -1;
8300 TempFile m_stdoutFile;
8301 TempFile m_stderrFile;
8302 std::string& m_stdoutDest;
8303 std::string& m_stderrDest;
8304 };
8305
8306} // end namespace Catch
8307
8308#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
8309// end catch_output_redirect.h
8310#include <cstdio>
8311#include <cstring>
8312#include <fstream>
8313#include <sstream>
8314#include <stdexcept>
8315
8316#if defined(_MSC_VER)
8317#include <io.h> //_dup and _dup2
8318#define dup _dup
8319#define dup2 _dup2
8320#define fileno _fileno
8321#else
8322#include <unistd.h> // dup and dup2
8323#endif
8324
8325namespace Catch {
8326
8327 RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )
8328 : m_originalStream( originalStream ),
8329 m_redirectionStream( redirectionStream ),
8330 m_prevBuf( m_originalStream.rdbuf() )
8331 {
8332 m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
8333 }
8334
8335 RedirectedStream::~RedirectedStream() {
8336 m_originalStream.rdbuf( m_prevBuf );
8337 }
8338
8339 RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}
8340 auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }
8341
8342 RedirectedStdErr::RedirectedStdErr()
8343 : m_cerr( Catch::cerr(), m_rss.get() ),
8344 m_clog( Catch::clog(), m_rss.get() )
8345 {}
8346 auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }
8347
8348#if defined(_MSC_VER)
8349 TempFile::TempFile() {
8350 if (tmpnam_s(m_buffer)) {
8351 throw std::runtime_error("Could not get a temp filename");
8352 }
8353 if (fopen_s(&m_file, m_buffer, "w")) {
8354 char buffer[100];
8355 if (strerror_s(buffer, errno)) {
8356 throw std::runtime_error("Could not translate errno to string");
8357 }
8358 throw std::runtime_error("Could not open the temp file: " + std::string(m_buffer) + buffer);
8359 }
8360 }
8361#else
8362 TempFile::TempFile() {
8363 m_file = std::tmpfile();
8364 if (!m_file) {
8365 throw std::runtime_error("Could not create a temp file.");
8366 }
8367 }
8368
8369#endif
8370
8371 TempFile::~TempFile() {
8372 // TBD: What to do about errors here?
8373 std::fclose(m_file);
8374 // We manually create the file on Windows only, on Linux
8375 // it will be autodeleted
8376#if defined(_MSC_VER)
8377 std::remove(m_buffer);
8378#endif
8379 }
8380
8381 FILE* TempFile::getFile() {
8382 return m_file;
8383 }
8384
8385 std::string TempFile::getContents() {
8386 std::stringstream sstr;
8387 char buffer[100] = {};
8388 std::rewind(m_file);
8389 while (std::fgets(buffer, sizeof(buffer), m_file)) {
8390 sstr << buffer;
8391 }
8392 return sstr.str();
8393 }
8394
8395 OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :
8396 m_originalStdout(dup(1)),
8397 m_originalStderr(dup(2)),
8398 m_stdoutDest(stdout_dest),
8399 m_stderrDest(stderr_dest) {
8400 dup2(fileno(m_stdoutFile.getFile()), 1);
8401 dup2(fileno(m_stderrFile.getFile()), 2);
8402 }
8403
8404 OutputRedirect::~OutputRedirect() {
8405 Catch::cout() << std::flush;
8406 fflush(stdout);
8407 // Since we support overriding these streams, we flush cerr
8408 // even though std::cerr is unbuffered
8409 Catch::cerr() << std::flush;
8410 Catch::clog() << std::flush;
8411 fflush(stderr);
8412
8413 dup2(m_originalStdout, 1);
8414 dup2(m_originalStderr, 2);
8415
8416 m_stdoutDest += m_stdoutFile.getContents();
8417 m_stderrDest += m_stderrFile.getContents();
8418 }
8419
8420} // namespace Catch
8421
8422#if defined(_MSC_VER)
8423#undef dup
8424#undef dup2
8425#undef fileno
8426#endif
8427// end catch_output_redirect.cpp
8428// start catch_random_number_generator.cpp
8429
8430// start catch_random_number_generator.h
8431
8432#include <algorithm>
8433
8434namespace Catch {
8435
8436 struct IConfig;
8437
8438 void seedRng( IConfig const& config );
8439
8440 unsigned int rngSeed();
8441
8442 struct RandomNumberGenerator {
8443 using result_type = unsigned int;
8444
8445 static constexpr result_type (min)() { return 0; }
8446 static constexpr result_type (max)() { return 1000000; }
8447
8448 result_type operator()( result_type n ) const;
8449 result_type operator()() const;
8450
8451 template<typename V>
8452 static void shuffle( V& vector ) {
8453 RandomNumberGenerator rng;
8454 std::shuffle( vector.begin(), vector.end(), rng );
8455 }
8456 };
8457
8458}
8459
8460// end catch_random_number_generator.h
8461#include <cstdlib>
8462
8463namespace Catch {
8464
8465 void seedRng( IConfig const& config ) {
8466 if( config.rngSeed() != 0 )
8467 std::srand( config.rngSeed() );
8468 }
8469 unsigned int rngSeed() {
8470 return getCurrentContext().getConfig()->rngSeed();
8471 }
8472
8473 RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const {
8474 return std::rand() % n;
8475 }
8476 RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const {
8477 return std::rand() % (max)();
8478 }
8479
8480}
8481// end catch_random_number_generator.cpp
8482// start catch_registry_hub.cpp
8483
8484// start catch_test_case_registry_impl.h
8485
8486#include <vector>
8487#include <set>
8488#include <algorithm>
8489#include <ios>
8490
8491namespace Catch {
8492
8493 class TestCase;
8494 struct IConfig;
8495
8496 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );
8497 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
8498
8499 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );
8500
8501 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
8502 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
8503
8504 class TestRegistry : public ITestCaseRegistry {
8505 public:
8506 virtual ~TestRegistry() = default;
8507
8508 virtual void registerTest( TestCase const& testCase );
8509
8510 std::vector<TestCase> const& getAllTests() const override;
8511 std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override;
8512
8513 private:
8514 std::vector<TestCase> m_functions;
8515 mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
8516 mutable std::vector<TestCase> m_sortedFunctions;
8517 std::size_t m_unnamedCount = 0;
8518 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
8519 };
8520
8522
8523 class TestInvokerAsFunction : public ITestInvoker {
8524 void(*m_testAsFunction)();
8525 public:
8526 TestInvokerAsFunction( void(*testAsFunction)() ) noexcept;
8527
8528 void invoke() const override;
8529 };
8530
8531 std::string extractClassName( StringRef const& classOrQualifiedMethodName );
8532
8534
8535} // end namespace Catch
8536
8537// end catch_test_case_registry_impl.h
8538// start catch_reporter_registry.h
8539
8540#include <map>
8541
8542namespace Catch {
8543
8544 class ReporterRegistry : public IReporterRegistry {
8545
8546 public:
8547
8548 ~ReporterRegistry() override;
8549
8550 IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override;
8551
8552 void registerReporter( std::string const& name, IReporterFactoryPtr const& factory );
8553 void registerListener( IReporterFactoryPtr const& factory );
8554
8555 FactoryMap const& getFactories() const override;
8556 Listeners const& getListeners() const override;
8557
8558 private:
8559 FactoryMap m_factories;
8560 Listeners m_listeners;
8561 };
8562}
8563
8564// end catch_reporter_registry.h
8565// start catch_tag_alias_registry.h
8566
8567// start catch_tag_alias.h
8568
8569#include <string>
8570
8571namespace Catch {
8572
8573 struct TagAlias {
8574 TagAlias(std::string const& _tag, SourceLineInfo _lineInfo);
8575
8576 std::string tag;
8577 SourceLineInfo lineInfo;
8578 };
8579
8580} // end namespace Catch
8581
8582// end catch_tag_alias.h
8583#include <map>
8584
8585namespace Catch {
8586
8587 class TagAliasRegistry : public ITagAliasRegistry {
8588 public:
8589 ~TagAliasRegistry() override;
8590 TagAlias const* find( std::string const& alias ) const override;
8591 std::string expandAliases( std::string const& unexpandedTestSpec ) const override;
8592 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
8593
8594 private:
8595 std::map<std::string, TagAlias> m_registry;
8596 };
8597
8598} // end namespace Catch
8599
8600// end catch_tag_alias_registry.h
8601// start catch_startup_exception_registry.h
8602
8603#include <vector>
8604#include <exception>
8605
8606namespace Catch {
8607
8608 class StartupExceptionRegistry {
8609 public:
8610 void add(std::exception_ptr const& exception) noexcept;
8611 std::vector<std::exception_ptr> const& getExceptions() const noexcept;
8612 private:
8613 std::vector<std::exception_ptr> m_exceptions;
8614 };
8615
8616} // end namespace Catch
8617
8618// end catch_startup_exception_registry.h
8619namespace Catch {
8620
8621 namespace {
8622
8623 class RegistryHub : public IRegistryHub, public IMutableRegistryHub,
8624 private NonCopyable {
8625
8626 public: // IRegistryHub
8627 RegistryHub() = default;
8628 IReporterRegistry const& getReporterRegistry() const override {
8629 return m_reporterRegistry;
8630 }
8631 ITestCaseRegistry const& getTestCaseRegistry() const override {
8632 return m_testCaseRegistry;
8633 }
8634 IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override {
8635 return m_exceptionTranslatorRegistry;
8636 }
8637 ITagAliasRegistry const& getTagAliasRegistry() const override {
8638 return m_tagAliasRegistry;
8639 }
8640 StartupExceptionRegistry const& getStartupExceptionRegistry() const override {
8641 return m_exceptionRegistry;
8642 }
8643
8644 public: // IMutableRegistryHub
8645 void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override {
8646 m_reporterRegistry.registerReporter( name, factory );
8647 }
8648 void registerListener( IReporterFactoryPtr const& factory ) override {
8649 m_reporterRegistry.registerListener( factory );
8650 }
8651 void registerTest( TestCase const& testInfo ) override {
8652 m_testCaseRegistry.registerTest( testInfo );
8653 }
8654 void registerTranslator( const IExceptionTranslator* translator ) override {
8655 m_exceptionTranslatorRegistry.registerTranslator( translator );
8656 }
8657 void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {
8658 m_tagAliasRegistry.add( alias, tag, lineInfo );
8659 }
8660 void registerStartupException() noexcept override {
8661 m_exceptionRegistry.add(std::current_exception());
8662 }
8663
8664 private:
8665 TestRegistry m_testCaseRegistry;
8666 ReporterRegistry m_reporterRegistry;
8667 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
8668 TagAliasRegistry m_tagAliasRegistry;
8669 StartupExceptionRegistry m_exceptionRegistry;
8670 };
8671
8672 // Single, global, instance
8673 RegistryHub*& getTheRegistryHub() {
8674 static RegistryHub* theRegistryHub = nullptr;
8675 if( !theRegistryHub )
8676 theRegistryHub = new RegistryHub();
8677 return theRegistryHub;
8678 }
8679 }
8680
8681 IRegistryHub& getRegistryHub() {
8682 return *getTheRegistryHub();
8683 }
8684 IMutableRegistryHub& getMutableRegistryHub() {
8685 return *getTheRegistryHub();
8686 }
8687 void cleanUp() {
8688 delete getTheRegistryHub();
8689 getTheRegistryHub() = nullptr;
8690 cleanUpContext();
8692 }
8695 }
8696
8697} // end namespace Catch
8698// end catch_registry_hub.cpp
8699// start catch_reporter_registry.cpp
8700
8701namespace Catch {
8702
8703 ReporterRegistry::~ReporterRegistry() = default;
8704
8705 IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const {
8706 auto it = m_factories.find( name );
8707 if( it == m_factories.end() )
8708 return nullptr;
8709 return it->second->create( ReporterConfig( config ) );
8710 }
8711
8712 void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) {
8713 m_factories.emplace(name, factory);
8714 }
8715 void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) {
8716 m_listeners.push_back( factory );
8717 }
8718
8719 IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const {
8720 return m_factories;
8721 }
8722 IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const {
8723 return m_listeners;
8724 }
8725
8726}
8727// end catch_reporter_registry.cpp
8728// start catch_result_type.cpp
8729
8730namespace Catch {
8731
8732 bool isOk( ResultWas::OfType resultType ) {
8733 return ( resultType & ResultWas::FailureBit ) == 0;
8734 }
8735 bool isJustInfo( int flags ) {
8736 return flags == ResultWas::Info;
8737 }
8738
8740 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
8741 }
8742
8743 bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
8744 bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
8745
8746} // end namespace Catch
8747// end catch_result_type.cpp
8748// start catch_run_context.cpp
8749
8750#include <cassert>
8751#include <algorithm>
8752#include <sstream>
8753
8754namespace Catch {
8755
8756 RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)
8757 : m_runInfo(_config->name()),
8758 m_context(getCurrentMutableContext()),
8759 m_config(_config),
8760 m_reporter(std::move(reporter)),
8761 m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },
8762 m_includeSuccessfulResults( m_config->includeSuccessfulResults() )
8763 {
8764 m_context.setRunner(this);
8765 m_context.setConfig(m_config);
8766 m_context.setResultCapture(this);
8767 m_reporter->testRunStarting(m_runInfo);
8768 }
8769
8770 RunContext::~RunContext() {
8771 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
8772 }
8773
8774 void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {
8775 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
8776 }
8777
8778 void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {
8779 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
8780 }
8781
8782 Totals RunContext::runTest(TestCase const& testCase) {
8783 Totals prevTotals = m_totals;
8784
8785 std::string redirectedCout;
8786 std::string redirectedCerr;
8787
8788 auto const& testInfo = testCase.getTestCaseInfo();
8789
8790 m_reporter->testCaseStarting(testInfo);
8791
8792 m_activeTestCase = &testCase;
8793
8794 ITracker& rootTracker = m_trackerContext.startRun();
8795 assert(rootTracker.isSectionTracker());
8796 static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
8797 do {
8798 m_trackerContext.startCycle();
8799 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
8800 runCurrentTest(redirectedCout, redirectedCerr);
8801 } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
8802
8803 Totals deltaTotals = m_totals.delta(prevTotals);
8804 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
8805 deltaTotals.assertions.failed++;
8806 deltaTotals.testCases.passed--;
8807 deltaTotals.testCases.failed++;
8808 }
8809 m_totals.testCases += deltaTotals.testCases;
8810 m_reporter->testCaseEnded(TestCaseStats(testInfo,
8811 deltaTotals,
8812 redirectedCout,
8813 redirectedCerr,
8814 aborting()));
8815
8816 m_activeTestCase = nullptr;
8817 m_testCaseTracker = nullptr;
8818
8819 return deltaTotals;
8820 }
8821
8822 IConfigPtr RunContext::config() const {
8823 return m_config;
8824 }
8825
8826 IStreamingReporter& RunContext::reporter() const {
8827 return *m_reporter;
8828 }
8829
8830 void RunContext::assertionEnded(AssertionResult const & result) {
8831 if (result.getResultType() == ResultWas::Ok) {
8832 m_totals.assertions.passed++;
8833 m_lastAssertionPassed = true;
8834 } else if (!result.isOk()) {
8835 m_lastAssertionPassed = false;
8836 if( m_activeTestCase->getTestCaseInfo().okToFail() )
8837 m_totals.assertions.failedButOk++;
8838 else
8839 m_totals.assertions.failed++;
8840 }
8841 else {
8842 m_lastAssertionPassed = true;
8843 }
8844
8845 // We have no use for the return value (whether messages should be cleared), because messages were made scoped
8846 // and should be let to clear themselves out.
8847 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
8848
8849 // Reset working state
8850 resetAssertionInfo();
8851 m_lastResult = result;
8852 }
8853 void RunContext::resetAssertionInfo() {
8854 m_lastAssertionInfo.macroName = StringRef();
8855 m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;
8856 }
8857
8858 bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {
8859 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
8860 if (!sectionTracker.isOpen())
8861 return false;
8862 m_activeSections.push_back(&sectionTracker);
8863
8864 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
8865
8866 m_reporter->sectionStarting(sectionInfo);
8867
8868 assertions = m_totals.assertions;
8869
8870 return true;
8871 }
8872
8873 bool RunContext::testForMissingAssertions(Counts& assertions) {
8874 if (assertions.total() != 0)
8875 return false;
8876 if (!m_config->warnAboutMissingAssertions())
8877 return false;
8878 if (m_trackerContext.currentTracker().hasChildren())
8879 return false;
8880 m_totals.assertions.failed++;
8881 assertions.failed++;
8882 return true;
8883 }
8884
8885 void RunContext::sectionEnded(SectionEndInfo const & endInfo) {
8886 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
8887 bool missingAssertions = testForMissingAssertions(assertions);
8888
8889 if (!m_activeSections.empty()) {
8890 m_activeSections.back()->close();
8891 m_activeSections.pop_back();
8892 }
8893
8894 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
8895 m_messages.clear();
8896 }
8897
8898 void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {
8899 if (m_unfinishedSections.empty())
8900 m_activeSections.back()->fail();
8901 else
8902 m_activeSections.back()->close();
8903 m_activeSections.pop_back();
8904
8905 m_unfinishedSections.push_back(endInfo);
8906 }
8907 void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
8908 m_reporter->benchmarkStarting( info );
8909 }
8910 void RunContext::benchmarkEnded( BenchmarkStats const& stats ) {
8911 m_reporter->benchmarkEnded( stats );
8912 }
8913
8914 void RunContext::pushScopedMessage(MessageInfo const & message) {
8915 m_messages.push_back(message);
8916 }
8917
8918 void RunContext::popScopedMessage(MessageInfo const & message) {
8919 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
8920 }
8921
8922 std::string RunContext::getCurrentTestName() const {
8923 return m_activeTestCase
8924 ? m_activeTestCase->getTestCaseInfo().name
8925 : std::string();
8926 }
8927
8928 const AssertionResult * RunContext::getLastResult() const {
8929 return &(*m_lastResult);
8930 }
8931
8932 void RunContext::exceptionEarlyReported() {
8933 m_shouldReportUnexpected = false;
8934 }
8935
8936 void RunContext::handleFatalErrorCondition( StringRef message ) {
8937 // First notify reporter that bad things happened
8938 m_reporter->fatalErrorEncountered(message);
8939
8940 // Don't rebuild the result -- the stringification itself can cause more fatal errors
8941 // Instead, fake a result data.
8942 AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );
8943 tempResult.message = message;
8944 AssertionResult result(m_lastAssertionInfo, tempResult);
8945
8946 assertionEnded(result);
8947
8948 handleUnfinishedSections();
8949
8950 // Recreate section for test case (as we will lose the one that was in scope)
8951 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
8952 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
8953
8954 Counts assertions;
8955 assertions.failed = 1;
8956 SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);
8957 m_reporter->sectionEnded(testCaseSectionStats);
8958
8959 auto const& testInfo = m_activeTestCase->getTestCaseInfo();
8960
8961 Totals deltaTotals;
8962 deltaTotals.testCases.failed = 1;
8963 deltaTotals.assertions.failed = 1;
8964 m_reporter->testCaseEnded(TestCaseStats(testInfo,
8965 deltaTotals,
8966 std::string(),
8967 std::string(),
8968 false));
8969 m_totals.testCases.failed++;
8970 testGroupEnded(std::string(), m_totals, 1, 1);
8971 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));
8972 }
8973
8974 bool RunContext::lastAssertionPassed() {
8975 return m_lastAssertionPassed;
8976 }
8977
8978 void RunContext::assertionPassed() {
8979 m_lastAssertionPassed = true;
8980 ++m_totals.assertions.passed;
8981 resetAssertionInfo();
8982 }
8983
8984 bool RunContext::aborting() const {
8985 return m_totals.assertions.failed == static_cast<std::size_t>(m_config->abortAfter());
8986 }
8987
8988 void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {
8989 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
8990 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description);
8991 m_reporter->sectionStarting(testCaseSection);
8992 Counts prevAssertions = m_totals.assertions;
8993 double duration = 0;
8994 m_shouldReportUnexpected = true;
8995 m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };
8996
8997 seedRng(*m_config);
8998
8999 Timer timer;
9000 try {
9001 if (m_reporter->getPreferences().shouldRedirectStdOut) {
9002#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
9003 RedirectedStdOut redirectedStdOut;
9004 RedirectedStdErr redirectedStdErr;
9005
9006 timer.start();
9007 invokeActiveTestCase();
9008 redirectedCout += redirectedStdOut.str();
9009 redirectedCerr += redirectedStdErr.str();
9010#else
9011 OutputRedirect r(redirectedCout, redirectedCerr);
9012 timer.start();
9013 invokeActiveTestCase();
9014#endif
9015 } else {
9016 timer.start();
9017 invokeActiveTestCase();
9018 }
9019 duration = timer.getElapsedSeconds();
9020 } catch (TestFailureException&) {
9021 // This just means the test was aborted due to failure
9022 } catch (...) {
9023 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
9024 // are reported without translation at the point of origin.
9025 if( m_shouldReportUnexpected ) {
9026 AssertionReaction dummyReaction;
9027 handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
9028 }
9029 }
9030 Counts assertions = m_totals.assertions - prevAssertions;
9031 bool missingAssertions = testForMissingAssertions(assertions);
9032
9033 m_testCaseTracker->close();
9034 handleUnfinishedSections();
9035 m_messages.clear();
9036
9037 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
9038 m_reporter->sectionEnded(testCaseSectionStats);
9039 }
9040
9041 void RunContext::invokeActiveTestCase() {
9042 FatalConditionHandler fatalConditionHandler; // Handle signals
9043 m_activeTestCase->invoke();
9044 fatalConditionHandler.reset();
9045 }
9046
9047 void RunContext::handleUnfinishedSections() {
9048 // If sections ended prematurely due to an exception we stored their
9049 // infos here so we can tear them down outside the unwind process.
9050 for (auto it = m_unfinishedSections.rbegin(),
9051 itEnd = m_unfinishedSections.rend();
9052 it != itEnd;
9053 ++it)
9054 sectionEnded(*it);
9055 m_unfinishedSections.clear();
9056 }
9057
9058 void RunContext::handleExpr(
9059 AssertionInfo const& info,
9060 ITransientExpression const& expr,
9061 AssertionReaction& reaction
9062 ) {
9063 m_reporter->assertionStarting( info );
9064
9065 bool negated = isFalseTest( info.resultDisposition );
9066 bool result = expr.getResult() != negated;
9067
9068 if( result ) {
9069 if (!m_includeSuccessfulResults) {
9070 assertionPassed();
9071 }
9072 else {
9073 reportExpr(info, ResultWas::Ok, &expr, negated);
9074 }
9075 }
9076 else {
9077 reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
9078 populateReaction( reaction );
9079 }
9080 }
9081 void RunContext::reportExpr(
9082 AssertionInfo const &info,
9083 ResultWas::OfType resultType,
9084 ITransientExpression const *expr,
9085 bool negated ) {
9086
9087 m_lastAssertionInfo = info;
9088 AssertionResultData data( resultType, LazyExpression( negated ) );
9089
9090 AssertionResult assertionResult{ info, data };
9091 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
9092
9093 assertionEnded( assertionResult );
9094 }
9095
9096 void RunContext::handleMessage(
9097 AssertionInfo const& info,
9098 ResultWas::OfType resultType,
9099 StringRef const& message,
9100 AssertionReaction& reaction
9101 ) {
9102 m_reporter->assertionStarting( info );
9103
9104 m_lastAssertionInfo = info;
9105
9106 AssertionResultData data( resultType, LazyExpression( false ) );
9107 data.message = message;
9108 AssertionResult assertionResult{ m_lastAssertionInfo, data };
9109 assertionEnded( assertionResult );
9110 if( !assertionResult.isOk() )
9111 populateReaction( reaction );
9112 }
9113 void RunContext::handleUnexpectedExceptionNotThrown(
9114 AssertionInfo const& info,
9115 AssertionReaction& reaction
9116 ) {
9117 handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
9118 }
9119
9120 void RunContext::handleUnexpectedInflightException(
9121 AssertionInfo const& info,
9122 std::string const& message,
9123 AssertionReaction& reaction
9124 ) {
9125 m_lastAssertionInfo = info;
9126
9127 AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
9128 data.message = message;
9129 AssertionResult assertionResult{ info, data };
9130 assertionEnded( assertionResult );
9131 populateReaction( reaction );
9132 }
9133
9134 void RunContext::populateReaction( AssertionReaction& reaction ) {
9135 reaction.shouldDebugBreak = m_config->shouldDebugBreak();
9136 reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
9137 }
9138
9139 void RunContext::handleIncomplete(
9140 AssertionInfo const& info
9141 ) {
9142 m_lastAssertionInfo = info;
9143
9144 AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
9145 data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
9146 AssertionResult assertionResult{ info, data };
9147 assertionEnded( assertionResult );
9148 }
9149 void RunContext::handleNonExpr(
9150 AssertionInfo const &info,
9151 ResultWas::OfType resultType,
9152 AssertionReaction &reaction
9153 ) {
9154 m_lastAssertionInfo = info;
9155
9156 AssertionResultData data( resultType, LazyExpression( false ) );
9157 AssertionResult assertionResult{ info, data };
9158 assertionEnded( assertionResult );
9159
9160 if( !assertionResult.isOk() )
9161 populateReaction( reaction );
9162 }
9163
9164 IResultCapture& getResultCapture() {
9165 if (auto* capture = getCurrentContext().getResultCapture())
9166 return *capture;
9167 else
9168 CATCH_INTERNAL_ERROR("No result capture instance");
9169 }
9170}
9171// end catch_run_context.cpp
9172// start catch_section.cpp
9173
9174namespace Catch {
9175
9176 Section::Section( SectionInfo const& info )
9177 : m_info( info ),
9178 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
9179 {
9180 m_timer.start();
9181 }
9182
9184 if( m_sectionIncluded ) {
9185 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
9186 if( uncaught_exceptions() )
9188 else
9189 getResultCapture().sectionEnded( endInfo );
9190 }
9191 }
9192
9193 // This indicates whether the section should be executed or not
9194 Section::operator bool() const {
9195 return m_sectionIncluded;
9196 }
9197
9198} // end namespace Catch
9199// end catch_section.cpp
9200// start catch_section_info.cpp
9201
9202namespace Catch {
9203
9205 ( SourceLineInfo const& _lineInfo,
9206 std::string const& _name,
9207 std::string const& _description )
9208 : name( _name ),
9209 description( _description ),
9210 lineInfo( _lineInfo )
9211 {}
9212
9213 SectionEndInfo::SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
9214 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
9215 {}
9216
9217} // end namespace Catch
9218// end catch_section_info.cpp
9219// start catch_session.cpp
9220
9221// start catch_session.h
9222
9223#include <memory>
9224
9225namespace Catch {
9226
9227 class Session : NonCopyable {
9228 public:
9229
9230 Session();
9231 ~Session() override;
9232
9233 void showHelp() const;
9234 void libIdentify();
9235
9236 int applyCommandLine( int argc, char const * const * argv );
9237
9238 void useConfigData( ConfigData const& configData );
9239
9240 int run( int argc, char* argv[] );
9241 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
9242 int run( int argc, wchar_t* const argv[] );
9243 #endif
9244 int run();
9245
9246 clara::Parser const& cli() const;
9247 void cli( clara::Parser const& newParser );
9248 ConfigData& configData();
9249 Config& config();
9250 private:
9251 int runInternal();
9252
9253 clara::Parser m_cli;
9254 ConfigData m_configData;
9255 std::shared_ptr<Config> m_config;
9256 bool m_startupExceptions = false;
9257 };
9258
9259} // end namespace Catch
9260
9261// end catch_session.h
9262// start catch_version.h
9263
9264#include <iosfwd>
9265
9266namespace Catch {
9267
9268 // Versioning information
9269 struct Version {
9270 Version( Version const& ) = delete;
9271 Version& operator=( Version const& ) = delete;
9272 Version( unsigned int _majorVersion,
9273 unsigned int _minorVersion,
9274 unsigned int _patchNumber,
9275 char const * const _branchName,
9276 unsigned int _buildNumber );
9277
9278 unsigned int const majorVersion;
9279 unsigned int const minorVersion;
9280 unsigned int const patchNumber;
9281
9282 // buildNumber is only used if branchName is not null
9283 char const * const branchName;
9284 unsigned int const buildNumber;
9285
9286 friend std::ostream& operator << ( std::ostream& os, Version const& version );
9287 };
9288
9289 Version const& libraryVersion();
9290}
9291
9292// end catch_version.h
9293#include <cstdlib>
9294#include <iomanip>
9295
9296namespace Catch {
9297
9298 namespace {
9299 const int MaxExitCode = 255;
9300
9301 IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) {
9302 auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);
9303 CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'");
9304
9305 return reporter;
9306 }
9307
9308 IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {
9309 if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {
9310 return createReporter(config->getReporterName(), config);
9311 }
9312
9313 auto multi = std::unique_ptr<ListeningReporter>(new ListeningReporter);
9314
9315 auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();
9316 for (auto const& listener : listeners) {
9317 multi->addListener(listener->create(Catch::ReporterConfig(config)));
9318 }
9319 multi->addReporter(createReporter(config->getReporterName(), config));
9320 return std::move(multi);
9321 }
9322
9323 Catch::Totals runTests(std::shared_ptr<Config> const& config) {
9324 // FixMe: Add listeners in order first, then add reporters.
9325
9326 auto reporter = makeReporter(config);
9327
9328 RunContext context(config, std::move(reporter));
9329
9330 Totals totals;
9331
9332 context.testGroupStarting(config->name(), 1, 1);
9333
9334 TestSpec testSpec = config->testSpec();
9335
9336 auto const& allTestCases = getAllTestCasesSorted(*config);
9337 for (auto const& testCase : allTestCases) {
9338 if (!context.aborting() && matchTest(testCase, testSpec, *config))
9339 totals += context.runTest(testCase);
9340 else
9341 context.reporter().skipTest(testCase);
9342 }
9343
9344 if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
9345 ReusableStringStream testConfig;
9346
9347 bool first = true;
9348 for (const auto& input : config->getTestsOrTags()) {
9349 if (!first) { testConfig << ' '; }
9350 first = false;
9351 testConfig << input;
9352 }
9353
9354 context.reporter().noMatchingTestCases(testConfig.str());
9355 totals.error = -1;
9356 }
9357
9358 context.testGroupEnded(config->name(), totals, 1, 1);
9359 return totals;
9360 }
9361
9362 void applyFilenamesAsTags(Catch::IConfig const& config) {
9363 auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));
9364 for (auto& testCase : tests) {
9365 auto tags = testCase.tags;
9366
9367 std::string filename = testCase.lineInfo.file;
9368 auto lastSlash = filename.find_last_of("\\/");
9369 if (lastSlash != std::string::npos) {
9370 filename.erase(0, lastSlash);
9371 filename[0] = '#';
9372 }
9373
9374 auto lastDot = filename.find_last_of('.');
9375 if (lastDot != std::string::npos) {
9376 filename.erase(lastDot);
9377 }
9378
9379 tags.push_back(std::move(filename));
9380 setTags(testCase, tags);
9381 }
9382 }
9383
9384 } // anon namespace
9385
9386 Session::Session() {
9387 static bool alreadyInstantiated = false;
9388 if( alreadyInstantiated ) {
9389 try { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }
9391 }
9392
9393 const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();
9394 if ( !exceptions.empty() ) {
9395 m_startupExceptions = true;
9396 Colour colourGuard( Colour::Red );
9397 Catch::cerr() << "Errors occurred during startup!" << '\n';
9398 // iterate over all exceptions and notify user
9399 for ( const auto& ex_ptr : exceptions ) {
9400 try {
9401 std::rethrow_exception(ex_ptr);
9402 } catch ( std::exception const& ex ) {
9403 Catch::cerr() << Column( ex.what() ).indent(2) << '\n';
9404 }
9405 }
9406 }
9407
9408 alreadyInstantiated = true;
9409 m_cli = makeCommandLineParser( m_configData );
9410 }
9411 Session::~Session() {
9413 }
9414
9415 void Session::showHelp() const {
9416 Catch::cout()
9417 << "\nCatch v" << libraryVersion() << "\n"
9418 << m_cli << std::endl
9419 << "For more detailed usage please see the project docs\n" << std::endl;
9420 }
9421 void Session::libIdentify() {
9422 Catch::cout()
9423 << std::left << std::setw(16) << "description: " << "A Catch test executable\n"
9424 << std::left << std::setw(16) << "category: " << "testframework\n"
9425 << std::left << std::setw(16) << "framework: " << "Catch Test\n"
9426 << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;
9427 }
9428
9429 int Session::applyCommandLine( int argc, char const * const * argv ) {
9430 if( m_startupExceptions )
9431 return 1;
9432
9433 auto result = m_cli.parse( clara::Args( argc, argv ) );
9434 if( !result ) {
9435 Catch::cerr()
9436 << Colour( Colour::Red )
9437 << "\nError(s) in input:\n"
9438 << Column( result.errorMessage() ).indent( 2 )
9439 << "\n\n";
9440 Catch::cerr() << "Run with -? for usage\n" << std::endl;
9441 return MaxExitCode;
9442 }
9443
9444 if( m_configData.showHelp )
9445 showHelp();
9446 if( m_configData.libIdentify )
9447 libIdentify();
9448 m_config.reset();
9449 return 0;
9450 }
9451
9452 void Session::useConfigData( ConfigData const& configData ) {
9453 m_configData = configData;
9454 m_config.reset();
9455 }
9456
9457 int Session::run( int argc, char* argv[] ) {
9458 if( m_startupExceptions )
9459 return 1;
9460 int returnCode = applyCommandLine( argc, argv );
9461 if( returnCode == 0 )
9462 returnCode = run();
9463 return returnCode;
9464 }
9465
9466#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
9467 int Session::run( int argc, wchar_t* const argv[] ) {
9468
9469 char **utf8Argv = new char *[ argc ];
9470
9471 for ( int i = 0; i < argc; ++i ) {
9472 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
9473
9474 utf8Argv[ i ] = new char[ bufSize ];
9475
9476 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
9477 }
9478
9479 int returnCode = run( argc, utf8Argv );
9480
9481 for ( int i = 0; i < argc; ++i )
9482 delete [] utf8Argv[ i ];
9483
9484 delete [] utf8Argv;
9485
9486 return returnCode;
9487 }
9488#endif
9489 int Session::run() {
9490 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
9491 Catch::cout() << "...waiting for enter/ return before starting" << std::endl;
9492 static_cast<void>(std::getchar());
9493 }
9494 int exitCode = runInternal();
9495 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
9496 Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;
9497 static_cast<void>(std::getchar());
9498 }
9499 return exitCode;
9500 }
9501
9502 clara::Parser const& Session::cli() const {
9503 return m_cli;
9504 }
9505 void Session::cli( clara::Parser const& newParser ) {
9506 m_cli = newParser;
9507 }
9508 ConfigData& Session::configData() {
9509 return m_configData;
9510 }
9511 Config& Session::config() {
9512 if( !m_config )
9513 m_config = std::make_shared<Config>( m_configData );
9514 return *m_config;
9515 }
9516
9517 int Session::runInternal() {
9518 if( m_startupExceptions )
9519 return 1;
9520
9521 if( m_configData.showHelp || m_configData.libIdentify )
9522 return 0;
9523
9524 try
9525 {
9526 config(); // Force config to be constructed
9527
9528 seedRng( *m_config );
9529
9530 if( m_configData.filenamesAsTags )
9531 applyFilenamesAsTags( *m_config );
9532
9533 // Handle list request
9534 if( Option<std::size_t> listed = list( config() ) )
9535 return static_cast<int>( *listed );
9536
9537 auto totals = runTests( m_config );
9538 // Note that on unices only the lower 8 bits are usually used, clamping
9539 // the return value to 255 prevents false negative when some multiple
9540 // of 256 tests has failed
9541 return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));
9542 }
9543 catch( std::exception& ex ) {
9544 Catch::cerr() << ex.what() << std::endl;
9545 return MaxExitCode;
9546 }
9547 }
9548
9549} // end namespace Catch
9550// end catch_session.cpp
9551// start catch_startup_exception_registry.cpp
9552
9553namespace Catch {
9554 void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {
9555 try {
9556 m_exceptions.push_back(exception);
9557 }
9558 catch(...) {
9559 // If we run out of memory during start-up there's really not a lot more we can do about it
9560 std::terminate();
9561 }
9562 }
9563
9564 std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept {
9565 return m_exceptions;
9566 }
9567
9568} // end namespace Catch
9569// end catch_startup_exception_registry.cpp
9570// start catch_stream.cpp
9571
9572#include <cstdio>
9573#include <iostream>
9574#include <fstream>
9575#include <sstream>
9576#include <vector>
9577#include <memory>
9578
9579#if defined(__clang__)
9580# pragma clang diagnostic push
9581# pragma clang diagnostic ignored "-Wexit-time-destructors"
9582#endif
9583
9584namespace Catch {
9585
9586 Catch::IStream::~IStream() = default;
9587
9588 namespace detail { namespace {
9589 template<typename WriterF, std::size_t bufferSize=256>
9590 class StreamBufImpl : public std::streambuf {
9591 char data[bufferSize];
9592 WriterF m_writer;
9593
9594 public:
9595 StreamBufImpl() {
9596 setp( data, data + sizeof(data) );
9597 }
9598
9599 ~StreamBufImpl() noexcept {
9600 StreamBufImpl::sync();
9601 }
9602
9603 private:
9604 int overflow( int c ) override {
9605 sync();
9606
9607 if( c != EOF ) {
9608 if( pbase() == epptr() )
9609 m_writer( std::string( 1, static_cast<char>( c ) ) );
9610 else
9611 sputc( static_cast<char>( c ) );
9612 }
9613 return 0;
9614 }
9615
9616 int sync() override {
9617 if( pbase() != pptr() ) {
9618 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
9619 setp( pbase(), epptr() );
9620 }
9621 return 0;
9622 }
9623 };
9624
9626
9627 struct OutputDebugWriter {
9628
9629 void operator()( std::string const&str ) {
9630 writeToDebugConsole( str );
9631 }
9632 };
9633
9635
9636 class FileStream : public IStream {
9637 mutable std::ofstream m_ofs;
9638 public:
9639 FileStream( StringRef filename ) {
9640 m_ofs.open( filename.c_str() );
9641 CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" );
9642 }
9643 ~FileStream() override = default;
9644 public: // IStream
9645 std::ostream& stream() const override {
9646 return m_ofs;
9647 }
9648 };
9649
9651
9652 class CoutStream : public IStream {
9653 mutable std::ostream m_os;
9654 public:
9655 // Store the streambuf from cout up-front because
9656 // cout may get redirected when running tests
9657 CoutStream() : m_os( Catch::cout().rdbuf() ) {}
9658 ~CoutStream() override = default;
9659
9660 public: // IStream
9661 std::ostream& stream() const override { return m_os; }
9662 };
9663
9665
9666 class DebugOutStream : public IStream {
9667 std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;
9668 mutable std::ostream m_os;
9669 public:
9670 DebugOutStream()
9671 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
9672 m_os( m_streamBuf.get() )
9673 {}
9674
9675 ~DebugOutStream() override = default;
9676
9677 public: // IStream
9678 std::ostream& stream() const override { return m_os; }
9679 };
9680
9681 }} // namespace anon::detail
9682
9684
9685 auto makeStream( StringRef const &filename ) -> IStream const* {
9686 if( filename.empty() )
9687 return new detail::CoutStream();
9688 else if( filename[0] == '%' ) {
9689 if( filename == "%debug" )
9690 return new detail::DebugOutStream();
9691 else
9692 CATCH_ERROR( "Unrecognised stream: '" << filename << "'" );
9693 }
9694 else
9695 return new detail::FileStream( filename );
9696 }
9697
9698 // This class encapsulates the idea of a pool of ostringstreams that can be reused.
9699 struct StringStreams {
9700 std::vector<std::unique_ptr<std::ostringstream>> m_streams;
9701 std::vector<std::size_t> m_unused;
9702 std::ostringstream m_referenceStream; // Used for copy state/ flags from
9703 static StringStreams* s_instance;
9704
9705 auto add() -> std::size_t {
9706 if( m_unused.empty() ) {
9707 m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) );
9708 return m_streams.size()-1;
9709 }
9710 else {
9711 auto index = m_unused.back();
9712 m_unused.pop_back();
9713 return index;
9714 }
9715 }
9716
9717 void release( std::size_t index ) {
9718 m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state
9719 m_unused.push_back(index);
9720 }
9721
9722 // !TBD: put in TLS
9723 static auto instance() -> StringStreams& {
9724 if( !s_instance )
9725 s_instance = new StringStreams();
9726 return *s_instance;
9727 }
9728 static void cleanup() {
9729 delete s_instance;
9730 s_instance = nullptr;
9731 }
9732 };
9733
9734 StringStreams* StringStreams::s_instance = nullptr;
9735
9737 StringStreams::cleanup();
9738 }
9739
9741 : m_index( StringStreams::instance().add() ),
9742 m_oss( StringStreams::instance().m_streams[m_index].get() )
9743 {}
9744
9746 static_cast<std::ostringstream*>( m_oss )->str("");
9747 m_oss->clear();
9748 StringStreams::instance().release( m_index );
9749 }
9750
9751 auto ReusableStringStream::str() const -> std::string {
9752 return static_cast<std::ostringstream*>( m_oss )->str();
9753 }
9754
9756
9757#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
9758 std::ostream& cout() { return std::cout; }
9759 std::ostream& cerr() { return std::cerr; }
9760 std::ostream& clog() { return std::clog; }
9761#endif
9762}
9763
9764#if defined(__clang__)
9765# pragma clang diagnostic pop
9766#endif
9767// end catch_stream.cpp
9768// start catch_string_manip.cpp
9769
9770#include <algorithm>
9771#include <ostream>
9772#include <cstring>
9773#include <cctype>
9774
9775namespace Catch {
9776
9777 bool startsWith( std::string const& s, std::string const& prefix ) {
9778 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
9779 }
9780 bool startsWith( std::string const& s, char prefix ) {
9781 return !s.empty() && s[0] == prefix;
9782 }
9783 bool endsWith( std::string const& s, std::string const& suffix ) {
9784 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
9785 }
9786 bool endsWith( std::string const& s, char suffix ) {
9787 return !s.empty() && s[s.size()-1] == suffix;
9788 }
9789 bool contains( std::string const& s, std::string const& infix ) {
9790 return s.find( infix ) != std::string::npos;
9791 }
9792 char toLowerCh(char c) {
9793 return static_cast<char>( std::tolower( c ) );
9794 }
9795 void toLowerInPlace( std::string& s ) {
9796 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
9797 }
9798 std::string toLower( std::string const& s ) {
9799 std::string lc = s;
9800 toLowerInPlace( lc );
9801 return lc;
9802 }
9803 std::string trim( std::string const& str ) {
9804 static char const* whitespaceChars = "\n\r\t ";
9805 std::string::size_type start = str.find_first_not_of( whitespaceChars );
9806 std::string::size_type end = str.find_last_not_of( whitespaceChars );
9807
9808 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
9809 }
9810
9811 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
9812 bool replaced = false;
9813 std::size_t i = str.find( replaceThis );
9814 while( i != std::string::npos ) {
9815 replaced = true;
9816 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
9817 if( i < str.size()-withThis.size() )
9818 i = str.find( replaceThis, i+withThis.size() );
9819 else
9820 i = std::string::npos;
9821 }
9822 return replaced;
9823 }
9824
9825 pluralise::pluralise( std::size_t count, std::string const& label )
9826 : m_count( count ),
9827 m_label( label )
9828 {}
9829
9830 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
9831 os << pluraliser.m_count << ' ' << pluraliser.m_label;
9832 if( pluraliser.m_count != 1 )
9833 os << 's';
9834 return os;
9835 }
9836
9837}
9838// end catch_string_manip.cpp
9839// start catch_stringref.cpp
9840
9841#if defined(__clang__)
9842# pragma clang diagnostic push
9843# pragma clang diagnostic ignored "-Wexit-time-destructors"
9844#endif
9845
9846#include <ostream>
9847#include <cstring>
9848#include <cstdint>
9849
9850namespace {
9851 const uint32_t byte_2_lead = 0xC0;
9852 const uint32_t byte_3_lead = 0xE0;
9853 const uint32_t byte_4_lead = 0xF0;
9854}
9855
9856namespace Catch {
9857 StringRef::StringRef( char const* rawChars ) noexcept
9858 : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )
9859 {}
9860
9861 StringRef::operator std::string() const {
9862 return std::string( m_start, m_size );
9863 }
9864
9865 void StringRef::swap( StringRef& other ) noexcept {
9866 std::swap( m_start, other.m_start );
9867 std::swap( m_size, other.m_size );
9868 std::swap( m_data, other.m_data );
9869 }
9870
9871 auto StringRef::c_str() const -> char const* {
9872 if( isSubstring() )
9873 const_cast<StringRef*>( this )->takeOwnership();
9874 return m_start;
9875 }
9876 auto StringRef::currentData() const noexcept -> char const* {
9877 return m_start;
9878 }
9879
9880 auto StringRef::isOwned() const noexcept -> bool {
9881 return m_data != nullptr;
9882 }
9883 auto StringRef::isSubstring() const noexcept -> bool {
9884 return m_start[m_size] != '\0';
9885 }
9886
9887 void StringRef::takeOwnership() {
9888 if( !isOwned() ) {
9889 m_data = new char[m_size+1];
9890 memcpy( m_data, m_start, m_size );
9891 m_data[m_size] = '\0';
9892 m_start = m_data;
9893 }
9894 }
9895 auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {
9896 if( start < m_size )
9897 return StringRef( m_start+start, size );
9898 else
9899 return StringRef();
9900 }
9901 auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {
9902 return
9903 size() == other.size() &&
9904 (std::strncmp( m_start, other.m_start, size() ) == 0);
9905 }
9906 auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool {
9907 return !operator==( other );
9908 }
9909
9910 auto StringRef::operator[](size_type index) const noexcept -> char {
9911 return m_start[index];
9912 }
9913
9914 auto StringRef::numberOfCharacters() const noexcept -> size_type {
9915 size_type noChars = m_size;
9916 // Make adjustments for uft encodings
9917 for( size_type i=0; i < m_size; ++i ) {
9918 char c = m_start[i];
9919 if( ( c & byte_2_lead ) == byte_2_lead ) {
9920 noChars--;
9921 if (( c & byte_3_lead ) == byte_3_lead )
9922 noChars--;
9923 if( ( c & byte_4_lead ) == byte_4_lead )
9924 noChars--;
9925 }
9926 }
9927 return noChars;
9928 }
9929
9930 auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string {
9931 std::string str;
9932 str.reserve( lhs.size() + rhs.size() );
9933 str += lhs;
9934 str += rhs;
9935 return str;
9936 }
9937 auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string {
9938 return std::string( lhs ) + std::string( rhs );
9939 }
9940 auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string {
9941 return std::string( lhs ) + std::string( rhs );
9942 }
9943
9944 auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {
9945 return os.write(str.currentData(), str.size());
9946 }
9947
9948 auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {
9949 lhs.append(rhs.currentData(), rhs.size());
9950 return lhs;
9951 }
9952
9953} // namespace Catch
9954
9955#if defined(__clang__)
9956# pragma clang diagnostic pop
9957#endif
9958// end catch_stringref.cpp
9959// start catch_tag_alias.cpp
9960
9961namespace Catch {
9962 TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
9963}
9964// end catch_tag_alias.cpp
9965// start catch_tag_alias_autoregistrar.cpp
9966
9967namespace Catch {
9968
9969 RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {
9970 try {
9971 getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);
9972 } catch (...) {
9973 // Do not throw when constructing global objects, instead register the exception to be processed later
9975 }
9976 }
9977
9978}
9979// end catch_tag_alias_autoregistrar.cpp
9980// start catch_tag_alias_registry.cpp
9981
9982#include <sstream>
9983
9984namespace Catch {
9985
9986 TagAliasRegistry::~TagAliasRegistry() {}
9987
9988 TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {
9989 auto it = m_registry.find( alias );
9990 if( it != m_registry.end() )
9991 return &(it->second);
9992 else
9993 return nullptr;
9994 }
9995
9996 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
9997 std::string expandedTestSpec = unexpandedTestSpec;
9998 for( auto const& registryKvp : m_registry ) {
9999 std::size_t pos = expandedTestSpec.find( registryKvp.first );
10000 if( pos != std::string::npos ) {
10001 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
10002 registryKvp.second.tag +
10003 expandedTestSpec.substr( pos + registryKvp.first.size() );
10004 }
10005 }
10006 return expandedTestSpec;
10007 }
10008
10009 void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
10010 CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'),
10011 "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo );
10012
10013 CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,
10014 "error: tag alias, '" << alias << "' already registered.\n"
10015 << "\tFirst seen at: " << find(alias)->lineInfo << "\n"
10016 << "\tRedefined at: " << lineInfo );
10017 }
10018
10019 ITagAliasRegistry::~ITagAliasRegistry() {}
10020
10021 ITagAliasRegistry const& ITagAliasRegistry::get() {
10023 }
10024
10025} // end namespace Catch
10026// end catch_tag_alias_registry.cpp
10027// start catch_test_case_info.cpp
10028
10029#include <cctype>
10030#include <exception>
10031#include <algorithm>
10032#include <sstream>
10033
10034namespace Catch {
10035
10036 TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
10037 if( startsWith( tag, '.' ) ||
10038 tag == "!hide" )
10040 else if( tag == "!throws" )
10041 return TestCaseInfo::Throws;
10042 else if( tag == "!shouldfail" )
10044 else if( tag == "!mayfail" )
10045 return TestCaseInfo::MayFail;
10046 else if( tag == "!nonportable" )
10048 else if( tag == "!benchmark" )
10050 else
10051 return TestCaseInfo::None;
10052 }
10053 bool isReservedTag( std::string const& tag ) {
10054 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );
10055 }
10056 void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
10057 CATCH_ENFORCE( !isReservedTag(tag),
10058 "Tag name: [" << tag << "] is not allowed.\n"
10059 << "Tag names starting with non alpha-numeric characters are reserved\n"
10060 << _lineInfo );
10061 }
10062
10063 TestCase makeTestCase( ITestInvoker* _testCase,
10064 std::string const& _className,
10065 NameAndTags const& nameAndTags,
10066 SourceLineInfo const& _lineInfo )
10067 {
10068 bool isHidden = false;
10069
10070 // Parse out tags
10071 std::vector<std::string> tags;
10072 std::string desc, tag;
10073 bool inTag = false;
10074 std::string _descOrTags = nameAndTags.tags;
10075 for (char c : _descOrTags) {
10076 if( !inTag ) {
10077 if( c == '[' )
10078 inTag = true;
10079 else
10080 desc += c;
10081 }
10082 else {
10083 if( c == ']' ) {
10084 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
10085 if( ( prop & TestCaseInfo::IsHidden ) != 0 )
10086 isHidden = true;
10087 else if( prop == TestCaseInfo::None )
10088 enforceNotReservedTag( tag, _lineInfo );
10089
10090 tags.push_back( tag );
10091 tag.clear();
10092 inTag = false;
10093 }
10094 else
10095 tag += c;
10096 }
10097 }
10098 if( isHidden ) {
10099 tags.push_back( "." );
10100 }
10101
10102 TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo );
10103 return TestCase( _testCase, std::move(info) );
10104 }
10105
10106 void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {
10107 std::sort(begin(tags), end(tags));
10108 tags.erase(std::unique(begin(tags), end(tags)), end(tags));
10109 testCaseInfo.lcaseTags.clear();
10110
10111 for( auto const& tag : tags ) {
10112 std::string lcaseTag = toLower( tag );
10113 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
10114 testCaseInfo.lcaseTags.push_back( lcaseTag );
10115 }
10116 testCaseInfo.tags = std::move(tags);
10117 }
10118
10120 std::string const& _className,
10121 std::string const& _description,
10122 std::vector<std::string> const& _tags,
10123 SourceLineInfo const& _lineInfo )
10124 : name( _name ),
10125 className( _className ),
10126 description( _description ),
10127 lineInfo( _lineInfo ),
10128 properties( None )
10129 {
10130 setTags( *this, _tags );
10131 }
10132
10133 bool TestCaseInfo::isHidden() const {
10134 return ( properties & IsHidden ) != 0;
10135 }
10136 bool TestCaseInfo::throws() const {
10137 return ( properties & Throws ) != 0;
10138 }
10139 bool TestCaseInfo::okToFail() const {
10140 return ( properties & (ShouldFail | MayFail ) ) != 0;
10141 }
10142 bool TestCaseInfo::expectedToFail() const {
10143 return ( properties & (ShouldFail ) ) != 0;
10144 }
10145
10147 std::string ret;
10148 // '[' and ']' per tag
10149 std::size_t full_size = 2 * tags.size();
10150 for (const auto& tag : tags) {
10151 full_size += tag.size();
10152 }
10153 ret.reserve(full_size);
10154 for (const auto& tag : tags) {
10155 ret.push_back('[');
10156 ret.append(tag);
10157 ret.push_back(']');
10158 }
10159
10160 return ret;
10161 }
10162
10163 TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}
10164
10165 TestCase TestCase::withName( std::string const& _newName ) const {
10166 TestCase other( *this );
10167 other.name = _newName;
10168 return other;
10169 }
10170
10171 void TestCase::invoke() const {
10172 test->invoke();
10173 }
10174
10175 bool TestCase::operator == ( TestCase const& other ) const {
10176 return test.get() == other.test.get() &&
10177 name == other.name &&
10178 className == other.className;
10179 }
10180
10181 bool TestCase::operator < ( TestCase const& other ) const {
10182 return name < other.name;
10183 }
10184
10185 TestCaseInfo const& TestCase::getTestCaseInfo() const
10186 {
10187 return *this;
10188 }
10189
10190} // end namespace Catch
10191// end catch_test_case_info.cpp
10192// start catch_test_case_registry_impl.cpp
10193
10194#include <sstream>
10195
10196namespace Catch {
10197
10198 std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
10199
10200 std::vector<TestCase> sorted = unsortedTestCases;
10201
10202 switch( config.runOrder() ) {
10203 case RunTests::InLexicographicalOrder:
10204 std::sort( sorted.begin(), sorted.end() );
10205 break;
10206 case RunTests::InRandomOrder:
10207 seedRng( config );
10208 RandomNumberGenerator::shuffle( sorted );
10209 break;
10210 case RunTests::InDeclarationOrder:
10211 // already in declaration order
10212 break;
10213 }
10214 return sorted;
10215 }
10216 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
10217 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
10218 }
10219
10220 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
10221 std::set<TestCase> seenFunctions;
10222 for( auto const& function : functions ) {
10223 auto prev = seenFunctions.insert( function );
10224 CATCH_ENFORCE( prev.second,
10225 "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n"
10226 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
10227 << "\tRedefined at " << function.getTestCaseInfo().lineInfo );
10228 }
10229 }
10230
10231 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
10232 std::vector<TestCase> filtered;
10233 filtered.reserve( testCases.size() );
10234 for( auto const& testCase : testCases )
10235 if( matchTest( testCase, testSpec, config ) )
10236 filtered.push_back( testCase );
10237 return filtered;
10238 }
10239 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
10241 }
10242
10243 void TestRegistry::registerTest( TestCase const& testCase ) {
10244 std::string name = testCase.getTestCaseInfo().name;
10245 if( name.empty() ) {
10246 ReusableStringStream rss;
10247 rss << "Anonymous test case " << ++m_unnamedCount;
10248 return registerTest( testCase.withName( rss.str() ) );
10249 }
10250 m_functions.push_back( testCase );
10251 }
10252
10253 std::vector<TestCase> const& TestRegistry::getAllTests() const {
10254 return m_functions;
10255 }
10256 std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {
10257 if( m_sortedFunctions.empty() )
10258 enforceNoDuplicateTestCases( m_functions );
10259
10260 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
10261 m_sortedFunctions = sortTests( config, m_functions );
10262 m_currentSortOrder = config.runOrder();
10263 }
10264 return m_sortedFunctions;
10265 }
10266
10268 TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
10269
10270 void TestInvokerAsFunction::invoke() const {
10271 m_testAsFunction();
10272 }
10273
10274 std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {
10275 std::string className = classOrQualifiedMethodName;
10276 if( startsWith( className, '&' ) )
10277 {
10278 std::size_t lastColons = className.rfind( "::" );
10279 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
10280 if( penultimateColons == std::string::npos )
10281 penultimateColons = 1;
10282 className = className.substr( penultimateColons, lastColons-penultimateColons );
10283 }
10284 return className;
10285 }
10286
10287} // end namespace Catch
10288// end catch_test_case_registry_impl.cpp
10289// start catch_test_case_tracker.cpp
10290
10291#include <algorithm>
10292#include <cassert>
10293#include <stdexcept>
10294#include <memory>
10295#include <sstream>
10296
10297#if defined(__clang__)
10298# pragma clang diagnostic push
10299# pragma clang diagnostic ignored "-Wexit-time-destructors"
10300#endif
10301
10302namespace Catch {
10303namespace TestCaseTracking {
10304
10305 NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
10306 : name( _name ),
10307 location( _location )
10308 {}
10309
10310 ITracker::~ITracker() = default;
10311
10312 TrackerContext& TrackerContext::instance() {
10313 static TrackerContext s_instance;
10314 return s_instance;
10315 }
10316
10317 ITracker& TrackerContext::startRun() {
10318 m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr );
10319 m_currentTracker = nullptr;
10320 m_runState = Executing;
10321 return *m_rootTracker;
10322 }
10323
10324 void TrackerContext::endRun() {
10325 m_rootTracker.reset();
10326 m_currentTracker = nullptr;
10327 m_runState = NotStarted;
10328 }
10329
10330 void TrackerContext::startCycle() {
10331 m_currentTracker = m_rootTracker.get();
10332 m_runState = Executing;
10333 }
10334 void TrackerContext::completeCycle() {
10335 m_runState = CompletedCycle;
10336 }
10337
10338 bool TrackerContext::completedCycle() const {
10339 return m_runState == CompletedCycle;
10340 }
10341 ITracker& TrackerContext::currentTracker() {
10342 return *m_currentTracker;
10343 }
10344 void TrackerContext::setCurrentTracker( ITracker* tracker ) {
10345 m_currentTracker = tracker;
10346 }
10347
10348 TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
10349 bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const {
10350 return
10351 tracker->nameAndLocation().name == m_nameAndLocation.name &&
10352 tracker->nameAndLocation().location == m_nameAndLocation.location;
10353 }
10354
10355 TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
10356 : m_nameAndLocation( nameAndLocation ),
10357 m_ctx( ctx ),
10358 m_parent( parent )
10359 {}
10360
10361 NameAndLocation const& TrackerBase::nameAndLocation() const {
10362 return m_nameAndLocation;
10363 }
10364 bool TrackerBase::isComplete() const {
10365 return m_runState == CompletedSuccessfully || m_runState == Failed;
10366 }
10367 bool TrackerBase::isSuccessfullyCompleted() const {
10368 return m_runState == CompletedSuccessfully;
10369 }
10370 bool TrackerBase::isOpen() const {
10371 return m_runState != NotStarted && !isComplete();
10372 }
10373 bool TrackerBase::hasChildren() const {
10374 return !m_children.empty();
10375 }
10376
10377 void TrackerBase::addChild( ITrackerPtr const& child ) {
10378 m_children.push_back( child );
10379 }
10380
10381 ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) {
10382 auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
10383 return( it != m_children.end() )
10384 ? *it
10385 : nullptr;
10386 }
10387 ITracker& TrackerBase::parent() {
10388 assert( m_parent ); // Should always be non-null except for root
10389 return *m_parent;
10390 }
10391
10392 void TrackerBase::openChild() {
10393 if( m_runState != ExecutingChildren ) {
10394 m_runState = ExecutingChildren;
10395 if( m_parent )
10396 m_parent->openChild();
10397 }
10398 }
10399
10400 bool TrackerBase::isSectionTracker() const { return false; }
10401 bool TrackerBase::isIndexTracker() const { return false; }
10402
10403 void TrackerBase::open() {
10404 m_runState = Executing;
10405 moveToThis();
10406 if( m_parent )
10407 m_parent->openChild();
10408 }
10409
10410 void TrackerBase::close() {
10411
10412 // Close any still open children (e.g. generators)
10413 while( &m_ctx.currentTracker() != this )
10414 m_ctx.currentTracker().close();
10415
10416 switch( m_runState ) {
10417 case NeedsAnotherRun:
10418 break;
10419
10420 case Executing:
10421 m_runState = CompletedSuccessfully;
10422 break;
10423 case ExecutingChildren:
10424 if( m_children.empty() || m_children.back()->isComplete() )
10425 m_runState = CompletedSuccessfully;
10426 break;
10427
10428 case NotStarted:
10429 case CompletedSuccessfully:
10430 case Failed:
10431 CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState );
10432
10433 default:
10434 CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState );
10435 }
10436 moveToParent();
10437 m_ctx.completeCycle();
10438 }
10439 void TrackerBase::fail() {
10440 m_runState = Failed;
10441 if( m_parent )
10442 m_parent->markAsNeedingAnotherRun();
10443 moveToParent();
10444 m_ctx.completeCycle();
10445 }
10446 void TrackerBase::markAsNeedingAnotherRun() {
10447 m_runState = NeedsAnotherRun;
10448 }
10449
10450 void TrackerBase::moveToParent() {
10451 assert( m_parent );
10452 m_ctx.setCurrentTracker( m_parent );
10453 }
10454 void TrackerBase::moveToThis() {
10455 m_ctx.setCurrentTracker( this );
10456 }
10457
10458 SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
10459 : TrackerBase( nameAndLocation, ctx, parent )
10460 {
10461 if( parent ) {
10462 while( !parent->isSectionTracker() )
10463 parent = &parent->parent();
10464
10465 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
10466 addNextFilters( parentSection.m_filters );
10467 }
10468 }
10469
10470 bool SectionTracker::isSectionTracker() const { return true; }
10471
10472 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
10473 std::shared_ptr<SectionTracker> section;
10474
10475 ITracker& currentTracker = ctx.currentTracker();
10476 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
10477 assert( childTracker );
10478 assert( childTracker->isSectionTracker() );
10479 section = std::static_pointer_cast<SectionTracker>( childTracker );
10480 }
10481 else {
10482 section = std::make_shared<SectionTracker>( nameAndLocation, ctx, &currentTracker );
10483 currentTracker.addChild( section );
10484 }
10485 if( !ctx.completedCycle() )
10486 section->tryOpen();
10487 return *section;
10488 }
10489
10490 void SectionTracker::tryOpen() {
10491 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
10492 open();
10493 }
10494
10495 void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {
10496 if( !filters.empty() ) {
10497 m_filters.push_back(""); // Root - should never be consulted
10498 m_filters.push_back(""); // Test Case - not a section filter
10499 m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
10500 }
10501 }
10502 void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) {
10503 if( filters.size() > 1 )
10504 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
10505 }
10506
10507 IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
10508 : TrackerBase( nameAndLocation, ctx, parent ),
10509 m_size( size )
10510 {}
10511
10512 bool IndexTracker::isIndexTracker() const { return true; }
10513
10514 IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
10515 std::shared_ptr<IndexTracker> tracker;
10516
10517 ITracker& currentTracker = ctx.currentTracker();
10518 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
10519 assert( childTracker );
10520 assert( childTracker->isIndexTracker() );
10521 tracker = std::static_pointer_cast<IndexTracker>( childTracker );
10522 }
10523 else {
10524 tracker = std::make_shared<IndexTracker>( nameAndLocation, ctx, &currentTracker, size );
10525 currentTracker.addChild( tracker );
10526 }
10527
10528 if( !ctx.completedCycle() && !tracker->isComplete() ) {
10529 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
10530 tracker->moveNext();
10531 tracker->open();
10532 }
10533
10534 return *tracker;
10535 }
10536
10537 int IndexTracker::index() const { return m_index; }
10538
10539 void IndexTracker::moveNext() {
10540 m_index++;
10541 m_children.clear();
10542 }
10543
10544 void IndexTracker::close() {
10545 TrackerBase::close();
10546 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
10547 m_runState = Executing;
10548 }
10549
10550} // namespace TestCaseTracking
10551
10552using TestCaseTracking::ITracker;
10553using TestCaseTracking::TrackerContext;
10554using TestCaseTracking::SectionTracker;
10555using TestCaseTracking::IndexTracker;
10556
10557} // namespace Catch
10558
10559#if defined(__clang__)
10560# pragma clang diagnostic pop
10561#endif
10562// end catch_test_case_tracker.cpp
10563// start catch_test_registry.cpp
10564
10565namespace Catch {
10566
10567 auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* {
10568 return new(std::nothrow) TestInvokerAsFunction( testAsFunction );
10569 }
10570
10571 NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}
10572
10573 AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {
10574 try {
10576 .registerTest(
10578 invoker,
10579 extractClassName( classOrMethod ),
10580 nameAndTags,
10581 lineInfo));
10582 } catch (...) {
10583 // Do not throw when constructing global objects, instead register the exception to be processed later
10585 }
10586 }
10587
10588 AutoReg::~AutoReg() = default;
10589}
10590// end catch_test_registry.cpp
10591// start catch_test_spec.cpp
10592
10593#include <algorithm>
10594#include <string>
10595#include <vector>
10596#include <memory>
10597
10598namespace Catch {
10599
10600 TestSpec::Pattern::~Pattern() = default;
10601 TestSpec::NamePattern::~NamePattern() = default;
10602 TestSpec::TagPattern::~TagPattern() = default;
10603 TestSpec::ExcludedPattern::~ExcludedPattern() = default;
10604
10605 TestSpec::NamePattern::NamePattern( std::string const& name )
10606 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
10607 {}
10608 bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {
10609 return m_wildcardPattern.matches( toLower( testCase.name ) );
10610 }
10611
10612 TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
10613 bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {
10614 return std::find(begin(testCase.lcaseTags),
10615 end(testCase.lcaseTags),
10616 m_tag) != end(testCase.lcaseTags);
10617 }
10618
10619 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
10620 bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
10621
10622 bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {
10623 // All patterns in a filter must match for the filter to be a match
10624 for( auto const& pattern : m_patterns ) {
10625 if( !pattern->matches( testCase ) )
10626 return false;
10627 }
10628 return true;
10629 }
10630
10631 bool TestSpec::hasFilters() const {
10632 return !m_filters.empty();
10633 }
10634 bool TestSpec::matches( TestCaseInfo const& testCase ) const {
10635 // A TestSpec matches if any filter matches
10636 for( auto const& filter : m_filters )
10637 if( filter.matches( testCase ) )
10638 return true;
10639 return false;
10640 }
10641}
10642// end catch_test_spec.cpp
10643// start catch_test_spec_parser.cpp
10644
10645namespace Catch {
10646
10647 TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
10648
10649 TestSpecParser& TestSpecParser::parse( std::string const& arg ) {
10650 m_mode = None;
10651 m_exclusion = false;
10652 m_start = std::string::npos;
10653 m_arg = m_tagAliases->expandAliases( arg );
10654 m_escapeChars.clear();
10655 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
10656 visitChar( m_arg[m_pos] );
10657 if( m_mode == Name )
10658 addPattern<TestSpec::NamePattern>();
10659 return *this;
10660 }
10661 TestSpec TestSpecParser::testSpec() {
10662 addFilter();
10663 return m_testSpec;
10664 }
10665
10666 void TestSpecParser::visitChar( char c ) {
10667 if( m_mode == None ) {
10668 switch( c ) {
10669 case ' ': return;
10670 case '~': m_exclusion = true; return;
10671 case '[': return startNewMode( Tag, ++m_pos );
10672 case '"': return startNewMode( QuotedName, ++m_pos );
10673 case '\\': return escape();
10674 default: startNewMode( Name, m_pos ); break;
10675 }
10676 }
10677 if( m_mode == Name ) {
10678 if( c == ',' ) {
10679 addPattern<TestSpec::NamePattern>();
10680 addFilter();
10681 }
10682 else if( c == '[' ) {
10683 if( subString() == "exclude:" )
10684 m_exclusion = true;
10685 else
10686 addPattern<TestSpec::NamePattern>();
10687 startNewMode( Tag, ++m_pos );
10688 }
10689 else if( c == '\\' )
10690 escape();
10691 }
10692 else if( m_mode == EscapedName )
10693 m_mode = Name;
10694 else if( m_mode == QuotedName && c == '"' )
10695 addPattern<TestSpec::NamePattern>();
10696 else if( m_mode == Tag && c == ']' )
10697 addPattern<TestSpec::TagPattern>();
10698 }
10699 void TestSpecParser::startNewMode( Mode mode, std::size_t start ) {
10700 m_mode = mode;
10701 m_start = start;
10702 }
10703 void TestSpecParser::escape() {
10704 if( m_mode == None )
10705 m_start = m_pos;
10706 m_mode = EscapedName;
10707 m_escapeChars.push_back( m_pos );
10708 }
10709 std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
10710
10711 void TestSpecParser::addFilter() {
10712 if( !m_currentFilter.m_patterns.empty() ) {
10713 m_testSpec.m_filters.push_back( m_currentFilter );
10714 m_currentFilter = TestSpec::Filter();
10715 }
10716 }
10717
10718 TestSpec parseTestSpec( std::string const& arg ) {
10719 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
10720 }
10721
10722} // namespace Catch
10723// end catch_test_spec_parser.cpp
10724// start catch_timer.cpp
10725
10726#include <chrono>
10727
10728static const uint64_t nanosecondsInSecond = 1000000000;
10729
10730namespace Catch {
10731
10732 auto getCurrentNanosecondsSinceEpoch() -> uint64_t {
10733 return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();
10734 }
10735
10736 auto estimateClockResolution() -> uint64_t {
10737 uint64_t sum = 0;
10738 static const uint64_t iterations = 1000000;
10739
10740 auto startTime = getCurrentNanosecondsSinceEpoch();
10741
10742 for( std::size_t i = 0; i < iterations; ++i ) {
10743
10744 uint64_t ticks;
10745 uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();
10746 do {
10748 } while( ticks == baseTicks );
10749
10750 auto delta = ticks - baseTicks;
10751 sum += delta;
10752
10753 // If we have been calibrating for over 3 seconds -- the clock
10754 // is terrible and we should move on.
10755 // TBD: How to signal that the measured resolution is probably wrong?
10756 if (ticks > startTime + 3 * nanosecondsInSecond) {
10757 return sum / i;
10758 }
10759 }
10760
10761 // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers
10762 // - and potentially do more iterations if there's a high variance.
10763 return sum/iterations;
10764 }
10765 auto getEstimatedClockResolution() -> uint64_t {
10766 static auto s_resolution = estimateClockResolution();
10767 return s_resolution;
10768 }
10769
10770 void Timer::start() {
10771 m_nanoseconds = getCurrentNanosecondsSinceEpoch();
10772 }
10773 auto Timer::getElapsedNanoseconds() const -> uint64_t {
10774 return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;
10775 }
10776 auto Timer::getElapsedMicroseconds() const -> uint64_t {
10777 return getElapsedNanoseconds()/1000;
10778 }
10779 auto Timer::getElapsedMilliseconds() const -> unsigned int {
10780 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
10781 }
10782 auto Timer::getElapsedSeconds() const -> double {
10783 return getElapsedMicroseconds()/1000000.0;
10784 }
10785
10786} // namespace Catch
10787// end catch_timer.cpp
10788// start catch_tostring.cpp
10789
10790#if defined(__clang__)
10791# pragma clang diagnostic push
10792# pragma clang diagnostic ignored "-Wexit-time-destructors"
10793# pragma clang diagnostic ignored "-Wglobal-constructors"
10794#endif
10795
10796// Enable specific decls locally
10797#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
10798#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
10799#endif
10800
10801#include <cmath>
10802#include <iomanip>
10803
10804namespace Catch {
10805
10806namespace Detail {
10807
10808 const std::string unprintableString = "{?}";
10809
10810 namespace {
10811 const int hexThreshold = 255;
10812
10813 struct Endianness {
10814 enum Arch { Big, Little };
10815
10816 static Arch which() {
10817 union _{
10818 int asInt;
10819 char asChar[sizeof (int)];
10820 } u;
10821
10822 u.asInt = 1;
10823 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
10824 }
10825 };
10826 }
10827
10828 std::string rawMemoryToString( const void *object, std::size_t size ) {
10829 // Reverse order for little endian architectures
10830 int i = 0, end = static_cast<int>( size ), inc = 1;
10831 if( Endianness::which() == Endianness::Little ) {
10832 i = end-1;
10833 end = inc = -1;
10834 }
10835
10836 unsigned char const *bytes = static_cast<unsigned char const *>(object);
10837 ReusableStringStream rss;
10838 rss << "0x" << std::setfill('0') << std::hex;
10839 for( ; i != end; i += inc )
10840 rss << std::setw(2) << static_cast<unsigned>(bytes[i]);
10841 return rss.str();
10842 }
10843}
10844
10845template<typename T>
10846std::string fpToString( T value, int precision ) {
10847 if (std::isnan(value)) {
10848 return "nan";
10849 }
10850
10851 ReusableStringStream rss;
10852 rss << std::setprecision( precision )
10853 << std::fixed
10854 << value;
10855 std::string d = rss.str();
10856 std::size_t i = d.find_last_not_of( '0' );
10857 if( i != std::string::npos && i != d.size()-1 ) {
10858 if( d[i] == '.' )
10859 i++;
10860 d = d.substr( 0, i+1 );
10861 }
10862 return d;
10863}
10864
10866//
10867// Out-of-line defs for full specialization of StringMaker
10868//
10870
10872 if (!getCurrentContext().getConfig()->showInvisibles()) {
10873 return '"' + str + '"';
10874 }
10875
10876 std::string s("\"");
10877 for (char c : str) {
10878 switch (c) {
10879 case '\n':
10880 s.append("\\n");
10881 break;
10882 case '\t':
10883 s.append("\\t");
10884 break;
10885 default:
10886 s.push_back(c);
10887 break;
10888 }
10889 }
10890 s.append("\"");
10891 return s;
10892}
10893
10894#ifdef CATCH_CONFIG_WCHAR
10895std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {
10896 std::string s;
10897 s.reserve(wstr.size());
10898 for (auto c : wstr) {
10899 s += (c <= 0xff) ? static_cast<char>(c) : '?';
10900 }
10902}
10903#endif
10904
10906 if (str) {
10908 } else {
10909 return{ "{null string}" };
10910 }
10911}
10913 if (str) {
10915 } else {
10916 return{ "{null string}" };
10917 }
10918}
10919#ifdef CATCH_CONFIG_WCHAR
10921 if (str) {
10922 return ::Catch::Detail::stringify(std::wstring{ str });
10923 } else {
10924 return{ "{null string}" };
10925 }
10926}
10928 if (str) {
10929 return ::Catch::Detail::stringify(std::wstring{ str });
10930 } else {
10931 return{ "{null string}" };
10932 }
10933}
10934#endif
10935
10937 return ::Catch::Detail::stringify(static_cast<long long>(value));
10938}
10940 return ::Catch::Detail::stringify(static_cast<long long>(value));
10941}
10943 ReusableStringStream rss;
10944 rss << value;
10945 if (value > Detail::hexThreshold) {
10946 rss << " (0x" << std::hex << value << ')';
10947 }
10948 return rss.str();
10949}
10950
10952 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
10953}
10955 return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));
10956}
10958 ReusableStringStream rss;
10959 rss << value;
10960 if (value > Detail::hexThreshold) {
10961 rss << " (0x" << std::hex << value << ')';
10962 }
10963 return rss.str();
10964}
10965
10967 return b ? "true" : "false";
10968}
10969
10971 if (value == '\r') {
10972 return "'\\r'";
10973 } else if (value == '\f') {
10974 return "'\\f'";
10975 } else if (value == '\n') {
10976 return "'\\n'";
10977 } else if (value == '\t') {
10978 return "'\\t'";
10979 } else if ('\0' <= value && value < ' ') {
10980 return ::Catch::Detail::stringify(static_cast<unsigned int>(value));
10981 } else {
10982 char chstr[] = "' '";
10983 chstr[1] = value;
10984 return chstr;
10985 }
10986}
10988 return ::Catch::Detail::stringify(static_cast<char>(c));
10989}
10991 return ::Catch::Detail::stringify(static_cast<char>(c));
10992}
10993
10995 return "nullptr";
10996}
10997
10999 return fpToString(value, 5) + 'f';
11000}
11002 return fpToString(value, 10);
11003}
11004
11005std::string ratio_string<std::atto>::symbol() { return "a"; }
11006std::string ratio_string<std::femto>::symbol() { return "f"; }
11007std::string ratio_string<std::pico>::symbol() { return "p"; }
11008std::string ratio_string<std::nano>::symbol() { return "n"; }
11009std::string ratio_string<std::micro>::symbol() { return "u"; }
11010std::string ratio_string<std::milli>::symbol() { return "m"; }
11011
11012} // end namespace Catch
11013
11014#if defined(__clang__)
11015# pragma clang diagnostic pop
11016#endif
11017
11018// end catch_tostring.cpp
11019// start catch_totals.cpp
11020
11021namespace Catch {
11022
11023 Counts Counts::operator - ( Counts const& other ) const {
11024 Counts diff;
11025 diff.passed = passed - other.passed;
11026 diff.failed = failed - other.failed;
11027 diff.failedButOk = failedButOk - other.failedButOk;
11028 return diff;
11029 }
11030
11031 Counts& Counts::operator += ( Counts const& other ) {
11032 passed += other.passed;
11033 failed += other.failed;
11034 failedButOk += other.failedButOk;
11035 return *this;
11036 }
11037
11038 std::size_t Counts::total() const {
11039 return passed + failed + failedButOk;
11040 }
11041 bool Counts::allPassed() const {
11042 return failed == 0 && failedButOk == 0;
11043 }
11044 bool Counts::allOk() const {
11045 return failed == 0;
11046 }
11047
11048 Totals Totals::operator - ( Totals const& other ) const {
11049 Totals diff;
11050 diff.assertions = assertions - other.assertions;
11051 diff.testCases = testCases - other.testCases;
11052 return diff;
11053 }
11054
11055 Totals& Totals::operator += ( Totals const& other ) {
11056 assertions += other.assertions;
11057 testCases += other.testCases;
11058 return *this;
11059 }
11060
11061 Totals Totals::delta( Totals const& prevTotals ) const {
11062 Totals diff = *this - prevTotals;
11063 if( diff.assertions.failed > 0 )
11064 ++diff.testCases.failed;
11065 else if( diff.assertions.failedButOk > 0 )
11066 ++diff.testCases.failedButOk;
11067 else
11068 ++diff.testCases.passed;
11069 return diff;
11070 }
11071
11072}
11073// end catch_totals.cpp
11074// start catch_uncaught_exceptions.cpp
11075
11076#include <exception>
11077
11078namespace Catch {
11079 bool uncaught_exceptions() {
11080#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
11081 return std::uncaught_exceptions() > 0;
11082#else
11083 return std::uncaught_exception();
11084#endif
11085 }
11086} // end namespace Catch
11087// end catch_uncaught_exceptions.cpp
11088// start catch_version.cpp
11089
11090#include <ostream>
11091
11092namespace Catch {
11093
11094 Version::Version
11095 ( unsigned int _majorVersion,
11096 unsigned int _minorVersion,
11097 unsigned int _patchNumber,
11098 char const * const _branchName,
11099 unsigned int _buildNumber )
11100 : majorVersion( _majorVersion ),
11101 minorVersion( _minorVersion ),
11102 patchNumber( _patchNumber ),
11103 branchName( _branchName ),
11104 buildNumber( _buildNumber )
11105 {}
11106
11107 std::ostream& operator << ( std::ostream& os, Version const& version ) {
11108 os << version.majorVersion << '.'
11109 << version.minorVersion << '.'
11110 << version.patchNumber;
11111 // branchName is never null -> 0th char is \0 if it is empty
11112 if (version.branchName[0]) {
11113 os << '-' << version.branchName
11114 << '.' << version.buildNumber;
11115 }
11116 return os;
11117 }
11118
11119 Version const& libraryVersion() {
11120 static Version version( 2, 2, 3, "", 0 );
11121 return version;
11122 }
11123
11124}
11125// end catch_version.cpp
11126// start catch_wildcard_pattern.cpp
11127
11128#include <sstream>
11129
11130namespace Catch {
11131
11132 WildcardPattern::WildcardPattern( std::string const& pattern,
11133 CaseSensitive::Choice caseSensitivity )
11134 : m_caseSensitivity( caseSensitivity ),
11135 m_pattern( adjustCase( pattern ) )
11136 {
11137 if( startsWith( m_pattern, '*' ) ) {
11138 m_pattern = m_pattern.substr( 1 );
11139 m_wildcard = WildcardAtStart;
11140 }
11141 if( endsWith( m_pattern, '*' ) ) {
11142 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
11143 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
11144 }
11145 }
11146
11147 bool WildcardPattern::matches( std::string const& str ) const {
11148 switch( m_wildcard ) {
11149 case NoWildcard:
11150 return m_pattern == adjustCase( str );
11151 case WildcardAtStart:
11152 return endsWith( adjustCase( str ), m_pattern );
11153 case WildcardAtEnd:
11154 return startsWith( adjustCase( str ), m_pattern );
11155 case WildcardAtBothEnds:
11156 return contains( adjustCase( str ), m_pattern );
11157 default:
11158 CATCH_INTERNAL_ERROR( "Unknown enum" );
11159 }
11160 }
11161
11162 std::string WildcardPattern::adjustCase( std::string const& str ) const {
11163 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
11164 }
11165}
11166// end catch_wildcard_pattern.cpp
11167// start catch_xmlwriter.cpp
11168
11169#include <iomanip>
11170
11171using uchar = unsigned char;
11172
11173namespace Catch {
11174
11175namespace {
11176
11177 size_t trailingBytes(unsigned char c) {
11178 if ((c & 0xE0) == 0xC0) {
11179 return 2;
11180 }
11181 if ((c & 0xF0) == 0xE0) {
11182 return 3;
11183 }
11184 if ((c & 0xF8) == 0xF0) {
11185 return 4;
11186 }
11187 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
11188 }
11189
11190 uint32_t headerValue(unsigned char c) {
11191 if ((c & 0xE0) == 0xC0) {
11192 return c & 0x1F;
11193 }
11194 if ((c & 0xF0) == 0xE0) {
11195 return c & 0x0F;
11196 }
11197 if ((c & 0xF8) == 0xF0) {
11198 return c & 0x07;
11199 }
11200 CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");
11201 }
11202
11203 void hexEscapeChar(std::ostream& os, unsigned char c) {
11204 os << "\\x"
11205 << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
11206 << static_cast<int>(c);
11207 }
11208
11209} // anonymous namespace
11210
11211 XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )
11212 : m_str( str ),
11213 m_forWhat( forWhat )
11214 {}
11215
11216 void XmlEncode::encodeTo( std::ostream& os ) const {
11217 // Apostrophe escaping not necessary if we always use " to write attributes
11218 // (see: http://www.w3.org/TR/xml/#syntax)
11219
11220 for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
11221 uchar c = m_str[idx];
11222 switch (c) {
11223 case '<': os << "&lt;"; break;
11224 case '&': os << "&amp;"; break;
11225
11226 case '>':
11227 // See: http://www.w3.org/TR/xml/#syntax
11228 if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')
11229 os << "&gt;";
11230 else
11231 os << c;
11232 break;
11233
11234 case '\"':
11235 if (m_forWhat == ForAttributes)
11236 os << "&quot;";
11237 else
11238 os << c;
11239 break;
11240
11241 default:
11242 // Check for control characters and invalid utf-8
11243
11244 // Escape control characters in standard ascii
11245 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
11246 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
11247 hexEscapeChar(os, c);
11248 break;
11249 }
11250
11251 // Plain ASCII: Write it to stream
11252 if (c < 0x7F) {
11253 os << c;
11254 break;
11255 }
11256
11257 // UTF-8 territory
11258 // Check if the encoding is valid and if it is not, hex escape bytes.
11259 // Important: We do not check the exact decoded values for validity, only the encoding format
11260 // First check that this bytes is a valid lead byte:
11261 // This means that it is not encoded as 1111 1XXX
11262 // Or as 10XX XXXX
11263 if (c < 0xC0 ||
11264 c >= 0xF8) {
11265 hexEscapeChar(os, c);
11266 break;
11267 }
11268
11269 auto encBytes = trailingBytes(c);
11270 // Are there enough bytes left to avoid accessing out-of-bounds memory?
11271 if (idx + encBytes - 1 >= m_str.size()) {
11272 hexEscapeChar(os, c);
11273 break;
11274 }
11275 // The header is valid, check data
11276 // The next encBytes bytes must together be a valid utf-8
11277 // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)
11278 bool valid = true;
11279 uint32_t value = headerValue(c);
11280 for (std::size_t n = 1; n < encBytes; ++n) {
11281 uchar nc = m_str[idx + n];
11282 valid &= ((nc & 0xC0) == 0x80);
11283 value = (value << 6) | (nc & 0x3F);
11284 }
11285
11286 if (
11287 // Wrong bit pattern of following bytes
11288 (!valid) ||
11289 // Overlong encodings
11290 (value < 0x80) ||
11291 (0x80 <= value && value < 0x800 && encBytes > 2) ||
11292 (0x800 < value && value < 0x10000 && encBytes > 3) ||
11293 // Encoded value out of range
11294 (value >= 0x110000)
11295 ) {
11296 hexEscapeChar(os, c);
11297 break;
11298 }
11299
11300 // If we got here, this is in fact a valid(ish) utf-8 sequence
11301 for (std::size_t n = 0; n < encBytes; ++n) {
11302 os << m_str[idx + n];
11303 }
11304 idx += encBytes - 1;
11305 break;
11306 }
11307 }
11308 }
11309
11310 std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
11311 xmlEncode.encodeTo( os );
11312 return os;
11313 }
11314
11315 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
11316 : m_writer( writer )
11317 {}
11318
11319 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
11320 : m_writer( other.m_writer ){
11321 other.m_writer = nullptr;
11322 }
11323 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {
11324 if ( m_writer ) {
11325 m_writer->endElement();
11326 }
11327 m_writer = other.m_writer;
11328 other.m_writer = nullptr;
11329 return *this;
11330 }
11331
11332 XmlWriter::ScopedElement::~ScopedElement() {
11333 if( m_writer )
11334 m_writer->endElement();
11335 }
11336
11337 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) {
11338 m_writer->writeText( text, indent );
11339 return *this;
11340 }
11341
11342 XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )
11343 {
11344 writeDeclaration();
11345 }
11346
11347 XmlWriter::~XmlWriter() {
11348 while( !m_tags.empty() )
11349 endElement();
11350 }
11351
11352 XmlWriter& XmlWriter::startElement( std::string const& name ) {
11353 ensureTagClosed();
11354 newlineIfNecessary();
11355 m_os << m_indent << '<' << name;
11356 m_tags.push_back( name );
11357 m_indent += " ";
11358 m_tagIsOpen = true;
11359 return *this;
11360 }
11361
11362 XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) {
11363 ScopedElement scoped( this );
11364 startElement( name );
11365 return scoped;
11366 }
11367
11368 XmlWriter& XmlWriter::endElement() {
11369 newlineIfNecessary();
11370 m_indent = m_indent.substr( 0, m_indent.size()-2 );
11371 if( m_tagIsOpen ) {
11372 m_os << "/>";
11373 m_tagIsOpen = false;
11374 }
11375 else {
11376 m_os << m_indent << "</" << m_tags.back() << ">";
11377 }
11378 m_os << std::endl;
11379 m_tags.pop_back();
11380 return *this;
11381 }
11382
11383 XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {
11384 if( !name.empty() && !attribute.empty() )
11385 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
11386 return *this;
11387 }
11388
11389 XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {
11390 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
11391 return *this;
11392 }
11393
11394 XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) {
11395 if( !text.empty() ){
11396 bool tagWasOpen = m_tagIsOpen;
11397 ensureTagClosed();
11398 if( tagWasOpen && indent )
11399 m_os << m_indent;
11400 m_os << XmlEncode( text );
11401 m_needsNewline = true;
11402 }
11403 return *this;
11404 }
11405
11406 XmlWriter& XmlWriter::writeComment( std::string const& text ) {
11407 ensureTagClosed();
11408 m_os << m_indent << "<!--" << text << "-->";
11409 m_needsNewline = true;
11410 return *this;
11411 }
11412
11413 void XmlWriter::writeStylesheetRef( std::string const& url ) {
11414 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
11415 }
11416
11417 XmlWriter& XmlWriter::writeBlankLine() {
11418 ensureTagClosed();
11419 m_os << '\n';
11420 return *this;
11421 }
11422
11423 void XmlWriter::ensureTagClosed() {
11424 if( m_tagIsOpen ) {
11425 m_os << ">" << std::endl;
11426 m_tagIsOpen = false;
11427 }
11428 }
11429
11430 void XmlWriter::writeDeclaration() {
11431 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
11432 }
11433
11434 void XmlWriter::newlineIfNecessary() {
11435 if( m_needsNewline ) {
11436 m_os << std::endl;
11437 m_needsNewline = false;
11438 }
11439 }
11440}
11441// end catch_xmlwriter.cpp
11442// start catch_reporter_bases.cpp
11443
11444#include <cstring>
11445#include <cfloat>
11446#include <cstdio>
11447#include <cassert>
11448#include <memory>
11449
11450namespace Catch {
11451 void prepareExpandedExpression(AssertionResult& result) {
11452 result.getExpandedExpression();
11453 }
11454
11455 // Because formatting using c++ streams is stateful, drop down to C is required
11456 // Alternatively we could use stringstream, but its performance is... not good.
11457 std::string getFormattedDuration( double duration ) {
11458 // Max exponent + 1 is required to represent the whole part
11459 // + 1 for decimal point
11460 // + 3 for the 3 decimal places
11461 // + 1 for null terminator
11462 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
11463 char buffer[maxDoubleSize];
11464
11465 // Save previous errno, to prevent sprintf from overwriting it
11466 ErrnoGuard guard;
11467#ifdef _MSC_VER
11468 sprintf_s(buffer, "%.3f", duration);
11469#else
11470 sprintf(buffer, "%.3f", duration);
11471#endif
11472 return std::string(buffer);
11473 }
11474
11475 TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
11476 :StreamingReporterBase(_config) {}
11477
11478 void TestEventListenerBase::assertionStarting(AssertionInfo const &) {}
11479
11480 bool TestEventListenerBase::assertionEnded(AssertionStats const &) {
11481 return false;
11482 }
11483
11484} // end namespace Catch
11485// end catch_reporter_bases.cpp
11486// start catch_reporter_compact.cpp
11487
11488namespace {
11489
11490#ifdef CATCH_PLATFORM_MAC
11491 const char* failedString() { return "FAILED"; }
11492 const char* passedString() { return "PASSED"; }
11493#else
11494 const char* failedString() { return "failed"; }
11495 const char* passedString() { return "passed"; }
11496#endif
11497
11498 // Colour::LightGrey
11499 Catch::Colour::Code dimColour() { return Catch::Colour::FileName; }
11500
11501 std::string bothOrAll( std::size_t count ) {
11502 return count == 1 ? std::string() :
11503 count == 2 ? "both " : "all " ;
11504 }
11505
11506} // anon namespace
11507
11508namespace Catch {
11509namespace {
11510// Colour, message variants:
11511// - white: No tests ran.
11512// - red: Failed [both/all] N test cases, failed [both/all] M assertions.
11513// - white: Passed [both/all] N test cases (no assertions).
11514// - red: Failed N tests cases, failed M assertions.
11515// - green: Passed [both/all] N tests cases with M assertions.
11516void printTotals(std::ostream& out, const Totals& totals) {
11517 if (totals.testCases.total() == 0) {
11518 out << "No tests ran.";
11519 } else if (totals.testCases.failed == totals.testCases.total()) {
11520 Colour colour(Colour::ResultError);
11521 const std::string qualify_assertions_failed =
11522 totals.assertions.failed == totals.assertions.total() ?
11523 bothOrAll(totals.assertions.failed) : std::string();
11524 out <<
11525 "Failed " << bothOrAll(totals.testCases.failed)
11526 << pluralise(totals.testCases.failed, "test case") << ", "
11527 "failed " << qualify_assertions_failed <<
11528 pluralise(totals.assertions.failed, "assertion") << '.';
11529 } else if (totals.assertions.total() == 0) {
11530 out <<
11531 "Passed " << bothOrAll(totals.testCases.total())
11532 << pluralise(totals.testCases.total(), "test case")
11533 << " (no assertions).";
11534 } else if (totals.assertions.failed) {
11535 Colour colour(Colour::ResultError);
11536 out <<
11537 "Failed " << pluralise(totals.testCases.failed, "test case") << ", "
11538 "failed " << pluralise(totals.assertions.failed, "assertion") << '.';
11539 } else {
11540 Colour colour(Colour::ResultSuccess);
11541 out <<
11542 "Passed " << bothOrAll(totals.testCases.passed)
11543 << pluralise(totals.testCases.passed, "test case") <<
11544 " with " << pluralise(totals.assertions.passed, "assertion") << '.';
11545 }
11546}
11547
11548// Implementation of CompactReporter formatting
11549class AssertionPrinter {
11550public:
11551 AssertionPrinter& operator= (AssertionPrinter const&) = delete;
11552 AssertionPrinter(AssertionPrinter const&) = delete;
11553 AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
11554 : stream(_stream)
11555 , result(_stats.assertionResult)
11556 , messages(_stats.infoMessages)
11557 , itMessage(_stats.infoMessages.begin())
11558 , printInfoMessages(_printInfoMessages) {}
11559
11560 void print() {
11561 printSourceInfo();
11562
11563 itMessage = messages.begin();
11564
11565 switch (result.getResultType()) {
11566 case ResultWas::Ok:
11567 printResultType(Colour::ResultSuccess, passedString());
11568 printOriginalExpression();
11569 printReconstructedExpression();
11570 if (!result.hasExpression())
11571 printRemainingMessages(Colour::None);
11572 else
11573 printRemainingMessages();
11574 break;
11576 if (result.isOk())
11577 printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok"));
11578 else
11579 printResultType(Colour::Error, failedString());
11580 printOriginalExpression();
11581 printReconstructedExpression();
11582 printRemainingMessages();
11583 break;
11585 printResultType(Colour::Error, failedString());
11586 printIssue("unexpected exception with message:");
11587 printMessage();
11588 printExpressionWas();
11589 printRemainingMessages();
11590 break;
11592 printResultType(Colour::Error, failedString());
11593 printIssue("fatal error condition with message:");
11594 printMessage();
11595 printExpressionWas();
11596 printRemainingMessages();
11597 break;
11599 printResultType(Colour::Error, failedString());
11600 printIssue("expected exception, got none");
11601 printExpressionWas();
11602 printRemainingMessages();
11603 break;
11604 case ResultWas::Info:
11605 printResultType(Colour::None, "info");
11606 printMessage();
11607 printRemainingMessages();
11608 break;
11609 case ResultWas::Warning:
11610 printResultType(Colour::None, "warning");
11611 printMessage();
11612 printRemainingMessages();
11613 break;
11615 printResultType(Colour::Error, failedString());
11616 printIssue("explicitly");
11617 printRemainingMessages(Colour::None);
11618 break;
11619 // These cases are here to prevent compiler warnings
11620 case ResultWas::Unknown:
11623 printResultType(Colour::Error, "** internal error **");
11624 break;
11625 }
11626 }
11627
11628private:
11629 void printSourceInfo() const {
11630 Colour colourGuard(Colour::FileName);
11631 stream << result.getSourceInfo() << ':';
11632 }
11633
11634 void printResultType(Colour::Code colour, std::string const& passOrFail) const {
11635 if (!passOrFail.empty()) {
11636 {
11637 Colour colourGuard(colour);
11638 stream << ' ' << passOrFail;
11639 }
11640 stream << ':';
11641 }
11642 }
11643
11644 void printIssue(std::string const& issue) const {
11645 stream << ' ' << issue;
11646 }
11647
11648 void printExpressionWas() {
11649 if (result.hasExpression()) {
11650 stream << ';';
11651 {
11652 Colour colour(dimColour());
11653 stream << " expression was:";
11654 }
11655 printOriginalExpression();
11656 }
11657 }
11658
11659 void printOriginalExpression() const {
11660 if (result.hasExpression()) {
11661 stream << ' ' << result.getExpression();
11662 }
11663 }
11664
11665 void printReconstructedExpression() const {
11666 if (result.hasExpandedExpression()) {
11667 {
11668 Colour colour(dimColour());
11669 stream << " for: ";
11670 }
11671 stream << result.getExpandedExpression();
11672 }
11673 }
11674
11675 void printMessage() {
11676 if (itMessage != messages.end()) {
11677 stream << " '" << itMessage->message << '\'';
11678 ++itMessage;
11679 }
11680 }
11681
11682 void printRemainingMessages(Colour::Code colour = dimColour()) {
11683 if (itMessage == messages.end())
11684 return;
11685
11686 // using messages.end() directly yields (or auto) compilation error:
11687 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
11688 const std::size_t N = static_cast<std::size_t>(std::distance(itMessage, itEnd));
11689
11690 {
11691 Colour colourGuard(colour);
11692 stream << " with " << pluralise(N, "message") << ':';
11693 }
11694
11695 for (; itMessage != itEnd; ) {
11696 // If this assertion is a warning ignore any INFO messages
11697 if (printInfoMessages || itMessage->type != ResultWas::Info) {
11698 stream << " '" << itMessage->message << '\'';
11699 if (++itMessage != itEnd) {
11700 Colour colourGuard(dimColour());
11701 stream << " and";
11702 }
11703 }
11704 }
11705 }
11706
11707private:
11708 std::ostream& stream;
11709 AssertionResult const& result;
11710 std::vector<MessageInfo> messages;
11711 std::vector<MessageInfo>::const_iterator itMessage;
11712 bool printInfoMessages;
11713};
11714
11715} // anon namespace
11716
11717 std::string CompactReporter::getDescription() {
11718 return "Reports test results on a single line, suitable for IDEs";
11719 }
11720
11721 ReporterPreferences CompactReporter::getPreferences() const {
11722 ReporterPreferences prefs;
11723 prefs.shouldRedirectStdOut = false;
11724 return prefs;
11725 }
11726
11727 void CompactReporter::noMatchingTestCases( std::string const& spec ) {
11728 stream << "No test cases matched '" << spec << '\'' << std::endl;
11729 }
11730
11731 void CompactReporter::assertionStarting( AssertionInfo const& ) {}
11732
11733 bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {
11734 AssertionResult const& result = _assertionStats.assertionResult;
11735
11736 bool printInfoMessages = true;
11737
11738 // Drop out if result was successful and we're not printing those
11739 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
11740 if( result.getResultType() != ResultWas::Warning )
11741 return false;
11742 printInfoMessages = false;
11743 }
11744
11745 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
11746 printer.print();
11747
11748 stream << std::endl;
11749 return true;
11750 }
11751
11752 void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {
11753 if (m_config->showDurations() == ShowDurations::Always) {
11754 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
11755 }
11756 }
11757
11758 void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) {
11759 printTotals( stream, _testRunStats.totals );
11760 stream << '\n' << std::endl;
11761 StreamingReporterBase::testRunEnded( _testRunStats );
11762 }
11763
11764 CompactReporter::~CompactReporter() {}
11765
11766 CATCH_REGISTER_REPORTER( "compact", CompactReporter )
11767
11768} // end namespace Catch
11769// end catch_reporter_compact.cpp
11770// start catch_reporter_console.cpp
11771
11772#include <cfloat>
11773#include <cstdio>
11774
11775#if defined(_MSC_VER)
11776#pragma warning(push)
11777#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
11778 // Note that 4062 (not all labels are handled
11779 // and default is missing) is enabled
11780#endif
11781
11782namespace Catch {
11783
11784namespace {
11785
11786// Formatter impl for ConsoleReporter
11787class ConsoleAssertionPrinter {
11788public:
11789 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete;
11790 ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete;
11791 ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)
11792 : stream(_stream),
11793 stats(_stats),
11794 result(_stats.assertionResult),
11795 colour(Colour::None),
11796 message(result.getMessage()),
11797 messages(_stats.infoMessages),
11798 printInfoMessages(_printInfoMessages) {
11799 switch (result.getResultType()) {
11800 case ResultWas::Ok:
11801 colour = Colour::Success;
11802 passOrFail = "PASSED";
11803 //if( result.hasMessage() )
11804 if (_stats.infoMessages.size() == 1)
11805 messageLabel = "with message";
11806 if (_stats.infoMessages.size() > 1)
11807 messageLabel = "with messages";
11808 break;
11810 if (result.isOk()) {
11811 colour = Colour::Success;
11812 passOrFail = "FAILED - but was ok";
11813 } else {
11814 colour = Colour::Error;
11815 passOrFail = "FAILED";
11816 }
11817 if (_stats.infoMessages.size() == 1)
11818 messageLabel = "with message";
11819 if (_stats.infoMessages.size() > 1)
11820 messageLabel = "with messages";
11821 break;
11823 colour = Colour::Error;
11824 passOrFail = "FAILED";
11825 messageLabel = "due to unexpected exception with ";
11826 if (_stats.infoMessages.size() == 1)
11827 messageLabel += "message";
11828 if (_stats.infoMessages.size() > 1)
11829 messageLabel += "messages";
11830 break;
11832 colour = Colour::Error;
11833 passOrFail = "FAILED";
11834 messageLabel = "due to a fatal error condition";
11835 break;
11837 colour = Colour::Error;
11838 passOrFail = "FAILED";
11839 messageLabel = "because no exception was thrown where one was expected";
11840 break;
11841 case ResultWas::Info:
11842 messageLabel = "info";
11843 break;
11844 case ResultWas::Warning:
11845 messageLabel = "warning";
11846 break;
11848 passOrFail = "FAILED";
11849 colour = Colour::Error;
11850 if (_stats.infoMessages.size() == 1)
11851 messageLabel = "explicitly with message";
11852 if (_stats.infoMessages.size() > 1)
11853 messageLabel = "explicitly with messages";
11854 break;
11855 // These cases are here to prevent compiler warnings
11856 case ResultWas::Unknown:
11859 passOrFail = "** internal error **";
11860 colour = Colour::Error;
11861 break;
11862 }
11863 }
11864
11865 void print() const {
11866 printSourceInfo();
11867 if (stats.totals.assertions.total() > 0) {
11868 if (result.isOk())
11869 stream << '\n';
11870 printResultType();
11871 printOriginalExpression();
11872 printReconstructedExpression();
11873 } else {
11874 stream << '\n';
11875 }
11876 printMessage();
11877 }
11878
11879private:
11880 void printResultType() const {
11881 if (!passOrFail.empty()) {
11882 Colour colourGuard(colour);
11883 stream << passOrFail << ":\n";
11884 }
11885 }
11886 void printOriginalExpression() const {
11887 if (result.hasExpression()) {
11888 Colour colourGuard(Colour::OriginalExpression);
11889 stream << " ";
11890 stream << result.getExpressionInMacro();
11891 stream << '\n';
11892 }
11893 }
11894 void printReconstructedExpression() const {
11895 if (result.hasExpandedExpression()) {
11896 stream << "with expansion:\n";
11897 Colour colourGuard(Colour::ReconstructedExpression);
11898 stream << Column(result.getExpandedExpression()).indent(2) << '\n';
11899 }
11900 }
11901 void printMessage() const {
11902 if (!messageLabel.empty())
11903 stream << messageLabel << ':' << '\n';
11904 for (auto const& msg : messages) {
11905 // If this assertion is a warning ignore any INFO messages
11906 if (printInfoMessages || msg.type != ResultWas::Info)
11907 stream << Column(msg.message).indent(2) << '\n';
11908 }
11909 }
11910 void printSourceInfo() const {
11911 Colour colourGuard(Colour::FileName);
11912 stream << result.getSourceInfo() << ": ";
11913 }
11914
11915 std::ostream& stream;
11916 AssertionStats const& stats;
11917 AssertionResult const& result;
11918 Colour::Code colour;
11919 std::string passOrFail;
11920 std::string messageLabel;
11921 std::string message;
11922 std::vector<MessageInfo> messages;
11923 bool printInfoMessages;
11924};
11925
11926std::size_t makeRatio(std::size_t number, std::size_t total) {
11927 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
11928 return (ratio == 0 && number > 0) ? 1 : ratio;
11929}
11930
11931std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {
11932 if (i > j && i > k)
11933 return i;
11934 else if (j > k)
11935 return j;
11936 else
11937 return k;
11938}
11939
11940struct ColumnInfo {
11941 enum Justification { Left, Right };
11943 int width;
11944 Justification justification;
11945};
11946struct ColumnBreak {};
11947struct RowBreak {};
11948
11949class Duration {
11950 enum class Unit {
11951 Auto,
11952 Nanoseconds,
11953 Microseconds,
11954 Milliseconds,
11955 Seconds,
11956 Minutes
11957 };
11958 static const uint64_t s_nanosecondsInAMicrosecond = 1000;
11959 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
11960 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
11961 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
11962
11963 uint64_t m_inNanoseconds;
11964 Unit m_units;
11965
11966public:
11967 explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
11968 : m_inNanoseconds(inNanoseconds),
11969 m_units(units) {
11970 if (m_units == Unit::Auto) {
11971 if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
11972 m_units = Unit::Nanoseconds;
11973 else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
11974 m_units = Unit::Microseconds;
11975 else if (m_inNanoseconds < s_nanosecondsInASecond)
11976 m_units = Unit::Milliseconds;
11977 else if (m_inNanoseconds < s_nanosecondsInAMinute)
11978 m_units = Unit::Seconds;
11979 else
11980 m_units = Unit::Minutes;
11981 }
11982
11983 }
11984
11985 auto value() const -> double {
11986 switch (m_units) {
11987 case Unit::Microseconds:
11988 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond);
11989 case Unit::Milliseconds:
11990 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond);
11991 case Unit::Seconds:
11992 return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond);
11993 case Unit::Minutes:
11994 return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);
11995 default:
11996 return static_cast<double>(m_inNanoseconds);
11997 }
11998 }
11999 auto unitsAsString() const -> std::string {
12000 switch (m_units) {
12001 case Unit::Nanoseconds:
12002 return "ns";
12003 case Unit::Microseconds:
12004 return "µs";
12005 case Unit::Milliseconds:
12006 return "ms";
12007 case Unit::Seconds:
12008 return "s";
12009 case Unit::Minutes:
12010 return "m";
12011 default:
12012 return "** internal error **";
12013 }
12014
12015 }
12016 friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {
12017 return os << duration.value() << " " << duration.unitsAsString();
12018 }
12019};
12020} // end anon namespace
12021
12022class TablePrinter {
12023 std::ostream& m_os;
12024 std::vector<ColumnInfo> m_columnInfos;
12025 std::ostringstream m_oss;
12026 int m_currentColumn = -1;
12027 bool m_isOpen = false;
12028
12029public:
12030 TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )
12031 : m_os( os ),
12032 m_columnInfos( std::move( columnInfos ) ) {}
12033
12034 auto columnInfos() const -> std::vector<ColumnInfo> const& {
12035 return m_columnInfos;
12036 }
12037
12038 void open() {
12039 if (!m_isOpen) {
12040 m_isOpen = true;
12041 *this << RowBreak();
12042 for (auto const& info : m_columnInfos)
12043 *this << info.name << ColumnBreak();
12044 *this << RowBreak();
12045 m_os << Catch::getLineOfChars<'-'>() << "\n";
12046 }
12047 }
12048 void close() {
12049 if (m_isOpen) {
12050 *this << RowBreak();
12051 m_os << std::endl;
12052 m_isOpen = false;
12053 }
12054 }
12055
12056 template<typename T>
12057 friend TablePrinter& operator << (TablePrinter& tp, T const& value) {
12058 tp.m_oss << value;
12059 return tp;
12060 }
12061
12062 friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) {
12063 auto colStr = tp.m_oss.str();
12064 // This takes account of utf8 encodings
12065 auto strSize = Catch::StringRef(colStr).numberOfCharacters();
12066 tp.m_oss.str("");
12067 tp.open();
12068 if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {
12069 tp.m_currentColumn = -1;
12070 tp.m_os << "\n";
12071 }
12072 tp.m_currentColumn++;
12073
12074 auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
12075 auto padding = (strSize + 2 < static_cast<std::size_t>(colInfo.width))
12076 ? std::string(colInfo.width - (strSize + 2), ' ')
12077 : std::string();
12078 if (colInfo.justification == ColumnInfo::Left)
12079 tp.m_os << colStr << padding << " ";
12080 else
12081 tp.m_os << padding << colStr << " ";
12082 return tp;
12083 }
12084
12085 friend TablePrinter& operator << (TablePrinter& tp, RowBreak) {
12086 if (tp.m_currentColumn > 0) {
12087 tp.m_os << "\n";
12088 tp.m_currentColumn = -1;
12089 }
12090 return tp;
12091 }
12092};
12093
12094ConsoleReporter::ConsoleReporter(ReporterConfig const& config)
12095 : StreamingReporterBase(config),
12096 m_tablePrinter(new TablePrinter(config.stream(),
12097 {
12098 { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
12099 { "iters", 8, ColumnInfo::Right },
12100 { "elapsed ns", 14, ColumnInfo::Right },
12101 { "average", 14, ColumnInfo::Right }
12102 })) {}
12103ConsoleReporter::~ConsoleReporter() = default;
12104
12105std::string ConsoleReporter::getDescription() {
12106 return "Reports test results as plain lines of text";
12107}
12108
12109void ConsoleReporter::noMatchingTestCases(std::string const& spec) {
12110 stream << "No test cases matched '" << spec << '\'' << std::endl;
12111}
12112
12113void ConsoleReporter::assertionStarting(AssertionInfo const&) {}
12114
12115bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {
12116 AssertionResult const& result = _assertionStats.assertionResult;
12117
12118 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
12119
12120 // Drop out if result was successful but we're not printing them.
12121 if (!includeResults && result.getResultType() != ResultWas::Warning)
12122 return false;
12123
12124 lazyPrint();
12125
12126 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
12127 printer.print();
12128 stream << std::endl;
12129 return true;
12130}
12131
12132void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) {
12133 m_headerPrinted = false;
12134 StreamingReporterBase::sectionStarting(_sectionInfo);
12135}
12136void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
12137 m_tablePrinter->close();
12138 if (_sectionStats.missingAssertions) {
12139 lazyPrint();
12140 Colour colour(Colour::ResultError);
12141 if (m_sectionStack.size() > 1)
12142 stream << "\nNo assertions in section";
12143 else
12144 stream << "\nNo assertions in test case";
12145 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
12146 }
12147 if (m_config->showDurations() == ShowDurations::Always) {
12148 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
12149 }
12150 if (m_headerPrinted) {
12151 m_headerPrinted = false;
12152 }
12153 StreamingReporterBase::sectionEnded(_sectionStats);
12154}
12155
12156void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
12157 lazyPrintWithoutClosingBenchmarkTable();
12158
12159 auto nameCol = Column( info.name ).width( static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) );
12160
12161 bool firstLine = true;
12162 for (auto line : nameCol) {
12163 if (!firstLine)
12164 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
12165 else
12166 firstLine = false;
12167
12168 (*m_tablePrinter) << line << ColumnBreak();
12169 }
12170}
12171void ConsoleReporter::benchmarkEnded(BenchmarkStats const& stats) {
12172 Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
12173 (*m_tablePrinter)
12174 << stats.iterations << ColumnBreak()
12175 << stats.elapsedTimeInNanoseconds << ColumnBreak()
12176 << average << ColumnBreak();
12177}
12178
12179void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {
12180 m_tablePrinter->close();
12181 StreamingReporterBase::testCaseEnded(_testCaseStats);
12182 m_headerPrinted = false;
12183}
12184void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) {
12185 if (currentGroupInfo.used) {
12186 printSummaryDivider();
12187 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
12188 printTotals(_testGroupStats.totals);
12189 stream << '\n' << std::endl;
12190 }
12191 StreamingReporterBase::testGroupEnded(_testGroupStats);
12192}
12193void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
12194 printTotalsDivider(_testRunStats.totals);
12195 printTotals(_testRunStats.totals);
12196 stream << std::endl;
12197 StreamingReporterBase::testRunEnded(_testRunStats);
12198}
12199
12200void ConsoleReporter::lazyPrint() {
12201
12202 m_tablePrinter->close();
12203 lazyPrintWithoutClosingBenchmarkTable();
12204}
12205
12206void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
12207
12208 if (!currentTestRunInfo.used)
12209 lazyPrintRunInfo();
12210 if (!currentGroupInfo.used)
12211 lazyPrintGroupInfo();
12212
12213 if (!m_headerPrinted) {
12214 printTestCaseAndSectionHeader();
12215 m_headerPrinted = true;
12216 }
12217}
12218void ConsoleReporter::lazyPrintRunInfo() {
12219 stream << '\n' << getLineOfChars<'~'>() << '\n';
12220 Colour colour(Colour::SecondaryText);
12221 stream << currentTestRunInfo->name
12222 << " is a Catch v" << libraryVersion() << " host application.\n"
12223 << "Run with -? for options\n\n";
12224
12225 if (m_config->rngSeed() != 0)
12226 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
12227
12228 currentTestRunInfo.used = true;
12229}
12230void ConsoleReporter::lazyPrintGroupInfo() {
12231 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
12232 printClosedHeader("Group: " + currentGroupInfo->name);
12233 currentGroupInfo.used = true;
12234 }
12235}
12236void ConsoleReporter::printTestCaseAndSectionHeader() {
12237 assert(!m_sectionStack.empty());
12238 printOpenHeader(currentTestCaseInfo->name);
12239
12240 if (m_sectionStack.size() > 1) {
12241 Colour colourGuard(Colour::Headers);
12242
12243 auto
12244 it = m_sectionStack.begin() + 1, // Skip first section (test case)
12245 itEnd = m_sectionStack.end();
12246 for (; it != itEnd; ++it)
12247 printHeaderString(it->name, 2);
12248 }
12249
12250 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
12251
12252 if (!lineInfo.empty()) {
12253 stream << getLineOfChars<'-'>() << '\n';
12254 Colour colourGuard(Colour::FileName);
12255 stream << lineInfo << '\n';
12256 }
12257 stream << getLineOfChars<'.'>() << '\n' << std::endl;
12258}
12259
12260void ConsoleReporter::printClosedHeader(std::string const& _name) {
12261 printOpenHeader(_name);
12262 stream << getLineOfChars<'.'>() << '\n';
12263}
12264void ConsoleReporter::printOpenHeader(std::string const& _name) {
12265 stream << getLineOfChars<'-'>() << '\n';
12266 {
12267 Colour colourGuard(Colour::Headers);
12268 printHeaderString(_name);
12269 }
12270}
12271
12272// if string has a : in first line will set indent to follow it on
12273// subsequent lines
12274void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) {
12275 std::size_t i = _string.find(": ");
12276 if (i != std::string::npos)
12277 i += 2;
12278 else
12279 i = 0;
12280 stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n';
12281}
12282
12283struct SummaryColumn {
12284
12285 SummaryColumn( std::string _label, Colour::Code _colour )
12286 : label( std::move( _label ) ),
12287 colour( _colour ) {}
12288 SummaryColumn addRow( std::size_t count ) {
12289 ReusableStringStream rss;
12290 rss << count;
12291 std::string row = rss.str();
12292 for (auto& oldRow : rows) {
12293 while (oldRow.size() < row.size())
12294 oldRow = ' ' + oldRow;
12295 while (oldRow.size() > row.size())
12296 row = ' ' + row;
12297 }
12298 rows.push_back(row);
12299 return *this;
12300 }
12301
12302 std::string label;
12303 Colour::Code colour;
12304 std::vector<std::string> rows;
12305
12306};
12307
12308void ConsoleReporter::printTotals( Totals const& totals ) {
12309 if (totals.testCases.total() == 0) {
12310 stream << Colour(Colour::Warning) << "No tests ran\n";
12311 } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {
12312 stream << Colour(Colour::ResultSuccess) << "All tests passed";
12313 stream << " ("
12314 << pluralise(totals.assertions.passed, "assertion") << " in "
12315 << pluralise(totals.testCases.passed, "test case") << ')'
12316 << '\n';
12317 } else {
12318
12319 std::vector<SummaryColumn> columns;
12320 columns.push_back(SummaryColumn("", Colour::None)
12321 .addRow(totals.testCases.total())
12322 .addRow(totals.assertions.total()));
12323 columns.push_back(SummaryColumn("passed", Colour::Success)
12324 .addRow(totals.testCases.passed)
12325 .addRow(totals.assertions.passed));
12326 columns.push_back(SummaryColumn("failed", Colour::ResultError)
12327 .addRow(totals.testCases.failed)
12328 .addRow(totals.assertions.failed));
12329 columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure)
12330 .addRow(totals.testCases.failedButOk)
12331 .addRow(totals.assertions.failedButOk));
12332
12333 printSummaryRow("test cases", columns, 0);
12334 printSummaryRow("assertions", columns, 1);
12335 }
12336}
12337void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) {
12338 for (auto col : cols) {
12339 std::string value = col.rows[row];
12340 if (col.label.empty()) {
12341 stream << label << ": ";
12342 if (value != "0")
12343 stream << value;
12344 else
12345 stream << Colour(Colour::Warning) << "- none -";
12346 } else if (value != "0") {
12347 stream << Colour(Colour::LightGrey) << " | ";
12348 stream << Colour(col.colour)
12349 << value << ' ' << col.label;
12350 }
12351 }
12352 stream << '\n';
12353}
12354
12355void ConsoleReporter::printTotalsDivider(Totals const& totals) {
12356 if (totals.testCases.total() > 0) {
12357 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
12358 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
12359 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
12360 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
12361 findMax(failedRatio, failedButOkRatio, passedRatio)++;
12362 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
12363 findMax(failedRatio, failedButOkRatio, passedRatio)--;
12364
12365 stream << Colour(Colour::Error) << std::string(failedRatio, '=');
12366 stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '=');
12367 if (totals.testCases.allPassed())
12368 stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '=');
12369 else
12370 stream << Colour(Colour::Success) << std::string(passedRatio, '=');
12371 } else {
12372 stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '=');
12373 }
12374 stream << '\n';
12375}
12376void ConsoleReporter::printSummaryDivider() {
12377 stream << getLineOfChars<'-'>() << '\n';
12378}
12379
12380CATCH_REGISTER_REPORTER("console", ConsoleReporter)
12381
12382} // end namespace Catch
12383
12384#if defined(_MSC_VER)
12385#pragma warning(pop)
12386#endif
12387// end catch_reporter_console.cpp
12388// start catch_reporter_junit.cpp
12389
12390#include <cassert>
12391#include <sstream>
12392#include <ctime>
12393#include <algorithm>
12394
12395namespace Catch {
12396
12397 namespace {
12398 std::string getCurrentTimestamp() {
12399 // Beware, this is not reentrant because of backward compatibility issues
12400 // Also, UTC only, again because of backward compatibility (%z is C++11)
12401 time_t rawtime;
12402 std::time(&rawtime);
12403 auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");
12404
12405#ifdef _MSC_VER
12406 std::tm timeInfo = {};
12407 gmtime_s(&timeInfo, &rawtime);
12408#else
12409 std::tm* timeInfo;
12410 timeInfo = std::gmtime(&rawtime);
12411#endif
12412
12413 char timeStamp[timeStampSize];
12414 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
12415
12416#ifdef _MSC_VER
12417 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
12418#else
12419 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
12420#endif
12421 return std::string(timeStamp);
12422 }
12423
12424 std::string fileNameTag(const std::vector<std::string> &tags) {
12425 auto it = std::find_if(begin(tags),
12426 end(tags),
12427 [] (std::string const& tag) {return tag.front() == '#'; });
12428 if (it != tags.end())
12429 return it->substr(1);
12430 return std::string();
12431 }
12432 } // anonymous namespace
12433
12434 JunitReporter::JunitReporter( ReporterConfig const& _config )
12435 : CumulativeReporterBase( _config ),
12436 xml( _config.stream() )
12437 {
12438 m_reporterPrefs.shouldRedirectStdOut = true;
12439 }
12440
12441 JunitReporter::~JunitReporter() {}
12442
12443 std::string JunitReporter::getDescription() {
12444 return "Reports test results in an XML format that looks like Ant's junitreport target";
12445 }
12446
12447 void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {}
12448
12449 void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) {
12450 CumulativeReporterBase::testRunStarting( runInfo );
12451 xml.startElement( "testsuites" );
12452 }
12453
12454 void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
12455 suiteTimer.start();
12456 stdOutForSuite.clear();
12457 stdErrForSuite.clear();
12458 unexpectedExceptions = 0;
12459 CumulativeReporterBase::testGroupStarting( groupInfo );
12460 }
12461
12462 void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) {
12463 m_okToFail = testCaseInfo.okToFail();
12464 }
12465
12466 bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) {
12467 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
12468 unexpectedExceptions++;
12469 return CumulativeReporterBase::assertionEnded( assertionStats );
12470 }
12471
12472 void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
12473 stdOutForSuite += testCaseStats.stdOut;
12474 stdErrForSuite += testCaseStats.stdErr;
12475 CumulativeReporterBase::testCaseEnded( testCaseStats );
12476 }
12477
12478 void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
12479 double suiteTime = suiteTimer.getElapsedSeconds();
12480 CumulativeReporterBase::testGroupEnded( testGroupStats );
12481 writeGroup( *m_testGroups.back(), suiteTime );
12482 }
12483
12484 void JunitReporter::testRunEndedCumulative() {
12485 xml.endElement();
12486 }
12487
12488 void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
12489 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
12490 TestGroupStats const& stats = groupNode.value;
12491 xml.writeAttribute( "name", stats.groupInfo.name );
12492 xml.writeAttribute( "errors", unexpectedExceptions );
12493 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
12494 xml.writeAttribute( "tests", stats.totals.assertions.total() );
12495 xml.writeAttribute( "hostname", "tbd" ); // !TBD
12496 if( m_config->showDurations() == ShowDurations::Never )
12497 xml.writeAttribute( "time", "" );
12498 else
12499 xml.writeAttribute( "time", suiteTime );
12500 xml.writeAttribute( "timestamp", getCurrentTimestamp() );
12501
12502 // Write test cases
12503 for( auto const& child : groupNode.children )
12504 writeTestCase( *child );
12505
12506 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), false );
12507 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), false );
12508 }
12509
12510 void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {
12511 TestCaseStats const& stats = testCaseNode.value;
12512
12513 // All test cases have exactly one section - which represents the
12514 // test case itself. That section may have 0-n nested sections
12515 assert( testCaseNode.children.size() == 1 );
12516 SectionNode const& rootSection = *testCaseNode.children.front();
12517
12518 std::string className = stats.testInfo.className;
12519
12520 if( className.empty() ) {
12521 className = fileNameTag(stats.testInfo.tags);
12522 if ( className.empty() )
12523 className = "global";
12524 }
12525
12526 if ( !m_config->name().empty() )
12527 className = m_config->name() + "." + className;
12528
12529 writeSection( className, "", rootSection );
12530 }
12531
12532 void JunitReporter::writeSection( std::string const& className,
12533 std::string const& rootName,
12534 SectionNode const& sectionNode ) {
12535 std::string name = trim( sectionNode.stats.sectionInfo.name );
12536 if( !rootName.empty() )
12537 name = rootName + '/' + name;
12538
12539 if( !sectionNode.assertions.empty() ||
12540 !sectionNode.stdOut.empty() ||
12541 !sectionNode.stdErr.empty() ) {
12542 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
12543 if( className.empty() ) {
12544 xml.writeAttribute( "classname", name );
12545 xml.writeAttribute( "name", "root" );
12546 }
12547 else {
12548 xml.writeAttribute( "classname", className );
12549 xml.writeAttribute( "name", name );
12550 }
12551 xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) );
12552
12553 writeAssertions( sectionNode );
12554
12555 if( !sectionNode.stdOut.empty() )
12556 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
12557 if( !sectionNode.stdErr.empty() )
12558 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
12559 }
12560 for( auto const& childNode : sectionNode.childSections )
12561 if( className.empty() )
12562 writeSection( name, "", *childNode );
12563 else
12564 writeSection( className, name, *childNode );
12565 }
12566
12567 void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {
12568 for( auto const& assertion : sectionNode.assertions )
12569 writeAssertion( assertion );
12570 }
12571
12572 void JunitReporter::writeAssertion( AssertionStats const& stats ) {
12573 AssertionResult const& result = stats.assertionResult;
12574 if( !result.isOk() ) {
12575 std::string elementName;
12576 switch( result.getResultType() ) {
12579 elementName = "error";
12580 break;
12582 elementName = "failure";
12583 break;
12585 elementName = "failure";
12586 break;
12588 elementName = "failure";
12589 break;
12590
12591 // We should never see these here:
12592 case ResultWas::Info:
12593 case ResultWas::Warning:
12594 case ResultWas::Ok:
12595 case ResultWas::Unknown:
12598 elementName = "internalError";
12599 break;
12600 }
12601
12602 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
12603
12604 xml.writeAttribute( "message", result.getExpandedExpression() );
12605 xml.writeAttribute( "type", result.getTestMacroName() );
12606
12607 ReusableStringStream rss;
12608 if( !result.getMessage().empty() )
12609 rss << result.getMessage() << '\n';
12610 for( auto const& msg : stats.infoMessages )
12611 if( msg.type == ResultWas::Info )
12612 rss << msg.message << '\n';
12613
12614 rss << "at " << result.getSourceInfo();
12615 xml.writeText( rss.str(), false );
12616 }
12617 }
12618
12619 CATCH_REGISTER_REPORTER( "junit", JunitReporter )
12620
12621} // end namespace Catch
12622// end catch_reporter_junit.cpp
12623// start catch_reporter_listening.cpp
12624
12625#include <cassert>
12626
12627namespace Catch {
12628
12629 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
12630 m_listeners.push_back( std::move( listener ) );
12631 }
12632
12633 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
12634 assert(!m_reporter && "Listening reporter can wrap only 1 real reporter");
12635 m_reporter = std::move( reporter );
12636 }
12637
12638 ReporterPreferences ListeningReporter::getPreferences() const {
12639 return m_reporter->getPreferences();
12640 }
12641
12642 std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {
12643 return std::set<Verbosity>{ };
12644 }
12645
12646 void ListeningReporter::noMatchingTestCases( std::string const& spec ) {
12647 for ( auto const& listener : m_listeners ) {
12648 listener->noMatchingTestCases( spec );
12649 }
12650 m_reporter->noMatchingTestCases( spec );
12651 }
12652
12653 void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {
12654 for ( auto const& listener : m_listeners ) {
12655 listener->benchmarkStarting( benchmarkInfo );
12656 }
12657 m_reporter->benchmarkStarting( benchmarkInfo );
12658 }
12659 void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) {
12660 for ( auto const& listener : m_listeners ) {
12661 listener->benchmarkEnded( benchmarkStats );
12662 }
12663 m_reporter->benchmarkEnded( benchmarkStats );
12664 }
12665
12666 void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) {
12667 for ( auto const& listener : m_listeners ) {
12668 listener->testRunStarting( testRunInfo );
12669 }
12670 m_reporter->testRunStarting( testRunInfo );
12671 }
12672
12673 void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) {
12674 for ( auto const& listener : m_listeners ) {
12675 listener->testGroupStarting( groupInfo );
12676 }
12677 m_reporter->testGroupStarting( groupInfo );
12678 }
12679
12680 void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
12681 for ( auto const& listener : m_listeners ) {
12682 listener->testCaseStarting( testInfo );
12683 }
12684 m_reporter->testCaseStarting( testInfo );
12685 }
12686
12687 void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) {
12688 for ( auto const& listener : m_listeners ) {
12689 listener->sectionStarting( sectionInfo );
12690 }
12691 m_reporter->sectionStarting( sectionInfo );
12692 }
12693
12694 void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) {
12695 for ( auto const& listener : m_listeners ) {
12696 listener->assertionStarting( assertionInfo );
12697 }
12698 m_reporter->assertionStarting( assertionInfo );
12699 }
12700
12701 // The return value indicates if the messages buffer should be cleared:
12702 bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) {
12703 for( auto const& listener : m_listeners ) {
12704 static_cast<void>( listener->assertionEnded( assertionStats ) );
12705 }
12706 return m_reporter->assertionEnded( assertionStats );
12707 }
12708
12709 void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) {
12710 for ( auto const& listener : m_listeners ) {
12711 listener->sectionEnded( sectionStats );
12712 }
12713 m_reporter->sectionEnded( sectionStats );
12714 }
12715
12716 void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
12717 for ( auto const& listener : m_listeners ) {
12718 listener->testCaseEnded( testCaseStats );
12719 }
12720 m_reporter->testCaseEnded( testCaseStats );
12721 }
12722
12723 void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
12724 for ( auto const& listener : m_listeners ) {
12725 listener->testGroupEnded( testGroupStats );
12726 }
12727 m_reporter->testGroupEnded( testGroupStats );
12728 }
12729
12730 void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) {
12731 for ( auto const& listener : m_listeners ) {
12732 listener->testRunEnded( testRunStats );
12733 }
12734 m_reporter->testRunEnded( testRunStats );
12735 }
12736
12737 void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) {
12738 for ( auto const& listener : m_listeners ) {
12739 listener->skipTest( testInfo );
12740 }
12741 m_reporter->skipTest( testInfo );
12742 }
12743
12744 bool ListeningReporter::isMulti() const {
12745 return true;
12746 }
12747
12748} // end namespace Catch
12749// end catch_reporter_listening.cpp
12750// start catch_reporter_xml.cpp
12751
12752#if defined(_MSC_VER)
12753#pragma warning(push)
12754#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch
12755 // Note that 4062 (not all labels are handled
12756 // and default is missing) is enabled
12757#endif
12758
12759namespace Catch {
12760 XmlReporter::XmlReporter( ReporterConfig const& _config )
12761 : StreamingReporterBase( _config ),
12762 m_xml(_config.stream())
12763 {
12764 m_reporterPrefs.shouldRedirectStdOut = true;
12765 }
12766
12767 XmlReporter::~XmlReporter() = default;
12768
12769 std::string XmlReporter::getDescription() {
12770 return "Reports test results as an XML document";
12771 }
12772
12773 std::string XmlReporter::getStylesheetRef() const {
12774 return std::string();
12775 }
12776
12777 void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) {
12778 m_xml
12779 .writeAttribute( "filename", sourceInfo.file )
12780 .writeAttribute( "line", sourceInfo.line );
12781 }
12782
12783 void XmlReporter::noMatchingTestCases( std::string const& s ) {
12784 StreamingReporterBase::noMatchingTestCases( s );
12785 }
12786
12787 void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) {
12788 StreamingReporterBase::testRunStarting( testInfo );
12789 std::string stylesheetRef = getStylesheetRef();
12790 if( !stylesheetRef.empty() )
12791 m_xml.writeStylesheetRef( stylesheetRef );
12792 m_xml.startElement( "Catch" );
12793 if( !m_config->name().empty() )
12794 m_xml.writeAttribute( "name", m_config->name() );
12795 }
12796
12797 void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) {
12798 StreamingReporterBase::testGroupStarting( groupInfo );
12799 m_xml.startElement( "Group" )
12800 .writeAttribute( "name", groupInfo.name );
12801 }
12802
12803 void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {
12804 StreamingReporterBase::testCaseStarting(testInfo);
12805 m_xml.startElement( "TestCase" )
12806 .writeAttribute( "name", trim( testInfo.name ) )
12807 .writeAttribute( "description", testInfo.description )
12808 .writeAttribute( "tags", testInfo.tagsAsString() );
12809
12810 writeSourceInfo( testInfo.lineInfo );
12811
12812 if ( m_config->showDurations() == ShowDurations::Always )
12813 m_testCaseTimer.start();
12814 m_xml.ensureTagClosed();
12815 }
12816
12817 void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) {
12818 StreamingReporterBase::sectionStarting( sectionInfo );
12819 if( m_sectionDepth++ > 0 ) {
12820 m_xml.startElement( "Section" )
12821 .writeAttribute( "name", trim( sectionInfo.name ) )
12822 .writeAttribute( "description", sectionInfo.description );
12823 writeSourceInfo( sectionInfo.lineInfo );
12824 m_xml.ensureTagClosed();
12825 }
12826 }
12827
12828 void XmlReporter::assertionStarting( AssertionInfo const& ) { }
12829
12830 bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {
12831
12832 AssertionResult const& result = assertionStats.assertionResult;
12833
12834 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
12835
12836 if( includeResults || result.getResultType() == ResultWas::Warning ) {
12837 // Print any info messages in <Info> tags.
12838 for( auto const& msg : assertionStats.infoMessages ) {
12839 if( msg.type == ResultWas::Info && includeResults ) {
12840 m_xml.scopedElement( "Info" )
12841 .writeText( msg.message );
12842 } else if ( msg.type == ResultWas::Warning ) {
12843 m_xml.scopedElement( "Warning" )
12844 .writeText( msg.message );
12845 }
12846 }
12847 }
12848
12849 // Drop out if result was successful but we're not printing them.
12850 if( !includeResults && result.getResultType() != ResultWas::Warning )
12851 return true;
12852
12853 // Print the expression if there is one.
12854 if( result.hasExpression() ) {
12855 m_xml.startElement( "Expression" )
12856 .writeAttribute( "success", result.succeeded() )
12857 .writeAttribute( "type", result.getTestMacroName() );
12858
12859 writeSourceInfo( result.getSourceInfo() );
12860
12861 m_xml.scopedElement( "Original" )
12862 .writeText( result.getExpression() );
12863 m_xml.scopedElement( "Expanded" )
12864 .writeText( result.getExpandedExpression() );
12865 }
12866
12867 // And... Print a result applicable to each result type.
12868 switch( result.getResultType() ) {
12870 m_xml.startElement( "Exception" );
12871 writeSourceInfo( result.getSourceInfo() );
12872 m_xml.writeText( result.getMessage() );
12873 m_xml.endElement();
12874 break;
12876 m_xml.startElement( "FatalErrorCondition" );
12877 writeSourceInfo( result.getSourceInfo() );
12878 m_xml.writeText( result.getMessage() );
12879 m_xml.endElement();
12880 break;
12881 case ResultWas::Info:
12882 m_xml.scopedElement( "Info" )
12883 .writeText( result.getMessage() );
12884 break;
12885 case ResultWas::Warning:
12886 // Warning will already have been written
12887 break;
12889 m_xml.startElement( "Failure" );
12890 writeSourceInfo( result.getSourceInfo() );
12891 m_xml.writeText( result.getMessage() );
12892 m_xml.endElement();
12893 break;
12894 default:
12895 break;
12896 }
12897
12898 if( result.hasExpression() )
12899 m_xml.endElement();
12900
12901 return true;
12902 }
12903
12904 void XmlReporter::sectionEnded( SectionStats const& sectionStats ) {
12905 StreamingReporterBase::sectionEnded( sectionStats );
12906 if( --m_sectionDepth > 0 ) {
12907 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
12908 e.writeAttribute( "successes", sectionStats.assertions.passed );
12909 e.writeAttribute( "failures", sectionStats.assertions.failed );
12910 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
12911
12912 if ( m_config->showDurations() == ShowDurations::Always )
12913 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
12914
12915 m_xml.endElement();
12916 }
12917 }
12918
12919 void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {
12920 StreamingReporterBase::testCaseEnded( testCaseStats );
12921 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
12922 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
12923
12924 if ( m_config->showDurations() == ShowDurations::Always )
12925 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
12926
12927 if( !testCaseStats.stdOut.empty() )
12928 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
12929 if( !testCaseStats.stdErr.empty() )
12930 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
12931
12932 m_xml.endElement();
12933 }
12934
12935 void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {
12936 StreamingReporterBase::testGroupEnded( testGroupStats );
12937 // TODO: Check testGroupStats.aborting and act accordingly.
12938 m_xml.scopedElement( "OverallResults" )
12939 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
12940 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
12941 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
12942 m_xml.endElement();
12943 }
12944
12945 void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) {
12946 StreamingReporterBase::testRunEnded( testRunStats );
12947 m_xml.scopedElement( "OverallResults" )
12948 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
12949 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
12950 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
12951 m_xml.endElement();
12952 }
12953
12954 CATCH_REGISTER_REPORTER( "xml", XmlReporter )
12955
12956} // end namespace Catch
12957
12958#if defined(_MSC_VER)
12959#pragma warning(pop)
12960#endif
12961// end catch_reporter_xml.cpp
12962
12963namespace Catch {
12964 LeakDetector leakDetector;
12965}
12966
12967#ifdef __clang__
12968#pragma clang diagnostic pop
12969#endif
12970
12971// end catch_impl.hpp
12972#endif
12973
12974#ifdef CATCH_CONFIG_MAIN
12975// start catch_default_main.hpp
12976
12977#ifndef __OBJC__
12978
12979#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
12980// Standard C/C++ Win32 Unicode wmain entry point
12981extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
12982#else
12983// Standard C/C++ main entry point
12984int main (int argc, char * argv[]) {
12985#endif
12986
12987 return Catch::Session().run( argc, argv );
12988}
12989
12990#else // __OBJC__
12991
12992// Objective-C entry point
12993int main (int argc, char * const argv[]) {
12994#if !CATCH_ARC_ENABLED
12995 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
12996#endif
12997
12998 Catch::registerTestMethods();
12999 int result = Catch::Session().run( argc, (char**)argv );
13000
13001#if !CATCH_ARC_ENABLED
13002 [pool drain];
13003#endif
13004
13005 return result;
13006}
13007
13008#endif // __OBJC__
13009
13010// end catch_default_main.hpp
13011#endif
13012
13013#if !defined(CATCH_CONFIG_IMPL_ONLY)
13014
13015#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
13016# undef CLARA_CONFIG_MAIN
13017#endif
13018
13019#if !defined(CATCH_CONFIG_DISABLE)
13021// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
13022#ifdef CATCH_CONFIG_PREFIX_ALL
13023
13024#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
13025#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
13026
13027#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ )
13028#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
13029#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
13030#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13031#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
13032#endif// CATCH_CONFIG_DISABLE_MATCHERS
13033#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
13034
13035#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13036#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
13037#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13038#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13039#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
13040
13041#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ )
13042#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
13043#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
13044#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13045#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
13046#endif // CATCH_CONFIG_DISABLE_MATCHERS
13047#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13048
13049#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13050#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
13051
13052#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
13053#endif // CATCH_CONFIG_DISABLE_MATCHERS
13054
13055#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
13056#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
13057#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
13058
13059#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
13060#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
13061#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
13062#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
13063#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
13064#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
13065#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13066#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13067
13068#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
13069
13070// "BDD-style" convenience wrappers
13071#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
13072#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
13073#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc )
13074#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc )
13075#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
13076#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc )
13077#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc )
13078
13079// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
13080#else
13081
13082#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
13083#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
13084
13085#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
13086#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
13087#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
13088#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13089#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
13090#endif // CATCH_CONFIG_DISABLE_MATCHERS
13091#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
13092
13093#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13094#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
13095#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13096#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13097#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
13098
13099#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13100#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
13101#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
13102#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13103#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
13104#endif // CATCH_CONFIG_DISABLE_MATCHERS
13105#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13106
13107#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13108#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
13109
13110#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
13111#endif // CATCH_CONFIG_DISABLE_MATCHERS
13112
13113#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
13114#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
13115#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) )
13116
13117#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
13118#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
13119#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
13120#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
13121#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
13122#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
13123#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13124#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
13125#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
13126
13127#endif
13128
13129#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
13130
13131// "BDD-style" convenience wrappers
13132#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
13133#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
13134
13135#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc )
13136#define WHEN( desc ) SECTION( std::string(" When: ") + desc )
13137#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc )
13138#define THEN( desc ) SECTION( std::string(" Then: ") + desc )
13139#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc )
13140
13142
13143#else
13145// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
13146#ifdef CATCH_CONFIG_PREFIX_ALL
13147
13148#define CATCH_REQUIRE( ... ) (void)(0)
13149#define CATCH_REQUIRE_FALSE( ... ) (void)(0)
13150
13151#define CATCH_REQUIRE_THROWS( ... ) (void)(0)
13152#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
13153#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
13154#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13155#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
13156#endif// CATCH_CONFIG_DISABLE_MATCHERS
13157#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
13158
13159#define CATCH_CHECK( ... ) (void)(0)
13160#define CATCH_CHECK_FALSE( ... ) (void)(0)
13161#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__)
13162#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
13163#define CATCH_CHECK_NOFAIL( ... ) (void)(0)
13164
13165#define CATCH_CHECK_THROWS( ... ) (void)(0)
13166#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
13167#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0)
13168#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13169#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
13170#endif // CATCH_CONFIG_DISABLE_MATCHERS
13171#define CATCH_CHECK_NOTHROW( ... ) (void)(0)
13172
13173#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13174#define CATCH_CHECK_THAT( arg, matcher ) (void)(0)
13175
13176#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
13177#endif // CATCH_CONFIG_DISABLE_MATCHERS
13178
13179#define CATCH_INFO( msg ) (void)(0)
13180#define CATCH_WARN( msg ) (void)(0)
13181#define CATCH_CAPTURE( msg ) (void)(0)
13182
13183#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13184#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13185#define CATCH_METHOD_AS_TEST_CASE( method, ... )
13186#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
13187#define CATCH_SECTION( ... )
13188#define CATCH_FAIL( ... ) (void)(0)
13189#define CATCH_FAIL_CHECK( ... ) (void)(0)
13190#define CATCH_SUCCEED( ... ) (void)(0)
13191
13192#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13193
13194// "BDD-style" convenience wrappers
13195#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13196#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 )
13197#define CATCH_GIVEN( desc )
13198#define CATCH_WHEN( desc )
13199#define CATCH_AND_WHEN( desc )
13200#define CATCH_THEN( desc )
13201#define CATCH_AND_THEN( desc )
13202
13203// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
13204#else
13205
13206#define REQUIRE( ... ) (void)(0)
13207#define REQUIRE_FALSE( ... ) (void)(0)
13208
13209#define REQUIRE_THROWS( ... ) (void)(0)
13210#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
13211#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
13212#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13213#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
13214#endif // CATCH_CONFIG_DISABLE_MATCHERS
13215#define REQUIRE_NOTHROW( ... ) (void)(0)
13216
13217#define CHECK( ... ) (void)(0)
13218#define CHECK_FALSE( ... ) (void)(0)
13219#define CHECKED_IF( ... ) if (__VA_ARGS__)
13220#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
13221#define CHECK_NOFAIL( ... ) (void)(0)
13222
13223#define CHECK_THROWS( ... ) (void)(0)
13224#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
13225#define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
13226#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13227#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
13228#endif // CATCH_CONFIG_DISABLE_MATCHERS
13229#define CHECK_NOTHROW( ... ) (void)(0)
13230
13231#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
13232#define CHECK_THAT( arg, matcher ) (void)(0)
13233
13234#define REQUIRE_THAT( arg, matcher ) (void)(0)
13235#endif // CATCH_CONFIG_DISABLE_MATCHERS
13236
13237#define INFO( msg ) (void)(0)
13238#define WARN( msg ) (void)(0)
13239#define CAPTURE( msg ) (void)(0)
13240
13241#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13242#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13243#define METHOD_AS_TEST_CASE( method, ... )
13244#define REGISTER_TEST_CASE( Function, ... ) (void)(0)
13245#define SECTION( ... )
13246#define FAIL( ... ) (void)(0)
13247#define FAIL_CHECK( ... ) (void)(0)
13248#define SUCCEED( ... ) (void)(0)
13249#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
13250
13251#endif
13252
13253#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
13254
13255// "BDD-style" convenience wrappers
13256#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )
13257#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
13258
13259#define GIVEN( desc )
13260#define WHEN( desc )
13261#define AND_WHEN( desc )
13262#define THEN( desc )
13263#define AND_THEN( desc )
13264
13266
13267#endif
13268
13269#endif // ! CATCH_CONFIG_IMPL_ONLY
13270
13271// start catch_reenable_warnings.h
13272
13273
13274#ifdef __clang__
13275# ifdef __ICC // icpc defines the __clang__ macro
13276# pragma warning(pop)
13277# else
13278# pragma clang diagnostic pop
13279# endif
13280#elif defined __GNUC__
13281# pragma GCC diagnostic pop
13282#endif
13283
13284// end catch_reenable_warnings.h
13285// end catch.hpp
13286#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
13287
const char *const const double number
Definition: cJSON.h:262
char const int length
Definition: cJSON.h:161
const cJSON *const b
Definition: cJSON.h:251
const char *const name
Definition: cJSON.h:258
int index
Definition: cJSON.h:168
int which
Definition: cJSON.h:230
int cJSON_bool fmt
Definition: cJSON.h:158
cJSON * item
Definition: cJSON.h:218
int count
Definition: cJSON.h:212
const char *const string
Definition: cJSON.h:170
char * buffer
Definition: cJSON.h:161
std::ostream & operator<<(std::ostream &, Catch_global_namespace_dummy)
#define CATCH_INTERNAL_LINEINFO
Definition: catch.hpp:324
Definition: catch.hpp:1574
auto allowThrows() const -> bool
~AssertionHandler()
Definition: catch.hpp:1586
void handleExpr(ExprLhs< T > const &expr)
Definition: catch.hpp:1593
void handleExceptionNotThrownAsExpected()
AssertionHandler(StringRef macroName, SourceLineInfo const &lineInfo, StringRef capturedExpression, ResultDisposition::Flags resultDisposition)
void handleUnexpectedExceptionNotThrown()
void handleUnexpectedInflightException()
void handleExceptionThrownAsExpected()
void handleMessage(ResultWas::OfType resultType, StringRef const &message)
void handleExpr(ITransientExpression const &expr)
Definition: catch.hpp:1928
void increment()
Definition: catch.hpp:1953
auto needsMoreIterations() -> bool
BenchmarkLooper(StringRef name)
Definition: catch.hpp:1939
Definition: catch.hpp:1348
BinaryExpr(bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs)
Definition: catch.hpp:1359
Definition: catch.hpp:2096
Approx(double value)
Approx & epsilon(T const &newEpsilon)
Definition: catch.hpp:2160
Approx & margin(T const &newMargin)
Definition: catch.hpp:2173
Approx & scale(T const &newScale)
Definition: catch.hpp:2187
std::string toString() const
static Approx custom()
Approx(T const &value)
Definition: catch.hpp:2115
Approx operator()(T const &value)
Definition: catch.hpp:2106
Definition: catch.hpp:778
static const bool value
Definition: catch.hpp:787
Definition: catch.hpp:2043
ExceptionTranslatorRegistrar(std::string(*translateFunction)(T &))
Definition: catch.hpp:2070
Definition: catch.hpp:1406
auto operator!=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1420
auto operator>=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1436
auto operator>(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1428
auto operator<=(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1440
auto makeUnaryExpr() const -> UnaryExpr< LhsT >
Definition: catch.hpp:1444
ExprLhs(LhsT lhs)
Definition: catch.hpp:1409
auto operator==(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1412
auto operator<(RhsT const &rhs) -> BinaryExpr< LhsT, RhsT const & > const
Definition: catch.hpp:1432
Definition: catch.hpp:1552
LazyExpression & operator=(LazyExpression const &)=delete
LazyExpression(bool isNegated)
friend struct AssertionStats
Definition: catch.hpp:1554
friend auto operator<<(std::ostream &os, LazyExpression const &lazyExpr) -> std::ostream &
LazyExpression(LazyExpression const &other)
friend class RunContext
Definition: catch.hpp:1555
Definition: catch.hpp:2724
MatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef matcherString)
Definition: catch.hpp:2729
void streamReconstructedExpression(std::ostream &os) const override
Definition: catch.hpp:2736
bool match(T const &item) const override
Definition: catch.hpp:2455
PredicateMatcher(std::function< bool(T const &)> const &elem, std::string const &descr)
Definition: catch.hpp:2450
std::string describe() const override
Definition: catch.hpp:2459
virtual std::string describe() const =0
std::string m_cachedToString
Definition: catch.hpp:2264
MatcherUntypedBase(MatcherUntypedBase const &)=default
Definition: catch.hpp:277
virtual ~NonCopyable()
Definition: catch.hpp:685
auto str() const -> std::string
auto get() -> std::ostream &
Definition: catch.hpp:699
Definition: catch.hpp:1666
ScopedMessage(MessageBuilder const &builder)
MessageInfo m_info
Definition: catch.hpp:1671
Definition: catch.hpp:1898
Section(SectionInfo const &info)
Definition: catch.hpp:393
std::size_t size_type
Definition: catch.hpp:395
auto operator=(StringRef const &other) noexcept -> StringRef &
Definition: catch.hpp:443
auto c_str() const -> char const *
auto substr(size_type start, size_type size) const noexcept -> StringRef
StringRef(StringRef const &other) noexcept
Definition: catch.hpp:414
StringRef(char const *rawChars, size_type size) noexcept
Definition: catch.hpp:429
~StringRef() noexcept
Definition: catch.hpp:439
StringRef(StringRef &&other) noexcept
Definition: catch.hpp:419
friend struct StringRefTestAccess
Definition: catch.hpp:398
auto operator[](size_type index) const noexcept -> char
auto numberOfCharacters() const noexcept -> size_type
StringRef(std::string const &stdString) noexcept
Definition: catch.hpp:434
void swap(StringRef &other) noexcept
StringRef() noexcept
Definition: catch.hpp:410
auto operator!=(StringRef const &other) const noexcept -> bool
auto operator==(StringRef const &other) const noexcept -> bool
auto empty() const noexcept -> bool
Definition: catch.hpp:462
auto size() const noexcept -> size_type
Definition: catch.hpp:465
StringRef(char const *rawChars) noexcept
auto currentData() const noexcept -> char const *
Definition: catch.hpp:2842
bool operator<(TestCase const &other) const
TestCase withName(std::string const &_newName) const
void invoke() const
bool operator==(TestCase const &other) const
TestCaseInfo const & getTestCaseInfo() const
TestCase(ITestInvoker *testCase, TestCaseInfo &&info)
Definition: catch.hpp:501
TestInvokerAsMethod(void(C::*testAsMethod)()) noexcept
Definition: catch.hpp:504
void invoke() const override
Definition: catch.hpp:506
Definition: catch.hpp:1881
auto getElapsedSeconds() const -> double
auto getElapsedNanoseconds() const -> uint64_t
Definition: catch.hpp:1368
UnaryExpr(LhsT lhs)
Definition: catch.hpp:1376
#define true
Definition: msvc_stdbool.h:18
#define false
Definition: msvc_stdbool.h:19
char bool
Definition: msvc_stdbool.h:17
std::string convertUnknownEnumToString(E e)
Definition: catch.hpp:863
std::string rawMemoryToString(const T &object)
Definition: catch.hpp:773
const std::string unprintableString
std::string rangeToString(InputIterator first, InputIterator last)
Definition: catch.hpp:1021
std::enable_if<!std::is_enum< T >::value &&!std::is_base_of< std::exception, T >::value, std::string >::type convertUnstreamable(T const &)
Definition: catch.hpp:796
std::string rawMemoryToString(const void *object, std::size_t size)
std::string stringify(const T &e)
Definition: catch.hpp:858
std::string finalizeDescription(const std::string &desc)
bool contains(InputIterator first, InputIterator last, T const &item)
Definition: catch.hpp:2568
Floating::WithinAbsMatcher WithinAbs(double target, double margin)
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
Definition: catch.hpp:2471
StdString::RegexMatcher Matches(std::string const &regex, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Vector::EqualsMatcher< T > Equals(std::vector< T > const &comparator)
Definition: catch.hpp:2708
Vector::ContainsElementMatcher< T > VectorContains(T const &comparator)
Definition: catch.hpp:2703
Vector::ContainsMatcher< T > Contains(std::vector< T > const &comparator)
Definition: catch.hpp:2698
StdString::StartsWithMatcher StartsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff)
Vector::UnorderedEqualsMatcher< T > UnorderedEquals(std::vector< T > const &target)
Definition: catch.hpp:2713
StdString::EndsWithMatcher EndsWith(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
StdString::EqualsMatcher Equals(std::string const &str, CaseSensitive::Choice caseSensitivity=CaseSensitive::Yes)
Definition: catch.hpp:90
std::ostream & cout()
T const & operator+(T const &value, StreamEndStop)
Definition: catch.hpp:319
void toLowerInPlace(std::string &s)
std::string trim(std::string const &str)
auto makeMatchExpr(ArgT const &arg, MatcherT const &matcher, StringRef matcherString) -> MatchExpr< ArgT, MatcherT >
Definition: catch.hpp:2751
void cleanUp()
std::vector< TestCase > filterTests(std::vector< TestCase > const &testCases, TestSpec const &testSpec, IConfig const &config)
std::ostream & clog()
void formatReconstructedExpression(std::ostream &os, std::string const &lhs, StringRef op, std::string const &rhs)
bool isOk(ResultWas::OfType resultType)
void handleExceptionMatchExpr(AssertionHandler &handler, std::string const &str, StringRef matcherString)
bool isJustInfo(int flags)
std::ostream & cerr()
IMutableRegistryHub & getMutableRegistryHub()
TestCase makeTestCase(ITestInvoker *testCase, std::string const &className, NameAndTags const &nameAndTags, SourceLineInfo const &lineInfo)
auto operator+=(std::string &lhs, StringRef const &sr) -> std::string &
void handleExpression(ITransientExpression const &expr)
bool startsWith(std::string const &s, std::string const &prefix)
IRegistryHub & getRegistryHub()
not_this_one end(...)
auto operator+(char const *lhs, StringRef const &rhs) -> std::string
std::vector< std::unique_ptr< IExceptionTranslator const > > ExceptionTranslators
Definition: catch.hpp:2030
bool shouldContinueOnFailure(int flags)
auto compareNotEqual(LhsT const &lhs, RhsT &&rhs) -> bool
Definition: catch.hpp:1395
std::ostream & operator<<(std::ostream &os, SourceLineInfo const &info)
bool isFalseTest(int flags)
Definition: catch.hpp:633
std::vector< TestCase > const & getAllTestCasesSorted(IConfig const &config)
auto getCurrentNanosecondsSinceEpoch() -> uint64_t
bool contains(std::string const &s, std::string const &infix)
bool matchTest(TestCase const &testCase, TestSpec const &testSpec, IConfig const &config)
ResultDisposition::Flags operator|(ResultDisposition::Flags lhs, ResultDisposition::Flags rhs)
auto makeTestInvoker(void(*testAsFunction)()) noexcept -> ITestInvoker *
bool shouldSuppressFailure(int flags)
Matchers::Impl::MatcherBase< std::string > StringMatcher
Definition: catch.hpp:2746
std::string toLower(std::string const &s)
not_this_one begin(...)
auto getEstimatedClockResolution() -> uint64_t
unsigned int rngSeed()
std::shared_ptr< IReporterFactory > IReporterFactoryPtr
Definition: catch.hpp:1985
bool endsWith(std::string const &s, std::string const &suffix)
std::string translateActiveException()
std::string rangeToString(std::vector< bool, Allocator > const &v)
Definition: catch.hpp:1161
std::string(*)() exceptionTranslateFunction
Definition: catch.hpp:2027
std::string rangeToString(Range const &range)
Definition: catch.hpp:1155
auto makeStream(StringRef const &filename) -> IStream const *
IResultCapture & getResultCapture()
auto compareEqual(LhsT const &lhs, RhsT const &rhs) -> bool
Definition: catch.hpp:1384
std::shared_ptr< ITestInvoker > ITestCasePtr
Definition: catch.hpp:358
bool replaceInPlace(std::string &str, std::string const &replaceThis, std::string const &withThis)
const std::string none
Definition: LogUtil.hpp:48
const int64_t Error
Definition: LogUtil.hpp:36
const int64_t Warning
Definition: LogUtil.hpp:35
function get(const std::string &func, double alpha, double beta)
std::function< double(double, double)> function
Definition: Operate.hpp:28
time_point now()
std::time_t to_time_t(const time_point &tp)
constexpr const double micro
Definition: custom-opm-common/opm-common/opm/parser/eclipse/Units/Units.hpp:60
constexpr const double milli
Definition: custom-opm-common/opm-common/opm/parser/eclipse/Units/Units.hpp:61
constexpr const double second
Definition: custom-opm-common/opm-common/opm/parser/eclipse/Units/Units.hpp:104
bool operator==(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
UDQScalar operator-(const UDQScalar &lhs, const UDQScalar &rhs)
std::chrono::time_point< std::chrono::system_clock, std::chrono::duration< int64_t, std::ratio< 1, 1000 > > > time_point
Definition: TimeService.hpp:31
bool operator<(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
bool operator<=(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
Definition: SummaryConfig.hpp:101
UDQScalar operator*(const UDQScalar &lhs, const UDQScalar &rhs)
TokenType
Definition: ActionValue.hpp:7
@ end
Definition: ActionValue.hpp:20
bool operator>=(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
Definition: SummaryConfig.hpp:111
bool operator!=(const SummaryConfigNode &lhs, const SummaryConfigNode &rhs)
Definition: SummaryConfig.hpp:96
U & uppercase(const T &src, U &dst)
Definition: String.hpp:13
static const double e
Definition: exprtk.hpp:758
T min(const T v0, const T v1)
Definition: exprtk.hpp:1400
T equal(const T v0, const T v1)
Definition: exprtk.hpp:1414
T max(const T v0, const T v1)
Definition: exprtk.hpp:1407
T value(details::expression_node< T > *n)
Definition: exprtk.hpp:12955
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t t(t+t)") define_sfop3(16
x y t t *t x y t t t x y t t t x *y t *t t x *y t *t t x y t t t x y t t t x(y+z)
static const char * version
Definition: exprtk.hpp:40016
static std::string data()
Definition: exprtk.hpp:40022
FloatingPoint< float > Float
Definition: gtest.h:6756
FloatingPoint< double > Double
Definition: gtest.h:6757
internal::ParamGenerator< T > Range(T start, T end, IncrementT step)
Definition: gtest.h:11204
Definition: catch.hpp:642
SourceLineInfo lineInfo
Definition: catch.hpp:644
ResultDisposition::Flags resultDisposition
Definition: catch.hpp:646
StringRef macroName
Definition: catch.hpp:643
StringRef capturedExpression
Definition: catch.hpp:645
Definition: catch.hpp:1569
bool shouldThrow
Definition: catch.hpp:1571
bool shouldDebugBreak
Definition: catch.hpp:1570
Definition: catch.hpp:525
AutoReg(ITestInvoker *invoker, SourceLineInfo const &lineInfo, StringRef const &classOrMethod, NameAndTags const &nameAndTags) noexcept
Definition: catch.hpp:272
Choice
Definition: catch.hpp:272
@ No
Definition: catch.hpp:274
@ Yes
Definition: catch.hpp:273
Definition: catch.hpp:1819
Counts & operator+=(Counts const &other)
std::size_t failed
Definition: catch.hpp:1828
bool allOk() const
bool allPassed() const
std::size_t total() const
Counts operator-(Counts const &other) const
std::size_t failedButOk
Definition: catch.hpp:1829
std::size_t passed
Definition: catch.hpp:1827
Definition: catch.hpp:1456
auto operator<=(T const &lhs) -> ExprLhs< T const & >
Definition: catch.hpp:1458
Definition: catch.hpp:2032
virtual std::string translate(ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd) const =0
Definition: catch.hpp:2037
virtual std::string translateActiveException() const =0
Definition: catch.hpp:1999
virtual void registerTest(TestCase const &testInfo)=0
virtual void registerReporter(std::string const &name, IReporterFactoryPtr const &factory)=0
virtual void registerStartupException() noexcept=0
virtual void registerListener(IReporterFactoryPtr const &factory)=0
virtual void registerTagAlias(std::string const &alias, std::string const &tag, SourceLineInfo const &lineInfo)=0
virtual void registerTranslator(const IExceptionTranslator *translator)=0
Definition: catch.hpp:1987
virtual ~IRegistryHub()
virtual ITestCaseRegistry const & getTestCaseRegistry() const =0
virtual ITagAliasRegistry const & getTagAliasRegistry() const =0
virtual StartupExceptionRegistry const & getStartupExceptionRegistry() const =0
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry()=0
virtual IReporterRegistry const & getReporterRegistry() const =0
Definition: catch.hpp:1492
virtual void handleMessage(AssertionInfo const &info, ResultWas::OfType resultType, StringRef const &message, AssertionReaction &reaction)=0
virtual void benchmarkStarting(BenchmarkInfo const &info)=0
virtual const AssertionResult * getLastResult() const =0
virtual void popScopedMessage(MessageInfo const &message)=0
virtual void handleFatalErrorCondition(StringRef message)=0
virtual void sectionEnded(SectionEndInfo const &endInfo)=0
virtual void handleExpr(AssertionInfo const &info, ITransientExpression const &expr, AssertionReaction &reaction)=0
virtual bool sectionStarted(SectionInfo const &sectionInfo, Counts &assertions)=0
virtual void handleUnexpectedExceptionNotThrown(AssertionInfo const &info, AssertionReaction &reaction)=0
virtual void benchmarkEnded(BenchmarkStats const &stats)=0
virtual void handleIncomplete(AssertionInfo const &info)=0
virtual void pushScopedMessage(MessageInfo const &message)=0
virtual bool lastAssertionPassed()=0
virtual void assertionPassed()=0
virtual void handleNonExpr(AssertionInfo const &info, ResultWas::OfType resultType, AssertionReaction &reaction)=0
virtual void exceptionEarlyReported()=0
virtual std::string getCurrentTestName() const =0
virtual void handleUnexpectedInflightException(AssertionInfo const &info, std::string const &message, AssertionReaction &reaction)=0
virtual void sectionEndedEarly(SectionEndInfo const &endInfo)=0
Definition: catch.hpp:2875
virtual bool aborting() const =0
virtual ~IRunner()
Definition: catch.hpp:678
virtual ~IStream()
virtual std::ostream & stream() const =0
Definition: catch.hpp:363
virtual std::vector< TestCase > const & getAllTestsSorted(IConfig const &config) const =0
virtual std::vector< TestCase > const & getAllTests() const =0
Definition: catch.hpp:353
virtual ~ITestInvoker()
virtual void invoke() const =0
Definition: catch.hpp:1326
auto getResult() const -> bool
Definition: catch.hpp:1328
auto isBinaryExpression() const -> bool
Definition: catch.hpp:1327
bool m_result
Definition: catch.hpp:1341
bool m_isBinaryExpression
Definition: catch.hpp:1340
virtual void streamReconstructedExpression(std::ostream &os) const =0
ITransientExpression(bool isBinaryExpression, bool result)
Definition: catch.hpp:1331
std::string describe() const override
WithinAbsMatcher(double target, double margin)
bool match(double const &matchee) const override
WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType)
bool match(double const &matchee) const override
std::string describe() const override
Definition: catch.hpp:2285
std::vector< MatcherBase< ArgT > const * > m_matchers
Definition: catch.hpp:2314
std::string describe() const override
Definition: catch.hpp:2293
bool match(ArgT const &arg) const override
Definition: catch.hpp:2286
Definition: catch.hpp:2317
std::vector< MatcherBase< ArgT > const * > m_matchers
Definition: catch.hpp:2347
std::string describe() const override
Definition: catch.hpp:2326
bool match(ArgT const &arg) const override
Definition: catch.hpp:2319
Definition: catch.hpp:2351
bool match(ArgT const &arg) const override
Definition: catch.hpp:2355
MatchNotOf(MatcherBase< ArgT > const &underlyingMatcher)
Definition: catch.hpp:2353
std::string describe() const override
Definition: catch.hpp:2359
MatcherBase< ArgT > const & m_underlyingMatcher
Definition: catch.hpp:2362
Definition: catch.hpp:2277
MatchNotOf< T > operator!() const
Definition: catch.hpp:2374
MatchAnyOf< T > operator||(MatcherBase const &other) const
Definition: catch.hpp:2370
MatchAllOf< T > operator&&(MatcherBase const &other) const
Definition: catch.hpp:2366
virtual bool match(PtrT *arg) const =0
Definition: catch.hpp:2268
virtual bool match(ObjectT const &arg) const =0
Definition: catch.hpp:2489
std::string adjustString(std::string const &str) const
CasedString(std::string const &str, CaseSensitive::Choice caseSensitivity)
std::string m_str
Definition: catch.hpp:2495
CaseSensitive::Choice m_caseSensitivity
Definition: catch.hpp:2494
bool match(std::string const &source) const override
ContainsMatcher(CasedString const &comparator)
EndsWithMatcher(CasedString const &comparator)
bool match(std::string const &source) const override
bool match(std::string const &source) const override
EqualsMatcher(CasedString const &comparator)
std::string describe() const override
bool match(std::string const &matchee) const override
RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity)
StartsWithMatcher(CasedString const &comparator)
bool match(std::string const &source) const override
CasedString m_comparator
Definition: catch.hpp:2502
StringMatcherBase(std::string const &operation, CasedString const &comparator)
std::string describe() const override
std::string m_operation
Definition: catch.hpp:2503
ContainsElementMatcher(T const &comparator)
Definition: catch.hpp:2581
bool match(std::vector< T > const &v) const override
Definition: catch.hpp:2583
T const & m_comparator
Definition: catch.hpp:2596
std::string describe() const override
Definition: catch.hpp:2592
std::vector< T > const & m_comparator
Definition: catch.hpp:2626
std::string describe() const override
Definition: catch.hpp:2622
ContainsMatcher(std::vector< T > const &comparator)
Definition: catch.hpp:2602
bool match(std::vector< T > const &v) const override
Definition: catch.hpp:2604
Definition: catch.hpp:2630
bool match(std::vector< T > const &v) const override
Definition: catch.hpp:2634
std::string describe() const override
Definition: catch.hpp:2646
EqualsMatcher(std::vector< T > const &comparator)
Definition: catch.hpp:2632
std::vector< T > const & m_comparator
Definition: catch.hpp:2649
bool match(std::vector< T > const &vec) const override
Definition: catch.hpp:2655
UnorderedEqualsMatcher(std::vector< T > const &target)
Definition: catch.hpp:2654
std::string describe() const override
Definition: catch.hpp:2685
Definition: catch.hpp:1652
MessageInfo m_info
Definition: catch.hpp:1663
MessageBuilder(std::string const &macroName, SourceLineInfo const &lineInfo, ResultWas::OfType type)
Definition: catch.hpp:1624
std::string macroName
Definition: catch.hpp:1629
MessageInfo(std::string const &_macroName, SourceLineInfo const &_lineInfo, ResultWas::OfType _type)
unsigned int sequence
Definition: catch.hpp:1633
bool operator<(MessageInfo const &other) const
SourceLineInfo lineInfo
Definition: catch.hpp:1631
std::string message
Definition: catch.hpp:1630
ResultWas::OfType type
Definition: catch.hpp:1632
bool operator==(MessageInfo const &other) const
Definition: catch.hpp:1641
ReusableStringStream m_stream
Definition: catch.hpp:1649
Definition: catch.hpp:519
StringRef tags
Definition: catch.hpp:522
StringRef name
Definition: catch.hpp:521
NameAndTags(StringRef const &name_=StringRef(), StringRef const &tags_=StringRef()) noexcept
Definition: catch.hpp:330
RegistrarForTagAliases(char const *alias, char const *tag, SourceLineInfo const &lineInfo)
Definition: catch.hpp:622
Flags
Definition: catch.hpp:622
@ SuppressFail
Definition: catch.hpp:627
@ FalseTest
Definition: catch.hpp:626
@ ContinueOnFailure
Definition: catch.hpp:625
@ Normal
Definition: catch.hpp:623
Definition: catch.hpp:598
OfType
Definition: catch.hpp:598
@ FailureBit
Definition: catch.hpp:604
@ Info
Definition: catch.hpp:601
@ ThrewException
Definition: catch.hpp:611
@ ExpressionFailed
Definition: catch.hpp:606
@ Unknown
Definition: catch.hpp:599
@ Warning
Definition: catch.hpp:602
@ FatalErrorCondition
Definition: catch.hpp:614
@ DidntThrowException
Definition: catch.hpp:612
@ Exception
Definition: catch.hpp:609
@ ExplicitFailure
Definition: catch.hpp:607
@ Ok
Definition: catch.hpp:600
Definition: catch.hpp:1861
SectionInfo sectionInfo
Definition: catch.hpp:1864
double durationInSeconds
Definition: catch.hpp:1866
SectionEndInfo(SectionInfo const &_sectionInfo, Counts const &_prevAssertions, double _durationInSeconds)
Counts prevAssertions
Definition: catch.hpp:1865
Definition: catch.hpp:1850
std::string description
Definition: catch.hpp:1857
SectionInfo(SourceLineInfo const &_lineInfo, std::string const &_name, std::string const &_description=std::string())
std::string name
Definition: catch.hpp:1856
SourceLineInfo lineInfo
Definition: catch.hpp:1858
Definition: catch.hpp:288
bool empty() const noexcept
SourceLineInfo(char const *_file, std::size_t _line) noexcept
Definition: catch.hpp:291
SourceLineInfo(SourceLineInfo &&)=default
SourceLineInfo(SourceLineInfo const &other)=default
std::size_t line
Definition: catch.hpp:306
SourceLineInfo & operator=(SourceLineInfo const &)=default
char const * file
Definition: catch.hpp:305
bool operator==(SourceLineInfo const &other) const noexcept
bool operator<(SourceLineInfo const &other) const noexcept
Definition: catch.hpp:315
std::string operator+() const
static std::string convert(Catch::Detail::Approx const &value)
static std::string convert(R C::*p)
Definition: catch.hpp:1001
static std::string convert(U *p)
Definition: catch.hpp:990
static std::string convert(T const(&arr)[SZ])
Definition: catch.hpp:1185
static std::string convert(bool b)
static std::string convert(char c)
static std::string convert(char *str)
static std::string convert(char const *str)
static std::string convert(char const *str)
Definition: catch.hpp:913
static std::string convert(double value)
static std::string convert(float value)
static std::string convert(int value)
static std::string convert(long value)
static std::string convert(long long value)
static std::string convert(signed char c)
static std::string convert(signed char const *str)
Definition: catch.hpp:919
static std::string convert(std::nullptr_t)
static std::string convert(const std::string &str)
static std::string convert(const std::wstring &wstr)
static std::string convert(unsigned char c)
static std::string convert(unsigned char const *str)
Definition: catch.hpp:925
static std::string convert(unsigned int value)
static std::string convert(unsigned long value)
static std::string convert(unsigned long long value)
static std::string convert(wchar_t *str)
static std::string convert(wchar_t const *str)
Definition: catch.hpp:829
static std::enable_if<::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
Definition: catch.hpp:833
static std::enable_if<!::Catch::Detail::IsStreamInsertable< Fake >::value, std::string >::type convert(const Fake &value)
Definition: catch.hpp:844
Definition: catch.hpp:2807
friend void setTags(TestCaseInfo &testCaseInfo, std::vector< std::string > tags)
std::vector< std::string > tags
Definition: catch.hpp:2836
std::string tagsAsString() const
std::string className
Definition: catch.hpp:2834
std::string description
Definition: catch.hpp:2835
SpecialProperties
Definition: catch.hpp:2808
@ NonPortable
Definition: catch.hpp:2814
@ Throws
Definition: catch.hpp:2813
@ Benchmark
Definition: catch.hpp:2815
@ MayFail
Definition: catch.hpp:2812
@ IsHidden
Definition: catch.hpp:2810
@ ShouldFail
Definition: catch.hpp:2811
@ None
Definition: catch.hpp:2809
std::string name
Definition: catch.hpp:2833
bool okToFail() const
std::vector< std::string > lcaseTags
Definition: catch.hpp:2837
bool isHidden() const
SourceLineInfo lineInfo
Definition: catch.hpp:2838
bool expectedToFail() const
TestCaseInfo(std::string const &_name, std::string const &_className, std::string const &_description, std::vector< std::string > const &_tags, SourceLineInfo const &_lineInfo)
SpecialProperties properties
Definition: catch.hpp:2839
bool throws() const
Definition: catch.hpp:1547
Definition: catch.hpp:1832
Totals delta(Totals const &prevTotals) const
Counts assertions
Definition: catch.hpp:1840
Totals operator-(Totals const &other) const
Totals & operator+=(Totals const &other)
Counts testCases
Definition: catch.hpp:1841
Definition: catch.hpp:1141
static const bool value
Definition: catch.hpp:1142
Definition: catch.hpp:1131
Definition: catch.hpp:2227
std::size_t m_count
Definition: catch.hpp:2232
pluralise(std::size_t count, std::string const &label)
std::string m_label
Definition: catch.hpp:2233
Definition: catch.hpp:759