3 * Generated: 2017-05-16 13:51:55.506519
4 * ----------------------------------------------------------
5 * This file has been merged from multiple headers. Please don't edit it directly
6 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
8 * Distributed under the Boost Software License, Version 1.0. (See accompanying
9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
14 #define TWOBLUECUBES_CATCH_HPP_INCLUDED
17 # pragma clang system_header
18 #elif defined __GNUC__
19 # pragma GCC system_header
22 // #included from: internal/catch_suppress_warnings.h
25 # ifdef __ICC // icpc defines the __clang__ macro
26 # pragma warning(push)
27 # pragma warning(disable: 161 1682)
29 # pragma clang diagnostic ignored "-Wglobal-constructors"
30 # pragma clang diagnostic ignored "-Wvariadic-macros"
31 # pragma clang diagnostic ignored "-Wc99-extensions"
32 # pragma clang diagnostic ignored "-Wunused-variable"
33 # pragma clang diagnostic push
34 # pragma clang diagnostic ignored "-Wpadded"
35 # pragma clang diagnostic ignored "-Wc++98-compat"
36 # pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
37 # pragma clang diagnostic ignored "-Wswitch-enum"
38 # pragma clang diagnostic ignored "-Wcovered-switch-default"
40 #elif defined __GNUC__
41 # pragma GCC diagnostic ignored "-Wvariadic-macros"
42 # pragma GCC diagnostic ignored "-Wunused-variable"
43 # pragma GCC diagnostic ignored "-Wparentheses"
45 # pragma GCC diagnostic push
46 # pragma GCC diagnostic ignored "-Wpadded"
48 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
53 # ifndef CLARA_CONFIG_MAIN
54 # define CLARA_CONFIG_MAIN_NOT_DEFINED
55 # define CLARA_CONFIG_MAIN
59 // #included from: internal/catch_notimplemented_exception.h
60 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
62 // #included from: catch_common.h
63 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
65 // #included from: catch_compiler_capabilities.h
66 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
68 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
69 // The following features are defined:
71 // CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
72 // CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
73 // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
74 // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
75 // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
76 // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
77 // CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
78 // CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
79 // CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported?
80 // CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
82 // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
84 // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
85 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
86 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
87 // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
89 // Note to maintainers: if new toggles are added please document them
90 // in configuration.md, too
93 // In general each macro has a _NO_<feature name> form
94 // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
95 // Many features, at point of detection, define an _INTERNAL_ macro, so they
96 // can be combined, en-mass, with the _NO_ forms later.
98 // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
102 # if __cplusplus >= 201103L
103 # define CATCH_CPP11_OR_GREATER
106 # if __cplusplus >= 201402L
107 # define CATCH_CPP14_OR_GREATER
114 # if __has_feature(cxx_nullptr)
115 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
118 # if __has_feature(cxx_noexcept)
119 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
122 # if defined(CATCH_CPP11_OR_GREATER)
123 # define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
124 _Pragma( "clang diagnostic push" ) \
125 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" )
126 # define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
127 _Pragma( "clang diagnostic pop" )
129 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
130 _Pragma( "clang diagnostic push" ) \
131 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
132 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
133 _Pragma( "clang diagnostic pop" )
138 ////////////////////////////////////////////////////////////////////////////////
139 // We know some environments not to support full POSIX signals
140 #if defined(__CYGWIN__) || defined(__QNX__)
142 # if !defined(CATCH_CONFIG_POSIX_SIGNALS)
143 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
148 ////////////////////////////////////////////////////////////////////////////////
152 // Required for some versions of Cygwin to declare gettimeofday
153 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
158 ////////////////////////////////////////////////////////////////////////////////
162 #endif // __BORLANDC__
164 ////////////////////////////////////////////////////////////////////////////////
166 #ifdef __EDG_VERSION__
168 #endif // __EDG_VERSION__
170 ////////////////////////////////////////////////////////////////////////////////
176 ////////////////////////////////////////////////////////////////////////////////
180 # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
181 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
184 // - otherwise more recent versions define __cplusplus >= 201103L
185 // and will get picked up below
189 ////////////////////////////////////////////////////////////////////////////////
193 #define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
195 #if (_MSC_VER >= 1600)
196 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
197 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
200 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
201 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
202 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
203 #define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
204 #define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
209 ////////////////////////////////////////////////////////////////////////////////
211 // Use variadic macros if the compiler supports them
212 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
213 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
214 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
215 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
217 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
221 // Use __COUNTER__ if the compiler supports it
222 #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
223 ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
224 ( defined __clang__ && __clang_major__ >= 3 )
226 #define CATCH_INTERNAL_CONFIG_COUNTER
230 ////////////////////////////////////////////////////////////////////////////////
231 // C++ language feature support
233 // catch all support for C++11
234 #if defined(CATCH_CPP11_OR_GREATER)
236 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
237 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
240 # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
241 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
244 # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
245 # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
248 # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
249 # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
252 # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
253 # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
256 # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
257 # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
260 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
261 # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
264 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
265 # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
267 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
268 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
270 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
271 # define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
273 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
274 # define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
277 #endif // __cplusplus >= 201103L
279 // Now set the actual defines based on the above + anything the user has configured
280 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
281 # define CATCH_CONFIG_CPP11_NULLPTR
283 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
284 # define CATCH_CONFIG_CPP11_NOEXCEPT
286 #if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
287 # define CATCH_CONFIG_CPP11_GENERATED_METHODS
289 #if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
290 # define CATCH_CONFIG_CPP11_IS_ENUM
292 #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
293 # define CATCH_CONFIG_CPP11_TUPLE
295 #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
296 # define CATCH_CONFIG_VARIADIC_MACROS
298 #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
299 # define CATCH_CONFIG_CPP11_LONG_LONG
301 #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
302 # define CATCH_CONFIG_CPP11_OVERRIDE
304 #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
305 # define CATCH_CONFIG_CPP11_UNIQUE_PTR
307 // Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
308 // analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
309 // This does not affect compilation
310 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
311 # define CATCH_CONFIG_COUNTER
313 #if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
314 # define CATCH_CONFIG_CPP11_SHUFFLE
316 # if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11)
317 # define CATCH_CONFIG_CPP11_TYPE_TRAITS
319 #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
320 # define CATCH_CONFIG_WINDOWS_SEH
322 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
323 #if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
324 # define CATCH_CONFIG_POSIX_SIGNALS
327 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
328 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
329 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
331 #if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS)
332 # define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
333 # define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
337 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
338 # define CATCH_NOEXCEPT noexcept
339 # define CATCH_NOEXCEPT_IS(x) noexcept(x)
341 # define CATCH_NOEXCEPT throw()
342 # define CATCH_NOEXCEPT_IS(x)
346 #ifdef CATCH_CONFIG_CPP11_NULLPTR
347 # define CATCH_NULL nullptr
349 # define CATCH_NULL NULL
353 #ifdef CATCH_CONFIG_CPP11_OVERRIDE
354 # define CATCH_OVERRIDE override
356 # define CATCH_OVERRIDE
359 // unique_ptr support
360 #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
361 # define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
363 # define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
366 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
367 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
368 #ifdef CATCH_CONFIG_COUNTER
369 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
371 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
374 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
375 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
384 struct CaseSensitive { enum Choice {
390 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
391 NonCopyable( NonCopyable const& ) = delete;
392 NonCopyable( NonCopyable && ) = delete;
393 NonCopyable& operator = ( NonCopyable const& ) = delete;
394 NonCopyable& operator = ( NonCopyable && ) = delete;
396 NonCopyable( NonCopyable const& info );
397 NonCopyable& operator = ( NonCopyable const& );
402 virtual ~NonCopyable();
407 typedef void (SafeBool::*type)() const;
409 static type makeSafe( bool value ) {
410 return value ? &SafeBool::trueValue : 0;
413 void trueValue() const {}
416 template<typename ContainerT>
417 inline void deleteAll( ContainerT& container ) {
418 typename ContainerT::const_iterator it = container.begin();
419 typename ContainerT::const_iterator itEnd = container.end();
420 for(; it != itEnd; ++it )
423 template<typename AssociativeContainerT>
424 inline void deleteAllValues( AssociativeContainerT& container ) {
425 typename AssociativeContainerT::const_iterator it = container.begin();
426 typename AssociativeContainerT::const_iterator itEnd = container.end();
427 for(; it != itEnd; ++it )
431 bool startsWith( std::string const& s, std::string const& prefix );
432 bool startsWith( std::string const& s, char prefix );
433 bool endsWith( std::string const& s, std::string const& suffix );
434 bool endsWith( std::string const& s, char suffix );
435 bool contains( std::string const& s, std::string const& infix );
436 void toLowerInPlace( std::string& s );
437 std::string toLower( std::string const& s );
438 std::string trim( std::string const& str );
439 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
442 pluralise( std::size_t count, std::string const& label );
444 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
450 struct SourceLineInfo {
453 SourceLineInfo( char const* _file, std::size_t _line );
454 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
455 SourceLineInfo(SourceLineInfo const& other) = default;
456 SourceLineInfo( SourceLineInfo && ) = default;
457 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
458 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
461 bool operator == ( SourceLineInfo const& other ) const;
462 bool operator < ( SourceLineInfo const& other ) const;
468 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
470 // This is just here to avoid compiler warnings with macro constants and boolean literals
471 inline bool isTrue( bool value ){ return value; }
472 inline bool alwaysTrue() { return true; }
473 inline bool alwaysFalse() { return false; }
475 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
477 void seedRng( IConfig const& config );
478 unsigned int rngSeed();
480 // Use this in variadic streaming macros to allow
483 // >> stuff +StreamEndStop
484 struct StreamEndStop {
485 std::string operator+() {
486 return std::string();
490 T const& operator + ( T const& value, StreamEndStop ) {
495 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
496 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
500 class NotImplementedException : public std::exception
503 NotImplementedException( SourceLineInfo const& lineInfo );
504 NotImplementedException( NotImplementedException const& ) {}
506 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
508 virtual const char* what() const CATCH_NOEXCEPT;
512 SourceLineInfo m_lineInfo;
515 } // end namespace Catch
517 ///////////////////////////////////////////////////////////////////////////////
518 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
520 // #included from: internal/catch_context.h
521 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
523 // #included from: catch_interfaces_generators.h
524 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
530 struct IGeneratorInfo {
531 virtual ~IGeneratorInfo();
532 virtual bool moveNext() = 0;
533 virtual std::size_t getCurrentIndex() const = 0;
536 struct IGeneratorsForTest {
537 virtual ~IGeneratorsForTest();
539 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
540 virtual bool moveNext() = 0;
543 IGeneratorsForTest* createGeneratorsForTest();
545 } // end namespace Catch
547 // #included from: catch_ptr.hpp
548 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
551 #pragma clang diagnostic push
552 #pragma clang diagnostic ignored "-Wpadded"
557 // An intrusive reference counting smart pointer.
558 // T must implement addRef() and release() methods
559 // typically implementing the IShared interface
563 Ptr() : m_p( CATCH_NULL ){}
564 Ptr( T* p ) : m_p( p ){
568 Ptr( Ptr const& other ) : m_p( other.m_p ){
581 Ptr& operator = ( T* p ){
586 Ptr& operator = ( Ptr const& other ){
591 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
592 T* get() const{ return m_p; }
593 T& operator*() const { return *m_p; }
594 T* operator->() const { return m_p; }
595 bool operator !() const { return m_p == CATCH_NULL; }
596 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
602 struct IShared : NonCopyable {
604 virtual void addRef() const = 0;
605 virtual void release() const = 0;
608 template<typename T = IShared>
609 struct SharedImpl : T {
611 SharedImpl() : m_rc( 0 ){}
613 virtual void addRef() const {
616 virtual void release() const {
621 mutable unsigned int m_rc;
624 } // end namespace Catch
627 #pragma clang diagnostic pop
634 struct IResultCapture;
636 struct IGeneratorsForTest;
643 virtual IResultCapture* getResultCapture() = 0;
644 virtual IRunner* getRunner() = 0;
645 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
646 virtual bool advanceGeneratorsForCurrentTest() = 0;
647 virtual Ptr<IConfig const> getConfig() const = 0;
650 struct IMutableContext : IContext
652 virtual ~IMutableContext();
653 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
654 virtual void setRunner( IRunner* runner ) = 0;
655 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
658 IContext& getCurrentContext();
659 IMutableContext& getCurrentMutableContext();
660 void cleanUpContext();
661 Stream createStream( std::string const& streamName );
665 // #included from: internal/catch_test_registry.hpp
666 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
668 // #included from: catch_interfaces_testcase.h
669 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
677 struct ITestCase : IShared {
678 virtual void invoke () const = 0;
680 virtual ~ITestCase();
686 struct ITestCaseRegistry {
687 virtual ~ITestCaseRegistry();
688 virtual std::vector<TestCase> const& getAllTests() const = 0;
689 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
692 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
693 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
694 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
701 class MethodTestCase : public SharedImpl<ITestCase> {
704 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
706 virtual void invoke() const {
712 virtual ~MethodTestCase() {}
714 void (C::*m_method)();
717 typedef void(*TestFunction)();
720 NameAndDesc( const char* _name = "", const char* _description= "" )
721 : name( _name ), description( _description )
725 const char* description;
728 void registerTestCase
729 ( ITestCase* testCase,
730 char const* className,
731 NameAndDesc const& nameAndDesc,
732 SourceLineInfo const& lineInfo );
737 ( TestFunction function,
738 SourceLineInfo const& lineInfo,
739 NameAndDesc const& nameAndDesc );
743 ( void (C::*method)(),
744 char const* className,
745 NameAndDesc const& nameAndDesc,
746 SourceLineInfo const& lineInfo ) {
749 ( new MethodTestCase<C>( method ),
758 AutoReg( AutoReg const& );
759 void operator= ( AutoReg const& );
762 void registerTestCaseFunction
763 ( TestFunction function,
764 SourceLineInfo const& lineInfo,
765 NameAndDesc const& nameAndDesc );
767 } // end namespace Catch
769 #ifdef CATCH_CONFIG_VARIADIC_MACROS
770 ///////////////////////////////////////////////////////////////////////////////
771 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
772 static void TestName(); \
773 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
774 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } \
775 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
776 static void TestName()
777 #define INTERNAL_CATCH_TESTCASE( ... ) \
778 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
780 ///////////////////////////////////////////////////////////////////////////////
781 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
782 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
783 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } \
784 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
786 ///////////////////////////////////////////////////////////////////////////////
787 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
788 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
790 struct TestName : ClassName{ \
793 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
795 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
796 void TestName::test()
797 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
798 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
800 ///////////////////////////////////////////////////////////////////////////////
801 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
802 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
803 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \
804 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
807 ///////////////////////////////////////////////////////////////////////////////
808 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
809 static void TestName(); \
810 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
811 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
812 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
813 static void TestName()
814 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
815 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
817 ///////////////////////////////////////////////////////////////////////////////
818 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
819 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
820 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } \
821 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
823 ///////////////////////////////////////////////////////////////////////////////
824 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
825 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
827 struct TestCaseName : ClassName{ \
830 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
832 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
833 void TestCaseName::test()
834 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
835 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
837 ///////////////////////////////////////////////////////////////////////////////
838 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
839 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
840 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); \
841 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
845 // #included from: internal/catch_capture.hpp
846 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
848 // #included from: catch_result_builder.h
849 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
851 // #included from: catch_result_type.h
852 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
856 // ResultWas::OfType enum
857 struct ResultWas { enum OfType {
865 ExpressionFailed = FailureBit | 1,
866 ExplicitFailure = FailureBit | 2,
868 Exception = 0x100 | FailureBit,
870 ThrewException = Exception | 1,
871 DidntThrowException = Exception | 2,
873 FatalErrorCondition = 0x200 | FailureBit
877 inline bool isOk( ResultWas::OfType resultType ) {
878 return ( resultType & ResultWas::FailureBit ) == 0;
880 inline bool isJustInfo( int flags ) {
881 return flags == ResultWas::Info;
884 // ResultDisposition::Flags enum
885 struct ResultDisposition { enum Flags {
888 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
889 FalseTest = 0x04, // Prefix expression with !
890 SuppressFail = 0x08 // Failures are reported but do not fail the test
893 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
894 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
897 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
898 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
899 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
901 } // end namespace Catch
903 // #included from: catch_assertionresult.h
904 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
910 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
912 struct DecomposedExpression
914 virtual ~DecomposedExpression() {}
915 virtual bool isBinaryExpression() const {
918 virtual void reconstructExpression( std::string& dest ) const = 0;
920 // Only simple binary comparisons can be decomposed.
921 // If more complex check is required then wrap sub-expressions in parentheses.
922 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& );
923 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& );
924 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& );
925 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& );
926 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& );
927 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
928 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
931 DecomposedExpression& operator = (DecomposedExpression const&);
937 AssertionInfo( std::string const& _macroName,
938 SourceLineInfo const& _lineInfo,
939 std::string const& _capturedExpression,
940 ResultDisposition::Flags _resultDisposition );
942 std::string macroName;
943 SourceLineInfo lineInfo;
944 std::string capturedExpression;
945 ResultDisposition::Flags resultDisposition;
948 struct AssertionResultData
950 AssertionResultData() : decomposedExpression( CATCH_NULL )
951 , resultType( ResultWas::Unknown )
953 , parenthesized( false ) {}
955 void negate( bool parenthesize ) {
957 parenthesized = parenthesize;
958 if( resultType == ResultWas::Ok )
959 resultType = ResultWas::ExpressionFailed;
960 else if( resultType == ResultWas::ExpressionFailed )
961 resultType = ResultWas::Ok;
964 std::string const& reconstructExpression() const {
965 if( decomposedExpression != CATCH_NULL ) {
966 decomposedExpression->reconstructExpression( reconstructedExpression );
967 if( parenthesized ) {
968 reconstructedExpression.insert( 0, 1, '(' );
969 reconstructedExpression.append( 1, ')' );
972 reconstructedExpression.insert( 0, 1, '!' );
974 decomposedExpression = CATCH_NULL;
976 return reconstructedExpression;
979 mutable DecomposedExpression const* decomposedExpression;
980 mutable std::string reconstructedExpression;
982 ResultWas::OfType resultType;
987 class AssertionResult {
990 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
992 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
993 AssertionResult( AssertionResult const& ) = default;
994 AssertionResult( AssertionResult && ) = default;
995 AssertionResult& operator = ( AssertionResult const& ) = default;
996 AssertionResult& operator = ( AssertionResult && ) = default;
1000 bool succeeded() const;
1001 ResultWas::OfType getResultType() const;
1002 bool hasExpression() const;
1003 bool hasMessage() const;
1004 std::string getExpression() const;
1005 std::string getExpressionInMacro() const;
1006 bool hasExpandedExpression() const;
1007 std::string getExpandedExpression() const;
1008 std::string getMessage() const;
1009 SourceLineInfo getSourceInfo() const;
1010 std::string getTestMacroName() const;
1011 void discardDecomposedExpression() const;
1012 void expandDecomposedExpression() const;
1015 AssertionInfo m_info;
1016 AssertionResultData m_resultData;
1019 } // end namespace Catch
1021 // #included from: catch_matchers.hpp
1022 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
1025 namespace Matchers {
1028 template<typename ArgT> struct MatchAllOf;
1029 template<typename ArgT> struct MatchAnyOf;
1030 template<typename ArgT> struct MatchNotOf;
1032 class MatcherUntypedBase {
1034 std::string toString() const {
1035 if( m_cachedToString.empty() )
1036 m_cachedToString = describe();
1037 return m_cachedToString;
1041 virtual ~MatcherUntypedBase();
1042 virtual std::string describe() const = 0;
1043 mutable std::string m_cachedToString;
1045 MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
1048 template<typename ObjectT>
1049 struct MatcherMethod {
1050 virtual bool match( ObjectT const& arg ) const = 0;
1052 template<typename PtrT>
1053 struct MatcherMethod<PtrT*> {
1054 virtual bool match( PtrT* arg ) const = 0;
1057 template<typename ObjectT, typename ComparatorT = ObjectT>
1058 struct MatcherBase : MatcherUntypedBase, MatcherMethod<ObjectT> {
1060 MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
1061 MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
1062 MatchNotOf<ComparatorT> operator ! () const;
1065 template<typename ArgT>
1066 struct MatchAllOf : MatcherBase<ArgT> {
1067 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1068 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1069 if (!m_matchers[i]->match(arg))
1074 virtual std::string describe() const CATCH_OVERRIDE {
1075 std::string description;
1076 description.reserve( 4 + m_matchers.size()*32 );
1077 description += "( ";
1078 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1080 description += " and ";
1081 description += m_matchers[i]->toString();
1083 description += " )";
1087 MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
1088 m_matchers.push_back( &other );
1092 std::vector<MatcherBase<ArgT> const*> m_matchers;
1094 template<typename ArgT>
1095 struct MatchAnyOf : MatcherBase<ArgT> {
1097 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1098 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1099 if (m_matchers[i]->match(arg))
1104 virtual std::string describe() const CATCH_OVERRIDE {
1105 std::string description;
1106 description.reserve( 4 + m_matchers.size()*32 );
1107 description += "( ";
1108 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1110 description += " or ";
1111 description += m_matchers[i]->toString();
1113 description += " )";
1117 MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
1118 m_matchers.push_back( &other );
1122 std::vector<MatcherBase<ArgT> const*> m_matchers;
1125 template<typename ArgT>
1126 struct MatchNotOf : MatcherBase<ArgT> {
1128 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
1130 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1131 return !m_underlyingMatcher.match( arg );
1134 virtual std::string describe() const CATCH_OVERRIDE {
1135 return "not " + m_underlyingMatcher.toString();
1137 MatcherBase<ArgT> const& m_underlyingMatcher;
1140 template<typename ObjectT, typename ComparatorT>
1141 MatchAllOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator && ( MatcherBase const& other ) const {
1142 return MatchAllOf<ComparatorT>() && *this && other;
1144 template<typename ObjectT, typename ComparatorT>
1145 MatchAnyOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator || ( MatcherBase const& other ) const {
1146 return MatchAnyOf<ComparatorT>() || *this || other;
1148 template<typename ObjectT, typename ComparatorT>
1149 MatchNotOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator ! () const {
1150 return MatchNotOf<ComparatorT>( *this );
1155 // The following functions create the actual matcher objects.
1156 // This allows the types to be inferred
1157 // - deprecated: prefer ||, && and !
1158 template<typename T>
1159 inline Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
1160 return Impl::MatchNotOf<T>( underlyingMatcher );
1162 template<typename T>
1163 inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
1164 return Impl::MatchAllOf<T>() && m1 && m2;
1166 template<typename T>
1167 inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
1168 return Impl::MatchAllOf<T>() && m1 && m2 && m3;
1170 template<typename T>
1171 inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
1172 return Impl::MatchAnyOf<T>() || m1 || m2;
1174 template<typename T>
1175 inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
1176 return Impl::MatchAnyOf<T>() || m1 || m2 || m3;
1179 } // namespace Matchers
1181 using namespace Matchers;
1182 using Matchers::Impl::MatcherBase;
1184 } // namespace Catch
1188 struct TestFailureException{};
1190 template<typename T> class ExpressionLhs;
1192 struct CopyableStream {
1194 CopyableStream( CopyableStream const& other ) {
1195 oss << other.oss.str();
1197 CopyableStream& operator=( CopyableStream const& other ) {
1198 oss.str(std::string());
1199 oss << other.oss.str();
1202 std::ostringstream oss;
1205 class ResultBuilder : public DecomposedExpression {
1207 ResultBuilder( char const* macroName,
1208 SourceLineInfo const& lineInfo,
1209 char const* capturedExpression,
1210 ResultDisposition::Flags resultDisposition,
1211 char const* secondArg = "" );
1214 template<typename T>
1215 ExpressionLhs<T const&> operator <= ( T const& operand );
1216 ExpressionLhs<bool> operator <= ( bool value );
1218 template<typename T>
1219 ResultBuilder& operator << ( T const& value ) {
1220 m_stream.oss << value;
1224 ResultBuilder& setResultType( ResultWas::OfType result );
1225 ResultBuilder& setResultType( bool result );
1227 void endExpression( DecomposedExpression const& expr );
1229 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
1231 AssertionResult build() const;
1232 AssertionResult build( DecomposedExpression const& expr ) const;
1234 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
1235 void captureResult( ResultWas::OfType resultType );
1236 void captureExpression();
1237 void captureExpectedException( std::string const& expectedMessage );
1238 void captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher );
1239 void handleResult( AssertionResult const& result );
1241 bool shouldDebugBreak() const;
1242 bool allowThrows() const;
1244 template<typename ArgT, typename MatcherT>
1245 void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
1247 void setExceptionGuard();
1248 void unsetExceptionGuard();
1251 AssertionInfo m_assertionInfo;
1252 AssertionResultData m_data;
1253 CopyableStream m_stream;
1255 bool m_shouldDebugBreak;
1257 bool m_guardException;
1260 } // namespace Catch
1262 // Include after due to circular dependency:
1263 // #included from: catch_expression_lhs.hpp
1264 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1266 // #included from: catch_evaluate.hpp
1267 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
1270 #pragma warning(push)
1271 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1272 #pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
1278 namespace Internal {
1285 IsLessThanOrEqualTo,
1286 IsGreaterThanOrEqualTo
1289 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
1290 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
1291 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
1292 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
1293 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
1294 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
1295 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
1297 template<typename T>
1298 inline T& opCast(T const& t) { return const_cast<T&>(t); }
1300 // nullptr_t support based on pull request #154 from Konstantin Baumann
1301 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1302 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1303 #endif // CATCH_CONFIG_CPP11_NULLPTR
1305 // So the compare overloads can be operator agnostic we convey the operator as a template
1306 // enum, which is used to specialise an Evaluator for doing the comparison.
1307 template<typename T1, typename T2, Operator Op>
1310 template<typename T1, typename T2>
1311 struct Evaluator<T1, T2, IsEqualTo> {
1312 static bool evaluate( T1 const& lhs, T2 const& rhs) {
1313 return bool( opCast( lhs ) == opCast( rhs ) );
1316 template<typename T1, typename T2>
1317 struct Evaluator<T1, T2, IsNotEqualTo> {
1318 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1319 return bool( opCast( lhs ) != opCast( rhs ) );
1322 template<typename T1, typename T2>
1323 struct Evaluator<T1, T2, IsLessThan> {
1324 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1325 return bool( opCast( lhs ) < opCast( rhs ) );
1328 template<typename T1, typename T2>
1329 struct Evaluator<T1, T2, IsGreaterThan> {
1330 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1331 return bool( opCast( lhs ) > opCast( rhs ) );
1334 template<typename T1, typename T2>
1335 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
1336 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1337 return bool( opCast( lhs ) >= opCast( rhs ) );
1340 template<typename T1, typename T2>
1341 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
1342 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
1343 return bool( opCast( lhs ) <= opCast( rhs ) );
1347 template<Operator Op, typename T1, typename T2>
1348 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
1349 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1352 // This level of indirection allows us to specialise for integer types
1353 // to avoid signed/ unsigned warnings
1356 template<Operator Op, typename T1, typename T2>
1357 bool compare( T1 const& lhs, T2 const& rhs ) {
1358 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1361 // unsigned X to int
1362 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
1363 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1365 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
1366 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1368 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
1369 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1372 // unsigned X to long
1373 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
1374 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1376 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
1377 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1379 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
1380 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1383 // int to unsigned X
1384 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
1385 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1387 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
1388 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1390 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
1391 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1394 // long to unsigned X
1395 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
1396 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1398 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
1399 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1401 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
1402 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1405 // pointer to long (when comparing against NULL)
1406 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
1407 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1409 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
1410 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1413 // pointer to int (when comparing against NULL)
1414 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
1415 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1417 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
1418 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1421 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1422 // long long to unsigned X
1423 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
1424 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1426 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
1427 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1429 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
1430 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1432 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
1433 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1436 // unsigned long long to X
1437 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
1438 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1440 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
1441 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1443 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
1444 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1446 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
1447 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1450 // pointer to long long (when comparing against NULL)
1451 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
1452 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1454 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
1455 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1457 #endif // CATCH_CONFIG_CPP11_LONG_LONG
1459 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1460 // pointer to nullptr_t (when comparing against nullptr)
1461 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
1462 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
1464 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
1465 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
1467 #endif // CATCH_CONFIG_CPP11_NULLPTR
1469 } // end of namespace Internal
1470 } // end of namespace Catch
1473 #pragma warning(pop)
1476 // #included from: catch_tostring.h
1477 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1486 // #included from: catch_objc_arc.hpp
1487 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1489 #import <Foundation/Foundation.h>
1491 #ifdef __has_feature
1492 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
1494 #define CATCH_ARC_ENABLED 0
1497 void arcSafeRelease( NSObject* obj );
1498 id performOptionalSelector( id obj, SEL sel );
1500 #if !CATCH_ARC_ENABLED
1501 inline void arcSafeRelease( NSObject* obj ) {
1504 inline id performOptionalSelector( id obj, SEL sel ) {
1505 if( [obj respondsToSelector: sel] )
1506 return [obj performSelector: sel];
1509 #define CATCH_UNSAFE_UNRETAINED
1510 #define CATCH_ARC_STRONG
1512 inline void arcSafeRelease( NSObject* ){}
1513 inline id performOptionalSelector( id obj, SEL sel ) {
1515 #pragma clang diagnostic push
1516 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1518 if( [obj respondsToSelector: sel] )
1519 return [obj performSelector: sel];
1521 #pragma clang diagnostic pop
1525 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1526 #define CATCH_ARC_STRONG __strong
1531 #ifdef CATCH_CONFIG_CPP11_TUPLE
1535 #ifdef CATCH_CONFIG_CPP11_IS_ENUM
1536 #include <type_traits>
1542 template<typename T>
1543 std::string toString( T const& value );
1545 // Built in overloads
1547 std::string toString( std::string const& value );
1548 std::string toString( std::wstring const& value );
1549 std::string toString( const char* const value );
1550 std::string toString( char* const value );
1551 std::string toString( const wchar_t* const value );
1552 std::string toString( wchar_t* const value );
1553 std::string toString( int value );
1554 std::string toString( unsigned long value );
1555 std::string toString( unsigned int value );
1556 std::string toString( const double value );
1557 std::string toString( const float value );
1558 std::string toString( bool value );
1559 std::string toString( char value );
1560 std::string toString( signed char value );
1561 std::string toString( unsigned char value );
1563 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
1564 std::string toString( long long value );
1565 std::string toString( unsigned long long value );
1568 #ifdef CATCH_CONFIG_CPP11_NULLPTR
1569 std::string toString( std::nullptr_t );
1573 std::string toString( NSString const * const& nsstring );
1574 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
1575 std::string toString( NSObject* const& nsObject );
1580 extern const std::string unprintableString;
1582 #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK)
1584 template<typename T> BorgType( T const& );
1587 struct TrueType { char sizer[1]; };
1588 struct FalseType { char sizer[2]; };
1590 TrueType& testStreamable( std::ostream& );
1591 FalseType testStreamable( FalseType );
1593 FalseType operator<<( std::ostream const&, BorgType const& );
1595 template<typename T>
1596 struct IsStreamInsertable {
1597 static std::ostream &s;
1599 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
1602 template<typename T>
1603 class IsStreamInsertable {
1604 template<typename SS, typename TT>
1605 static auto test(int)
1606 -> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
1608 template<typename, typename>
1609 static auto test(...) -> std::false_type;
1612 static const bool value = decltype(test<std::ostream,const T&>(0))::value;
1616 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1617 template<typename T,
1618 bool IsEnum = std::is_enum<T>::value
1620 struct EnumStringMaker
1622 static std::string convert( T const& ) { return unprintableString; }
1625 template<typename T>
1626 struct EnumStringMaker<T,true>
1628 static std::string convert( T const& v )
1630 return ::Catch::toString(
1631 static_cast<typename std::underlying_type<T>::type>(v)
1637 struct StringMakerBase {
1638 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
1639 template<typename T>
1640 static std::string convert( T const& v )
1642 return EnumStringMaker<T>::convert( v );
1645 template<typename T>
1646 static std::string convert( T const& ) { return unprintableString; }
1651 struct StringMakerBase<true> {
1652 template<typename T>
1653 static std::string convert( T const& _value ) {
1654 std::ostringstream oss;
1660 std::string rawMemoryToString( const void *object, std::size_t size );
1662 template<typename T>
1663 inline std::string rawMemoryToString( const T& object ) {
1664 return rawMemoryToString( &object, sizeof(object) );
1667 } // end namespace Detail
1669 template<typename T>
1670 struct StringMaker :
1671 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
1673 template<typename T>
1674 struct StringMaker<T*> {
1675 template<typename U>
1676 static std::string convert( U* p ) {
1680 return Detail::rawMemoryToString( p );
1684 template<typename R, typename C>
1685 struct StringMaker<R C::*> {
1686 static std::string convert( R C::* p ) {
1690 return Detail::rawMemoryToString( p );
1695 template<typename InputIterator>
1696 std::string rangeToString( InputIterator first, InputIterator last );
1699 //template<typename T, typename Allocator>
1700 //struct StringMaker<std::vector<T, Allocator> > {
1701 // static std::string convert( std::vector<T,Allocator> const& v ) {
1702 // return Detail::rangeToString( v.begin(), v.end() );
1706 template<typename T, typename Allocator>
1707 std::string toString( std::vector<T,Allocator> const& v ) {
1708 return Detail::rangeToString( v.begin(), v.end() );
1711 #ifdef CATCH_CONFIG_CPP11_TUPLE
1713 // toString for tuples
1714 namespace TupleDetail {
1718 bool = (N < std::tuple_size<Tuple>::value)
1720 struct ElementPrinter {
1721 static void print( const Tuple& tuple, std::ostream& os )
1723 os << ( N ? ", " : " " )
1724 << Catch::toString(std::get<N>(tuple));
1725 ElementPrinter<Tuple,N+1>::print(tuple,os);
1733 struct ElementPrinter<Tuple,N,false> {
1734 static void print( const Tuple&, std::ostream& ) {}
1739 template<typename ...Types>
1740 struct StringMaker<std::tuple<Types...>> {
1742 static std::string convert( const std::tuple<Types...>& tuple )
1744 std::ostringstream os;
1746 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1751 #endif // CATCH_CONFIG_CPP11_TUPLE
1754 template<typename T>
1755 std::string makeString( T const& value ) {
1756 return StringMaker<T>::convert( value );
1758 } // end namespace Detail
1760 /// \brief converts any type to a string
1762 /// The default template forwards on to ostringstream - except when an
1763 /// ostringstream overload does not exist - in which case it attempts to detect
1764 /// that and writes {?}.
1765 /// Overload (not specialise) this template for custom typs that you don't want
1766 /// to provide an ostream overload for.
1767 template<typename T>
1768 std::string toString( T const& value ) {
1769 return StringMaker<T>::convert( value );
1773 template<typename InputIterator>
1774 std::string rangeToString( InputIterator first, InputIterator last ) {
1775 std::ostringstream oss;
1777 if( first != last ) {
1778 oss << Catch::toString( *first );
1779 for( ++first ; first != last ; ++first )
1780 oss << ", " << Catch::toString( *first );
1787 } // end namespace Catch
1791 template<typename LhsT, Internal::Operator Op, typename RhsT>
1792 class BinaryExpression;
1794 template<typename ArgT, typename MatcherT>
1795 class MatchExpression;
1797 // Wraps the LHS of an expression and overloads comparison operators
1798 // for also capturing those and RHS (if any)
1799 template<typename T>
1800 class ExpressionLhs : public DecomposedExpression {
1802 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
1804 ExpressionLhs& operator = ( const ExpressionLhs& );
1806 template<typename RhsT>
1807 BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
1808 operator == ( RhsT const& rhs ) {
1809 return captureExpression<Internal::IsEqualTo>( rhs );
1812 template<typename RhsT>
1813 BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
1814 operator != ( RhsT const& rhs ) {
1815 return captureExpression<Internal::IsNotEqualTo>( rhs );
1818 template<typename RhsT>
1819 BinaryExpression<T, Internal::IsLessThan, RhsT const&>
1820 operator < ( RhsT const& rhs ) {
1821 return captureExpression<Internal::IsLessThan>( rhs );
1824 template<typename RhsT>
1825 BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
1826 operator > ( RhsT const& rhs ) {
1827 return captureExpression<Internal::IsGreaterThan>( rhs );
1830 template<typename RhsT>
1831 BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
1832 operator <= ( RhsT const& rhs ) {
1833 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
1836 template<typename RhsT>
1837 BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
1838 operator >= ( RhsT const& rhs ) {
1839 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
1842 BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
1843 return captureExpression<Internal::IsEqualTo>( rhs );
1846 BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
1847 return captureExpression<Internal::IsNotEqualTo>( rhs );
1850 void endExpression() {
1851 m_truthy = m_lhs ? true : false;
1853 .setResultType( m_truthy )
1854 .endExpression( *this );
1857 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1858 dest = Catch::toString( m_truthy );
1862 template<Internal::Operator Op, typename RhsT>
1863 BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
1864 return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
1867 template<Internal::Operator Op>
1868 BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
1869 return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
1873 ResultBuilder& m_rb;
1878 template<typename LhsT, Internal::Operator Op, typename RhsT>
1879 class BinaryExpression : public DecomposedExpression {
1881 BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
1882 : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
1884 BinaryExpression& operator = ( BinaryExpression& );
1886 void endExpression() const {
1888 .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
1889 .endExpression( *this );
1892 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1896 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1897 std::string lhs = Catch::toString( m_lhs );
1898 std::string rhs = Catch::toString( m_rhs );
1899 char delim = lhs.size() + rhs.size() < 40 &&
1900 lhs.find('\n') == std::string::npos &&
1901 rhs.find('\n') == std::string::npos ? ' ' : '\n';
1902 dest.reserve( 7 + lhs.size() + rhs.size() );
1903 // 2 for spaces around operator
1905 // 2 for parentheses (conditionally added later)
1906 // 1 for negation (conditionally added later)
1909 dest += Internal::OperatorTraits<Op>::getName();
1915 ResultBuilder& m_rb;
1920 template<typename ArgT, typename MatcherT>
1921 class MatchExpression : public DecomposedExpression {
1923 MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
1924 : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
1926 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1930 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1931 std::string matcherAsString = m_matcher.toString();
1932 dest = Catch::toString( m_arg );
1934 if( matcherAsString == Detail::unprintableString )
1935 dest += m_matcherString;
1937 dest += matcherAsString;
1943 char const* m_matcherString;
1946 } // end namespace Catch
1951 template<typename T>
1952 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
1953 return ExpressionLhs<T const&>( *this, operand );
1956 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
1957 return ExpressionLhs<bool>( *this, value );
1960 template<typename ArgT, typename MatcherT>
1961 inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
1962 char const* matcherString ) {
1963 MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
1964 setResultType( matcher.match( arg ) );
1965 endExpression( expr );
1968 } // namespace Catch
1970 // #included from: catch_message.h
1971 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1977 struct MessageInfo {
1978 MessageInfo( std::string const& _macroName,
1979 SourceLineInfo const& _lineInfo,
1980 ResultWas::OfType _type );
1982 std::string macroName;
1983 SourceLineInfo lineInfo;
1984 ResultWas::OfType type;
1985 std::string message;
1986 unsigned int sequence;
1988 bool operator == ( MessageInfo const& other ) const {
1989 return sequence == other.sequence;
1991 bool operator < ( MessageInfo const& other ) const {
1992 return sequence < other.sequence;
1995 static unsigned int globalCount;
1998 struct MessageBuilder {
1999 MessageBuilder( std::string const& macroName,
2000 SourceLineInfo const& lineInfo,
2001 ResultWas::OfType type )
2002 : m_info( macroName, lineInfo, type )
2005 template<typename T>
2006 MessageBuilder& operator << ( T const& value ) {
2012 std::ostringstream m_stream;
2015 class ScopedMessage {
2017 ScopedMessage( MessageBuilder const& builder );
2018 ScopedMessage( ScopedMessage const& other );
2024 } // end namespace Catch
2026 // #included from: catch_interfaces_capture.h
2027 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
2034 class AssertionResult;
2035 struct AssertionInfo;
2037 struct SectionEndInfo;
2039 class ScopedMessageBuilder;
2042 struct IResultCapture {
2044 virtual ~IResultCapture();
2046 virtual void assertionEnded( AssertionResult const& result ) = 0;
2047 virtual bool sectionStarted( SectionInfo const& sectionInfo,
2048 Counts& assertions ) = 0;
2049 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
2050 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
2051 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
2052 virtual void popScopedMessage( MessageInfo const& message ) = 0;
2054 virtual std::string getCurrentTestName() const = 0;
2055 virtual const AssertionResult* getLastResult() const = 0;
2057 virtual void exceptionEarlyReported() = 0;
2059 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
2062 IResultCapture& getResultCapture();
2065 // #included from: catch_debugger.h
2066 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
2068 // #included from: catch_platform.h
2069 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
2071 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
2072 # define CATCH_PLATFORM_MAC
2073 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
2074 # define CATCH_PLATFORM_IPHONE
2075 #elif defined(linux) || defined(__linux) || defined(__linux__)
2076 # define CATCH_PLATFORM_LINUX
2077 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
2078 # define CATCH_PLATFORM_WINDOWS
2079 # if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
2080 # define CATCH_DEFINES_NOMINMAX
2082 # if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
2083 # define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
2091 bool isDebuggerActive();
2092 void writeToDebugConsole( std::string const& text );
2095 #ifdef CATCH_PLATFORM_MAC
2097 // The following code snippet based on:
2098 // http://cocoawithlove.com/2008/03/break-into-debugger.html
2099 #if defined(__ppc64__) || defined(__ppc__)
2100 #define CATCH_TRAP() \
2101 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
2102 : : : "memory","r0","r3","r4" )
2104 #define CATCH_TRAP() __asm__("int $3\n" : : )
2107 #elif defined(CATCH_PLATFORM_LINUX)
2108 // If we can use inline assembler, do it because this allows us to break
2109 // directly at the location of the failing check instead of breaking inside
2110 // raise() called from it, i.e. one stack frame below.
2111 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
2112 #define CATCH_TRAP() asm volatile ("int $3")
2113 #else // Fall back to the generic way.
2116 #define CATCH_TRAP() raise(SIGTRAP)
2118 #elif defined(_MSC_VER)
2119 #define CATCH_TRAP() __debugbreak()
2120 #elif defined(__MINGW32__)
2121 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
2122 #define CATCH_TRAP() DebugBreak()
2126 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
2128 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
2131 // #included from: catch_interfaces_runner.h
2132 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2139 virtual bool aborting() const = 0;
2143 #if defined(CATCH_CONFIG_FAST_COMPILE)
2144 ///////////////////////////////////////////////////////////////////////////////
2145 // We can speedup compilation significantly by breaking into debugger lower in
2146 // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER
2147 // macro in each assertion
2148 #define INTERNAL_CATCH_REACT( resultBuilder ) \
2149 resultBuilder.react();
2151 ///////////////////////////////////////////////////////////////////////////////
2152 // Another way to speed-up compilation is to omit local try-catch for REQUIRE*
2154 // This can potentially cause false negative, if the test code catches
2155 // the exception before it propagates back up to the runner.
2156 #define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \
2158 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2159 __catchResult.setExceptionGuard(); \
2160 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2161 ( __catchResult <= expr ).endExpression(); \
2162 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
2163 __catchResult.unsetExceptionGuard(); \
2164 INTERNAL_CATCH_REACT( __catchResult ) \
2165 } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
2166 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
2168 #define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \
2170 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
2171 __catchResult.setExceptionGuard(); \
2172 __catchResult.captureMatch( arg, matcher, #matcher ); \
2173 __catchResult.unsetExceptionGuard(); \
2174 INTERNAL_CATCH_REACT( __catchResult ) \
2175 } while( Catch::alwaysFalse() )
2178 ///////////////////////////////////////////////////////////////////////////////
2179 // In the event of a failure works out if the debugger needs to be invoked
2180 // and/or an exception thrown and takes appropriate action.
2181 // This needs to be done as a macro so the debugger will stop in the user
2182 // source code rather than in Catch library code
2183 #define INTERNAL_CATCH_REACT( resultBuilder ) \
2184 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2185 resultBuilder.react();
2188 ///////////////////////////////////////////////////////////////////////////////
2189 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \
2191 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2193 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2194 ( __catchResult <= expr ).endExpression(); \
2195 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
2198 __catchResult.useActiveException( resultDisposition ); \
2200 INTERNAL_CATCH_REACT( __catchResult ) \
2201 } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
2202 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
2204 ///////////////////////////////////////////////////////////////////////////////
2205 #define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \
2206 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
2207 if( Catch::getResultCapture().getLastResult()->succeeded() )
2209 ///////////////////////////////////////////////////////////////////////////////
2210 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \
2211 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
2212 if( !Catch::getResultCapture().getLastResult()->succeeded() )
2214 ///////////////////////////////////////////////////////////////////////////////
2215 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \
2217 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2219 static_cast<void>(expr); \
2220 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2223 __catchResult.useActiveException( resultDisposition ); \
2225 INTERNAL_CATCH_REACT( __catchResult ) \
2226 } while( Catch::alwaysFalse() )
2228 ///////////////////////////////////////////////////////////////////////////////
2229 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \
2231 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
2232 if( __catchResult.allowThrows() ) \
2234 static_cast<void>(expr); \
2235 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2238 __catchResult.captureExpectedException( matcher ); \
2241 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2242 INTERNAL_CATCH_REACT( __catchResult ) \
2243 } while( Catch::alwaysFalse() )
2245 ///////////////////////////////////////////////////////////////////////////////
2246 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
2248 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
2249 if( __catchResult.allowThrows() ) \
2251 static_cast<void>(expr); \
2252 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2254 catch( exceptionType ) { \
2255 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2258 __catchResult.useActiveException( resultDisposition ); \
2261 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2262 INTERNAL_CATCH_REACT( __catchResult ) \
2263 } while( Catch::alwaysFalse() )
2265 ///////////////////////////////////////////////////////////////////////////////
2266 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2267 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
2269 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2270 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2271 __catchResult.captureResult( messageType ); \
2272 INTERNAL_CATCH_REACT( __catchResult ) \
2273 } while( Catch::alwaysFalse() )
2275 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \
2277 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2278 __catchResult << log + ::Catch::StreamEndStop(); \
2279 __catchResult.captureResult( messageType ); \
2280 INTERNAL_CATCH_REACT( __catchResult ) \
2281 } while( Catch::alwaysFalse() )
2284 ///////////////////////////////////////////////////////////////////////////////
2285 #define INTERNAL_CATCH_INFO( macroName, log ) \
2286 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
2288 ///////////////////////////////////////////////////////////////////////////////
2289 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
2291 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
2293 __catchResult.captureMatch( arg, matcher, #matcher ); \
2295 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
2297 INTERNAL_CATCH_REACT( __catchResult ) \
2298 } while( Catch::alwaysFalse() )
2300 // #included from: internal/catch_section.h
2301 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2303 // #included from: catch_section_info.h
2304 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2306 // #included from: catch_totals.hpp
2307 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2314 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
2316 Counts operator - ( Counts const& other ) const {
2318 diff.passed = passed - other.passed;
2319 diff.failed = failed - other.failed;
2320 diff.failedButOk = failedButOk - other.failedButOk;
2323 Counts& operator += ( Counts const& other ) {
2324 passed += other.passed;
2325 failed += other.failed;
2326 failedButOk += other.failedButOk;
2330 std::size_t total() const {
2331 return passed + failed + failedButOk;
2333 bool allPassed() const {
2334 return failed == 0 && failedButOk == 0;
2336 bool allOk() const {
2342 std::size_t failedButOk;
2347 Totals operator - ( Totals const& other ) const {
2349 diff.assertions = assertions - other.assertions;
2350 diff.testCases = testCases - other.testCases;
2354 Totals delta( Totals const& prevTotals ) const {
2355 Totals diff = *this - prevTotals;
2356 if( diff.assertions.failed > 0 )
2357 ++diff.testCases.failed;
2358 else if( diff.assertions.failedButOk > 0 )
2359 ++diff.testCases.failedButOk;
2361 ++diff.testCases.passed;
2365 Totals& operator += ( Totals const& other ) {
2366 assertions += other.assertions;
2367 testCases += other.testCases;
2380 struct SectionInfo {
2382 ( SourceLineInfo const& _lineInfo,
2383 std::string const& _name,
2384 std::string const& _description = std::string() );
2387 std::string description;
2388 SourceLineInfo lineInfo;
2391 struct SectionEndInfo {
2392 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
2393 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2396 SectionInfo sectionInfo;
2397 Counts prevAssertions;
2398 double durationInSeconds;
2401 } // end namespace Catch
2403 // #included from: catch_timer.h
2404 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2409 typedef unsigned long long UInt64;
2414 typedef uint64_t UInt64;
2421 Timer() : m_ticks( 0 ) {}
2423 unsigned int getElapsedMicroseconds() const;
2424 unsigned int getElapsedMilliseconds() const;
2425 double getElapsedSeconds() const;
2431 } // namespace Catch
2437 class Section : NonCopyable {
2439 Section( SectionInfo const& info );
2442 // This indicates whether the section should be executed or not
2443 operator bool() const;
2449 Counts m_assertions;
2450 bool m_sectionIncluded;
2454 } // end namespace Catch
2456 #ifdef CATCH_CONFIG_VARIADIC_MACROS
2457 #define INTERNAL_CATCH_SECTION( ... ) \
2458 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2460 #define INTERNAL_CATCH_SECTION( name, desc ) \
2461 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
2464 // #included from: internal/catch_generators.hpp
2465 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2473 template<typename T>
2475 virtual ~IGenerator() {}
2476 virtual T getValue( std::size_t index ) const = 0;
2477 virtual std::size_t size () const = 0;
2480 template<typename T>
2481 class BetweenGenerator : public IGenerator<T> {
2483 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2485 virtual T getValue( std::size_t index ) const {
2486 return m_from+static_cast<int>( index );
2489 virtual std::size_t size() const {
2490 return static_cast<std::size_t>( 1+m_to-m_from );
2499 template<typename T>
2500 class ValuesGenerator : public IGenerator<T> {
2504 void add( T value ) {
2505 m_values.push_back( value );
2508 virtual T getValue( std::size_t index ) const {
2509 return m_values[index];
2512 virtual std::size_t size() const {
2513 return m_values.size();
2517 std::vector<T> m_values;
2520 template<typename T>
2521 class CompositeGenerator {
2523 CompositeGenerator() : m_totalSize( 0 ) {}
2525 // *** Move semantics, similar to auto_ptr ***
2526 CompositeGenerator( CompositeGenerator& other )
2527 : m_fileInfo( other.m_fileInfo ),
2533 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2534 m_fileInfo = fileInfo;
2538 ~CompositeGenerator() {
2539 deleteAll( m_composed );
2542 operator T () const {
2543 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2545 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2546 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2547 for( size_t index = 0; it != itEnd; ++it )
2549 const IGenerator<T>* generator = *it;
2550 if( overallIndex >= index && overallIndex < index + generator->size() )
2552 return generator->getValue( overallIndex-index );
2554 index += generator->size();
2556 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
2557 return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
2560 void add( const IGenerator<T>* generator ) {
2561 m_totalSize += generator->size();
2562 m_composed.push_back( generator );
2565 CompositeGenerator& then( CompositeGenerator& other ) {
2570 CompositeGenerator& then( T value ) {
2571 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2572 valuesGen->add( value );
2579 void move( CompositeGenerator& other ) {
2580 m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() );
2581 m_totalSize += other.m_totalSize;
2582 other.m_composed.clear();
2585 std::vector<const IGenerator<T>*> m_composed;
2586 std::string m_fileInfo;
2590 namespace Generators
2592 template<typename T>
2593 CompositeGenerator<T> between( T from, T to ) {
2594 CompositeGenerator<T> generators;
2595 generators.add( new BetweenGenerator<T>( from, to ) );
2599 template<typename T>
2600 CompositeGenerator<T> values( T val1, T val2 ) {
2601 CompositeGenerator<T> generators;
2602 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2603 valuesGen->add( val1 );
2604 valuesGen->add( val2 );
2605 generators.add( valuesGen );
2609 template<typename T>
2610 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2611 CompositeGenerator<T> generators;
2612 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2613 valuesGen->add( val1 );
2614 valuesGen->add( val2 );
2615 valuesGen->add( val3 );
2616 generators.add( valuesGen );
2620 template<typename T>
2621 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2622 CompositeGenerator<T> generators;
2623 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2624 valuesGen->add( val1 );
2625 valuesGen->add( val2 );
2626 valuesGen->add( val3 );
2627 valuesGen->add( val4 );
2628 generators.add( valuesGen );
2632 } // end namespace Generators
2634 using namespace Generators;
2636 } // end namespace Catch
2638 #define INTERNAL_CATCH_LINESTR2( line ) #line
2639 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2641 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2643 // #included from: internal/catch_interfaces_exception.h
2644 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2649 // #included from: catch_interfaces_registry_hub.h
2650 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2657 struct ITestCaseRegistry;
2658 struct IExceptionTranslatorRegistry;
2659 struct IExceptionTranslator;
2660 struct IReporterRegistry;
2661 struct IReporterFactory;
2662 struct ITagAliasRegistry;
2664 struct IRegistryHub {
2665 virtual ~IRegistryHub();
2667 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2668 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2669 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
2671 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2674 struct IMutableRegistryHub {
2675 virtual ~IMutableRegistryHub();
2676 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
2677 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
2678 virtual void registerTest( TestCase const& testInfo ) = 0;
2679 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2680 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
2683 IRegistryHub& getRegistryHub();
2684 IMutableRegistryHub& getMutableRegistryHub();
2686 std::string translateActiveException();
2692 typedef std::string(*exceptionTranslateFunction)();
2694 struct IExceptionTranslator;
2695 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2697 struct IExceptionTranslator {
2698 virtual ~IExceptionTranslator();
2699 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
2702 struct IExceptionTranslatorRegistry {
2703 virtual ~IExceptionTranslatorRegistry();
2705 virtual std::string translateActiveException() const = 0;
2708 class ExceptionTranslatorRegistrar {
2709 template<typename T>
2710 class ExceptionTranslator : public IExceptionTranslator {
2713 ExceptionTranslator( std::string(*translateFunction)( T& ) )
2714 : m_translateFunction( translateFunction )
2717 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
2722 return (*it)->translate( it+1, itEnd );
2725 return m_translateFunction( ex );
2730 std::string(*m_translateFunction)( T& );
2734 template<typename T>
2735 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
2736 getMutableRegistryHub().registerTranslator
2737 ( new ExceptionTranslator<T>( translateFunction ) );
2742 ///////////////////////////////////////////////////////////////////////////////
2743 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2744 static std::string translatorName( signature ); \
2745 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
2746 static std::string translatorName( signature )
2748 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
2750 // #included from: internal/catch_approx.hpp
2751 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2756 #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2757 #include <type_traits>
2765 explicit Approx ( double value )
2766 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2772 Approx( Approx const& other )
2773 : m_epsilon( other.m_epsilon ),
2774 m_margin( other.m_margin ),
2775 m_scale( other.m_scale ),
2776 m_value( other.m_value )
2779 static Approx custom() {
2783 #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2785 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2786 Approx operator()( T value ) {
2787 Approx approx( static_cast<double>(value) );
2788 approx.epsilon( m_epsilon );
2789 approx.margin( m_margin );
2790 approx.scale( m_scale );
2794 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2795 explicit Approx( T value ): Approx(static_cast<double>(value))
2798 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2799 friend bool operator == ( const T& lhs, Approx const& rhs ) {
2800 // Thanks to Richard Harris for his help refining this formula
2801 auto lhs_v = double(lhs);
2802 bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value)));
2806 return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
2809 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2810 friend bool operator == ( Approx const& lhs, const T& rhs ) {
2811 return operator==( rhs, lhs );
2814 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2815 friend bool operator != ( T lhs, Approx const& rhs ) {
2816 return !operator==( lhs, rhs );
2819 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2820 friend bool operator != ( Approx const& lhs, T rhs ) {
2821 return !operator==( rhs, lhs );
2824 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2825 friend bool operator <= ( T lhs, Approx const& rhs ) {
2826 return double(lhs) < rhs.m_value || lhs == rhs;
2829 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2830 friend bool operator <= ( Approx const& lhs, T rhs ) {
2831 return lhs.m_value < double(rhs) || lhs == rhs;
2834 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2835 friend bool operator >= ( T lhs, Approx const& rhs ) {
2836 return double(lhs) > rhs.m_value || lhs == rhs;
2839 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2840 friend bool operator >= ( Approx const& lhs, T rhs ) {
2841 return lhs.m_value > double(rhs) || lhs == rhs;
2844 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2845 Approx& epsilon( T newEpsilon ) {
2846 m_epsilon = double(newEpsilon);
2850 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2851 Approx& margin( T newMargin ) {
2852 m_margin = double(newMargin);
2856 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2857 Approx& scale( T newScale ) {
2858 m_scale = double(newScale);
2864 Approx operator()( double value ) {
2865 Approx approx( value );
2866 approx.epsilon( m_epsilon );
2867 approx.margin( m_margin );
2868 approx.scale( m_scale );
2872 friend bool operator == ( double lhs, Approx const& rhs ) {
2873 // Thanks to Richard Harris for his help refining this formula
2874 bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) );
2878 return std::fabs(lhs - rhs.m_value) < rhs.m_margin;
2881 friend bool operator == ( Approx const& lhs, double rhs ) {
2882 return operator==( rhs, lhs );
2885 friend bool operator != ( double lhs, Approx const& rhs ) {
2886 return !operator==( lhs, rhs );
2889 friend bool operator != ( Approx const& lhs, double rhs ) {
2890 return !operator==( rhs, lhs );
2893 friend bool operator <= ( double lhs, Approx const& rhs ) {
2894 return lhs < rhs.m_value || lhs == rhs;
2897 friend bool operator <= ( Approx const& lhs, double rhs ) {
2898 return lhs.m_value < rhs || lhs == rhs;
2901 friend bool operator >= ( double lhs, Approx const& rhs ) {
2902 return lhs > rhs.m_value || lhs == rhs;
2905 friend bool operator >= ( Approx const& lhs, double rhs ) {
2906 return lhs.m_value > rhs || lhs == rhs;
2909 Approx& epsilon( double newEpsilon ) {
2910 m_epsilon = newEpsilon;
2914 Approx& margin( double newMargin ) {
2915 m_margin = newMargin;
2919 Approx& scale( double newScale ) {
2925 std::string toString() const {
2926 std::ostringstream oss;
2927 oss << "Approx( " << Catch::toString( m_value ) << " )";
2940 inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
2941 return value.toString();
2944 } // end namespace Catch
2946 // #included from: internal/catch_matchers_string.h
2947 #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
2950 namespace Matchers {
2952 namespace StdString {
2956 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
2957 std::string adjustString( std::string const& str ) const;
2958 std::string caseSensitivitySuffix() const;
2960 CaseSensitive::Choice m_caseSensitivity;
2964 struct StringMatcherBase : MatcherBase<std::string> {
2965 StringMatcherBase( std::string const& operation, CasedString const& comparator );
2966 virtual std::string describe() const CATCH_OVERRIDE;
2968 CasedString m_comparator;
2969 std::string m_operation;
2972 struct EqualsMatcher : StringMatcherBase {
2973 EqualsMatcher( CasedString const& comparator );
2974 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2976 struct ContainsMatcher : StringMatcherBase {
2977 ContainsMatcher( CasedString const& comparator );
2978 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2980 struct StartsWithMatcher : StringMatcherBase {
2981 StartsWithMatcher( CasedString const& comparator );
2982 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2984 struct EndsWithMatcher : StringMatcherBase {
2985 EndsWithMatcher( CasedString const& comparator );
2986 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2989 } // namespace StdString
2991 // The following functions create the actual matcher objects.
2992 // This allows the types to be inferred
2994 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2995 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2996 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2997 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2999 } // namespace Matchers
3000 } // namespace Catch
3002 // #included from: internal/catch_matchers_vector.h
3003 #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
3006 namespace Matchers {
3010 template<typename T>
3011 struct ContainsElementMatcher : MatcherBase<std::vector<T>, T> {
3013 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
3015 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3016 return std::find(v.begin(), v.end(), m_comparator) != v.end();
3019 virtual std::string describe() const CATCH_OVERRIDE {
3020 return "Contains: " + Catch::toString( m_comparator );
3023 T const& m_comparator;
3026 template<typename T>
3027 struct ContainsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
3029 ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3031 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3032 // !TBD: see note in EqualsMatcher
3033 if (m_comparator.size() > v.size())
3035 for (size_t i = 0; i < m_comparator.size(); ++i)
3036 if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end())
3040 virtual std::string describe() const CATCH_OVERRIDE {
3041 return "Contains: " + Catch::toString( m_comparator );
3044 std::vector<T> const& m_comparator;
3047 template<typename T>
3048 struct EqualsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
3050 EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3052 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3053 // !TBD: This currently works if all elements can be compared using !=
3054 // - a more general approach would be via a compare template that defaults
3055 // to using !=. but could be specialised for, e.g. std::vector<T> etc
3056 // - then just call that directly
3057 if (m_comparator.size() != v.size())
3059 for (size_t i = 0; i < v.size(); ++i)
3060 if (m_comparator[i] != v[i])
3064 virtual std::string describe() const CATCH_OVERRIDE {
3065 return "Equals: " + Catch::toString( m_comparator );
3067 std::vector<T> const& m_comparator;
3070 } // namespace Vector
3072 // The following functions create the actual matcher objects.
3073 // This allows the types to be inferred
3075 template<typename T>
3076 Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
3077 return Vector::ContainsMatcher<T>( comparator );
3080 template<typename T>
3081 Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
3082 return Vector::ContainsElementMatcher<T>( comparator );
3085 template<typename T>
3086 Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
3087 return Vector::EqualsMatcher<T>( comparator );
3090 } // namespace Matchers
3091 } // namespace Catch
3093 // #included from: internal/catch_interfaces_tag_alias_registry.h
3094 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
3096 // #included from: catch_tag_alias.h
3097 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
3104 TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
3107 SourceLineInfo lineInfo;
3110 struct RegistrarForTagAliases {
3111 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
3114 } // end namespace Catch
3116 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
3117 // #included from: catch_option.hpp
3118 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
3123 template<typename T>
3126 Option() : nullableValue( CATCH_NULL ) {}
3127 Option( T const& _value )
3128 : nullableValue( new( storage ) T( _value ) )
3130 Option( Option const& _other )
3131 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
3138 Option& operator= ( Option const& _other ) {
3139 if( &_other != this ) {
3142 nullableValue = new( storage ) T( *_other );
3146 Option& operator = ( T const& _value ) {
3148 nullableValue = new( storage ) T( _value );
3154 nullableValue->~T();
3155 nullableValue = CATCH_NULL;
3158 T& operator*() { return *nullableValue; }
3159 T const& operator*() const { return *nullableValue; }
3160 T* operator->() { return nullableValue; }
3161 const T* operator->() const { return nullableValue; }
3163 T valueOr( T const& defaultValue ) const {
3164 return nullableValue ? *nullableValue : defaultValue;
3167 bool some() const { return nullableValue != CATCH_NULL; }
3168 bool none() const { return nullableValue == CATCH_NULL; }
3170 bool operator !() const { return nullableValue == CATCH_NULL; }
3171 operator SafeBool::type() const {
3172 return SafeBool::makeSafe( some() );
3178 char storage[sizeof(T)];
3180 // These are here to force alignment for the storage
3184 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
3190 } // end namespace Catch
3194 struct ITagAliasRegistry {
3195 virtual ~ITagAliasRegistry();
3196 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
3197 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
3199 static ITagAliasRegistry const& get();
3202 } // end namespace Catch
3204 // These files are included here so the single_include script doesn't put them
3205 // in the conditionally compiled sections
3206 // #included from: internal/catch_test_case_info.h
3207 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
3213 #pragma clang diagnostic push
3214 #pragma clang diagnostic ignored "-Wpadded"
3221 struct TestCaseInfo {
3222 enum SpecialProperties{
3225 ShouldFail = 1 << 2,
3228 NonPortable = 1 << 5
3231 TestCaseInfo( std::string const& _name,
3232 std::string const& _className,
3233 std::string const& _description,
3234 std::set<std::string> const& _tags,
3235 SourceLineInfo const& _lineInfo );
3237 TestCaseInfo( TestCaseInfo const& other );
3239 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
3241 bool isHidden() const;
3242 bool throws() const;
3243 bool okToFail() const;
3244 bool expectedToFail() const;
3247 std::string className;
3248 std::string description;
3249 std::set<std::string> tags;
3250 std::set<std::string> lcaseTags;
3251 std::string tagsAsString;
3252 SourceLineInfo lineInfo;
3253 SpecialProperties properties;
3256 class TestCase : public TestCaseInfo {
3259 TestCase( ITestCase* testCase, TestCaseInfo const& info );
3260 TestCase( TestCase const& other );
3262 TestCase withName( std::string const& _newName ) const;
3264 void invoke() const;
3266 TestCaseInfo const& getTestCaseInfo() const;
3268 void swap( TestCase& other );
3269 bool operator == ( TestCase const& other ) const;
3270 bool operator < ( TestCase const& other ) const;
3271 TestCase& operator = ( TestCase const& other );
3274 Ptr<ITestCase> test;
3277 TestCase makeTestCase( ITestCase* testCase,
3278 std::string const& className,
3279 std::string const& name,
3280 std::string const& description,
3281 SourceLineInfo const& lineInfo );
3285 #pragma clang diagnostic pop
3290 // #included from: internal/catch_objc.hpp
3291 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
3293 #import <objc/runtime.h>
3297 // NB. Any general catch headers included here must be included
3298 // in catch.hpp first to make sure they are included by the single
3299 // header for non obj-usage
3301 ///////////////////////////////////////////////////////////////////////////////
3302 // This protocol is really only here for (self) documenting purposes, since
3303 // all its methods are optional.
3315 class OcMethod : public SharedImpl<ITestCase> {
3318 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
3320 virtual void invoke() const {
3321 id obj = [[m_cls alloc] init];
3323 performOptionalSelector( obj, @selector(setUp) );
3324 performOptionalSelector( obj, m_sel );
3325 performOptionalSelector( obj, @selector(tearDown) );
3327 arcSafeRelease( obj );
3330 virtual ~OcMethod() {}
3338 inline std::string getAnnotation( Class cls,
3339 std::string const& annotationName,
3340 std::string const& testCaseName ) {
3341 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3342 SEL sel = NSSelectorFromString( selStr );
3343 arcSafeRelease( selStr );
3344 id value = performOptionalSelector( cls, sel );
3346 return [(NSString*)value UTF8String];
3351 inline size_t registerTestMethods() {
3352 size_t noTestMethods = 0;
3353 int noClasses = objc_getClassList( CATCH_NULL, 0 );
3355 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
3356 objc_getClassList( classes, noClasses );
3358 for( int c = 0; c < noClasses; c++ ) {
3359 Class cls = classes[c];
3362 Method* methods = class_copyMethodList( cls, &count );
3363 for( u_int m = 0; m < count ; m++ ) {
3364 SEL selector = method_getName(methods[m]);
3365 std::string methodName = sel_getName(selector);
3366 if( startsWith( methodName, "Catch_TestCase_" ) ) {
3367 std::string testCaseName = methodName.substr( 15 );
3368 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
3369 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
3370 const char* className = class_getName( cls );
3372 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
3379 return noTestMethods;
3382 namespace Matchers {
3384 namespace NSStringMatchers {
3386 struct StringHolder : MatcherBase<NSString*>{
3387 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
3388 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
3390 arcSafeRelease( m_substr );
3393 virtual bool match( NSString* arg ) const CATCH_OVERRIDE {
3400 struct Equals : StringHolder {
3401 Equals( NSString* substr ) : StringHolder( substr ){}
3403 virtual bool match( NSString* str ) const CATCH_OVERRIDE {
3404 return (str != nil || m_substr == nil ) &&
3405 [str isEqualToString:m_substr];
3408 virtual std::string describe() const CATCH_OVERRIDE {
3409 return "equals string: " + Catch::toString( m_substr );
3413 struct Contains : StringHolder {
3414 Contains( NSString* substr ) : StringHolder( substr ){}
3416 virtual bool match( NSString* str ) const {
3417 return (str != nil || m_substr == nil ) &&
3418 [str rangeOfString:m_substr].location != NSNotFound;
3421 virtual std::string describe() const CATCH_OVERRIDE {
3422 return "contains string: " + Catch::toString( m_substr );
3426 struct StartsWith : StringHolder {
3427 StartsWith( NSString* substr ) : StringHolder( substr ){}
3429 virtual bool match( NSString* str ) const {
3430 return (str != nil || m_substr == nil ) &&
3431 [str rangeOfString:m_substr].location == 0;
3434 virtual std::string describe() const CATCH_OVERRIDE {
3435 return "starts with: " + Catch::toString( m_substr );
3438 struct EndsWith : StringHolder {
3439 EndsWith( NSString* substr ) : StringHolder( substr ){}
3441 virtual bool match( NSString* str ) const {
3442 return (str != nil || m_substr == nil ) &&
3443 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
3446 virtual std::string describe() const CATCH_OVERRIDE {
3447 return "ends with: " + Catch::toString( m_substr );
3451 } // namespace NSStringMatchers
3454 inline Impl::NSStringMatchers::Equals
3455 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3457 inline Impl::NSStringMatchers::Contains
3458 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
3460 inline Impl::NSStringMatchers::StartsWith
3461 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
3463 inline Impl::NSStringMatchers::EndsWith
3464 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3466 } // namespace Matchers
3468 using namespace Matchers;
3470 } // namespace Catch
3472 ///////////////////////////////////////////////////////////////////////////////
3473 #define OC_TEST_CASE( name, desc )\
3474 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
3478 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
3482 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3488 // !TBD: Move the leak detector code into a separate header
3489 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG
3491 class LeakDetector {
3494 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
3495 flag |= _CRTDBG_LEAK_CHECK_DF;
3496 flag |= _CRTDBG_ALLOC_MEM_DF;
3497 _CrtSetDbgFlag(flag);
3498 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3499 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3500 // Change this to leaking allocation's number to break there
3501 _CrtSetBreakAlloc(-1);
3505 class LeakDetector {};
3508 LeakDetector leakDetector;
3510 // #included from: internal/catch_impl.hpp
3511 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
3513 // Collect all the implementation files together here
3514 // These are the equivalent of what would usually be cpp files
3517 #pragma clang diagnostic push
3518 #pragma clang diagnostic ignored "-Wweak-vtables"
3521 // #included from: ../catch_session.hpp
3522 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
3524 // #included from: internal/catch_commandline.hpp
3525 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3527 // #included from: catch_config.hpp
3528 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3530 // #included from: catch_test_spec_parser.hpp
3531 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
3534 #pragma clang diagnostic push
3535 #pragma clang diagnostic ignored "-Wpadded"
3538 // #included from: catch_test_spec.hpp
3539 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
3542 #pragma clang diagnostic push
3543 #pragma clang diagnostic ignored "-Wpadded"
3546 // #included from: catch_wildcard_pattern.hpp
3547 #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3549 #include <stdexcept>
3553 class WildcardPattern {
3554 enum WildcardPosition {
3556 WildcardAtStart = 1,
3558 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3563 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
3564 : m_caseSensitivity( caseSensitivity ),
3565 m_wildcard( NoWildcard ),
3566 m_pattern( adjustCase( pattern ) )
3568 if( startsWith( m_pattern, '*' ) ) {
3569 m_pattern = m_pattern.substr( 1 );
3570 m_wildcard = WildcardAtStart;
3572 if( endsWith( m_pattern, '*' ) ) {
3573 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3574 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
3577 virtual ~WildcardPattern();
3578 virtual bool matches( std::string const& str ) const {
3579 switch( m_wildcard ) {
3581 return m_pattern == adjustCase( str );
3582 case WildcardAtStart:
3583 return endsWith( adjustCase( str ), m_pattern );
3585 return startsWith( adjustCase( str ), m_pattern );
3586 case WildcardAtBothEnds:
3587 return contains( adjustCase( str ), m_pattern );
3591 #pragma clang diagnostic push
3592 #pragma clang diagnostic ignored "-Wunreachable-code"
3594 throw std::logic_error( "Unknown enum" );
3596 #pragma clang diagnostic pop
3600 std::string adjustCase( std::string const& str ) const {
3601 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
3603 CaseSensitive::Choice m_caseSensitivity;
3604 WildcardPosition m_wildcard;
3605 std::string m_pattern;
3615 struct Pattern : SharedImpl<> {
3617 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3619 class NamePattern : public Pattern {
3621 NamePattern( std::string const& name )
3622 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
3624 virtual ~NamePattern();
3625 virtual bool matches( TestCaseInfo const& testCase ) const {
3626 return m_wildcardPattern.matches( toLower( testCase.name ) );
3629 WildcardPattern m_wildcardPattern;
3632 class TagPattern : public Pattern {
3634 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
3635 virtual ~TagPattern();
3636 virtual bool matches( TestCaseInfo const& testCase ) const {
3637 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
3643 class ExcludedPattern : public Pattern {
3645 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3646 virtual ~ExcludedPattern();
3647 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
3649 Ptr<Pattern> m_underlyingPattern;
3653 std::vector<Ptr<Pattern> > m_patterns;
3655 bool matches( TestCaseInfo const& testCase ) const {
3656 // All patterns in a filter must match for the filter to be a match
3657 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
3658 if( !(*it)->matches( testCase ) )
3666 bool hasFilters() const {
3667 return !m_filters.empty();
3669 bool matches( TestCaseInfo const& testCase ) const {
3670 // A TestSpec matches if any filter matches
3671 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3672 if( it->matches( testCase ) )
3678 std::vector<Filter> m_filters;
3680 friend class TestSpecParser;
3685 #pragma clang diagnostic pop
3690 class TestSpecParser {
3691 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
3694 std::size_t m_start, m_pos;
3696 std::vector<std::size_t> m_escapeChars;
3697 TestSpec::Filter m_currentFilter;
3698 TestSpec m_testSpec;
3699 ITagAliasRegistry const* m_tagAliases;
3702 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
3704 TestSpecParser& parse( std::string const& arg ) {
3706 m_exclusion = false;
3707 m_start = std::string::npos;
3708 m_arg = m_tagAliases->expandAliases( arg );
3709 m_escapeChars.clear();
3710 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3711 visitChar( m_arg[m_pos] );
3712 if( m_mode == Name )
3713 addPattern<TestSpec::NamePattern>();
3716 TestSpec testSpec() {
3721 void visitChar( char c ) {
3722 if( m_mode == None ) {
3725 case '~': m_exclusion = true; return;
3726 case '[': return startNewMode( Tag, ++m_pos );
3727 case '"': return startNewMode( QuotedName, ++m_pos );
3728 case '\\': return escape();
3729 default: startNewMode( Name, m_pos ); break;
3732 if( m_mode == Name ) {
3734 addPattern<TestSpec::NamePattern>();
3737 else if( c == '[' ) {
3738 if( subString() == "exclude:" )
3741 addPattern<TestSpec::NamePattern>();
3742 startNewMode( Tag, ++m_pos );
3744 else if( c == '\\' )
3747 else if( m_mode == EscapedName )
3749 else if( m_mode == QuotedName && c == '"' )
3750 addPattern<TestSpec::NamePattern>();
3751 else if( m_mode == Tag && c == ']' )
3752 addPattern<TestSpec::TagPattern>();
3754 void startNewMode( Mode mode, std::size_t start ) {
3759 if( m_mode == None )
3761 m_mode = EscapedName;
3762 m_escapeChars.push_back( m_pos );
3764 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
3765 template<typename T>
3767 std::string token = subString();
3768 for( size_t i = 0; i < m_escapeChars.size(); ++i )
3769 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
3770 m_escapeChars.clear();
3771 if( startsWith( token, "exclude:" ) ) {
3773 token = token.substr( 8 );
3775 if( !token.empty() ) {
3776 Ptr<TestSpec::Pattern> pattern = new T( token );
3778 pattern = new TestSpec::ExcludedPattern( pattern );
3779 m_currentFilter.m_patterns.push_back( pattern );
3781 m_exclusion = false;
3785 if( !m_currentFilter.m_patterns.empty() ) {
3786 m_testSpec.m_filters.push_back( m_currentFilter );
3787 m_currentFilter = TestSpec::Filter();
3791 inline TestSpec parseTestSpec( std::string const& arg ) {
3792 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
3795 } // namespace Catch
3798 #pragma clang diagnostic pop
3801 // #included from: catch_interfaces_config.h
3802 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3810 struct Verbosity { enum Level {
3816 struct WarnAbout { enum What {
3821 struct ShowDurations { enum OrNot {
3826 struct RunTests { enum InWhatOrder {
3828 InLexicographicalOrder,
3831 struct UseColour { enum YesOrNo {
3839 struct IConfig : IShared {
3843 virtual bool allowThrows() const = 0;
3844 virtual std::ostream& stream() const = 0;
3845 virtual std::string name() const = 0;
3846 virtual bool includeSuccessfulResults() const = 0;
3847 virtual bool shouldDebugBreak() const = 0;
3848 virtual bool warnAboutMissingAssertions() const = 0;
3849 virtual int abortAfter() const = 0;
3850 virtual bool showInvisibles() const = 0;
3851 virtual ShowDurations::OrNot showDurations() const = 0;
3852 virtual TestSpec const& testSpec() const = 0;
3853 virtual RunTests::InWhatOrder runOrder() const = 0;
3854 virtual unsigned int rngSeed() const = 0;
3855 virtual UseColour::YesOrNo useColour() const = 0;
3856 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
3861 // #included from: catch_stream.h
3862 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3864 // #included from: catch_streambuf.h
3865 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
3867 #include <streambuf>
3871 class StreamBufBase : public std::streambuf {
3873 virtual ~StreamBufBase() CATCH_NOEXCEPT;
3877 #include <streambuf>
3884 std::ostream& cout();
3885 std::ostream& cerr();
3888 virtual ~IStream() CATCH_NOEXCEPT;
3889 virtual std::ostream& stream() const = 0;
3892 class FileStream : public IStream {
3893 mutable std::ofstream m_ofs;
3895 FileStream( std::string const& filename );
3896 virtual ~FileStream() CATCH_NOEXCEPT;
3898 virtual std::ostream& stream() const CATCH_OVERRIDE;
3901 class CoutStream : public IStream {
3902 mutable std::ostream m_os;
3905 virtual ~CoutStream() CATCH_NOEXCEPT;
3908 virtual std::ostream& stream() const CATCH_OVERRIDE;
3911 class DebugOutStream : public IStream {
3912 CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
3913 mutable std::ostream m_os;
3916 virtual ~DebugOutStream() CATCH_NOEXCEPT;
3919 virtual std::ostream& stream() const CATCH_OVERRIDE;
3926 #include <stdexcept>
3928 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
3929 #define CATCH_CONFIG_CONSOLE_WIDTH 80
3937 : listTests( false ),
3939 listReporters( false ),
3940 listTestNamesOnly( false ),
3941 showSuccessfulTests( false ),
3942 shouldDebugBreak( false ),
3945 showInvisibles( false ),
3946 filenamesAsTags( false ),
3949 verbosity( Verbosity::Normal ),
3950 warnings( WarnAbout::Nothing ),
3951 showDurations( ShowDurations::DefaultForReporter ),
3952 runOrder( RunTests::InDeclarationOrder ),
3953 useColour( UseColour::Auto )
3959 bool listTestNamesOnly;
3961 bool showSuccessfulTests;
3962 bool shouldDebugBreak;
3965 bool showInvisibles;
3966 bool filenamesAsTags;
3969 unsigned int rngSeed;
3971 Verbosity::Level verbosity;
3972 WarnAbout::What warnings;
3973 ShowDurations::OrNot showDurations;
3974 RunTests::InWhatOrder runOrder;
3975 UseColour::YesOrNo useColour;
3977 std::string outputFilename;
3979 std::string processName;
3981 std::vector<std::string> reporterNames;
3982 std::vector<std::string> testsOrTags;
3983 std::vector<std::string> sectionsToRun;
3986 class Config : public SharedImpl<IConfig> {
3988 Config( Config const& other );
3989 Config& operator = ( Config const& other );
3990 virtual void dummy();
3996 Config( ConfigData const& data )
3998 m_stream( openStream() )
4000 if( !data.testsOrTags.empty() ) {
4001 TestSpecParser parser( ITagAliasRegistry::get() );
4002 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
4003 parser.parse( data.testsOrTags[i] );
4004 m_testSpec = parser.testSpec();
4008 virtual ~Config() {}
4010 std::string const& getFilename() const {
4011 return m_data.outputFilename ;
4014 bool listTests() const { return m_data.listTests; }
4015 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
4016 bool listTags() const { return m_data.listTags; }
4017 bool listReporters() const { return m_data.listReporters; }
4019 std::string getProcessName() const { return m_data.processName; }
4021 std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
4022 std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
4024 virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; }
4026 bool showHelp() const { return m_data.showHelp; }
4028 // IConfig interface
4029 virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; }
4030 virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); }
4031 virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; }
4032 virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; }
4033 virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; }
4034 virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; }
4035 virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; }
4036 virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; }
4037 virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; }
4038 virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; }
4039 virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; }
4040 virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; }
4044 IStream const* openStream() {
4045 if( m_data.outputFilename.empty() )
4046 return new CoutStream();
4047 else if( m_data.outputFilename[0] == '%' ) {
4048 if( m_data.outputFilename == "%debug" )
4049 return new DebugOutStream();
4051 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
4054 return new FileStream( m_data.outputFilename );
4058 CATCH_AUTO_PTR( IStream const ) m_stream;
4059 TestSpec m_testSpec;
4062 } // end namespace Catch
4064 // #included from: catch_clara.h
4065 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
4067 // Use Catch's value for console width (store Clara's off to the side, if present)
4068 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
4069 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
4070 #undef CLARA_CONFIG_CONSOLE_WIDTH
4072 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4074 // Declare Clara inside the Catch namespace
4075 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
4076 // #included from: ../external/clara.h
4080 // Only use header guard if we are not using an outer namespace
4081 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
4083 #ifndef STITCH_CLARA_OPEN_NAMESPACE
4084 #define TWOBLUECUBES_CLARA_H_INCLUDED
4085 #define STITCH_CLARA_OPEN_NAMESPACE
4086 #define STITCH_CLARA_CLOSE_NAMESPACE
4088 #define STITCH_CLARA_CLOSE_NAMESPACE }
4091 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
4093 // ----------- #included from tbc_text_format.h -----------
4095 // Only use header guard if we are not using an outer namespace
4096 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
4097 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4098 #define TBC_TEXT_FORMAT_H_INCLUDED
4104 #include <algorithm>
4107 // Use optional outer namespace
4108 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4109 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4114 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4115 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4117 const unsigned int consoleWidth = 80;
4120 struct TextAttributes {
4122 : initialIndent( std::string::npos ),
4124 width( consoleWidth-1 ),
4128 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
4129 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
4130 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
4131 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
4133 std::size_t initialIndent; // indent of first line, or npos
4134 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4135 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4136 char tabChar; // If this char is seen the indent is changed to current pos
4141 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
4144 std::string wrappableChars = " [({.,/|\\-";
4145 std::size_t indent = _attr.initialIndent != std::string::npos
4146 ? _attr.initialIndent
4148 std::string remainder = _str;
4150 while( !remainder.empty() ) {
4151 if( lines.size() >= 1000 ) {
4152 lines.push_back( "... message truncated due to excessive size" );
4155 std::size_t tabPos = std::string::npos;
4156 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4157 std::size_t pos = remainder.find_first_of( '\n' );
4158 if( pos <= width ) {
4161 pos = remainder.find_last_of( _attr.tabChar, width );
4162 if( pos != std::string::npos ) {
4164 if( remainder[width] == '\n' )
4166 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4169 if( width == remainder.size() ) {
4170 spliceLine( indent, remainder, width );
4172 else if( remainder[width] == '\n' ) {
4173 spliceLine( indent, remainder, width );
4174 if( width <= 1 || remainder.size() != 1 )
4175 remainder = remainder.substr( 1 );
4176 indent = _attr.indent;
4179 pos = remainder.find_last_of( wrappableChars, width );
4180 if( pos != std::string::npos && pos > 0 ) {
4181 spliceLine( indent, remainder, pos );
4182 if( remainder[0] == ' ' )
4183 remainder = remainder.substr( 1 );
4186 spliceLine( indent, remainder, width-1 );
4187 lines.back() += "-";
4189 if( lines.size() == 1 )
4190 indent = _attr.indent;
4191 if( tabPos != std::string::npos )
4197 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4198 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4199 _remainder = _remainder.substr( _pos );
4202 typedef std::vector<std::string>::const_iterator const_iterator;
4204 const_iterator begin() const { return lines.begin(); }
4205 const_iterator end() const { return lines.end(); }
4206 std::string const& last() const { return lines.back(); }
4207 std::size_t size() const { return lines.size(); }
4208 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
4209 std::string toString() const {
4210 std::ostringstream oss;
4215 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4216 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4217 it != itEnd; ++it ) {
4218 if( it != _text.begin() )
4227 TextAttributes attr;
4228 std::vector<std::string> lines;
4231 } // end namespace Tbc
4233 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4234 } // end outer namespace
4237 #endif // TBC_TEXT_FORMAT_H_INCLUDED
4239 // ----------- end of #include from tbc_text_format.h -----------
4240 // ........... back in clara.h
4242 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
4244 // ----------- #included from clara_compilers.h -----------
4246 #ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4247 #define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4249 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
4250 // The following features are defined:
4252 // CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
4253 // CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
4254 // CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
4255 // CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
4256 // CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
4258 // CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
4260 // CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
4262 // In general each macro has a _NO_<feature name> form
4263 // (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
4264 // Many features, at point of detection, define an _INTERNAL_ macro, so they
4265 // can be combined, en-mass, with the _NO_ forms later.
4267 // All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
4271 #if __has_feature(cxx_nullptr)
4272 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4275 #if __has_feature(cxx_noexcept)
4276 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4281 ////////////////////////////////////////////////////////////////////////////////
4285 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
4286 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4289 // - otherwise more recent versions define __cplusplus >= 201103L
4290 // and will get picked up below
4294 ////////////////////////////////////////////////////////////////////////////////
4298 #if (_MSC_VER >= 1600)
4299 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4300 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4303 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
4304 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4305 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4310 ////////////////////////////////////////////////////////////////////////////////
4311 // C++ language feature support
4313 // catch all support for C++11
4314 #if defined(__cplusplus) && __cplusplus >= 201103L
4316 #define CLARA_CPP11_OR_GREATER
4318 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
4319 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4322 #ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4323 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4326 #ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4327 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4330 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
4331 #define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
4333 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
4334 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4337 #endif // __cplusplus >= 201103L
4339 // Now set the actual defines based on the above + anything the user has configured
4340 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
4341 #define CLARA_CONFIG_CPP11_NULLPTR
4343 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
4344 #define CLARA_CONFIG_CPP11_NOEXCEPT
4346 #if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11)
4347 #define CLARA_CONFIG_CPP11_GENERATED_METHODS
4349 #if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
4350 #define CLARA_CONFIG_CPP11_OVERRIDE
4352 #if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11)
4353 #define CLARA_CONFIG_CPP11_UNIQUE_PTR
4356 // noexcept support:
4357 #if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
4358 #define CLARA_NOEXCEPT noexcept
4359 # define CLARA_NOEXCEPT_IS(x) noexcept(x)
4361 #define CLARA_NOEXCEPT throw()
4362 # define CLARA_NOEXCEPT_IS(x)
4366 #ifdef CLARA_CONFIG_CPP11_NULLPTR
4367 #define CLARA_NULL nullptr
4369 #define CLARA_NULL NULL
4373 #ifdef CLARA_CONFIG_CPP11_OVERRIDE
4374 #define CLARA_OVERRIDE override
4376 #define CLARA_OVERRIDE
4379 // unique_ptr support
4380 #ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
4381 # define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
4383 # define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
4386 #endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4388 // ----------- end of #include from clara_compilers.h -----------
4389 // ........... back in clara.h
4392 #include <stdexcept>
4395 #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
4396 #define CLARA_PLATFORM_WINDOWS
4399 // Use optional outer namespace
4400 #ifdef STITCH_CLARA_OPEN_NAMESPACE
4401 STITCH_CLARA_OPEN_NAMESPACE
4406 struct UnpositionalTag {};
4408 extern UnpositionalTag _;
4410 #ifdef CLARA_CONFIG_MAIN
4416 #ifdef CLARA_CONSOLE_WIDTH
4417 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
4419 const unsigned int consoleWidth = 80;
4422 using namespace Tbc;
4424 inline bool startsWith( std::string const& str, std::string const& prefix ) {
4425 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
4428 template<typename T> struct RemoveConstRef{ typedef T type; };
4429 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
4430 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
4431 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
4433 template<typename T> struct IsBool { static const bool value = false; };
4434 template<> struct IsBool<bool> { static const bool value = true; };
4436 template<typename T>
4437 void convertInto( std::string const& _source, T& _dest ) {
4438 std::stringstream ss;
4442 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
4444 inline void convertInto( std::string const& _source, std::string& _dest ) {
4447 char toLowerCh(char c) {
4448 return static_cast<char>( std::tolower( c ) );
4450 inline void convertInto( std::string const& _source, bool& _dest ) {
4451 std::string sourceLC = _source;
4452 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
4453 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
4455 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
4458 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
4461 template<typename ConfigT>
4462 struct IArgFunction {
4463 virtual ~IArgFunction() {}
4464 #ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
4465 IArgFunction() = default;
4466 IArgFunction( IArgFunction const& ) = default;
4468 virtual void set( ConfigT& config, std::string const& value ) const = 0;
4469 virtual bool takesArg() const = 0;
4470 virtual IArgFunction* clone() const = 0;
4473 template<typename ConfigT>
4474 class BoundArgFunction {
4476 BoundArgFunction() : functionObj( CLARA_NULL ) {}
4477 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
4478 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
4479 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
4480 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
4482 functionObj = newFunctionObj;
4485 ~BoundArgFunction() { delete functionObj; }
4487 void set( ConfigT& config, std::string const& value ) const {
4488 functionObj->set( config, value );
4490 bool takesArg() const { return functionObj->takesArg(); }
4492 bool isSet() const {
4493 return functionObj != CLARA_NULL;
4496 IArgFunction<ConfigT>* functionObj;
4499 template<typename C>
4500 struct NullBinder : IArgFunction<C>{
4501 virtual void set( C&, std::string const& ) const {}
4502 virtual bool takesArg() const { return true; }
4503 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
4506 template<typename C, typename M>
4507 struct BoundDataMember : IArgFunction<C>{
4508 BoundDataMember( M C::* _member ) : member( _member ) {}
4509 virtual void set( C& p, std::string const& stringValue ) const {
4510 convertInto( stringValue, p.*member );
4512 virtual bool takesArg() const { return !IsBool<M>::value; }
4513 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
4516 template<typename C, typename M>
4517 struct BoundUnaryMethod : IArgFunction<C>{
4518 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
4519 virtual void set( C& p, std::string const& stringValue ) const {
4520 typename RemoveConstRef<M>::type value;
4521 convertInto( stringValue, value );
4522 (p.*member)( value );
4524 virtual bool takesArg() const { return !IsBool<M>::value; }
4525 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
4526 void (C::*member)( M );
4528 template<typename C>
4529 struct BoundNullaryMethod : IArgFunction<C>{
4530 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
4531 virtual void set( C& p, std::string const& stringValue ) const {
4533 convertInto( stringValue, value );
4537 virtual bool takesArg() const { return false; }
4538 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
4539 void (C::*member)();
4542 template<typename C>
4543 struct BoundUnaryFunction : IArgFunction<C>{
4544 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
4545 virtual void set( C& obj, std::string const& stringValue ) const {
4547 convertInto( stringValue, value );
4551 virtual bool takesArg() const { return false; }
4552 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
4553 void (*function)( C& );
4556 template<typename C, typename T>
4557 struct BoundBinaryFunction : IArgFunction<C>{
4558 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
4559 virtual void set( C& obj, std::string const& stringValue ) const {
4560 typename RemoveConstRef<T>::type value;
4561 convertInto( stringValue, value );
4562 function( obj, value );
4564 virtual bool takesArg() const { return !IsBool<T>::value; }
4565 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
4566 void (*function)( C&, T );
4569 } // namespace Detail
4571 inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
4572 std::vector<std::string> args( static_cast<std::size_t>( argc ) );
4573 for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
4580 enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
4587 enum Type { Positional, ShortOpt, LongOpt };
4588 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
4593 Parser() : mode( None ), from( 0 ), inQuotes( false ){}
4595 void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
4596 const std::string doubleDash = "--";
4597 for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
4598 parseIntoTokens( args[i], tokens);
4601 void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
4602 for( std::size_t i = 0; i < arg.size(); ++i ) {
4605 inQuotes = !inQuotes;
4606 mode = handleMode( i, c, arg, tokens );
4608 mode = handleMode( arg.size(), '\0', arg, tokens );
4610 Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4612 case None: return handleNone( i, c );
4613 case MaybeShortOpt: return handleMaybeShortOpt( i, c );
4616 case SlashOpt: return handleOpt( i, c, arg, tokens );
4617 case Positional: return handlePositional( i, c, arg, tokens );
4618 default: throw std::logic_error( "Unknown mode" );
4622 Mode handleNone( std::size_t i, char c ) {
4628 case '-': return MaybeShortOpt;
4629 #ifdef CLARA_PLATFORM_WINDOWS
4630 case '/': from = i+1; return SlashOpt;
4632 default: from = i; return Positional;
4635 Mode handleMaybeShortOpt( std::size_t i, char c ) {
4637 case '-': from = i+1; return LongOpt;
4638 default: from = i; return ShortOpt;
4642 Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4643 if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
4646 std::string optName = arg.substr( from, i-from );
4647 if( mode == ShortOpt )
4648 for( std::size_t j = 0; j < optName.size(); ++j )
4649 tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
4650 else if( mode == SlashOpt && optName.size() == 1 )
4651 tokens.push_back( Token( Token::ShortOpt, optName ) );
4653 tokens.push_back( Token( Token::LongOpt, optName ) );
4656 Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4657 if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
4660 std::string data = arg.substr( from, i-from );
4661 tokens.push_back( Token( Token::Positional, data ) );
4666 template<typename ConfigT>
4667 struct CommonArgProperties {
4668 CommonArgProperties() {}
4669 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
4671 Detail::BoundArgFunction<ConfigT> boundField;
4672 std::string description;
4674 std::string placeholder; // Only value if boundField takes an arg
4676 bool takesArg() const {
4677 return !placeholder.empty();
4679 void validate() const {
4680 if( !boundField.isSet() )
4681 throw std::logic_error( "option not bound" );
4684 struct OptionArgProperties {
4685 std::vector<std::string> shortNames;
4686 std::string longName;
4688 bool hasShortName( std::string const& shortName ) const {
4689 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4691 bool hasLongName( std::string const& _longName ) const {
4692 return _longName == longName;
4695 struct PositionalArgProperties {
4696 PositionalArgProperties() : position( -1 ) {}
4697 int position; // -1 means non-positional (floating)
4699 bool isFixedPositional() const {
4700 return position != -1;
4704 template<typename ConfigT>
4707 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
4709 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
4711 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4713 std::string dbgName() const {
4714 if( !longName.empty() )
4715 return "--" + longName;
4716 if( !shortNames.empty() )
4717 return "-" + shortNames[0];
4718 return "positional args";
4720 std::string commands() const {
4721 std::ostringstream oss;
4723 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4724 for(; it != itEnd; ++it ) {
4731 if( !longName.empty() ) {
4734 oss << "--" << longName;
4736 if( !placeholder.empty() )
4737 oss << " <" << placeholder << ">";
4742 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
4744 friend void addOptName( Arg& arg, std::string const& optName )
4746 if( optName.empty() )
4748 if( Detail::startsWith( optName, "--" ) ) {
4749 if( !arg.longName.empty() )
4750 throw std::logic_error( "Only one long opt may be specified. '"
4752 + "' already specified, now attempting to add '"
4754 arg.longName = optName.substr( 2 );
4756 else if( Detail::startsWith( optName, "-" ) )
4757 arg.shortNames.push_back( optName.substr( 1 ) );
4759 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
4761 friend void setPositionalArg( Arg& arg, int position )
4763 arg.position = position;
4768 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
4770 // Bind a non-boolean data member (requires placeholder string)
4771 template<typename C, typename M>
4772 void bind( M C::* field, std::string const& placeholder ) {
4773 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
4774 m_arg->placeholder = placeholder;
4776 // Bind a boolean data member (no placeholder required)
4777 template<typename C>
4778 void bind( bool C::* field ) {
4779 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
4782 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4783 template<typename C, typename M>
4784 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
4785 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4786 m_arg->placeholder = placeholder;
4789 // Bind a method taking a single, boolean argument (no placeholder string required)
4790 template<typename C>
4791 void bind( void (C::* unaryMethod)( bool ) ) {
4792 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
4795 // Bind a method that takes no arguments (will be called if opt is present)
4796 template<typename C>
4797 void bind( void (C::* nullaryMethod)() ) {
4798 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
4801 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4802 template<typename C>
4803 void bind( void (* unaryFunction)( C& ) ) {
4804 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
4807 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4808 template<typename C, typename T>
4809 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
4810 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4811 m_arg->placeholder = placeholder;
4814 ArgBuilder& describe( std::string const& description ) {
4815 m_arg->description = description;
4818 ArgBuilder& detail( std::string const& detail ) {
4819 m_arg->detail = detail;
4827 class OptBuilder : public ArgBuilder {
4829 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
4830 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4832 OptBuilder& operator[]( std::string const& optName ) {
4833 addOptName( *ArgBuilder::m_arg, optName );
4841 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
4842 m_highestSpecifiedArgPosition( 0 ),
4843 m_throwOnUnrecognisedTokens( false )
4845 CommandLine( CommandLine const& other )
4846 : m_boundProcessName( other.m_boundProcessName ),
4847 m_options ( other.m_options ),
4848 m_positionalArgs( other.m_positionalArgs ),
4849 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4850 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
4852 if( other.m_floatingArg.get() )
4853 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
4856 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
4857 m_throwOnUnrecognisedTokens = shouldThrow;
4861 OptBuilder operator[]( std::string const& optName ) {
4862 m_options.push_back( Arg() );
4863 addOptName( m_options.back(), optName );
4864 OptBuilder builder( &m_options.back() );
4868 ArgBuilder operator[]( int position ) {
4869 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4870 if( position > m_highestSpecifiedArgPosition )
4871 m_highestSpecifiedArgPosition = position;
4872 setPositionalArg( m_positionalArgs[position], position );
4873 ArgBuilder builder( &m_positionalArgs[position] );
4877 // Invoke this with the _ instance
4878 ArgBuilder operator[]( UnpositionalTag ) {
4879 if( m_floatingArg.get() )
4880 throw std::logic_error( "Only one unpositional argument can be added" );
4881 m_floatingArg.reset( new Arg() );
4882 ArgBuilder builder( m_floatingArg.get() );
4886 template<typename C, typename M>
4887 void bindProcessName( M C::* field ) {
4888 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
4890 template<typename C, typename M>
4891 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
4892 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
4895 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
4896 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4897 std::size_t maxWidth = 0;
4898 for( it = itBegin; it != itEnd; ++it )
4899 maxWidth = (std::max)( maxWidth, it->commands().size() );
4901 for( it = itBegin; it != itEnd; ++it ) {
4902 Detail::Text usage( it->commands(), Detail::TextAttributes()
4903 .setWidth( maxWidth+indent )
4904 .setIndent( indent ) );
4905 Detail::Text desc( it->description, Detail::TextAttributes()
4906 .setWidth( width - maxWidth - 3 ) );
4908 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
4909 std::string usageCol = i < usage.size() ? usage[i] : "";
4912 if( i < desc.size() && !desc[i].empty() )
4913 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
4919 std::string optUsage() const {
4920 std::ostringstream oss;
4925 void argSynopsis( std::ostream& os ) const {
4926 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4929 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4930 if( it != m_positionalArgs.end() )
4931 os << "<" << it->second.placeholder << ">";
4932 else if( m_floatingArg.get() )
4933 os << "<" << m_floatingArg->placeholder << ">";
4935 throw std::logic_error( "non consecutive positional arguments with no floating args" );
4937 // !TBD No indication of mandatory args
4938 if( m_floatingArg.get() ) {
4939 if( m_highestSpecifiedArgPosition > 1 )
4941 os << "[<" << m_floatingArg->placeholder << "> ...]";
4944 std::string argSynopsis() const {
4945 std::ostringstream oss;
4950 void usage( std::ostream& os, std::string const& procName ) const {
4952 os << "usage:\n " << procName << " ";
4954 if( !m_options.empty() ) {
4955 os << " [options]\n\nwhere options are: \n";
4960 std::string usage( std::string const& procName ) const {
4961 std::ostringstream oss;
4962 usage( oss, procName );
4966 ConfigT parse( std::vector<std::string> const& args ) const {
4968 parseInto( args, config );
4972 std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
4973 std::string processName = args.empty() ? std::string() : args[0];
4974 std::size_t lastSlash = processName.find_last_of( "/\\" );
4975 if( lastSlash != std::string::npos )
4976 processName = processName.substr( lastSlash+1 );
4977 m_boundProcessName.set( config, processName );
4978 std::vector<Parser::Token> tokens;
4980 parser.parseIntoTokens( args, tokens );
4981 return populate( tokens, config );
4984 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4986 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4987 unusedTokens = populateFixedArgs( unusedTokens, config );
4988 unusedTokens = populateFloatingArgs( unusedTokens, config );
4989 return unusedTokens;
4992 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4993 std::vector<Parser::Token> unusedTokens;
4994 std::vector<std::string> errors;
4995 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4996 Parser::Token const& token = tokens[i];
4997 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4998 for(; it != itEnd; ++it ) {
4999 Arg const& arg = *it;
5002 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
5003 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
5004 if( arg.takesArg() ) {
5005 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
5006 errors.push_back( "Expected argument to option: " + token.data );
5008 arg.boundField.set( config, tokens[++i].data );
5011 arg.boundField.set( config, "true" );
5016 catch( std::exception& ex ) {
5017 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
5021 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
5022 unusedTokens.push_back( token );
5023 else if( errors.empty() && m_throwOnUnrecognisedTokens )
5024 errors.push_back( "unrecognised option: " + token.data );
5027 if( !errors.empty() ) {
5028 std::ostringstream oss;
5029 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
5032 if( it != errors.begin() )
5036 throw std::runtime_error( oss.str() );
5038 return unusedTokens;
5040 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
5041 std::vector<Parser::Token> unusedTokens;
5043 for( std::size_t i = 0; i < tokens.size(); ++i ) {
5044 Parser::Token const& token = tokens[i];
5045 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
5046 if( it != m_positionalArgs.end() )
5047 it->second.boundField.set( config, token.data );
5049 unusedTokens.push_back( token );
5050 if( token.type == Parser::Token::Positional )
5053 return unusedTokens;
5055 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
5056 if( !m_floatingArg.get() )
5058 std::vector<Parser::Token> unusedTokens;
5059 for( std::size_t i = 0; i < tokens.size(); ++i ) {
5060 Parser::Token const& token = tokens[i];
5061 if( token.type == Parser::Token::Positional )
5062 m_floatingArg->boundField.set( config, token.data );
5064 unusedTokens.push_back( token );
5066 return unusedTokens;
5069 void validate() const
5071 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
5072 throw std::logic_error( "No options or arguments specified" );
5074 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
5075 itEnd = m_options.end();
5081 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
5082 std::vector<Arg> m_options;
5083 std::map<int, Arg> m_positionalArgs;
5084 ArgAutoPtr m_floatingArg;
5085 int m_highestSpecifiedArgPosition;
5086 bool m_throwOnUnrecognisedTokens;
5089 } // end namespace Clara
5091 STITCH_CLARA_CLOSE_NAMESPACE
5092 #undef STITCH_CLARA_OPEN_NAMESPACE
5093 #undef STITCH_CLARA_CLOSE_NAMESPACE
5095 #endif // TWOBLUECUBES_CLARA_H_INCLUDED
5096 #undef STITCH_CLARA_OPEN_NAMESPACE
5098 // Restore Clara's value for console width, if present
5099 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5100 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5101 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5109 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
5110 inline void abortAfterX( ConfigData& config, int x ) {
5112 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
5113 config.abortAfter = x;
5115 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
5116 inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
5117 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
5119 inline void addWarning( ConfigData& config, std::string const& _warning ) {
5120 if( _warning == "NoAssertions" )
5121 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
5123 throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
5125 inline void setOrder( ConfigData& config, std::string const& order ) {
5126 if( startsWith( "declared", order ) )
5127 config.runOrder = RunTests::InDeclarationOrder;
5128 else if( startsWith( "lexical", order ) )
5129 config.runOrder = RunTests::InLexicographicalOrder;
5130 else if( startsWith( "random", order ) )
5131 config.runOrder = RunTests::InRandomOrder;
5133 throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
5135 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
5136 if( seed == "time" ) {
5137 config.rngSeed = static_cast<unsigned int>( std::time(0) );
5140 std::stringstream ss;
5142 ss >> config.rngSeed;
5144 throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" );
5147 inline void setVerbosity( ConfigData& config, int level ) {
5148 // !TBD: accept strings?
5149 config.verbosity = static_cast<Verbosity::Level>( level );
5151 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
5152 config.showDurations = _showDurations
5153 ? ShowDurations::Always
5154 : ShowDurations::Never;
5156 inline void setUseColour( ConfigData& config, std::string const& value ) {
5157 std::string mode = toLower( value );
5160 config.useColour = UseColour::Yes;
5161 else if( mode == "no" )
5162 config.useColour = UseColour::No;
5163 else if( mode == "auto" )
5164 config.useColour = UseColour::Auto;
5166 throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
5168 inline void forceColour( ConfigData& config ) {
5169 config.useColour = UseColour::Yes;
5171 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
5172 std::ifstream f( _filename.c_str() );
5174 throw std::domain_error( "Unable to load input file: " + _filename );
5177 while( std::getline( f, line ) ) {
5179 if( !line.empty() && !startsWith( line, '#' ) ) {
5180 if( !startsWith( line, '"' ) )
5181 line = '"' + line + '"';
5182 addTestOrTags( config, line + ',' );
5187 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
5189 using namespace Clara;
5190 CommandLine<ConfigData> cli;
5192 cli.bindProcessName( &ConfigData::processName );
5194 cli["-?"]["-h"]["--help"]
5195 .describe( "display usage information" )
5196 .bind( &ConfigData::showHelp );
5198 cli["-l"]["--list-tests"]
5199 .describe( "list all/matching test cases" )
5200 .bind( &ConfigData::listTests );
5202 cli["-t"]["--list-tags"]
5203 .describe( "list all/matching tags" )
5204 .bind( &ConfigData::listTags );
5206 cli["-s"]["--success"]
5207 .describe( "include successful tests in output" )
5208 .bind( &ConfigData::showSuccessfulTests );
5210 cli["-b"]["--break"]
5211 .describe( "break into debugger on failure" )
5212 .bind( &ConfigData::shouldDebugBreak );
5214 cli["-e"]["--nothrow"]
5215 .describe( "skip exception tests" )
5216 .bind( &ConfigData::noThrow );
5218 cli["-i"]["--invisibles"]
5219 .describe( "show invisibles (tabs, newlines)" )
5220 .bind( &ConfigData::showInvisibles );
5223 .describe( "output filename" )
5224 .bind( &ConfigData::outputFilename, "filename" );
5226 cli["-r"]["--reporter"]
5227 // .placeholder( "name[:filename]" )
5228 .describe( "reporter to use (defaults to console)" )
5229 .bind( &addReporterName, "name" );
5232 .describe( "suite name" )
5233 .bind( &ConfigData::name, "name" );
5235 cli["-a"]["--abort"]
5236 .describe( "abort at first failure" )
5237 .bind( &abortAfterFirst );
5239 cli["-x"]["--abortx"]
5240 .describe( "abort after x failures" )
5241 .bind( &abortAfterX, "no. failures" );
5244 .describe( "enable warnings" )
5245 .bind( &addWarning, "warning name" );
5247 // - needs updating if reinstated
5248 // cli.into( &setVerbosity )
5249 // .describe( "level of verbosity (0=no output)" )
5251 // .longOpt( "verbosity" )
5252 // .placeholder( "level" );
5255 .describe( "which test or tests to use" )
5256 .bind( &addTestOrTags, "test name, pattern or tags" );
5258 cli["-d"]["--durations"]
5259 .describe( "show test durations" )
5260 .bind( &setShowDurations, "yes|no" );
5262 cli["-f"]["--input-file"]
5263 .describe( "load test names to run from a file" )
5264 .bind( &loadTestNamesFromFile, "filename" );
5266 cli["-#"]["--filenames-as-tags"]
5267 .describe( "adds a tag for the filename" )
5268 .bind( &ConfigData::filenamesAsTags );
5270 cli["-c"]["--section"]
5271 .describe( "specify section to run" )
5272 .bind( &addSectionToRun, "section name" );
5274 // Less common commands which don't have a short form
5275 cli["--list-test-names-only"]
5276 .describe( "list all/matching test cases names only" )
5277 .bind( &ConfigData::listTestNamesOnly );
5279 cli["--list-reporters"]
5280 .describe( "list all reporters" )
5281 .bind( &ConfigData::listReporters );
5284 .describe( "test case order (defaults to decl)" )
5285 .bind( &setOrder, "decl|lex|rand" );
5288 .describe( "set a specific seed for random numbers" )
5289 .bind( &setRngSeed, "'time'|number" );
5291 cli["--force-colour"]
5292 .describe( "force colourised output (deprecated)" )
5293 .bind( &forceColour );
5296 .describe( "should output be colourised" )
5297 .bind( &setUseColour, "yes|no" );
5302 } // end namespace Catch
5304 // #included from: internal/catch_list.hpp
5305 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
5307 // #included from: catch_text.h
5308 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
5310 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
5312 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
5313 // #included from: ../external/tbc_text_format.h
5314 // Only use header guard if we are not using an outer namespace
5315 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5316 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5317 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5318 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5321 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5324 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5329 // Use optional outer namespace
5330 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5331 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
5336 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
5337 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
5339 const unsigned int consoleWidth = 80;
5342 struct TextAttributes {
5344 : initialIndent( std::string::npos ),
5346 width( consoleWidth-1 )
5349 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
5350 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
5351 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
5353 std::size_t initialIndent; // indent of first line, or npos
5354 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
5355 std::size_t width; // maximum width of text, including indent. Longer text will wrap
5360 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
5363 const std::string wrappableBeforeChars = "[({<\t";
5364 const std::string wrappableAfterChars = "])}>-,./|\\";
5365 const std::string wrappableInsteadOfChars = " \n\r";
5366 std::string indent = _attr.initialIndent != std::string::npos
5367 ? std::string( _attr.initialIndent, ' ' )
5368 : std::string( _attr.indent, ' ' );
5370 typedef std::string::const_iterator iterator;
5371 iterator it = _str.begin();
5372 const iterator strEnd = _str.end();
5374 while( it != strEnd ) {
5376 if( lines.size() >= 1000 ) {
5377 lines.push_back( "... message truncated due to excessive size" );
5382 std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
5383 iterator itEnd = it+width;
5384 iterator itNext = _str.end();
5386 iterator itNewLine = std::find( it, itEnd, '\n' );
5387 if( itNewLine != itEnd )
5390 if( itEnd != strEnd ) {
5391 bool foundWrapPoint = false;
5392 iterator findIt = itEnd;
5394 if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
5397 foundWrapPoint = true;
5399 else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
5402 foundWrapPoint = true;
5404 else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
5407 foundWrapPoint = true;
5414 while( !foundWrapPoint );
5416 if( !foundWrapPoint ) {
5417 // No good wrap char, so we'll break mid word and add a hyphen
5423 while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
5427 lines.push_back( indent + std::string( it, itEnd ) + suffix );
5429 if( indent.size() != _attr.indent )
5430 indent = std::string( _attr.indent, ' ' );
5435 typedef std::vector<std::string>::const_iterator const_iterator;
5437 const_iterator begin() const { return lines.begin(); }
5438 const_iterator end() const { return lines.end(); }
5439 std::string const& last() const { return lines.back(); }
5440 std::size_t size() const { return lines.size(); }
5441 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
5442 std::string toString() const {
5443 std::ostringstream oss;
5448 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
5449 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
5450 it != itEnd; ++it ) {
5451 if( it != _text.begin() )
5460 TextAttributes attr;
5461 std::vector<std::string> lines;
5464 } // end namespace Tbc
5466 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5467 } // end outer namespace
5470 #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5471 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5475 using Tbc::TextAttributes;
5478 // #included from: catch_console_colour.hpp
5479 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
5497 BrightRed = Bright | Red,
5498 BrightGreen = Bright | Green,
5499 LightGrey = Bright | Grey,
5500 BrightWhite = Bright | White,
5503 FileName = LightGrey,
5505 ResultError = BrightRed,
5506 ResultSuccess = BrightGreen,
5507 ResultExpectedFailure = Warning,
5512 OriginalExpression = Cyan,
5513 ReconstructedExpression = Yellow,
5515 SecondaryText = LightGrey,
5519 // Use constructed object for RAII guard
5520 Colour( Code _colourCode );
5521 Colour( Colour const& other );
5524 // Use static method for one-shot changes
5525 static void use( Code _colourCode );
5531 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
5533 } // end namespace Catch
5535 // #included from: catch_interfaces_reporter.h
5536 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5544 struct ReporterConfig {
5545 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
5546 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
5548 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
5549 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
5551 std::ostream& stream() const { return *m_stream; }
5552 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
5555 std::ostream* m_stream;
5556 Ptr<IConfig const> m_fullConfig;
5559 struct ReporterPreferences {
5560 ReporterPreferences()
5561 : shouldRedirectStdOut( false )
5564 bool shouldRedirectStdOut;
5567 template<typename T>
5568 struct LazyStat : Option<T> {
5569 LazyStat() : used( false ) {}
5570 LazyStat& operator=( T const& _value ) {
5571 Option<T>::operator=( _value );
5582 struct TestRunInfo {
5583 TestRunInfo( std::string const& _name ) : name( _name ) {}
5587 GroupInfo( std::string const& _name,
5588 std::size_t _groupIndex,
5589 std::size_t _groupsCount )
5591 groupIndex( _groupIndex ),
5592 groupsCounts( _groupsCount )
5596 std::size_t groupIndex;
5597 std::size_t groupsCounts;
5600 struct AssertionStats {
5601 AssertionStats( AssertionResult const& _assertionResult,
5602 std::vector<MessageInfo> const& _infoMessages,
5603 Totals const& _totals )
5604 : assertionResult( _assertionResult ),
5605 infoMessages( _infoMessages ),
5608 if( assertionResult.hasMessage() ) {
5609 // Copy message into messages list.
5610 // !TBD This should have been done earlier, somewhere
5611 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
5612 builder << assertionResult.getMessage();
5613 builder.m_info.message = builder.m_stream.str();
5615 infoMessages.push_back( builder.m_info );
5618 virtual ~AssertionStats();
5620 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5621 AssertionStats( AssertionStats const& ) = default;
5622 AssertionStats( AssertionStats && ) = default;
5623 AssertionStats& operator = ( AssertionStats const& ) = default;
5624 AssertionStats& operator = ( AssertionStats && ) = default;
5627 AssertionResult assertionResult;
5628 std::vector<MessageInfo> infoMessages;
5632 struct SectionStats {
5633 SectionStats( SectionInfo const& _sectionInfo,
5634 Counts const& _assertions,
5635 double _durationInSeconds,
5636 bool _missingAssertions )
5637 : sectionInfo( _sectionInfo ),
5638 assertions( _assertions ),
5639 durationInSeconds( _durationInSeconds ),
5640 missingAssertions( _missingAssertions )
5642 virtual ~SectionStats();
5643 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5644 SectionStats( SectionStats const& ) = default;
5645 SectionStats( SectionStats && ) = default;
5646 SectionStats& operator = ( SectionStats const& ) = default;
5647 SectionStats& operator = ( SectionStats && ) = default;
5650 SectionInfo sectionInfo;
5652 double durationInSeconds;
5653 bool missingAssertions;
5656 struct TestCaseStats {
5657 TestCaseStats( TestCaseInfo const& _testInfo,
5658 Totals const& _totals,
5659 std::string const& _stdOut,
5660 std::string const& _stdErr,
5662 : testInfo( _testInfo ),
5666 aborting( _aborting )
5668 virtual ~TestCaseStats();
5670 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5671 TestCaseStats( TestCaseStats const& ) = default;
5672 TestCaseStats( TestCaseStats && ) = default;
5673 TestCaseStats& operator = ( TestCaseStats const& ) = default;
5674 TestCaseStats& operator = ( TestCaseStats && ) = default;
5677 TestCaseInfo testInfo;
5684 struct TestGroupStats {
5685 TestGroupStats( GroupInfo const& _groupInfo,
5686 Totals const& _totals,
5688 : groupInfo( _groupInfo ),
5690 aborting( _aborting )
5692 TestGroupStats( GroupInfo const& _groupInfo )
5693 : groupInfo( _groupInfo ),
5696 virtual ~TestGroupStats();
5698 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
5699 TestGroupStats( TestGroupStats const& ) = default;
5700 TestGroupStats( TestGroupStats && ) = default;
5701 TestGroupStats& operator = ( TestGroupStats const& ) = default;
5702 TestGroupStats& operator = ( TestGroupStats && ) = default;
5705 GroupInfo groupInfo;
5710 struct TestRunStats {
5711 TestRunStats( TestRunInfo const& _runInfo,
5712 Totals const& _totals,
5714 : runInfo( _runInfo ),
5716 aborting( _aborting )
5718 virtual ~TestRunStats();
5720 # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
5721 TestRunStats( TestRunStats const& _other )
5722 : runInfo( _other.runInfo ),
5723 totals( _other.totals ),
5724 aborting( _other.aborting )
5727 TestRunStats( TestRunStats const& ) = default;
5728 TestRunStats( TestRunStats && ) = default;
5729 TestRunStats& operator = ( TestRunStats const& ) = default;
5730 TestRunStats& operator = ( TestRunStats && ) = default;
5733 TestRunInfo runInfo;
5738 class MultipleReporters;
5740 struct IStreamingReporter : IShared {
5741 virtual ~IStreamingReporter();
5743 // Implementing class must also provide the following static method:
5744 // static std::string getDescription();
5746 virtual ReporterPreferences getPreferences() const = 0;
5748 virtual void noMatchingTestCases( std::string const& spec ) = 0;
5750 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5751 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5753 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5754 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5756 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5758 // The return value indicates if the messages buffer should be cleared:
5759 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
5761 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5762 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5763 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5764 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
5766 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
5768 virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
5771 struct IReporterFactory : IShared {
5772 virtual ~IReporterFactory();
5773 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
5774 virtual std::string getDescription() const = 0;
5777 struct IReporterRegistry {
5778 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5779 typedef std::vector<Ptr<IReporterFactory> > Listeners;
5781 virtual ~IReporterRegistry();
5782 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
5783 virtual FactoryMap const& getFactories() const = 0;
5784 virtual Listeners const& getListeners() const = 0;
5787 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
5792 #include <algorithm>
5796 inline std::size_t listTests( Config const& config ) {
5798 TestSpec testSpec = config.testSpec();
5799 if( config.testSpec().hasFilters() )
5800 Catch::cout() << "Matching test cases:\n";
5802 Catch::cout() << "All available test cases:\n";
5803 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5806 std::size_t matchedTests = 0;
5807 TextAttributes nameAttr, tagsAttr;
5808 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5809 tagsAttr.setIndent( 6 );
5811 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5812 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5816 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5817 Colour::Code colour = testCaseInfo.isHidden()
5818 ? Colour::SecondaryText
5820 Colour colourGuard( colour );
5822 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
5823 if( !testCaseInfo.tags.empty() )
5824 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
5827 if( !config.testSpec().hasFilters() )
5828 Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
5830 Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
5831 return matchedTests;
5834 inline std::size_t listTestsNamesOnly( Config const& config ) {
5835 TestSpec testSpec = config.testSpec();
5836 if( !config.testSpec().hasFilters() )
5837 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5838 std::size_t matchedTests = 0;
5839 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5840 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5844 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
5845 if( startsWith( testCaseInfo.name, '#' ) )
5846 Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl;
5848 Catch::cout() << testCaseInfo.name << std::endl;
5850 return matchedTests;
5854 TagInfo() : count ( 0 ) {}
5855 void add( std::string const& spelling ) {
5857 spellings.insert( spelling );
5859 std::string all() const {
5861 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5864 out += "[" + *it + "]";
5867 std::set<std::string> spellings;
5871 inline std::size_t listTags( Config const& config ) {
5872 TestSpec testSpec = config.testSpec();
5873 if( config.testSpec().hasFilters() )
5874 Catch::cout() << "Tags for matching test cases:\n";
5876 Catch::cout() << "All available tags:\n";
5877 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
5880 std::map<std::string, TagInfo> tagCounts;
5882 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
5883 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
5886 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5887 tagItEnd = it->getTestCaseInfo().tags.end();
5890 std::string tagName = *tagIt;
5891 std::string lcaseTagName = toLower( tagName );
5892 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
5893 if( countIt == tagCounts.end() )
5894 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5895 countIt->second.add( tagName );
5899 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5900 countItEnd = tagCounts.end();
5901 countIt != countItEnd;
5903 std::ostringstream oss;
5904 oss << " " << std::setw(2) << countIt->second.count << " ";
5905 Text wrapper( countIt->second.all(), TextAttributes()
5906 .setInitialIndent( 0 )
5907 .setIndent( oss.str().size() )
5908 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
5909 Catch::cout() << oss.str() << wrapper << '\n';
5911 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
5912 return tagCounts.size();
5915 inline std::size_t listReporters( Config const& /*config*/ ) {
5916 Catch::cout() << "Available reporters:\n";
5917 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
5918 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5919 std::size_t maxNameLen = 0;
5920 for(it = itBegin; it != itEnd; ++it )
5921 maxNameLen = (std::max)( maxNameLen, it->first.size() );
5923 for(it = itBegin; it != itEnd; ++it ) {
5924 Text wrapper( it->second->getDescription(), TextAttributes()
5925 .setInitialIndent( 0 )
5926 .setIndent( 7+maxNameLen )
5927 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
5928 Catch::cout() << " "
5931 << std::string( maxNameLen - it->first.size() + 2, ' ' )
5934 Catch::cout() << std::endl;
5935 return factories.size();
5938 inline Option<std::size_t> list( Config const& config ) {
5939 Option<std::size_t> listedCount;
5940 if( config.listTests() )
5941 listedCount = listedCount.valueOr(0) + listTests( config );
5942 if( config.listTestNamesOnly() )
5943 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
5944 if( config.listTags() )
5945 listedCount = listedCount.valueOr(0) + listTags( config );
5946 if( config.listReporters() )
5947 listedCount = listedCount.valueOr(0) + listReporters( config );
5951 } // end namespace Catch
5953 // #included from: internal/catch_run_context.hpp
5954 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
5956 // #included from: catch_test_case_tracker.hpp
5957 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
5959 #include <algorithm>
5963 #include <stdexcept>
5965 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
5968 namespace TestCaseTracking {
5970 struct NameAndLocation {
5972 SourceLineInfo location;
5974 NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
5976 location( _location )
5980 struct ITracker : SharedImpl<> {
5981 virtual ~ITracker();
5984 virtual NameAndLocation const& nameAndLocation() const = 0;
5987 virtual bool isComplete() const = 0; // Successfully completed or failed
5988 virtual bool isSuccessfullyCompleted() const = 0;
5989 virtual bool isOpen() const = 0; // Started but not complete
5990 virtual bool hasChildren() const = 0;
5992 virtual ITracker& parent() = 0;
5995 virtual void close() = 0; // Successfully complete
5996 virtual void fail() = 0;
5997 virtual void markAsNeedingAnotherRun() = 0;
5999 virtual void addChild( Ptr<ITracker> const& child ) = 0;
6000 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0;
6001 virtual void openChild() = 0;
6004 virtual bool isSectionTracker() const = 0;
6005 virtual bool isIndexTracker() const = 0;
6008 class TrackerContext {
6016 Ptr<ITracker> m_rootTracker;
6017 ITracker* m_currentTracker;
6018 RunState m_runState;
6022 static TrackerContext& instance() {
6023 static TrackerContext s_instance;
6028 : m_currentTracker( CATCH_NULL ),
6029 m_runState( NotStarted )
6032 ITracker& startRun();
6035 m_rootTracker.reset();
6036 m_currentTracker = CATCH_NULL;
6037 m_runState = NotStarted;
6041 m_currentTracker = m_rootTracker.get();
6042 m_runState = Executing;
6044 void completeCycle() {
6045 m_runState = CompletedCycle;
6048 bool completedCycle() const {
6049 return m_runState == CompletedCycle;
6051 ITracker& currentTracker() {
6052 return *m_currentTracker;
6054 void setCurrentTracker( ITracker* tracker ) {
6055 m_currentTracker = tracker;
6059 class TrackerBase : public ITracker {
6066 CompletedSuccessfully,
6069 class TrackerHasName {
6070 NameAndLocation m_nameAndLocation;
6072 TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
6073 bool operator ()( Ptr<ITracker> const& tracker ) {
6075 tracker->nameAndLocation().name == m_nameAndLocation.name &&
6076 tracker->nameAndLocation().location == m_nameAndLocation.location;
6079 typedef std::vector<Ptr<ITracker> > Children;
6080 NameAndLocation m_nameAndLocation;
6081 TrackerContext& m_ctx;
6083 Children m_children;
6084 CycleState m_runState;
6086 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6087 : m_nameAndLocation( nameAndLocation ),
6090 m_runState( NotStarted )
6092 virtual ~TrackerBase();
6094 virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE {
6095 return m_nameAndLocation;
6097 virtual bool isComplete() const CATCH_OVERRIDE {
6098 return m_runState == CompletedSuccessfully || m_runState == Failed;
6100 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
6101 return m_runState == CompletedSuccessfully;
6103 virtual bool isOpen() const CATCH_OVERRIDE {
6104 return m_runState != NotStarted && !isComplete();
6106 virtual bool hasChildren() const CATCH_OVERRIDE {
6107 return !m_children.empty();
6110 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
6111 m_children.push_back( child );
6114 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE {
6115 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
6116 return( it != m_children.end() )
6120 virtual ITracker& parent() CATCH_OVERRIDE {
6121 assert( m_parent ); // Should always be non-null except for root
6125 virtual void openChild() CATCH_OVERRIDE {
6126 if( m_runState != ExecutingChildren ) {
6127 m_runState = ExecutingChildren;
6129 m_parent->openChild();
6133 virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
6134 virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
6137 m_runState = Executing;
6140 m_parent->openChild();
6143 virtual void close() CATCH_OVERRIDE {
6145 // Close any still open children (e.g. generators)
6146 while( &m_ctx.currentTracker() != this )
6147 m_ctx.currentTracker().close();
6149 switch( m_runState ) {
6151 case CompletedSuccessfully:
6153 throw std::logic_error( "Illogical state" );
6155 case NeedsAnotherRun:
6159 m_runState = CompletedSuccessfully;
6161 case ExecutingChildren:
6162 if( m_children.empty() || m_children.back()->isComplete() )
6163 m_runState = CompletedSuccessfully;
6167 throw std::logic_error( "Unexpected state" );
6170 m_ctx.completeCycle();
6172 virtual void fail() CATCH_OVERRIDE {
6173 m_runState = Failed;
6175 m_parent->markAsNeedingAnotherRun();
6177 m_ctx.completeCycle();
6179 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
6180 m_runState = NeedsAnotherRun;
6183 void moveToParent() {
6185 m_ctx.setCurrentTracker( m_parent );
6188 m_ctx.setCurrentTracker( this );
6192 class SectionTracker : public TrackerBase {
6193 std::vector<std::string> m_filters;
6195 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6196 : TrackerBase( nameAndLocation, ctx, parent )
6199 while( !parent->isSectionTracker() )
6200 parent = &parent->parent();
6202 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
6203 addNextFilters( parentSection.m_filters );
6206 virtual ~SectionTracker();
6208 virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
6210 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
6211 SectionTracker* section = CATCH_NULL;
6213 ITracker& currentTracker = ctx.currentTracker();
6214 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
6215 assert( childTracker );
6216 assert( childTracker->isSectionTracker() );
6217 section = static_cast<SectionTracker*>( childTracker );
6220 section = new SectionTracker( nameAndLocation, ctx, ¤tTracker );
6221 currentTracker.addChild( section );
6223 if( !ctx.completedCycle() )
6229 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
6233 void addInitialFilters( std::vector<std::string> const& filters ) {
6234 if( !filters.empty() ) {
6235 m_filters.push_back(""); // Root - should never be consulted
6236 m_filters.push_back(""); // Test Case - not a section filter
6237 m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
6240 void addNextFilters( std::vector<std::string> const& filters ) {
6241 if( filters.size() > 1 )
6242 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
6246 class IndexTracker : public TrackerBase {
6250 IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
6251 : TrackerBase( nameAndLocation, ctx, parent ),
6255 virtual ~IndexTracker();
6257 virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
6259 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
6260 IndexTracker* tracker = CATCH_NULL;
6262 ITracker& currentTracker = ctx.currentTracker();
6263 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
6264 assert( childTracker );
6265 assert( childTracker->isIndexTracker() );
6266 tracker = static_cast<IndexTracker*>( childTracker );
6269 tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size );
6270 currentTracker.addChild( tracker );
6273 if( !ctx.completedCycle() && !tracker->isComplete() ) {
6274 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
6275 tracker->moveNext();
6282 int index() const { return m_index; }
6289 virtual void close() CATCH_OVERRIDE {
6290 TrackerBase::close();
6291 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
6292 m_runState = Executing;
6296 inline ITracker& TrackerContext::startRun() {
6297 m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL );
6298 m_currentTracker = CATCH_NULL;
6299 m_runState = Executing;
6300 return *m_rootTracker;
6303 } // namespace TestCaseTracking
6305 using TestCaseTracking::ITracker;
6306 using TestCaseTracking::TrackerContext;
6307 using TestCaseTracking::SectionTracker;
6308 using TestCaseTracking::IndexTracker;
6310 } // namespace Catch
6312 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
6314 // #included from: catch_fatal_condition.hpp
6315 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
6319 // Report the error condition
6320 inline void reportFatal( std::string const& message ) {
6321 IContext& context = Catch::getCurrentContext();
6322 IResultCapture* resultCapture = context.getResultCapture();
6323 resultCapture->handleFatalErrorCondition( message );
6326 } // namespace Catch
6328 #if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
6329 // #included from: catch_windows_h_proxy.h
6331 #define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
6333 #ifdef CATCH_DEFINES_NOMINMAX
6336 #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6337 # define WIN32_LEAN_AND_MEAN
6343 #include <windows.h>
6346 #ifdef CATCH_DEFINES_NOMINMAX
6349 #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6350 # undef WIN32_LEAN_AND_MEAN
6354 # if !defined ( CATCH_CONFIG_WINDOWS_SEH )
6357 struct FatalConditionHandler {
6362 # else // CATCH_CONFIG_WINDOWS_SEH is defined
6366 struct SignalDefs { DWORD id; const char* name; };
6367 extern SignalDefs signalDefs[];
6368 // There is no 1-1 mapping between signals and windows exceptions.
6369 // Windows can easily distinguish between SO and SigSegV,
6370 // but SigInt, SigTerm, etc are handled differently.
6371 SignalDefs signalDefs[] = {
6372 { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
6373 { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
6374 { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
6375 { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
6378 struct FatalConditionHandler {
6380 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
6381 for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6382 if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
6383 reportFatal(signalDefs[i].name);
6386 // If its not an exception we care about, pass it along.
6387 // This stops us from eating debugger breaks etc.
6388 return EXCEPTION_CONTINUE_SEARCH;
6391 FatalConditionHandler() {
6393 // 32k seems enough for Catch to handle stack overflow,
6394 // but the value was found experimentally, so there is no strong guarantee
6395 guaranteeSize = 32 * 1024;
6396 exceptionHandlerHandle = CATCH_NULL;
6397 // Register as first handler in current chain
6398 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
6399 // Pass in guarantee size to be filled
6400 SetThreadStackGuarantee(&guaranteeSize);
6403 static void reset() {
6405 // Unregister handler and restore the old guarantee
6406 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
6407 SetThreadStackGuarantee(&guaranteeSize);
6408 exceptionHandlerHandle = CATCH_NULL;
6413 ~FatalConditionHandler() {
6418 static ULONG guaranteeSize;
6419 static PVOID exceptionHandlerHandle;
6422 bool FatalConditionHandler::isSet = false;
6423 ULONG FatalConditionHandler::guaranteeSize = 0;
6424 PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
6426 } // namespace Catch
6428 # endif // CATCH_CONFIG_WINDOWS_SEH
6430 #else // Not Windows - assumed to be POSIX compatible //////////////////////////
6432 # if !defined(CATCH_CONFIG_POSIX_SIGNALS)
6435 struct FatalConditionHandler {
6440 # else // CATCH_CONFIG_POSIX_SIGNALS is defined
6450 extern SignalDefs signalDefs[];
6451 SignalDefs signalDefs[] = {
6452 { SIGINT, "SIGINT - Terminal interrupt signal" },
6453 { SIGILL, "SIGILL - Illegal instruction signal" },
6454 { SIGFPE, "SIGFPE - Floating point error signal" },
6455 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
6456 { SIGTERM, "SIGTERM - Termination request signal" },
6457 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
6460 struct FatalConditionHandler {
6463 static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
6464 static stack_t oldSigStack;
6465 static char altStackMem[SIGSTKSZ];
6467 static void handleSignal( int sig ) {
6468 std::string name = "<unknown signal>";
6469 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6470 SignalDefs &def = signalDefs[i];
6471 if (sig == def.id) {
6481 FatalConditionHandler() {
6484 sigStack.ss_sp = altStackMem;
6485 sigStack.ss_size = SIGSTKSZ;
6486 sigStack.ss_flags = 0;
6487 sigaltstack(&sigStack, &oldSigStack);
6488 struct sigaction sa = { 0 };
6490 sa.sa_handler = handleSignal;
6491 sa.sa_flags = SA_ONSTACK;
6492 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
6493 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
6497 ~FatalConditionHandler() {
6500 static void reset() {
6502 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
6503 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
6504 sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
6506 // Return the old stack
6507 sigaltstack(&oldSigStack, CATCH_NULL);
6513 bool FatalConditionHandler::isSet = false;
6514 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
6515 stack_t FatalConditionHandler::oldSigStack = {};
6516 char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
6518 } // namespace Catch
6520 # endif // CATCH_CONFIG_POSIX_SIGNALS
6522 #endif // not Windows
6529 class StreamRedirect {
6532 StreamRedirect( std::ostream& stream, std::string& targetString )
6533 : m_stream( stream ),
6534 m_prevBuf( stream.rdbuf() ),
6535 m_targetString( targetString )
6537 stream.rdbuf( m_oss.rdbuf() );
6541 m_targetString += m_oss.str();
6542 m_stream.rdbuf( m_prevBuf );
6546 std::ostream& m_stream;
6547 std::streambuf* m_prevBuf;
6548 std::ostringstream m_oss;
6549 std::string& m_targetString;
6552 ///////////////////////////////////////////////////////////////////////////
6554 class RunContext : public IResultCapture, public IRunner {
6556 RunContext( RunContext const& );
6557 void operator =( RunContext const& );
6561 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
6562 : m_runInfo( _config->name() ),
6563 m_context( getCurrentMutableContext() ),
6564 m_activeTestCase( CATCH_NULL ),
6565 m_config( _config ),
6566 m_reporter( reporter ),
6567 m_shouldReportUnexpected ( true )
6569 m_context.setRunner( this );
6570 m_context.setConfig( m_config );
6571 m_context.setResultCapture( this );
6572 m_reporter->testRunStarting( m_runInfo );
6575 virtual ~RunContext() {
6576 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
6579 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
6580 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
6582 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
6583 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
6586 Totals runTest( TestCase const& testCase ) {
6587 Totals prevTotals = m_totals;
6589 std::string redirectedCout;
6590 std::string redirectedCerr;
6592 TestCaseInfo testInfo = testCase.getTestCaseInfo();
6594 m_reporter->testCaseStarting( testInfo );
6596 m_activeTestCase = &testCase;
6599 ITracker& rootTracker = m_trackerContext.startRun();
6600 assert( rootTracker.isSectionTracker() );
6601 static_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() );
6603 m_trackerContext.startCycle();
6604 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) );
6605 runCurrentTest( redirectedCout, redirectedCerr );
6607 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
6609 // !TBD: deprecated - this will be replaced by indexed trackers
6610 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
6612 Totals deltaTotals = m_totals.delta( prevTotals );
6613 if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
6614 deltaTotals.assertions.failed++;
6615 deltaTotals.testCases.passed--;
6616 deltaTotals.testCases.failed++;
6618 m_totals.testCases += deltaTotals.testCases;
6619 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6625 m_activeTestCase = CATCH_NULL;
6626 m_testCaseTracker = CATCH_NULL;
6631 Ptr<IConfig const> config() const {
6635 private: // IResultCapture
6637 virtual void assertionEnded( AssertionResult const& result ) {
6638 if( result.getResultType() == ResultWas::Ok ) {
6639 m_totals.assertions.passed++;
6641 else if( !result.isOk() ) {
6642 m_totals.assertions.failed++;
6645 // We have no use for the return value (whether messages should be cleared), because messages were made scoped
6646 // and should be let to clear themselves out.
6647 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
6649 // Reset working state
6650 m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
6651 m_lastResult = result;
6654 virtual bool sectionStarted (
6655 SectionInfo const& sectionInfo,
6659 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) );
6660 if( !sectionTracker.isOpen() )
6662 m_activeSections.push_back( §ionTracker );
6664 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
6666 m_reporter->sectionStarting( sectionInfo );
6668 assertions = m_totals.assertions;
6672 bool testForMissingAssertions( Counts& assertions ) {
6673 if( assertions.total() != 0 )
6675 if( !m_config->warnAboutMissingAssertions() )
6677 if( m_trackerContext.currentTracker().hasChildren() )
6679 m_totals.assertions.failed++;
6680 assertions.failed++;
6684 virtual void sectionEnded( SectionEndInfo const& endInfo ) {
6685 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
6686 bool missingAssertions = testForMissingAssertions( assertions );
6688 if( !m_activeSections.empty() ) {
6689 m_activeSections.back()->close();
6690 m_activeSections.pop_back();
6693 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
6697 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
6698 if( m_unfinishedSections.empty() )
6699 m_activeSections.back()->fail();
6701 m_activeSections.back()->close();
6702 m_activeSections.pop_back();
6704 m_unfinishedSections.push_back( endInfo );
6707 virtual void pushScopedMessage( MessageInfo const& message ) {
6708 m_messages.push_back( message );
6711 virtual void popScopedMessage( MessageInfo const& message ) {
6712 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
6715 virtual std::string getCurrentTestName() const {
6716 return m_activeTestCase
6717 ? m_activeTestCase->getTestCaseInfo().name
6721 virtual const AssertionResult* getLastResult() const {
6722 return &m_lastResult;
6725 virtual void exceptionEarlyReported() {
6726 m_shouldReportUnexpected = false;
6729 virtual void handleFatalErrorCondition( std::string const& message ) {
6730 // Don't rebuild the result -- the stringification itself can cause more fatal errors
6731 // Instead, fake a result data.
6732 AssertionResultData tempResult;
6733 tempResult.resultType = ResultWas::FatalErrorCondition;
6734 tempResult.message = message;
6735 AssertionResult result(m_lastAssertionInfo, tempResult);
6737 getResultCapture().assertionEnded(result);
6739 handleUnfinishedSections();
6741 // Recreate section for test case (as we will lose the one that was in scope)
6742 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6743 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6746 assertions.failed = 1;
6747 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
6748 m_reporter->sectionEnded( testCaseSectionStats );
6750 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
6753 deltaTotals.testCases.failed = 1;
6754 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6759 m_totals.testCases.failed++;
6760 testGroupEnded( std::string(), m_totals, 1, 1 );
6761 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
6765 // !TBD We need to do this another way!
6766 bool aborting() const {
6767 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
6772 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
6773 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6774 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6775 m_reporter->sectionStarting( testCaseSection );
6776 Counts prevAssertions = m_totals.assertions;
6777 double duration = 0;
6778 m_shouldReportUnexpected = true;
6780 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
6782 seedRng( *m_config );
6786 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
6787 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
6788 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
6789 invokeActiveTestCase();
6792 invokeActiveTestCase();
6794 duration = timer.getElapsedSeconds();
6796 catch( TestFailureException& ) {
6797 // This just means the test was aborted due to failure
6800 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
6801 // are reported without translation at the point of origin.
6802 if (m_shouldReportUnexpected) {
6803 makeUnexpectedResultBuilder().useActiveException();
6806 m_testCaseTracker->close();
6807 handleUnfinishedSections();
6810 Counts assertions = m_totals.assertions - prevAssertions;
6811 bool missingAssertions = testForMissingAssertions( assertions );
6813 if( testCaseInfo.okToFail() ) {
6814 std::swap( assertions.failedButOk, assertions.failed );
6815 m_totals.assertions.failed -= assertions.failedButOk;
6816 m_totals.assertions.failedButOk += assertions.failedButOk;
6819 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
6820 m_reporter->sectionEnded( testCaseSectionStats );
6823 void invokeActiveTestCase() {
6824 FatalConditionHandler fatalConditionHandler; // Handle signals
6825 m_activeTestCase->invoke();
6826 fatalConditionHandler.reset();
6831 ResultBuilder makeUnexpectedResultBuilder() const {
6832 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
6833 m_lastAssertionInfo.lineInfo,
6834 m_lastAssertionInfo.capturedExpression.c_str(),
6835 m_lastAssertionInfo.resultDisposition );
6838 void handleUnfinishedSections() {
6839 // If sections ended prematurely due to an exception we stored their
6840 // infos here so we can tear them down outside the unwind process.
6841 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
6842 itEnd = m_unfinishedSections.rend();
6845 sectionEnded( *it );
6846 m_unfinishedSections.clear();
6849 TestRunInfo m_runInfo;
6850 IMutableContext& m_context;
6851 TestCase const* m_activeTestCase;
6852 ITracker* m_testCaseTracker;
6853 ITracker* m_currentSectionTracker;
6854 AssertionResult m_lastResult;
6856 Ptr<IConfig const> m_config;
6858 Ptr<IStreamingReporter> m_reporter;
6859 std::vector<MessageInfo> m_messages;
6860 AssertionInfo m_lastAssertionInfo;
6861 std::vector<SectionEndInfo> m_unfinishedSections;
6862 std::vector<ITracker*> m_activeSections;
6863 TrackerContext m_trackerContext;
6864 bool m_shouldReportUnexpected;
6867 IResultCapture& getResultCapture() {
6868 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
6871 throw std::logic_error( "No result capture instance" );
6874 } // end namespace Catch
6876 // #included from: internal/catch_version.h
6877 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6881 // Versioning information
6883 Version( unsigned int _majorVersion,
6884 unsigned int _minorVersion,
6885 unsigned int _patchNumber,
6886 char const * const _branchName,
6887 unsigned int _buildNumber );
6889 unsigned int const majorVersion;
6890 unsigned int const minorVersion;
6891 unsigned int const patchNumber;
6893 // buildNumber is only used if branchName is not null
6894 char const * const branchName;
6895 unsigned int const buildNumber;
6897 friend std::ostream& operator << ( std::ostream& os, Version const& version );
6900 void operator=( Version const& );
6903 inline Version libraryVersion();
6912 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
6913 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
6915 std::ostringstream oss;
6916 oss << "No reporter registered with name: '" << reporterName << "'";
6917 throw std::domain_error( oss.str() );
6922 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
6923 std::vector<std::string> reporters = config->getReporterNames();
6924 if( reporters.empty() )
6925 reporters.push_back( "console" );
6927 Ptr<IStreamingReporter> reporter;
6928 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
6931 reporter = addReporter( reporter, createReporter( *it, config ) );
6934 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
6935 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6936 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6939 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
6943 Totals runTests( Ptr<Config> const& config ) {
6945 Ptr<IConfig const> iconfig = config.get();
6947 Ptr<IStreamingReporter> reporter = makeReporter( config );
6948 reporter = addListeners( iconfig, reporter );
6950 RunContext context( iconfig, reporter );
6954 context.testGroupStarting( config->name(), 1, 1 );
6956 TestSpec testSpec = config->testSpec();
6957 if( !testSpec.hasFilters() )
6958 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
6960 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
6961 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
6964 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
6965 totals += context.runTest( *it );
6967 reporter->skipTest( *it );
6970 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
6974 void applyFilenamesAsTags( IConfig const& config ) {
6975 std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
6976 for(std::size_t i = 0; i < tests.size(); ++i ) {
6977 TestCase& test = const_cast<TestCase&>( tests[i] );
6978 std::set<std::string> tags = test.tags;
6980 std::string filename = test.lineInfo.file;
6981 std::string::size_type lastSlash = filename.find_last_of( "\\/" );
6982 if( lastSlash != std::string::npos )
6983 filename = filename.substr( lastSlash+1 );
6985 std::string::size_type lastDot = filename.find_last_of( "." );
6986 if( lastDot != std::string::npos )
6987 filename = filename.substr( 0, lastDot );
6989 tags.insert( "#" + filename );
6990 setTags( test, tags );
6994 class Session : NonCopyable {
6995 static bool alreadyInstantiated;
6999 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
7002 : m_cli( makeCommandLineParser() ) {
7003 if( alreadyInstantiated ) {
7004 std::string msg = "Only one instance of Catch::Session can ever be used";
7005 Catch::cerr() << msg << std::endl;
7006 throw std::logic_error( msg );
7008 alreadyInstantiated = true;
7014 void showHelp( std::string const& processName ) {
7015 Catch::cout() << "\nCatch v" << libraryVersion() << "\n";
7017 m_cli.usage( Catch::cout(), processName );
7018 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
7021 int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
7023 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
7024 m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
7025 if( m_configData.showHelp )
7026 showHelp( m_configData.processName );
7029 catch( std::exception& ex ) {
7031 Colour colourGuard( Colour::Red );
7033 << "\nError(s) in input:\n"
7034 << Text( ex.what(), TextAttributes().setIndent(2) )
7037 m_cli.usage( Catch::cout(), m_configData.processName );
7038 return (std::numeric_limits<int>::max)();
7043 void useConfigData( ConfigData const& _configData ) {
7044 m_configData = _configData;
7048 int run( int argc, char const* const* const argv ) {
7050 int returnCode = applyCommandLine( argc, argv );
7051 if( returnCode == 0 )
7056 #if defined(WIN32) && defined(UNICODE)
7057 int run( int argc, wchar_t const* const* const argv ) {
7059 char **utf8Argv = new char *[ argc ];
7061 for ( int i = 0; i < argc; ++i ) {
7062 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
7064 utf8Argv[ i ] = new char[ bufSize ];
7066 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
7069 int returnCode = applyCommandLine( argc, utf8Argv );
7070 if( returnCode == 0 )
7073 for ( int i = 0; i < argc; ++i )
7074 delete [] utf8Argv[ i ];
7083 if( m_configData.showHelp )
7088 config(); // Force config to be constructed
7090 seedRng( *m_config );
7092 if( m_configData.filenamesAsTags )
7093 applyFilenamesAsTags( *m_config );
7095 // Handle list request
7096 if( Option<std::size_t> listed = list( config() ) )
7097 return static_cast<int>( *listed );
7099 return static_cast<int>( runTests( m_config ).assertions.failed );
7101 catch( std::exception& ex ) {
7102 Catch::cerr() << ex.what() << std::endl;
7103 return (std::numeric_limits<int>::max)();
7107 Clara::CommandLine<ConfigData> const& cli() const {
7110 std::vector<Clara::Parser::Token> const& unusedTokens() const {
7111 return m_unusedTokens;
7113 ConfigData& configData() {
7114 return m_configData;
7118 m_config = new Config( m_configData );
7122 Clara::CommandLine<ConfigData> m_cli;
7123 std::vector<Clara::Parser::Token> m_unusedTokens;
7124 ConfigData m_configData;
7125 Ptr<Config> m_config;
7128 bool Session::alreadyInstantiated = false;
7130 } // end namespace Catch
7132 // #included from: catch_registry_hub.hpp
7133 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
7135 // #included from: catch_test_case_registry_impl.hpp
7136 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
7141 #include <algorithm>
7145 struct RandomNumberGenerator {
7146 typedef std::ptrdiff_t result_type;
7148 result_type operator()( result_type n ) const { return std::rand() % n; }
7150 #ifdef CATCH_CONFIG_CPP11_SHUFFLE
7151 static constexpr result_type min() { return 0; }
7152 static constexpr result_type max() { return 1000000; }
7153 result_type operator()() const { return std::rand() % max(); }
7155 template<typename V>
7156 static void shuffle( V& vector ) {
7157 RandomNumberGenerator rng;
7158 #ifdef CATCH_CONFIG_CPP11_SHUFFLE
7159 std::shuffle( vector.begin(), vector.end(), rng );
7161 std::random_shuffle( vector.begin(), vector.end(), rng );
7166 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
7168 std::vector<TestCase> sorted = unsortedTestCases;
7170 switch( config.runOrder() ) {
7171 case RunTests::InLexicographicalOrder:
7172 std::sort( sorted.begin(), sorted.end() );
7174 case RunTests::InRandomOrder:
7177 RandomNumberGenerator::shuffle( sorted );
7180 case RunTests::InDeclarationOrder:
7181 // already in declaration order
7186 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
7187 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
7190 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
7191 std::set<TestCase> seenFunctions;
7192 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
7195 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
7196 if( !prev.second ) {
7197 std::ostringstream ss;
7199 ss << Colour( Colour::Red )
7200 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
7201 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
7202 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
7204 throw std::runtime_error(ss.str());
7209 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
7210 std::vector<TestCase> filtered;
7211 filtered.reserve( testCases.size() );
7212 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
7215 if( matchTest( *it, testSpec, config ) )
7216 filtered.push_back( *it );
7219 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
7220 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
7223 class TestRegistry : public ITestCaseRegistry {
7226 : m_currentSortOrder( RunTests::InDeclarationOrder ),
7229 virtual ~TestRegistry();
7231 virtual void registerTest( TestCase const& testCase ) {
7232 std::string name = testCase.getTestCaseInfo().name;
7233 if( name.empty() ) {
7234 std::ostringstream oss;
7235 oss << "Anonymous test case " << ++m_unnamedCount;
7236 return registerTest( testCase.withName( oss.str() ) );
7238 m_functions.push_back( testCase );
7241 virtual std::vector<TestCase> const& getAllTests() const {
7244 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
7245 if( m_sortedFunctions.empty() )
7246 enforceNoDuplicateTestCases( m_functions );
7248 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
7249 m_sortedFunctions = sortTests( config, m_functions );
7250 m_currentSortOrder = config.runOrder();
7252 return m_sortedFunctions;
7256 std::vector<TestCase> m_functions;
7257 mutable RunTests::InWhatOrder m_currentSortOrder;
7258 mutable std::vector<TestCase> m_sortedFunctions;
7259 size_t m_unnamedCount;
7260 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
7263 ///////////////////////////////////////////////////////////////////////////
7265 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
7268 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
7270 virtual void invoke() const {
7275 virtual ~FreeFunctionTestCase();
7280 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
7281 std::string className = classOrQualifiedMethodName;
7282 if( startsWith( className, '&' ) )
7284 std::size_t lastColons = className.rfind( "::" );
7285 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
7286 if( penultimateColons == std::string::npos )
7287 penultimateColons = 1;
7288 className = className.substr( penultimateColons, lastColons-penultimateColons );
7293 void registerTestCase
7294 ( ITestCase* testCase,
7295 char const* classOrQualifiedMethodName,
7296 NameAndDesc const& nameAndDesc,
7297 SourceLineInfo const& lineInfo ) {
7299 getMutableRegistryHub().registerTest
7302 extractClassName( classOrQualifiedMethodName ),
7304 nameAndDesc.description,
7307 void registerTestCaseFunction
7308 ( TestFunction function,
7309 SourceLineInfo const& lineInfo,
7310 NameAndDesc const& nameAndDesc ) {
7311 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
7314 ///////////////////////////////////////////////////////////////////////////
7317 ( TestFunction function,
7318 SourceLineInfo const& lineInfo,
7319 NameAndDesc const& nameAndDesc ) {
7320 registerTestCaseFunction( function, lineInfo, nameAndDesc );
7323 AutoReg::~AutoReg() {}
7325 } // end namespace Catch
7327 // #included from: catch_reporter_registry.hpp
7328 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
7334 class ReporterRegistry : public IReporterRegistry {
7338 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
7340 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
7341 FactoryMap::const_iterator it = m_factories.find( name );
7342 if( it == m_factories.end() )
7344 return it->second->create( ReporterConfig( config ) );
7347 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
7348 m_factories.insert( std::make_pair( name, factory ) );
7350 void registerListener( Ptr<IReporterFactory> const& factory ) {
7351 m_listeners.push_back( factory );
7354 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
7357 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
7362 FactoryMap m_factories;
7363 Listeners m_listeners;
7367 // #included from: catch_exception_translator_registry.hpp
7368 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
7371 #import "Foundation/Foundation.h"
7376 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
7378 ~ExceptionTranslatorRegistry() {
7379 deleteAll( m_translators );
7382 virtual void registerTranslator( const IExceptionTranslator* translator ) {
7383 m_translators.push_back( translator );
7386 virtual std::string translateActiveException() const {
7389 // In Objective-C try objective-c exceptions first
7391 return tryTranslators();
7393 @catch (NSException *exception) {
7394 return Catch::toString( [exception description] );
7397 return tryTranslators();
7400 catch( TestFailureException& ) {
7403 catch( std::exception& ex ) {
7406 catch( std::string& msg ) {
7409 catch( const char* msg ) {
7413 return "Unknown exception";
7417 std::string tryTranslators() const {
7418 if( m_translators.empty() )
7421 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
7425 std::vector<const IExceptionTranslator*> m_translators;
7429 // #included from: catch_tag_alias_registry.h
7430 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
7436 class TagAliasRegistry : public ITagAliasRegistry {
7438 virtual ~TagAliasRegistry();
7439 virtual Option<TagAlias> find( std::string const& alias ) const;
7440 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
7441 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
7444 std::map<std::string, TagAlias> m_registry;
7447 } // end namespace Catch
7453 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
7455 RegistryHub( RegistryHub const& );
7456 void operator=( RegistryHub const& );
7458 public: // IRegistryHub
7461 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
7462 return m_reporterRegistry;
7464 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
7465 return m_testCaseRegistry;
7467 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
7468 return m_exceptionTranslatorRegistry;
7470 virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE {
7471 return m_tagAliasRegistry;
7474 public: // IMutableRegistryHub
7475 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
7476 m_reporterRegistry.registerReporter( name, factory );
7478 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
7479 m_reporterRegistry.registerListener( factory );
7481 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
7482 m_testCaseRegistry.registerTest( testInfo );
7484 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
7485 m_exceptionTranslatorRegistry.registerTranslator( translator );
7487 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE {
7488 m_tagAliasRegistry.add( alias, tag, lineInfo );
7492 TestRegistry m_testCaseRegistry;
7493 ReporterRegistry m_reporterRegistry;
7494 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
7495 TagAliasRegistry m_tagAliasRegistry;
7498 // Single, global, instance
7499 inline RegistryHub*& getTheRegistryHub() {
7500 static RegistryHub* theRegistryHub = CATCH_NULL;
7501 if( !theRegistryHub )
7502 theRegistryHub = new RegistryHub();
7503 return theRegistryHub;
7507 IRegistryHub& getRegistryHub() {
7508 return *getTheRegistryHub();
7510 IMutableRegistryHub& getMutableRegistryHub() {
7511 return *getTheRegistryHub();
7514 delete getTheRegistryHub();
7515 getTheRegistryHub() = CATCH_NULL;
7518 std::string translateActiveException() {
7519 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
7522 } // end namespace Catch
7524 // #included from: catch_notimplemented_exception.hpp
7525 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
7531 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
7532 : m_lineInfo( lineInfo ) {
7533 std::ostringstream oss;
7534 oss << lineInfo << ": function ";
7535 oss << "not implemented";
7539 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
7540 return m_what.c_str();
7543 } // end namespace Catch
7545 // #included from: catch_context_impl.hpp
7546 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
7548 // #included from: catch_stream.hpp
7549 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
7551 #include <stdexcept>
7557 template<typename WriterF, size_t bufferSize=256>
7558 class StreamBufImpl : public StreamBufBase {
7559 char data[bufferSize];
7564 setp( data, data + sizeof(data) );
7567 ~StreamBufImpl() CATCH_NOEXCEPT {
7572 int overflow( int c ) {
7576 if( pbase() == epptr() )
7577 m_writer( std::string( 1, static_cast<char>( c ) ) );
7579 sputc( static_cast<char>( c ) );
7585 if( pbase() != pptr() ) {
7586 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
7587 setp( pbase(), epptr() );
7593 ///////////////////////////////////////////////////////////////////////////
7595 FileStream::FileStream( std::string const& filename ) {
7596 m_ofs.open( filename.c_str() );
7597 if( m_ofs.fail() ) {
7598 std::ostringstream oss;
7599 oss << "Unable to open file: '" << filename << '\'';
7600 throw std::domain_error( oss.str() );
7604 std::ostream& FileStream::stream() const {
7608 struct OutputDebugWriter {
7610 void operator()( std::string const&str ) {
7611 writeToDebugConsole( str );
7615 DebugOutStream::DebugOutStream()
7616 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
7617 m_os( m_streamBuf.get() )
7620 std::ostream& DebugOutStream::stream() const {
7624 // Store the streambuf from cout up-front because
7625 // cout may get redirected when running tests
7626 CoutStream::CoutStream()
7627 : m_os( Catch::cout().rdbuf() )
7630 std::ostream& CoutStream::stream() const {
7634 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
7635 std::ostream& cout() {
7638 std::ostream& cerr() {
7646 class Context : public IMutableContext {
7648 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
7649 Context( Context const& );
7650 void operator=( Context const& );
7653 virtual ~Context() {
7654 deleteAllValues( m_generatorsByTestName );
7658 virtual IResultCapture* getResultCapture() {
7659 return m_resultCapture;
7661 virtual IRunner* getRunner() {
7664 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
7665 return getGeneratorsForCurrentTest()
7666 .getGeneratorInfo( fileInfo, totalSize )
7669 virtual bool advanceGeneratorsForCurrentTest() {
7670 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7671 return generators && generators->moveNext();
7674 virtual Ptr<IConfig const> getConfig() const {
7678 public: // IMutableContext
7679 virtual void setResultCapture( IResultCapture* resultCapture ) {
7680 m_resultCapture = resultCapture;
7682 virtual void setRunner( IRunner* runner ) {
7685 virtual void setConfig( Ptr<IConfig const> const& config ) {
7689 friend IMutableContext& getCurrentMutableContext();
7692 IGeneratorsForTest* findGeneratorsForCurrentTest() {
7693 std::string testName = getResultCapture()->getCurrentTestName();
7695 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
7696 m_generatorsByTestName.find( testName );
7697 return it != m_generatorsByTestName.end()
7702 IGeneratorsForTest& getGeneratorsForCurrentTest() {
7703 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7705 std::string testName = getResultCapture()->getCurrentTestName();
7706 generators = createGeneratorsForTest();
7707 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
7713 Ptr<IConfig const> m_config;
7715 IResultCapture* m_resultCapture;
7716 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
7720 Context* currentContext = CATCH_NULL;
7722 IMutableContext& getCurrentMutableContext() {
7723 if( !currentContext )
7724 currentContext = new Context();
7725 return *currentContext;
7727 IContext& getCurrentContext() {
7728 return getCurrentMutableContext();
7731 void cleanUpContext() {
7732 delete currentContext;
7733 currentContext = CATCH_NULL;
7737 // #included from: catch_console_colour_impl.hpp
7738 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
7740 // #included from: catch_errno_guard.hpp
7741 #define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
7749 ErrnoGuard():m_oldErrno(errno){}
7750 ~ErrnoGuard() { errno = m_oldErrno; }
7760 struct IColourImpl {
7761 virtual ~IColourImpl() {}
7762 virtual void use( Colour::Code _colourCode ) = 0;
7765 struct NoColourImpl : IColourImpl {
7766 void use( Colour::Code ) {}
7768 static IColourImpl* instance() {
7769 static NoColourImpl s_instance;
7775 } // namespace Catch
7777 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
7778 # ifdef CATCH_PLATFORM_WINDOWS
7779 # define CATCH_CONFIG_COLOUR_WINDOWS
7781 # define CATCH_CONFIG_COLOUR_ANSI
7785 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
7790 class Win32ColourImpl : public IColourImpl {
7792 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
7794 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7795 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
7796 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
7797 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
7800 virtual void use( Colour::Code _colourCode ) {
7801 switch( _colourCode ) {
7802 case Colour::None: return setTextAttribute( originalForegroundAttributes );
7803 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7804 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
7805 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
7806 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
7807 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
7808 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
7809 case Colour::Grey: return setTextAttribute( 0 );
7811 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
7812 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
7813 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
7814 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7816 case Colour::Bright: throw std::logic_error( "not a colour" );
7821 void setTextAttribute( WORD _textAttribute ) {
7822 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
7824 HANDLE stdoutHandle;
7825 WORD originalForegroundAttributes;
7826 WORD originalBackgroundAttributes;
7829 IColourImpl* platformColourInstance() {
7830 static Win32ColourImpl s_instance;
7832 Ptr<IConfig const> config = getCurrentContext().getConfig();
7833 UseColour::YesOrNo colourMode = config
7834 ? config->useColour()
7836 if( colourMode == UseColour::Auto )
7837 colourMode = !isDebuggerActive()
7840 return colourMode == UseColour::Yes
7842 : NoColourImpl::instance();
7845 } // end anon namespace
7846 } // end namespace Catch
7848 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
7855 // use POSIX/ ANSI console terminal codes
7856 // Thanks to Adam Strzelecki for original contribution
7857 // (http://github.com/nanoant)
7858 // https://github.com/philsquared/Catch/pull/131
7859 class PosixColourImpl : public IColourImpl {
7861 virtual void use( Colour::Code _colourCode ) {
7862 switch( _colourCode ) {
7864 case Colour::White: return setColour( "[0m" );
7865 case Colour::Red: return setColour( "[0;31m" );
7866 case Colour::Green: return setColour( "[0;32m" );
7867 case Colour::Blue: return setColour( "[0;34m" );
7868 case Colour::Cyan: return setColour( "[0;36m" );
7869 case Colour::Yellow: return setColour( "[0;33m" );
7870 case Colour::Grey: return setColour( "[1;30m" );
7872 case Colour::LightGrey: return setColour( "[0;37m" );
7873 case Colour::BrightRed: return setColour( "[1;31m" );
7874 case Colour::BrightGreen: return setColour( "[1;32m" );
7875 case Colour::BrightWhite: return setColour( "[1;37m" );
7877 case Colour::Bright: throw std::logic_error( "not a colour" );
7880 static IColourImpl* instance() {
7881 static PosixColourImpl s_instance;
7886 void setColour( const char* _escapeCode ) {
7887 Catch::cout() << '\033' << _escapeCode;
7891 IColourImpl* platformColourInstance() {
7893 Ptr<IConfig const> config = getCurrentContext().getConfig();
7894 UseColour::YesOrNo colourMode = config
7895 ? config->useColour()
7897 if( colourMode == UseColour::Auto )
7898 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
7901 return colourMode == UseColour::Yes
7902 ? PosixColourImpl::instance()
7903 : NoColourImpl::instance();
7906 } // end anon namespace
7907 } // end namespace Catch
7909 #else // not Windows or ANSI ///////////////////////////////////////////////
7913 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
7915 } // end namespace Catch
7917 #endif // Windows/ ANSI/ None
7921 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
7922 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
7923 Colour::~Colour(){ if( !m_moved ) use( None ); }
7925 void Colour::use( Code _colourCode ) {
7926 static IColourImpl* impl = platformColourInstance();
7927 impl->use( _colourCode );
7930 } // end namespace Catch
7932 // #included from: catch_generators_impl.hpp
7933 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
7941 struct GeneratorInfo : IGeneratorInfo {
7943 GeneratorInfo( std::size_t size )
7949 if( ++m_currentIndex == m_size ) {
7956 std::size_t getCurrentIndex() const {
7957 return m_currentIndex;
7961 std::size_t m_currentIndex;
7964 ///////////////////////////////////////////////////////////////////////////
7966 class GeneratorsForTest : public IGeneratorsForTest {
7969 ~GeneratorsForTest() {
7970 deleteAll( m_generatorsInOrder );
7973 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
7974 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
7975 if( it == m_generatorsByName.end() ) {
7976 IGeneratorInfo* info = new GeneratorInfo( size );
7977 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
7978 m_generatorsInOrder.push_back( info );
7985 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
7986 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
7987 for(; it != itEnd; ++it ) {
7988 if( (*it)->moveNext() )
7995 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
7996 std::vector<IGeneratorInfo*> m_generatorsInOrder;
7999 IGeneratorsForTest* createGeneratorsForTest()
8001 return new GeneratorsForTest();
8004 } // end namespace Catch
8006 // #included from: catch_assertionresult.hpp
8007 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
8011 AssertionInfo::AssertionInfo( std::string const& _macroName,
8012 SourceLineInfo const& _lineInfo,
8013 std::string const& _capturedExpression,
8014 ResultDisposition::Flags _resultDisposition )
8015 : macroName( _macroName ),
8016 lineInfo( _lineInfo ),
8017 capturedExpression( _capturedExpression ),
8018 resultDisposition( _resultDisposition )
8021 AssertionResult::AssertionResult() {}
8023 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
8025 m_resultData( data )
8028 AssertionResult::~AssertionResult() {}
8030 // Result was a success
8031 bool AssertionResult::succeeded() const {
8032 return Catch::isOk( m_resultData.resultType );
8035 // Result was a success, or failure is suppressed
8036 bool AssertionResult::isOk() const {
8037 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
8040 ResultWas::OfType AssertionResult::getResultType() const {
8041 return m_resultData.resultType;
8044 bool AssertionResult::hasExpression() const {
8045 return !m_info.capturedExpression.empty();
8048 bool AssertionResult::hasMessage() const {
8049 return !m_resultData.message.empty();
8052 std::string AssertionResult::getExpression() const {
8053 if( isFalseTest( m_info.resultDisposition ) )
8054 return '!' + m_info.capturedExpression;
8056 return m_info.capturedExpression;
8058 std::string AssertionResult::getExpressionInMacro() const {
8059 if( m_info.macroName.empty() )
8060 return m_info.capturedExpression;
8062 return m_info.macroName + "( " + m_info.capturedExpression + " )";
8065 bool AssertionResult::hasExpandedExpression() const {
8066 return hasExpression() && getExpandedExpression() != getExpression();
8069 std::string AssertionResult::getExpandedExpression() const {
8070 return m_resultData.reconstructExpression();
8073 std::string AssertionResult::getMessage() const {
8074 return m_resultData.message;
8076 SourceLineInfo AssertionResult::getSourceInfo() const {
8077 return m_info.lineInfo;
8080 std::string AssertionResult::getTestMacroName() const {
8081 return m_info.macroName;
8084 void AssertionResult::discardDecomposedExpression() const {
8085 m_resultData.decomposedExpression = CATCH_NULL;
8088 void AssertionResult::expandDecomposedExpression() const {
8089 m_resultData.reconstructExpression();
8092 } // end namespace Catch
8094 // #included from: catch_test_case_info.hpp
8095 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
8101 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
8102 if( startsWith( tag, '.' ) ||
8105 return TestCaseInfo::IsHidden;
8106 else if( tag == "!throws" )
8107 return TestCaseInfo::Throws;
8108 else if( tag == "!shouldfail" )
8109 return TestCaseInfo::ShouldFail;
8110 else if( tag == "!mayfail" )
8111 return TestCaseInfo::MayFail;
8112 else if( tag == "!nonportable" )
8113 return TestCaseInfo::NonPortable;
8115 return TestCaseInfo::None;
8117 inline bool isReservedTag( std::string const& tag ) {
8118 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
8120 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
8121 if( isReservedTag( tag ) ) {
8122 std::ostringstream ss;
8123 ss << Colour(Colour::Red)
8124 << "Tag name [" << tag << "] not allowed.\n"
8125 << "Tag names starting with non alpha-numeric characters are reserved\n"
8126 << Colour(Colour::FileName)
8127 << _lineInfo << '\n';
8128 throw std::runtime_error(ss.str());
8132 TestCase makeTestCase( ITestCase* _testCase,
8133 std::string const& _className,
8134 std::string const& _name,
8135 std::string const& _descOrTags,
8136 SourceLineInfo const& _lineInfo )
8138 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
8141 std::set<std::string> tags;
8142 std::string desc, tag;
8144 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
8145 char c = _descOrTags[i];
8154 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
8155 if( prop == TestCaseInfo::IsHidden )
8157 else if( prop == TestCaseInfo::None )
8158 enforceNotReservedTag( tag, _lineInfo );
8169 tags.insert( "hide" );
8173 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
8174 return TestCase( _testCase, info );
8177 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
8179 testCaseInfo.tags = tags;
8180 testCaseInfo.lcaseTags.clear();
8182 std::ostringstream oss;
8183 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
8184 oss << '[' << *it << ']';
8185 std::string lcaseTag = toLower( *it );
8186 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
8187 testCaseInfo.lcaseTags.insert( lcaseTag );
8189 testCaseInfo.tagsAsString = oss.str();
8192 TestCaseInfo::TestCaseInfo( std::string const& _name,
8193 std::string const& _className,
8194 std::string const& _description,
8195 std::set<std::string> const& _tags,
8196 SourceLineInfo const& _lineInfo )
8198 className( _className ),
8199 description( _description ),
8200 lineInfo( _lineInfo ),
8203 setTags( *this, _tags );
8206 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
8207 : name( other.name ),
8208 className( other.className ),
8209 description( other.description ),
8211 lcaseTags( other.lcaseTags ),
8212 tagsAsString( other.tagsAsString ),
8213 lineInfo( other.lineInfo ),
8214 properties( other.properties )
8217 bool TestCaseInfo::isHidden() const {
8218 return ( properties & IsHidden ) != 0;
8220 bool TestCaseInfo::throws() const {
8221 return ( properties & Throws ) != 0;
8223 bool TestCaseInfo::okToFail() const {
8224 return ( properties & (ShouldFail | MayFail ) ) != 0;
8226 bool TestCaseInfo::expectedToFail() const {
8227 return ( properties & (ShouldFail ) ) != 0;
8230 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
8232 TestCase::TestCase( TestCase const& other )
8233 : TestCaseInfo( other ),
8237 TestCase TestCase::withName( std::string const& _newName ) const {
8238 TestCase other( *this );
8239 other.name = _newName;
8243 void TestCase::swap( TestCase& other ) {
8244 test.swap( other.test );
8245 name.swap( other.name );
8246 className.swap( other.className );
8247 description.swap( other.description );
8248 tags.swap( other.tags );
8249 lcaseTags.swap( other.lcaseTags );
8250 tagsAsString.swap( other.tagsAsString );
8251 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
8252 std::swap( lineInfo, other.lineInfo );
8255 void TestCase::invoke() const {
8259 bool TestCase::operator == ( TestCase const& other ) const {
8260 return test.get() == other.test.get() &&
8261 name == other.name &&
8262 className == other.className;
8265 bool TestCase::operator < ( TestCase const& other ) const {
8266 return name < other.name;
8268 TestCase& TestCase::operator = ( TestCase const& other ) {
8269 TestCase temp( other );
8274 TestCaseInfo const& TestCase::getTestCaseInfo() const
8279 } // end namespace Catch
8281 // #included from: catch_version.hpp
8282 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
8287 ( unsigned int _majorVersion,
8288 unsigned int _minorVersion,
8289 unsigned int _patchNumber,
8290 char const * const _branchName,
8291 unsigned int _buildNumber )
8292 : majorVersion( _majorVersion ),
8293 minorVersion( _minorVersion ),
8294 patchNumber( _patchNumber ),
8295 branchName( _branchName ),
8296 buildNumber( _buildNumber )
8299 std::ostream& operator << ( std::ostream& os, Version const& version ) {
8300 os << version.majorVersion << '.'
8301 << version.minorVersion << '.'
8302 << version.patchNumber;
8303 // branchName is never null -> 0th char is \0 if it is empty
8304 if (version.branchName[0]) {
8305 os << '-' << version.branchName
8306 << '.' << version.buildNumber;
8311 inline Version libraryVersion() {
8312 static Version version( 1, 9, 4, "", 0 );
8318 // #included from: catch_message.hpp
8319 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
8323 MessageInfo::MessageInfo( std::string const& _macroName,
8324 SourceLineInfo const& _lineInfo,
8325 ResultWas::OfType _type )
8326 : macroName( _macroName ),
8327 lineInfo( _lineInfo ),
8329 sequence( ++globalCount )
8332 // This may need protecting if threading support is added
8333 unsigned int MessageInfo::globalCount = 0;
8335 ////////////////////////////////////////////////////////////////////////////
8337 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
8338 : m_info( builder.m_info )
8340 m_info.message = builder.m_stream.str();
8341 getResultCapture().pushScopedMessage( m_info );
8343 ScopedMessage::ScopedMessage( ScopedMessage const& other )
8344 : m_info( other.m_info )
8347 ScopedMessage::~ScopedMessage() {
8348 if ( !std::uncaught_exception() ){
8349 getResultCapture().popScopedMessage(m_info);
8353 } // end namespace Catch
8355 // #included from: catch_legacy_reporter_adapter.hpp
8356 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
8358 // #included from: catch_legacy_reporter_adapter.h
8359 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
8364 struct IReporter : IShared {
8365 virtual ~IReporter();
8367 virtual bool shouldRedirectStdout() const = 0;
8369 virtual void StartTesting() = 0;
8370 virtual void EndTesting( Totals const& totals ) = 0;
8371 virtual void StartGroup( std::string const& groupName ) = 0;
8372 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
8373 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
8374 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
8375 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
8376 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
8377 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
8378 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
8379 virtual void Aborted() = 0;
8380 virtual void Result( AssertionResult const& result ) = 0;
8383 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
8386 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
8387 virtual ~LegacyReporterAdapter();
8389 virtual ReporterPreferences getPreferences() const;
8390 virtual void noMatchingTestCases( std::string const& );
8391 virtual void testRunStarting( TestRunInfo const& );
8392 virtual void testGroupStarting( GroupInfo const& groupInfo );
8393 virtual void testCaseStarting( TestCaseInfo const& testInfo );
8394 virtual void sectionStarting( SectionInfo const& sectionInfo );
8395 virtual void assertionStarting( AssertionInfo const& );
8396 virtual bool assertionEnded( AssertionStats const& assertionStats );
8397 virtual void sectionEnded( SectionStats const& sectionStats );
8398 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
8399 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
8400 virtual void testRunEnded( TestRunStats const& testRunStats );
8401 virtual void skipTest( TestCaseInfo const& );
8404 Ptr<IReporter> m_legacyReporter;
8410 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
8411 : m_legacyReporter( legacyReporter )
8413 LegacyReporterAdapter::~LegacyReporterAdapter() {}
8415 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
8416 ReporterPreferences prefs;
8417 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
8421 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
8422 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
8423 m_legacyReporter->StartTesting();
8425 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
8426 m_legacyReporter->StartGroup( groupInfo.name );
8428 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
8429 m_legacyReporter->StartTestCase( testInfo );
8431 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
8432 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
8434 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
8435 // Not on legacy interface
8438 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
8439 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
8440 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
8443 if( it->type == ResultWas::Info ) {
8444 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
8446 rb.setResultType( ResultWas::Info );
8447 AssertionResult result = rb.build();
8448 m_legacyReporter->Result( result );
8452 m_legacyReporter->Result( assertionStats.assertionResult );
8455 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
8456 if( sectionStats.missingAssertions )
8457 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
8458 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
8460 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
8461 m_legacyReporter->EndTestCase
8462 ( testCaseStats.testInfo,
8463 testCaseStats.totals,
8464 testCaseStats.stdOut,
8465 testCaseStats.stdErr );
8467 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
8468 if( testGroupStats.aborting )
8469 m_legacyReporter->Aborted();
8470 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
8472 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
8473 m_legacyReporter->EndTesting( testRunStats.totals );
8475 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
8479 // #included from: catch_timer.hpp
8482 #pragma clang diagnostic push
8483 #pragma clang diagnostic ignored "-Wc++11-long-long"
8486 #ifdef CATCH_PLATFORM_WINDOWS
8490 #include <sys/time.h>
8497 #ifdef CATCH_PLATFORM_WINDOWS
8498 UInt64 getCurrentTicks() {
8499 static UInt64 hz=0, hzo=0;
8501 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
8502 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
8505 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
8506 return ((t-hzo)*1000000)/hz;
8509 UInt64 getCurrentTicks() {
8511 gettimeofday(&t,CATCH_NULL);
8512 return static_cast<UInt64>( t.tv_sec ) * 1000000ull + static_cast<UInt64>( t.tv_usec );
8517 void Timer::start() {
8518 m_ticks = getCurrentTicks();
8520 unsigned int Timer::getElapsedMicroseconds() const {
8521 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
8523 unsigned int Timer::getElapsedMilliseconds() const {
8524 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
8526 double Timer::getElapsedSeconds() const {
8527 return getElapsedMicroseconds()/1000000.0;
8530 } // namespace Catch
8533 #pragma clang diagnostic pop
8535 // #included from: catch_common.hpp
8536 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
8543 bool startsWith( std::string const& s, std::string const& prefix ) {
8544 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
8546 bool startsWith( std::string const& s, char prefix ) {
8547 return !s.empty() && s[0] == prefix;
8549 bool endsWith( std::string const& s, std::string const& suffix ) {
8550 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
8552 bool endsWith( std::string const& s, char suffix ) {
8553 return !s.empty() && s[s.size()-1] == suffix;
8555 bool contains( std::string const& s, std::string const& infix ) {
8556 return s.find( infix ) != std::string::npos;
8558 char toLowerCh(char c) {
8559 return static_cast<char>( std::tolower( c ) );
8561 void toLowerInPlace( std::string& s ) {
8562 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
8564 std::string toLower( std::string const& s ) {
8566 toLowerInPlace( lc );
8569 std::string trim( std::string const& str ) {
8570 static char const* whitespaceChars = "\n\r\t ";
8571 std::string::size_type start = str.find_first_not_of( whitespaceChars );
8572 std::string::size_type end = str.find_last_not_of( whitespaceChars );
8574 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
8577 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
8578 bool replaced = false;
8579 std::size_t i = str.find( replaceThis );
8580 while( i != std::string::npos ) {
8582 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
8583 if( i < str.size()-withThis.size() )
8584 i = str.find( replaceThis, i+withThis.size() );
8586 i = std::string::npos;
8591 pluralise::pluralise( std::size_t count, std::string const& label )
8596 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
8597 os << pluraliser.m_count << ' ' << pluraliser.m_label;
8598 if( pluraliser.m_count != 1 )
8603 SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){}
8604 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
8608 bool SourceLineInfo::empty() const {
8609 return file[0] == '\0';
8611 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
8612 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
8614 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
8615 return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
8618 void seedRng( IConfig const& config ) {
8619 if( config.rngSeed() != 0 )
8620 std::srand( config.rngSeed() );
8622 unsigned int rngSeed() {
8623 return getCurrentContext().getConfig()->rngSeed();
8626 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
8628 os << info.file << '(' << info.line << ')';
8630 os << info.file << ':' << info.line;
8635 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
8636 std::ostringstream oss;
8637 oss << locationInfo << ": Internal Catch error: '" << message << '\'';
8639 throw std::logic_error( oss.str() );
8643 // #included from: catch_section.hpp
8644 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
8648 SectionInfo::SectionInfo
8649 ( SourceLineInfo const& _lineInfo,
8650 std::string const& _name,
8651 std::string const& _description )
8653 description( _description ),
8654 lineInfo( _lineInfo )
8657 Section::Section( SectionInfo const& info )
8659 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
8664 Section::~Section() {
8665 if( m_sectionIncluded ) {
8666 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
8667 if( std::uncaught_exception() )
8668 getResultCapture().sectionEndedEarly( endInfo );
8670 getResultCapture().sectionEnded( endInfo );
8674 // This indicates whether the section should be executed or not
8675 Section::operator bool() const {
8676 return m_sectionIncluded;
8679 } // end namespace Catch
8681 // #included from: catch_debugger.hpp
8682 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
8684 #ifdef CATCH_PLATFORM_MAC
8687 #include <stdbool.h>
8688 #include <sys/types.h>
8690 #include <sys/sysctl.h>
8694 // The following function is taken directly from the following technical note:
8695 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
8697 // Returns true if the current process is being debugged (either
8698 // running under the debugger or has a debugger attached post facto).
8699 bool isDebuggerActive(){
8702 struct kinfo_proc info;
8705 // Initialize the flags so that, if sysctl fails for some bizarre
8706 // reason, we get a predictable result.
8708 info.kp_proc.p_flag = 0;
8710 // Initialize mib, which tells sysctl the info we want, in this case
8711 // we're looking for information about a specific process ID.
8715 mib[2] = KERN_PROC_PID;
8720 size = sizeof(info);
8721 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
8722 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
8726 // We're being debugged if the P_TRACED flag is set.
8728 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
8730 } // namespace Catch
8732 #elif defined(CATCH_PLATFORM_LINUX)
8737 // The standard POSIX way of detecting a debugger is to attempt to
8738 // ptrace() the process, but this needs to be done from a child and not
8739 // this process itself to still allow attaching to this process later
8740 // if wanted, so is rather heavy. Under Linux we have the PID of the
8741 // "debugger" (which doesn't need to be gdb, of course, it could also
8742 // be strace, for example) in /proc/$PID/status, so just get it from
8744 bool isDebuggerActive(){
8745 // Libstdc++ has a bug, where std::ifstream sets errno to 0
8746 // This way our users can properly assert over errno values
8748 std::ifstream in("/proc/self/status");
8749 for( std::string line; std::getline(in, line); ) {
8750 static const int PREFIX_LEN = 11;
8751 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
8752 // We're traced if the PID is not 0 and no other PID starts
8753 // with 0 digit, so it's enough to check for just a single
8755 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
8761 } // namespace Catch
8762 #elif defined(_MSC_VER)
8763 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8765 bool isDebuggerActive() {
8766 return IsDebuggerPresent() != 0;
8769 #elif defined(__MINGW32__)
8770 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8772 bool isDebuggerActive() {
8773 return IsDebuggerPresent() != 0;
8778 inline bool isDebuggerActive() { return false; }
8782 #ifdef CATCH_PLATFORM_WINDOWS
8785 void writeToDebugConsole( std::string const& text ) {
8786 ::OutputDebugStringA( text.c_str() );
8791 void writeToDebugConsole( std::string const& text ) {
8792 // !TBD: Need a version for Mac/ XCode and other IDEs
8793 Catch::cout() << text;
8798 // #included from: catch_tostring.hpp
8799 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
8805 const std::string unprintableString = "{?}";
8808 const int hexThreshold = 255;
8811 enum Arch { Big, Little };
8813 static Arch which() {
8816 char asChar[sizeof (int)];
8820 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
8825 std::string rawMemoryToString( const void *object, std::size_t size )
8827 // Reverse order for little endian architectures
8828 int i = 0, end = static_cast<int>( size ), inc = 1;
8829 if( Endianness::which() == Endianness::Little ) {
8834 unsigned char const *bytes = static_cast<unsigned char const *>(object);
8835 std::ostringstream os;
8836 os << "0x" << std::setfill('0') << std::hex;
8837 for( ; i != end; i += inc )
8838 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
8843 std::string toString( std::string const& value ) {
8844 std::string s = value;
8845 if( getCurrentContext().getConfig()->showInvisibles() ) {
8846 for(size_t i = 0; i < s.size(); ++i ) {
8849 case '\n': subs = "\\n"; break;
8850 case '\t': subs = "\\t"; break;
8853 if( !subs.empty() ) {
8854 s = s.substr( 0, i ) + subs + s.substr( i+1 );
8859 return '"' + s + '"';
8861 std::string toString( std::wstring const& value ) {
8864 s.reserve( value.size() );
8865 for(size_t i = 0; i < value.size(); ++i )
8866 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
8867 return Catch::toString( s );
8870 std::string toString( const char* const value ) {
8871 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
8874 std::string toString( char* const value ) {
8875 return Catch::toString( static_cast<const char*>( value ) );
8878 std::string toString( const wchar_t* const value )
8880 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
8883 std::string toString( wchar_t* const value )
8885 return Catch::toString( static_cast<const wchar_t*>( value ) );
8888 std::string toString( int value ) {
8889 std::ostringstream oss;
8891 if( value > Detail::hexThreshold )
8892 oss << " (0x" << std::hex << value << ')';
8896 std::string toString( unsigned long value ) {
8897 std::ostringstream oss;
8899 if( value > Detail::hexThreshold )
8900 oss << " (0x" << std::hex << value << ')';
8904 std::string toString( unsigned int value ) {
8905 return Catch::toString( static_cast<unsigned long>( value ) );
8908 template<typename T>
8909 std::string fpToString( T value, int precision ) {
8910 std::ostringstream oss;
8911 oss << std::setprecision( precision )
8914 std::string d = oss.str();
8915 std::size_t i = d.find_last_not_of( '0' );
8916 if( i != std::string::npos && i != d.size()-1 ) {
8919 d = d.substr( 0, i+1 );
8924 std::string toString( const double value ) {
8925 return fpToString( value, 10 );
8927 std::string toString( const float value ) {
8928 return fpToString( value, 5 ) + 'f';
8931 std::string toString( bool value ) {
8932 return value ? "true" : "false";
8935 std::string toString( char value ) {
8936 if ( value == '\r' )
8938 if ( value == '\f' )
8940 if ( value == '\n' )
8942 if ( value == '\t' )
8944 if ( '\0' <= value && value < ' ' )
8945 return toString( static_cast<unsigned int>( value ) );
8946 char chstr[] = "' '";
8951 std::string toString( signed char value ) {
8952 return toString( static_cast<char>( value ) );
8955 std::string toString( unsigned char value ) {
8956 return toString( static_cast<char>( value ) );
8959 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
8960 std::string toString( long long value ) {
8961 std::ostringstream oss;
8963 if( value > Detail::hexThreshold )
8964 oss << " (0x" << std::hex << value << ')';
8967 std::string toString( unsigned long long value ) {
8968 std::ostringstream oss;
8970 if( value > Detail::hexThreshold )
8971 oss << " (0x" << std::hex << value << ')';
8976 #ifdef CATCH_CONFIG_CPP11_NULLPTR
8977 std::string toString( std::nullptr_t ) {
8983 std::string toString( NSString const * const& nsstring ) {
8986 return "@" + toString([nsstring UTF8String]);
8988 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
8991 return "@" + toString([nsstring UTF8String]);
8993 std::string toString( NSObject* const& nsObject ) {
8994 return toString( [nsObject description] );
8998 } // end namespace Catch
9000 // #included from: catch_result_builder.hpp
9001 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
9005 std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
9006 return secondArg.empty() || secondArg == "\"\""
9007 ? capturedExpression
9008 : capturedExpression + ", " + secondArg;
9010 ResultBuilder::ResultBuilder( char const* macroName,
9011 SourceLineInfo const& lineInfo,
9012 char const* capturedExpression,
9013 ResultDisposition::Flags resultDisposition,
9014 char const* secondArg )
9015 : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
9016 m_shouldDebugBreak( false ),
9017 m_shouldThrow( false ),
9018 m_guardException( false )
9021 ResultBuilder::~ResultBuilder() {
9022 #if defined(CATCH_CONFIG_FAST_COMPILE)
9023 if ( m_guardException ) {
9024 m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
9025 captureResult( ResultWas::ThrewException );
9026 getCurrentContext().getResultCapture()->exceptionEarlyReported();
9031 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
9032 m_data.resultType = result;
9035 ResultBuilder& ResultBuilder::setResultType( bool result ) {
9036 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
9040 void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
9041 AssertionResult result = build( expr );
9042 handleResult( result );
9045 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
9046 m_assertionInfo.resultDisposition = resultDisposition;
9047 m_stream.oss << Catch::translateActiveException();
9048 captureResult( ResultWas::ThrewException );
9051 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
9052 setResultType( resultType );
9053 captureExpression();
9056 void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
9057 if( expectedMessage.empty() )
9058 captureExpectedException( Matchers::Impl::MatchAllOf<std::string>() );
9060 captureExpectedException( Matchers::Equals( expectedMessage ) );
9063 void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ) {
9065 assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
9066 AssertionResultData data = m_data;
9067 data.resultType = ResultWas::Ok;
9068 data.reconstructedExpression = m_assertionInfo.capturedExpression;
9070 std::string actualMessage = Catch::translateActiveException();
9071 if( !matcher.match( actualMessage ) ) {
9072 data.resultType = ResultWas::ExpressionFailed;
9073 data.reconstructedExpression = actualMessage;
9075 AssertionResult result( m_assertionInfo, data );
9076 handleResult( result );
9079 void ResultBuilder::captureExpression() {
9080 AssertionResult result = build();
9081 handleResult( result );
9084 void ResultBuilder::handleResult( AssertionResult const& result )
9086 getResultCapture().assertionEnded( result );
9088 if( !result.isOk() ) {
9089 if( getCurrentContext().getConfig()->shouldDebugBreak() )
9090 m_shouldDebugBreak = true;
9091 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
9092 m_shouldThrow = true;
9096 void ResultBuilder::react() {
9097 #if defined(CATCH_CONFIG_FAST_COMPILE)
9098 if (m_shouldDebugBreak) {
9099 ///////////////////////////////////////////////////////////////////
9100 // To inspect the state during test, you need to go one level up the callstack
9101 // To go back to the test and change execution, jump over the throw statement
9102 ///////////////////////////////////////////////////////////////////
9103 CATCH_BREAK_INTO_DEBUGGER();
9107 throw Catch::TestFailureException();
9110 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
9111 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
9113 AssertionResult ResultBuilder::build() const
9115 return build( *this );
9118 // CAVEAT: The returned AssertionResult stores a pointer to the argument expr,
9119 // a temporary DecomposedExpression, which in turn holds references to
9120 // operands, possibly temporary as well.
9121 // It should immediately be passed to handleResult; if the expression
9122 // needs to be reported, its string expansion must be composed before
9123 // the temporaries are destroyed.
9124 AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const
9126 assert( m_data.resultType != ResultWas::Unknown );
9127 AssertionResultData data = m_data;
9129 // Flip bool results if FalseTest flag is set
9130 if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
9131 data.negate( expr.isBinaryExpression() );
9134 data.message = m_stream.oss.str();
9135 data.decomposedExpression = &expr; // for lazy reconstruction
9136 return AssertionResult( m_assertionInfo, data );
9139 void ResultBuilder::reconstructExpression( std::string& dest ) const {
9140 dest = m_assertionInfo.capturedExpression;
9143 void ResultBuilder::setExceptionGuard() {
9144 m_guardException = true;
9146 void ResultBuilder::unsetExceptionGuard() {
9147 m_guardException = false;
9150 } // end namespace Catch
9152 // #included from: catch_tag_alias_registry.hpp
9153 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
9157 TagAliasRegistry::~TagAliasRegistry() {}
9159 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
9160 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
9161 if( it != m_registry.end() )
9164 return Option<TagAlias>();
9167 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
9168 std::string expandedTestSpec = unexpandedTestSpec;
9169 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
9172 std::size_t pos = expandedTestSpec.find( it->first );
9173 if( pos != std::string::npos ) {
9174 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
9176 expandedTestSpec.substr( pos + it->first.size() );
9179 return expandedTestSpec;
9182 void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
9184 if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) {
9185 std::ostringstream oss;
9186 oss << Colour( Colour::Red )
9187 << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n"
9188 << Colour( Colour::FileName )
9189 << lineInfo << '\n';
9190 throw std::domain_error( oss.str().c_str() );
9192 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
9193 std::ostringstream oss;
9194 oss << Colour( Colour::Red )
9195 << "error: tag alias, \"" << alias << "\" already registered.\n"
9196 << "\tFirst seen at "
9197 << Colour( Colour::Red ) << find(alias)->lineInfo << '\n'
9198 << Colour( Colour::Red ) << "\tRedefined at "
9199 << Colour( Colour::FileName) << lineInfo << '\n';
9200 throw std::domain_error( oss.str().c_str() );
9204 ITagAliasRegistry::~ITagAliasRegistry() {}
9206 ITagAliasRegistry const& ITagAliasRegistry::get() {
9207 return getRegistryHub().getTagAliasRegistry();
9210 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
9211 getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo );
9214 } // end namespace Catch
9216 // #included from: catch_matchers_string.hpp
9219 namespace Matchers {
9221 namespace StdString {
9223 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
9224 : m_caseSensitivity( caseSensitivity ),
9225 m_str( adjustString( str ) )
9227 std::string CasedString::adjustString( std::string const& str ) const {
9228 return m_caseSensitivity == CaseSensitive::No
9232 std::string CasedString::caseSensitivitySuffix() const {
9233 return m_caseSensitivity == CaseSensitive::No
9234 ? " (case insensitive)"
9238 StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
9239 : m_comparator( comparator ),
9240 m_operation( operation ) {
9243 std::string StringMatcherBase::describe() const {
9244 std::string description;
9245 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
9246 m_comparator.caseSensitivitySuffix().size());
9247 description += m_operation;
9248 description += ": \"";
9249 description += m_comparator.m_str;
9250 description += "\"";
9251 description += m_comparator.caseSensitivitySuffix();
9255 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
9257 bool EqualsMatcher::match( std::string const& source ) const {
9258 return m_comparator.adjustString( source ) == m_comparator.m_str;
9261 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
9263 bool ContainsMatcher::match( std::string const& source ) const {
9264 return contains( m_comparator.adjustString( source ), m_comparator.m_str );
9267 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
9269 bool StartsWithMatcher::match( std::string const& source ) const {
9270 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9273 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
9275 bool EndsWithMatcher::match( std::string const& source ) const {
9276 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9279 } // namespace StdString
9281 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9282 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
9284 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9285 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
9287 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9288 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9290 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9291 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9294 } // namespace Matchers
9295 } // namespace Catch
9296 // #included from: ../reporters/catch_reporter_multi.hpp
9297 #define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
9301 class MultipleReporters : public SharedImpl<IStreamingReporter> {
9302 typedef std::vector<Ptr<IStreamingReporter> > Reporters;
9303 Reporters m_reporters;
9306 void add( Ptr<IStreamingReporter> const& reporter ) {
9307 m_reporters.push_back( reporter );
9310 public: // IStreamingReporter
9312 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9313 return m_reporters[0]->getPreferences();
9316 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
9317 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9320 (*it)->noMatchingTestCases( spec );
9323 virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
9324 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9327 (*it)->testRunStarting( testRunInfo );
9330 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
9331 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9334 (*it)->testGroupStarting( groupInfo );
9337 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
9338 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9341 (*it)->testCaseStarting( testInfo );
9344 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
9345 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9348 (*it)->sectionStarting( sectionInfo );
9351 virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
9352 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9355 (*it)->assertionStarting( assertionInfo );
9358 // The return value indicates if the messages buffer should be cleared:
9359 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
9360 bool clearBuffer = false;
9361 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9364 clearBuffer |= (*it)->assertionEnded( assertionStats );
9368 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
9369 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9372 (*it)->sectionEnded( sectionStats );
9375 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
9376 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9379 (*it)->testCaseEnded( testCaseStats );
9382 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
9383 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9386 (*it)->testGroupEnded( testGroupStats );
9389 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
9390 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9393 (*it)->testRunEnded( testRunStats );
9396 virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
9397 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9400 (*it)->skipTest( testInfo );
9403 virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
9409 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
9410 Ptr<IStreamingReporter> resultingReporter;
9412 if( existingReporter ) {
9413 MultipleReporters* multi = existingReporter->tryAsMulti();
9415 multi = new MultipleReporters;
9416 resultingReporter = Ptr<IStreamingReporter>( multi );
9417 if( existingReporter )
9418 multi->add( existingReporter );
9421 resultingReporter = existingReporter;
9422 multi->add( additionalReporter );
9425 resultingReporter = additionalReporter;
9427 return resultingReporter;
9430 } // end namespace Catch
9432 // #included from: ../reporters/catch_reporter_xml.hpp
9433 #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
9435 // #included from: catch_reporter_bases.hpp
9436 #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
9446 // Because formatting using c++ streams is stateful, drop down to C is required
9447 // Alternatively we could use stringstream, but its performance is... not good.
9448 std::string getFormattedDuration( double duration ) {
9449 // Max exponent + 1 is required to represent the whole part
9450 // + 1 for decimal point
9451 // + 3 for the 3 decimal places
9452 // + 1 for null terminator
9453 const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
9454 char buffer[maxDoubleSize];
9456 // Save previous errno, to prevent sprintf from overwriting it
9459 sprintf_s(buffer, "%.3f", duration);
9461 sprintf(buffer, "%.3f", duration);
9463 return std::string(buffer);
9467 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
9469 StreamingReporterBase( ReporterConfig const& _config )
9470 : m_config( _config.fullConfig() ),
9471 stream( _config.stream() )
9473 m_reporterPrefs.shouldRedirectStdOut = false;
9476 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9477 return m_reporterPrefs;
9480 virtual ~StreamingReporterBase() CATCH_OVERRIDE;
9482 virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
9484 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
9485 currentTestRunInfo = _testRunInfo;
9487 virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
9488 currentGroupInfo = _groupInfo;
9491 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
9492 currentTestCaseInfo = _testInfo;
9494 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
9495 m_sectionStack.push_back( _sectionInfo );
9498 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
9499 m_sectionStack.pop_back();
9501 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
9502 currentTestCaseInfo.reset();
9504 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
9505 currentGroupInfo.reset();
9507 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
9508 currentTestCaseInfo.reset();
9509 currentGroupInfo.reset();
9510 currentTestRunInfo.reset();
9513 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
9514 // Don't do anything with this by default.
9515 // It can optionally be overridden in the derived class.
9518 Ptr<IConfig const> m_config;
9519 std::ostream& stream;
9521 LazyStat<TestRunInfo> currentTestRunInfo;
9522 LazyStat<GroupInfo> currentGroupInfo;
9523 LazyStat<TestCaseInfo> currentTestCaseInfo;
9525 std::vector<SectionInfo> m_sectionStack;
9526 ReporterPreferences m_reporterPrefs;
9529 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
9530 template<typename T, typename ChildNodeT>
9531 struct Node : SharedImpl<> {
9532 explicit Node( T const& _value ) : value( _value ) {}
9535 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
9537 ChildNodes children;
9539 struct SectionNode : SharedImpl<> {
9540 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
9541 virtual ~SectionNode();
9543 bool operator == ( SectionNode const& other ) const {
9544 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
9546 bool operator == ( Ptr<SectionNode> const& other ) const {
9547 return operator==( *other );
9551 typedef std::vector<Ptr<SectionNode> > ChildSections;
9552 typedef std::vector<AssertionStats> Assertions;
9553 ChildSections childSections;
9554 Assertions assertions;
9559 struct BySectionInfo {
9560 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
9561 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
9562 bool operator() ( Ptr<SectionNode> const& node ) const {
9563 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
9566 void operator=( BySectionInfo const& );
9567 SectionInfo const& m_other;
9570 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
9571 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
9572 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
9574 CumulativeReporterBase( ReporterConfig const& _config )
9575 : m_config( _config.fullConfig() ),
9576 stream( _config.stream() )
9578 m_reporterPrefs.shouldRedirectStdOut = false;
9580 ~CumulativeReporterBase();
9582 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9583 return m_reporterPrefs;
9586 virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
9587 virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
9589 virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
9591 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
9592 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
9593 Ptr<SectionNode> node;
9594 if( m_sectionStack.empty() ) {
9595 if( !m_rootSection )
9596 m_rootSection = new SectionNode( incompleteStats );
9597 node = m_rootSection;
9600 SectionNode& parentNode = *m_sectionStack.back();
9601 SectionNode::ChildSections::const_iterator it =
9602 std::find_if( parentNode.childSections.begin(),
9603 parentNode.childSections.end(),
9604 BySectionInfo( sectionInfo ) );
9605 if( it == parentNode.childSections.end() ) {
9606 node = new SectionNode( incompleteStats );
9607 parentNode.childSections.push_back( node );
9612 m_sectionStack.push_back( node );
9613 m_deepestSection = node;
9616 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
9618 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
9619 assert( !m_sectionStack.empty() );
9620 SectionNode& sectionNode = *m_sectionStack.back();
9621 sectionNode.assertions.push_back( assertionStats );
9622 // AssertionResult holds a pointer to a temporary DecomposedExpression,
9623 // which getExpandedExpression() calls to build the expression string.
9624 // Our section stack copy of the assertionResult will likely outlive the
9625 // temporary, so it must be expanded or discarded now to avoid calling
9626 // a destroyed object later.
9627 prepareExpandedExpression( sectionNode.assertions.back().assertionResult );
9630 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
9631 assert( !m_sectionStack.empty() );
9632 SectionNode& node = *m_sectionStack.back();
9633 node.stats = sectionStats;
9634 m_sectionStack.pop_back();
9636 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
9637 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
9638 assert( m_sectionStack.size() == 0 );
9639 node->children.push_back( m_rootSection );
9640 m_testCases.push_back( node );
9641 m_rootSection.reset();
9643 assert( m_deepestSection );
9644 m_deepestSection->stdOut = testCaseStats.stdOut;
9645 m_deepestSection->stdErr = testCaseStats.stdErr;
9647 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
9648 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
9649 node->children.swap( m_testCases );
9650 m_testGroups.push_back( node );
9652 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
9653 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
9654 node->children.swap( m_testGroups );
9655 m_testRuns.push_back( node );
9656 testRunEndedCumulative();
9658 virtual void testRunEndedCumulative() = 0;
9660 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
9662 virtual void prepareExpandedExpression( AssertionResult& result ) const {
9664 result.discardDecomposedExpression();
9666 result.expandDecomposedExpression();
9669 Ptr<IConfig const> m_config;
9670 std::ostream& stream;
9671 std::vector<AssertionStats> m_assertions;
9672 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
9673 std::vector<Ptr<TestCaseNode> > m_testCases;
9674 std::vector<Ptr<TestGroupNode> > m_testGroups;
9676 std::vector<Ptr<TestRunNode> > m_testRuns;
9678 Ptr<SectionNode> m_rootSection;
9679 Ptr<SectionNode> m_deepestSection;
9680 std::vector<Ptr<SectionNode> > m_sectionStack;
9681 ReporterPreferences m_reporterPrefs;
9686 char const* getLineOfChars() {
9687 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
9689 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
9690 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
9695 struct TestEventListenerBase : StreamingReporterBase {
9696 TestEventListenerBase( ReporterConfig const& _config )
9697 : StreamingReporterBase( _config )
9700 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
9701 virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
9706 } // end namespace Catch
9708 // #included from: ../internal/catch_reporter_registrars.hpp
9709 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
9713 template<typename T>
9714 class LegacyReporterRegistrar {
9716 class ReporterFactory : public IReporterFactory {
9717 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
9718 return new LegacyReporterAdapter( new T( config ) );
9721 virtual std::string getDescription() const {
9722 return T::getDescription();
9728 LegacyReporterRegistrar( std::string const& name ) {
9729 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
9733 template<typename T>
9734 class ReporterRegistrar {
9736 class ReporterFactory : public SharedImpl<IReporterFactory> {
9738 // *** Please Note ***:
9739 // - If you end up here looking at a compiler error because it's trying to register
9740 // your custom reporter class be aware that the native reporter interface has changed
9741 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
9742 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
9743 // However please consider updating to the new interface as the old one is now
9744 // deprecated and will probably be removed quite soon!
9745 // Please contact me via github if you have any questions at all about this.
9746 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
9747 // no idea who is actually using custom reporters at all (possibly no-one!).
9748 // The new interface is designed to minimise exposure to interface changes in the future.
9749 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
9750 return new T( config );
9753 virtual std::string getDescription() const {
9754 return T::getDescription();
9760 ReporterRegistrar( std::string const& name ) {
9761 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
9765 template<typename T>
9766 class ListenerRegistrar {
9768 class ListenerFactory : public SharedImpl<IReporterFactory> {
9770 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
9771 return new T( config );
9773 virtual std::string getDescription() const {
9774 return std::string();
9780 ListenerRegistrar() {
9781 getMutableRegistryHub().registerListener( new ListenerFactory() );
9786 #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
9787 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
9789 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
9790 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
9792 // Deprecated - use the form without INTERNAL_
9793 #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
9794 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
9796 #define CATCH_REGISTER_LISTENER( listenerType ) \
9797 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
9799 // #included from: ../internal/catch_xmlwriter.hpp
9800 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
9811 enum ForWhat { ForTextNodes, ForAttributes };
9813 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
9815 m_forWhat( forWhat )
9818 void encodeTo( std::ostream& os ) const {
9820 // Apostrophe escaping not necessary if we always use " to write attributes
9821 // (see: http://www.w3.org/TR/xml/#syntax)
9823 for( std::size_t i = 0; i < m_str.size(); ++ i ) {
9826 case '<': os << "<"; break;
9827 case '&': os << "&"; break;
9830 // See: http://www.w3.org/TR/xml/#syntax
9831 if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
9838 if( m_forWhat == ForAttributes )
9845 // Escape control chars - based on contribution by @espenalb in PR #465 and
9847 if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
9848 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
9849 os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
9850 << static_cast<int>( c );
9858 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
9859 xmlEncode.encodeTo( os );
9871 class ScopedElement {
9873 ScopedElement( XmlWriter* writer )
9874 : m_writer( writer )
9877 ScopedElement( ScopedElement const& other )
9878 : m_writer( other.m_writer ){
9879 other.m_writer = CATCH_NULL;
9884 m_writer->endElement();
9887 ScopedElement& writeText( std::string const& text, bool indent = true ) {
9888 m_writer->writeText( text, indent );
9892 template<typename T>
9893 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
9894 m_writer->writeAttribute( name, attribute );
9899 mutable XmlWriter* m_writer;
9903 : m_tagIsOpen( false ),
9904 m_needsNewline( false ),
9905 m_os( Catch::cout() )
9910 XmlWriter( std::ostream& os )
9911 : m_tagIsOpen( false ),
9912 m_needsNewline( false ),
9919 while( !m_tags.empty() )
9923 XmlWriter& startElement( std::string const& name ) {
9925 newlineIfNecessary();
9926 m_os << m_indent << '<' << name;
9927 m_tags.push_back( name );
9933 ScopedElement scopedElement( std::string const& name ) {
9934 ScopedElement scoped( this );
9935 startElement( name );
9939 XmlWriter& endElement() {
9940 newlineIfNecessary();
9941 m_indent = m_indent.substr( 0, m_indent.size()-2 );
9944 m_tagIsOpen = false;
9947 m_os << m_indent << "</" << m_tags.back() << ">";
9954 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
9955 if( !name.empty() && !attribute.empty() )
9956 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
9960 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
9961 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
9965 template<typename T>
9966 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
9967 std::ostringstream oss;
9969 return writeAttribute( name, oss.str() );
9972 XmlWriter& writeText( std::string const& text, bool indent = true ) {
9973 if( !text.empty() ){
9974 bool tagWasOpen = m_tagIsOpen;
9976 if( tagWasOpen && indent )
9978 m_os << XmlEncode( text );
9979 m_needsNewline = true;
9984 XmlWriter& writeComment( std::string const& text ) {
9986 m_os << m_indent << "<!--" << text << "-->";
9987 m_needsNewline = true;
9991 void writeStylesheetRef( std::string const& url ) {
9992 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
9995 XmlWriter& writeBlankLine() {
10001 void ensureTagClosed() {
10002 if( m_tagIsOpen ) {
10003 m_os << ">" << std::endl;
10004 m_tagIsOpen = false;
10009 XmlWriter( XmlWriter const& );
10010 void operator=( XmlWriter const& );
10012 void writeDeclaration() {
10013 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
10016 void newlineIfNecessary() {
10017 if( m_needsNewline ) {
10019 m_needsNewline = false;
10024 bool m_needsNewline;
10025 std::vector<std::string> m_tags;
10026 std::string m_indent;
10027 std::ostream& m_os;
10031 // #included from: catch_reenable_warnings.h
10033 #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
10036 # ifdef __ICC // icpc defines the __clang__ macro
10037 # pragma warning(pop)
10039 # pragma clang diagnostic pop
10041 #elif defined __GNUC__
10042 # pragma GCC diagnostic pop
10047 class XmlReporter : public StreamingReporterBase {
10049 XmlReporter( ReporterConfig const& _config )
10050 : StreamingReporterBase( _config ),
10051 m_xml(_config.stream()),
10052 m_sectionDepth( 0 )
10054 m_reporterPrefs.shouldRedirectStdOut = true;
10057 virtual ~XmlReporter() CATCH_OVERRIDE;
10059 static std::string getDescription() {
10060 return "Reports test results as an XML document";
10063 virtual std::string getStylesheetRef() const {
10064 return std::string();
10067 void writeSourceInfo( SourceLineInfo const& sourceInfo ) {
10069 .writeAttribute( "filename", sourceInfo.file )
10070 .writeAttribute( "line", sourceInfo.line );
10073 public: // StreamingReporterBase
10075 virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
10076 StreamingReporterBase::noMatchingTestCases( s );
10079 virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
10080 StreamingReporterBase::testRunStarting( testInfo );
10081 std::string stylesheetRef = getStylesheetRef();
10082 if( !stylesheetRef.empty() )
10083 m_xml.writeStylesheetRef( stylesheetRef );
10084 m_xml.startElement( "Catch" );
10085 if( !m_config->name().empty() )
10086 m_xml.writeAttribute( "name", m_config->name() );
10089 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
10090 StreamingReporterBase::testGroupStarting( groupInfo );
10091 m_xml.startElement( "Group" )
10092 .writeAttribute( "name", groupInfo.name );
10095 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
10096 StreamingReporterBase::testCaseStarting(testInfo);
10097 m_xml.startElement( "TestCase" )
10098 .writeAttribute( "name", trim( testInfo.name ) )
10099 .writeAttribute( "description", testInfo.description )
10100 .writeAttribute( "tags", testInfo.tagsAsString );
10102 writeSourceInfo( testInfo.lineInfo );
10104 if ( m_config->showDurations() == ShowDurations::Always )
10105 m_testCaseTimer.start();
10106 m_xml.ensureTagClosed();
10109 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
10110 StreamingReporterBase::sectionStarting( sectionInfo );
10111 if( m_sectionDepth++ > 0 ) {
10112 m_xml.startElement( "Section" )
10113 .writeAttribute( "name", trim( sectionInfo.name ) )
10114 .writeAttribute( "description", sectionInfo.description );
10115 writeSourceInfo( sectionInfo.lineInfo );
10116 m_xml.ensureTagClosed();
10120 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
10122 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
10124 AssertionResult const& result = assertionStats.assertionResult;
10126 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
10128 if( includeResults ) {
10129 // Print any info messages in <Info> tags.
10130 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
10133 if( it->type == ResultWas::Info ) {
10134 m_xml.scopedElement( "Info" )
10135 .writeText( it->message );
10136 } else if ( it->type == ResultWas::Warning ) {
10137 m_xml.scopedElement( "Warning" )
10138 .writeText( it->message );
10143 // Drop out if result was successful but we're not printing them.
10144 if( !includeResults && result.getResultType() != ResultWas::Warning )
10147 // Print the expression if there is one.
10148 if( result.hasExpression() ) {
10149 m_xml.startElement( "Expression" )
10150 .writeAttribute( "success", result.succeeded() )
10151 .writeAttribute( "type", result.getTestMacroName() );
10153 writeSourceInfo( result.getSourceInfo() );
10155 m_xml.scopedElement( "Original" )
10156 .writeText( result.getExpression() );
10157 m_xml.scopedElement( "Expanded" )
10158 .writeText( result.getExpandedExpression() );
10161 // And... Print a result applicable to each result type.
10162 switch( result.getResultType() ) {
10163 case ResultWas::ThrewException:
10164 m_xml.startElement( "Exception" );
10165 writeSourceInfo( result.getSourceInfo() );
10166 m_xml.writeText( result.getMessage() );
10167 m_xml.endElement();
10169 case ResultWas::FatalErrorCondition:
10170 m_xml.startElement( "FatalErrorCondition" );
10171 writeSourceInfo( result.getSourceInfo() );
10172 m_xml.writeText( result.getMessage() );
10173 m_xml.endElement();
10175 case ResultWas::Info:
10176 m_xml.scopedElement( "Info" )
10177 .writeText( result.getMessage() );
10179 case ResultWas::Warning:
10180 // Warning will already have been written
10182 case ResultWas::ExplicitFailure:
10183 m_xml.startElement( "Failure" );
10184 writeSourceInfo( result.getSourceInfo() );
10185 m_xml.writeText( result.getMessage() );
10186 m_xml.endElement();
10192 if( result.hasExpression() )
10193 m_xml.endElement();
10198 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
10199 StreamingReporterBase::sectionEnded( sectionStats );
10200 if( --m_sectionDepth > 0 ) {
10201 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
10202 e.writeAttribute( "successes", sectionStats.assertions.passed );
10203 e.writeAttribute( "failures", sectionStats.assertions.failed );
10204 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
10206 if ( m_config->showDurations() == ShowDurations::Always )
10207 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
10209 m_xml.endElement();
10213 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
10214 StreamingReporterBase::testCaseEnded( testCaseStats );
10215 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
10216 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
10218 if ( m_config->showDurations() == ShowDurations::Always )
10219 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
10221 if( !testCaseStats.stdOut.empty() )
10222 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
10223 if( !testCaseStats.stdErr.empty() )
10224 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
10226 m_xml.endElement();
10229 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
10230 StreamingReporterBase::testGroupEnded( testGroupStats );
10231 // TODO: Check testGroupStats.aborting and act accordingly.
10232 m_xml.scopedElement( "OverallResults" )
10233 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
10234 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
10235 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
10236 m_xml.endElement();
10239 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
10240 StreamingReporterBase::testRunEnded( testRunStats );
10241 m_xml.scopedElement( "OverallResults" )
10242 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
10243 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
10244 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
10245 m_xml.endElement();
10249 Timer m_testCaseTimer;
10251 int m_sectionDepth;
10254 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
10256 } // end namespace Catch
10258 // #included from: ../reporters/catch_reporter_junit.hpp
10259 #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
10261 #include <assert.h>
10266 std::string getCurrentTimestamp() {
10267 // Beware, this is not reentrant because of backward compatibility issues
10268 // Also, UTC only, again because of backward compatibility (%z is C++11)
10270 std::time(&rawtime);
10271 const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z");
10274 std::tm timeInfo = {};
10275 gmtime_s(&timeInfo, &rawtime);
10278 timeInfo = std::gmtime(&rawtime);
10281 char timeStamp[timeStampSize];
10282 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
10285 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
10287 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
10289 return std::string(timeStamp);
10294 class JunitReporter : public CumulativeReporterBase {
10296 JunitReporter( ReporterConfig const& _config )
10297 : CumulativeReporterBase( _config ),
10298 xml( _config.stream() ),
10299 m_okToFail( false )
10301 m_reporterPrefs.shouldRedirectStdOut = true;
10304 virtual ~JunitReporter() CATCH_OVERRIDE;
10306 static std::string getDescription() {
10307 return "Reports test results in an XML format that looks like Ant's junitreport target";
10310 virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
10312 virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
10313 CumulativeReporterBase::testRunStarting( runInfo );
10314 xml.startElement( "testsuites" );
10317 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
10318 suiteTimer.start();
10319 stdOutForSuite.str("");
10320 stdErrForSuite.str("");
10321 unexpectedExceptions = 0;
10322 CumulativeReporterBase::testGroupStarting( groupInfo );
10325 virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE {
10326 m_okToFail = testCaseInfo.okToFail();
10328 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
10329 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
10330 unexpectedExceptions++;
10331 return CumulativeReporterBase::assertionEnded( assertionStats );
10334 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
10335 stdOutForSuite << testCaseStats.stdOut;
10336 stdErrForSuite << testCaseStats.stdErr;
10337 CumulativeReporterBase::testCaseEnded( testCaseStats );
10340 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
10341 double suiteTime = suiteTimer.getElapsedSeconds();
10342 CumulativeReporterBase::testGroupEnded( testGroupStats );
10343 writeGroup( *m_testGroups.back(), suiteTime );
10346 virtual void testRunEndedCumulative() CATCH_OVERRIDE {
10350 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
10351 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
10352 TestGroupStats const& stats = groupNode.value;
10353 xml.writeAttribute( "name", stats.groupInfo.name );
10354 xml.writeAttribute( "errors", unexpectedExceptions );
10355 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
10356 xml.writeAttribute( "tests", stats.totals.assertions.total() );
10357 xml.writeAttribute( "hostname", "tbd" ); // !TBD
10358 if( m_config->showDurations() == ShowDurations::Never )
10359 xml.writeAttribute( "time", "" );
10361 xml.writeAttribute( "time", suiteTime );
10362 xml.writeAttribute( "timestamp", getCurrentTimestamp() );
10364 // Write test cases
10365 for( TestGroupNode::ChildNodes::const_iterator
10366 it = groupNode.children.begin(), itEnd = groupNode.children.end();
10369 writeTestCase( **it );
10371 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
10372 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
10375 void writeTestCase( TestCaseNode const& testCaseNode ) {
10376 TestCaseStats const& stats = testCaseNode.value;
10378 // All test cases have exactly one section - which represents the
10379 // test case itself. That section may have 0-n nested sections
10380 assert( testCaseNode.children.size() == 1 );
10381 SectionNode const& rootSection = *testCaseNode.children.front();
10383 std::string className = stats.testInfo.className;
10385 if( className.empty() ) {
10386 if( rootSection.childSections.empty() )
10387 className = "global";
10389 writeSection( className, "", rootSection );
10392 void writeSection( std::string const& className,
10393 std::string const& rootName,
10394 SectionNode const& sectionNode ) {
10395 std::string name = trim( sectionNode.stats.sectionInfo.name );
10396 if( !rootName.empty() )
10397 name = rootName + '/' + name;
10399 if( !sectionNode.assertions.empty() ||
10400 !sectionNode.stdOut.empty() ||
10401 !sectionNode.stdErr.empty() ) {
10402 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
10403 if( className.empty() ) {
10404 xml.writeAttribute( "classname", name );
10405 xml.writeAttribute( "name", "root" );
10408 xml.writeAttribute( "classname", className );
10409 xml.writeAttribute( "name", name );
10411 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
10413 writeAssertions( sectionNode );
10415 if( !sectionNode.stdOut.empty() )
10416 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
10417 if( !sectionNode.stdErr.empty() )
10418 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
10420 for( SectionNode::ChildSections::const_iterator
10421 it = sectionNode.childSections.begin(),
10422 itEnd = sectionNode.childSections.end();
10425 if( className.empty() )
10426 writeSection( name, "", **it );
10428 writeSection( className, name, **it );
10431 void writeAssertions( SectionNode const& sectionNode ) {
10432 for( SectionNode::Assertions::const_iterator
10433 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
10436 writeAssertion( *it );
10438 void writeAssertion( AssertionStats const& stats ) {
10439 AssertionResult const& result = stats.assertionResult;
10440 if( !result.isOk() ) {
10441 std::string elementName;
10442 switch( result.getResultType() ) {
10443 case ResultWas::ThrewException:
10444 case ResultWas::FatalErrorCondition:
10445 elementName = "error";
10447 case ResultWas::ExplicitFailure:
10448 elementName = "failure";
10450 case ResultWas::ExpressionFailed:
10451 elementName = "failure";
10453 case ResultWas::DidntThrowException:
10454 elementName = "failure";
10457 // We should never see these here:
10458 case ResultWas::Info:
10459 case ResultWas::Warning:
10460 case ResultWas::Ok:
10461 case ResultWas::Unknown:
10462 case ResultWas::FailureBit:
10463 case ResultWas::Exception:
10464 elementName = "internalError";
10468 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
10470 xml.writeAttribute( "message", result.getExpandedExpression() );
10471 xml.writeAttribute( "type", result.getTestMacroName() );
10473 std::ostringstream oss;
10474 if( !result.getMessage().empty() )
10475 oss << result.getMessage() << '\n';
10476 for( std::vector<MessageInfo>::const_iterator
10477 it = stats.infoMessages.begin(),
10478 itEnd = stats.infoMessages.end();
10481 if( it->type == ResultWas::Info )
10482 oss << it->message << '\n';
10484 oss << "at " << result.getSourceInfo();
10485 xml.writeText( oss.str(), false );
10491 std::ostringstream stdOutForSuite;
10492 std::ostringstream stdErrForSuite;
10493 unsigned int unexpectedExceptions;
10497 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
10499 } // end namespace Catch
10501 // #included from: ../reporters/catch_reporter_console.hpp
10502 #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
10509 struct ConsoleReporter : StreamingReporterBase {
10510 ConsoleReporter( ReporterConfig const& _config )
10511 : StreamingReporterBase( _config ),
10512 m_headerPrinted( false )
10515 virtual ~ConsoleReporter() CATCH_OVERRIDE;
10516 static std::string getDescription() {
10517 return "Reports test results as plain lines of text";
10520 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
10521 stream << "No test cases matched '" << spec << '\'' << std::endl;
10524 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
10527 virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
10528 AssertionResult const& result = _assertionStats.assertionResult;
10530 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
10532 // Drop out if result was successful but we're not printing them.
10533 if( !includeResults && result.getResultType() != ResultWas::Warning )
10538 AssertionPrinter printer( stream, _assertionStats, includeResults );
10540 stream << std::endl;
10544 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
10545 m_headerPrinted = false;
10546 StreamingReporterBase::sectionStarting( _sectionInfo );
10548 virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
10549 if( _sectionStats.missingAssertions ) {
10551 Colour colour( Colour::ResultError );
10552 if( m_sectionStack.size() > 1 )
10553 stream << "\nNo assertions in section";
10555 stream << "\nNo assertions in test case";
10556 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
10558 if( m_config->showDurations() == ShowDurations::Always ) {
10559 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
10561 if( m_headerPrinted ) {
10562 m_headerPrinted = false;
10564 StreamingReporterBase::sectionEnded( _sectionStats );
10567 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
10568 StreamingReporterBase::testCaseEnded( _testCaseStats );
10569 m_headerPrinted = false;
10571 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
10572 if( currentGroupInfo.used ) {
10573 printSummaryDivider();
10574 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
10575 printTotals( _testGroupStats.totals );
10576 stream << '\n' << std::endl;
10578 StreamingReporterBase::testGroupEnded( _testGroupStats );
10580 virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
10581 printTotalsDivider( _testRunStats.totals );
10582 printTotals( _testRunStats.totals );
10583 stream << std::endl;
10584 StreamingReporterBase::testRunEnded( _testRunStats );
10589 class AssertionPrinter {
10590 void operator= ( AssertionPrinter const& );
10592 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
10593 : stream( _stream ),
10595 result( _stats.assertionResult ),
10596 colour( Colour::None ),
10597 message( result.getMessage() ),
10598 messages( _stats.infoMessages ),
10599 printInfoMessages( _printInfoMessages )
10601 switch( result.getResultType() ) {
10602 case ResultWas::Ok:
10603 colour = Colour::Success;
10604 passOrFail = "PASSED";
10605 //if( result.hasMessage() )
10606 if( _stats.infoMessages.size() == 1 )
10607 messageLabel = "with message";
10608 if( _stats.infoMessages.size() > 1 )
10609 messageLabel = "with messages";
10611 case ResultWas::ExpressionFailed:
10612 if( result.isOk() ) {
10613 colour = Colour::Success;
10614 passOrFail = "FAILED - but was ok";
10617 colour = Colour::Error;
10618 passOrFail = "FAILED";
10620 if( _stats.infoMessages.size() == 1 )
10621 messageLabel = "with message";
10622 if( _stats.infoMessages.size() > 1 )
10623 messageLabel = "with messages";
10625 case ResultWas::ThrewException:
10626 colour = Colour::Error;
10627 passOrFail = "FAILED";
10628 messageLabel = "due to unexpected exception with ";
10629 if (_stats.infoMessages.size() == 1)
10630 messageLabel += "message";
10631 if (_stats.infoMessages.size() > 1)
10632 messageLabel += "messages";
10634 case ResultWas::FatalErrorCondition:
10635 colour = Colour::Error;
10636 passOrFail = "FAILED";
10637 messageLabel = "due to a fatal error condition";
10639 case ResultWas::DidntThrowException:
10640 colour = Colour::Error;
10641 passOrFail = "FAILED";
10642 messageLabel = "because no exception was thrown where one was expected";
10644 case ResultWas::Info:
10645 messageLabel = "info";
10647 case ResultWas::Warning:
10648 messageLabel = "warning";
10650 case ResultWas::ExplicitFailure:
10651 passOrFail = "FAILED";
10652 colour = Colour::Error;
10653 if( _stats.infoMessages.size() == 1 )
10654 messageLabel = "explicitly with message";
10655 if( _stats.infoMessages.size() > 1 )
10656 messageLabel = "explicitly with messages";
10658 // These cases are here to prevent compiler warnings
10659 case ResultWas::Unknown:
10660 case ResultWas::FailureBit:
10661 case ResultWas::Exception:
10662 passOrFail = "** internal error **";
10663 colour = Colour::Error;
10668 void print() const {
10670 if( stats.totals.assertions.total() > 0 ) {
10671 if( result.isOk() )
10674 printOriginalExpression();
10675 printReconstructedExpression();
10684 void printResultType() const {
10685 if( !passOrFail.empty() ) {
10686 Colour colourGuard( colour );
10687 stream << passOrFail << ":\n";
10690 void printOriginalExpression() const {
10691 if( result.hasExpression() ) {
10692 Colour colourGuard( Colour::OriginalExpression );
10694 stream << result.getExpressionInMacro();
10698 void printReconstructedExpression() const {
10699 if( result.hasExpandedExpression() ) {
10700 stream << "with expansion:\n";
10701 Colour colourGuard( Colour::ReconstructedExpression );
10702 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n';
10705 void printMessage() const {
10706 if( !messageLabel.empty() )
10707 stream << messageLabel << ':' << '\n';
10708 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
10711 // If this assertion is a warning ignore any INFO messages
10712 if( printInfoMessages || it->type != ResultWas::Info )
10713 stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n';
10716 void printSourceInfo() const {
10717 Colour colourGuard( Colour::FileName );
10718 stream << result.getSourceInfo() << ": ";
10721 std::ostream& stream;
10722 AssertionStats const& stats;
10723 AssertionResult const& result;
10724 Colour::Code colour;
10725 std::string passOrFail;
10726 std::string messageLabel;
10727 std::string message;
10728 std::vector<MessageInfo> messages;
10729 bool printInfoMessages;
10734 if( !currentTestRunInfo.used )
10735 lazyPrintRunInfo();
10736 if( !currentGroupInfo.used )
10737 lazyPrintGroupInfo();
10739 if( !m_headerPrinted ) {
10740 printTestCaseAndSectionHeader();
10741 m_headerPrinted = true;
10744 void lazyPrintRunInfo() {
10745 stream << '\n' << getLineOfChars<'~'>() << '\n';
10746 Colour colour( Colour::SecondaryText );
10747 stream << currentTestRunInfo->name
10748 << " is a Catch v" << libraryVersion() << " host application.\n"
10749 << "Run with -? for options\n\n";
10751 if( m_config->rngSeed() != 0 )
10752 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
10754 currentTestRunInfo.used = true;
10756 void lazyPrintGroupInfo() {
10757 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
10758 printClosedHeader( "Group: " + currentGroupInfo->name );
10759 currentGroupInfo.used = true;
10762 void printTestCaseAndSectionHeader() {
10763 assert( !m_sectionStack.empty() );
10764 printOpenHeader( currentTestCaseInfo->name );
10766 if( m_sectionStack.size() > 1 ) {
10767 Colour colourGuard( Colour::Headers );
10769 std::vector<SectionInfo>::const_iterator
10770 it = m_sectionStack.begin()+1, // Skip first section (test case)
10771 itEnd = m_sectionStack.end();
10772 for( ; it != itEnd; ++it )
10773 printHeaderString( it->name, 2 );
10776 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
10778 if( !lineInfo.empty() ){
10779 stream << getLineOfChars<'-'>() << '\n';
10780 Colour colourGuard( Colour::FileName );
10781 stream << lineInfo << '\n';
10783 stream << getLineOfChars<'.'>() << '\n' << std::endl;
10786 void printClosedHeader( std::string const& _name ) {
10787 printOpenHeader( _name );
10788 stream << getLineOfChars<'.'>() << '\n';
10790 void printOpenHeader( std::string const& _name ) {
10791 stream << getLineOfChars<'-'>() << '\n';
10793 Colour colourGuard( Colour::Headers );
10794 printHeaderString( _name );
10798 // if string has a : in first line will set indent to follow it on
10799 // subsequent lines
10800 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
10801 std::size_t i = _string.find( ": " );
10802 if( i != std::string::npos )
10806 stream << Text( _string, TextAttributes()
10807 .setIndent( indent+i)
10808 .setInitialIndent( indent ) ) << '\n';
10811 struct SummaryColumn {
10813 SummaryColumn( std::string const& _label, Colour::Code _colour )
10817 SummaryColumn addRow( std::size_t count ) {
10818 std::ostringstream oss;
10820 std::string row = oss.str();
10821 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
10822 while( it->size() < row.size() )
10824 while( it->size() > row.size() )
10827 rows.push_back( row );
10832 Colour::Code colour;
10833 std::vector<std::string> rows;
10837 void printTotals( Totals const& totals ) {
10838 if( totals.testCases.total() == 0 ) {
10839 stream << Colour( Colour::Warning ) << "No tests ran\n";
10841 else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
10842 stream << Colour( Colour::ResultSuccess ) << "All tests passed";
10844 << pluralise( totals.assertions.passed, "assertion" ) << " in "
10845 << pluralise( totals.testCases.passed, "test case" ) << ')'
10850 std::vector<SummaryColumn> columns;
10851 columns.push_back( SummaryColumn( "", Colour::None )
10852 .addRow( totals.testCases.total() )
10853 .addRow( totals.assertions.total() ) );
10854 columns.push_back( SummaryColumn( "passed", Colour::Success )
10855 .addRow( totals.testCases.passed )
10856 .addRow( totals.assertions.passed ) );
10857 columns.push_back( SummaryColumn( "failed", Colour::ResultError )
10858 .addRow( totals.testCases.failed )
10859 .addRow( totals.assertions.failed ) );
10860 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
10861 .addRow( totals.testCases.failedButOk )
10862 .addRow( totals.assertions.failedButOk ) );
10864 printSummaryRow( "test cases", columns, 0 );
10865 printSummaryRow( "assertions", columns, 1 );
10868 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
10869 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
10870 std::string value = it->rows[row];
10871 if( it->label.empty() ) {
10872 stream << label << ": ";
10876 stream << Colour( Colour::Warning ) << "- none -";
10878 else if( value != "0" ) {
10879 stream << Colour( Colour::LightGrey ) << " | ";
10880 stream << Colour( it->colour )
10881 << value << ' ' << it->label;
10887 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
10888 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
10889 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
10891 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
10892 if( i > j && i > k )
10900 void printTotalsDivider( Totals const& totals ) {
10901 if( totals.testCases.total() > 0 ) {
10902 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
10903 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
10904 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
10905 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
10906 findMax( failedRatio, failedButOkRatio, passedRatio )++;
10907 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
10908 findMax( failedRatio, failedButOkRatio, passedRatio )--;
10910 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
10911 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
10912 if( totals.testCases.allPassed() )
10913 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
10915 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
10918 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
10922 void printSummaryDivider() {
10923 stream << getLineOfChars<'-'>() << '\n';
10927 bool m_headerPrinted;
10930 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
10932 } // end namespace Catch
10934 // #included from: ../reporters/catch_reporter_compact.hpp
10935 #define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
10939 struct CompactReporter : StreamingReporterBase {
10941 CompactReporter( ReporterConfig const& _config )
10942 : StreamingReporterBase( _config )
10945 virtual ~CompactReporter();
10947 static std::string getDescription() {
10948 return "Reports test results on a single line, suitable for IDEs";
10951 virtual ReporterPreferences getPreferences() const {
10952 ReporterPreferences prefs;
10953 prefs.shouldRedirectStdOut = false;
10957 virtual void noMatchingTestCases( std::string const& spec ) {
10958 stream << "No test cases matched '" << spec << '\'' << std::endl;
10961 virtual void assertionStarting( AssertionInfo const& ) {}
10963 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
10964 AssertionResult const& result = _assertionStats.assertionResult;
10966 bool printInfoMessages = true;
10968 // Drop out if result was successful and we're not printing those
10969 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
10970 if( result.getResultType() != ResultWas::Warning )
10972 printInfoMessages = false;
10975 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
10978 stream << std::endl;
10982 virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE {
10983 if (m_config->showDurations() == ShowDurations::Always) {
10984 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
10988 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
10989 printTotals( _testRunStats.totals );
10990 stream << '\n' << std::endl;
10991 StreamingReporterBase::testRunEnded( _testRunStats );
10995 class AssertionPrinter {
10996 void operator= ( AssertionPrinter const& );
10998 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
10999 : stream( _stream )
11001 , result( _stats.assertionResult )
11002 , messages( _stats.infoMessages )
11003 , itMessage( _stats.infoMessages.begin() )
11004 , printInfoMessages( _printInfoMessages )
11010 itMessage = messages.begin();
11012 switch( result.getResultType() ) {
11013 case ResultWas::Ok:
11014 printResultType( Colour::ResultSuccess, passedString() );
11015 printOriginalExpression();
11016 printReconstructedExpression();
11017 if ( ! result.hasExpression() )
11018 printRemainingMessages( Colour::None );
11020 printRemainingMessages();
11022 case ResultWas::ExpressionFailed:
11023 if( result.isOk() )
11024 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
11026 printResultType( Colour::Error, failedString() );
11027 printOriginalExpression();
11028 printReconstructedExpression();
11029 printRemainingMessages();
11031 case ResultWas::ThrewException:
11032 printResultType( Colour::Error, failedString() );
11033 printIssue( "unexpected exception with message:" );
11035 printExpressionWas();
11036 printRemainingMessages();
11038 case ResultWas::FatalErrorCondition:
11039 printResultType( Colour::Error, failedString() );
11040 printIssue( "fatal error condition with message:" );
11042 printExpressionWas();
11043 printRemainingMessages();
11045 case ResultWas::DidntThrowException:
11046 printResultType( Colour::Error, failedString() );
11047 printIssue( "expected exception, got none" );
11048 printExpressionWas();
11049 printRemainingMessages();
11051 case ResultWas::Info:
11052 printResultType( Colour::None, "info" );
11054 printRemainingMessages();
11056 case ResultWas::Warning:
11057 printResultType( Colour::None, "warning" );
11059 printRemainingMessages();
11061 case ResultWas::ExplicitFailure:
11062 printResultType( Colour::Error, failedString() );
11063 printIssue( "explicitly" );
11064 printRemainingMessages( Colour::None );
11066 // These cases are here to prevent compiler warnings
11067 case ResultWas::Unknown:
11068 case ResultWas::FailureBit:
11069 case ResultWas::Exception:
11070 printResultType( Colour::Error, "** internal error **" );
11076 // Colour::LightGrey
11078 static Colour::Code dimColour() { return Colour::FileName; }
11080 #ifdef CATCH_PLATFORM_MAC
11081 static const char* failedString() { return "FAILED"; }
11082 static const char* passedString() { return "PASSED"; }
11084 static const char* failedString() { return "failed"; }
11085 static const char* passedString() { return "passed"; }
11088 void printSourceInfo() const {
11089 Colour colourGuard( Colour::FileName );
11090 stream << result.getSourceInfo() << ':';
11093 void printResultType( Colour::Code colour, std::string const& passOrFail ) const {
11094 if( !passOrFail.empty() ) {
11096 Colour colourGuard( colour );
11097 stream << ' ' << passOrFail;
11103 void printIssue( std::string const& issue ) const {
11104 stream << ' ' << issue;
11107 void printExpressionWas() {
11108 if( result.hasExpression() ) {
11111 Colour colour( dimColour() );
11112 stream << " expression was:";
11114 printOriginalExpression();
11118 void printOriginalExpression() const {
11119 if( result.hasExpression() ) {
11120 stream << ' ' << result.getExpression();
11124 void printReconstructedExpression() const {
11125 if( result.hasExpandedExpression() ) {
11127 Colour colour( dimColour() );
11128 stream << " for: ";
11130 stream << result.getExpandedExpression();
11134 void printMessage() {
11135 if ( itMessage != messages.end() ) {
11136 stream << " '" << itMessage->message << '\'';
11141 void printRemainingMessages( Colour::Code colour = dimColour() ) {
11142 if ( itMessage == messages.end() )
11145 // using messages.end() directly yields compilation error:
11146 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
11147 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
11150 Colour colourGuard( colour );
11151 stream << " with " << pluralise( N, "message" ) << ':';
11154 for(; itMessage != itEnd; ) {
11155 // If this assertion is a warning ignore any INFO messages
11156 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
11157 stream << " '" << itMessage->message << '\'';
11158 if ( ++itMessage != itEnd ) {
11159 Colour colourGuard( dimColour() );
11167 std::ostream& stream;
11168 AssertionStats const& stats;
11169 AssertionResult const& result;
11170 std::vector<MessageInfo> messages;
11171 std::vector<MessageInfo>::const_iterator itMessage;
11172 bool printInfoMessages;
11175 // Colour, message variants:
11176 // - white: No tests ran.
11177 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
11178 // - white: Passed [both/all] N test cases (no assertions).
11179 // - red: Failed N tests cases, failed M assertions.
11180 // - green: Passed [both/all] N tests cases with M assertions.
11182 std::string bothOrAll( std::size_t count ) const {
11183 return count == 1 ? std::string() : count == 2 ? "both " : "all " ;
11186 void printTotals( const Totals& totals ) const {
11187 if( totals.testCases.total() == 0 ) {
11188 stream << "No tests ran.";
11190 else if( totals.testCases.failed == totals.testCases.total() ) {
11191 Colour colour( Colour::ResultError );
11192 const std::string qualify_assertions_failed =
11193 totals.assertions.failed == totals.assertions.total() ?
11194 bothOrAll( totals.assertions.failed ) : std::string();
11196 "Failed " << bothOrAll( totals.testCases.failed )
11197 << pluralise( totals.testCases.failed, "test case" ) << ", "
11198 "failed " << qualify_assertions_failed <<
11199 pluralise( totals.assertions.failed, "assertion" ) << '.';
11201 else if( totals.assertions.total() == 0 ) {
11203 "Passed " << bothOrAll( totals.testCases.total() )
11204 << pluralise( totals.testCases.total(), "test case" )
11205 << " (no assertions).";
11207 else if( totals.assertions.failed ) {
11208 Colour colour( Colour::ResultError );
11210 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
11211 "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.';
11214 Colour colour( Colour::ResultSuccess );
11216 "Passed " << bothOrAll( totals.testCases.passed )
11217 << pluralise( totals.testCases.passed, "test case" ) <<
11218 " with " << pluralise( totals.assertions.passed, "assertion" ) << '.';
11223 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
11225 } // end namespace Catch
11228 // These are all here to avoid warnings about not having any out of line
11230 NonCopyable::~NonCopyable() {}
11231 IShared::~IShared() {}
11232 IStream::~IStream() CATCH_NOEXCEPT {}
11233 FileStream::~FileStream() CATCH_NOEXCEPT {}
11234 CoutStream::~CoutStream() CATCH_NOEXCEPT {}
11235 DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
11236 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
11237 IContext::~IContext() {}
11238 IResultCapture::~IResultCapture() {}
11239 ITestCase::~ITestCase() {}
11240 ITestCaseRegistry::~ITestCaseRegistry() {}
11241 IRegistryHub::~IRegistryHub() {}
11242 IMutableRegistryHub::~IMutableRegistryHub() {}
11243 IExceptionTranslator::~IExceptionTranslator() {}
11244 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
11245 IReporter::~IReporter() {}
11246 IReporterFactory::~IReporterFactory() {}
11247 IReporterRegistry::~IReporterRegistry() {}
11248 IStreamingReporter::~IStreamingReporter() {}
11249 AssertionStats::~AssertionStats() {}
11250 SectionStats::~SectionStats() {}
11251 TestCaseStats::~TestCaseStats() {}
11252 TestGroupStats::~TestGroupStats() {}
11253 TestRunStats::~TestRunStats() {}
11254 CumulativeReporterBase::SectionNode::~SectionNode() {}
11255 CumulativeReporterBase::~CumulativeReporterBase() {}
11257 StreamingReporterBase::~StreamingReporterBase() {}
11258 ConsoleReporter::~ConsoleReporter() {}
11259 CompactReporter::~CompactReporter() {}
11260 IRunner::~IRunner() {}
11261 IMutableContext::~IMutableContext() {}
11262 IConfig::~IConfig() {}
11263 XmlReporter::~XmlReporter() {}
11264 JunitReporter::~JunitReporter() {}
11265 TestRegistry::~TestRegistry() {}
11266 FreeFunctionTestCase::~FreeFunctionTestCase() {}
11267 IGeneratorInfo::~IGeneratorInfo() {}
11268 IGeneratorsForTest::~IGeneratorsForTest() {}
11269 WildcardPattern::~WildcardPattern() {}
11270 TestSpec::Pattern::~Pattern() {}
11271 TestSpec::NamePattern::~NamePattern() {}
11272 TestSpec::TagPattern::~TagPattern() {}
11273 TestSpec::ExcludedPattern::~ExcludedPattern() {}
11274 Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {}
11276 void Config::dummy() {}
11278 namespace TestCaseTracking {
11279 ITracker::~ITracker() {}
11280 TrackerBase::~TrackerBase() {}
11281 SectionTracker::~SectionTracker() {}
11282 IndexTracker::~IndexTracker() {}
11287 #pragma clang diagnostic pop
11292 #ifdef CATCH_CONFIG_MAIN
11293 // #included from: internal/catch_default_main.hpp
11294 #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
11298 #if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
11299 // Standard C/C++ Win32 Unicode wmain entry point
11300 extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {
11302 // Standard C/C++ main entry point
11303 int main (int argc, char * argv[]) {
11306 int result = Catch::Session().run( argc, argv );
11307 return ( result < 0xff ? result : 0xff );
11312 // Objective-C entry point
11313 int main (int argc, char * const argv[]) {
11314 #if !CATCH_ARC_ENABLED
11315 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
11318 Catch::registerTestMethods();
11319 int result = Catch::Session().run( argc, (char* const*)argv );
11321 #if !CATCH_ARC_ENABLED
11325 return ( result < 0xff ? result : 0xff );
11332 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
11333 # undef CLARA_CONFIG_MAIN
11338 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
11339 #ifdef CATCH_CONFIG_PREFIX_ALL
11341 #if defined(CATCH_CONFIG_FAST_COMPILE)
11342 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr )
11343 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11345 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr )
11346 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11349 #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr )
11350 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
11351 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
11352 #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr )
11354 #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr )
11355 #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr )
11356 #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr )
11357 #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr )
11358 #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr )
11360 #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr )
11361 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
11362 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11363 #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr )
11365 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
11367 #if defined(CATCH_CONFIG_FAST_COMPILE)
11368 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11370 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11373 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
11374 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
11375 #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
11376 #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
11377 #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
11379 #ifdef CATCH_CONFIG_VARIADIC_MACROS
11380 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
11381 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
11382 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
11383 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
11384 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
11385 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
11386 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
11387 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
11389 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
11390 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
11391 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
11392 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
11393 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
11394 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg )
11395 #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg )
11396 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg )
11398 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
11400 #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
11401 #define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
11403 #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
11405 // "BDD-style" convenience wrappers
11406 #ifdef CATCH_CONFIG_VARIADIC_MACROS
11407 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
11408 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
11410 #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
11411 #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
11413 #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
11414 #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
11415 #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
11416 #define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
11417 #define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
11419 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
11422 #if defined(CATCH_CONFIG_FAST_COMPILE)
11423 #define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr )
11424 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11427 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr )
11428 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11431 #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr )
11432 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
11433 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
11434 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr )
11436 #define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr )
11437 #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr )
11438 #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr )
11439 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr )
11440 #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr )
11442 #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr )
11443 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
11444 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11445 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr )
11447 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
11449 #if defined(CATCH_CONFIG_FAST_COMPILE)
11450 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11452 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11455 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
11456 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
11457 #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
11458 #define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
11459 #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
11461 #ifdef CATCH_CONFIG_VARIADIC_MACROS
11462 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
11463 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
11464 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
11465 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
11466 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
11467 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
11468 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
11469 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
11471 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
11472 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
11473 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
11474 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
11475 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
11476 #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg )
11477 #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg )
11478 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg )
11480 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
11482 #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
11483 #define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
11485 #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
11489 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
11491 // "BDD-style" convenience wrappers
11492 #ifdef CATCH_CONFIG_VARIADIC_MACROS
11493 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
11494 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
11496 #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
11497 #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
11499 #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
11500 #define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
11501 #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
11502 #define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
11503 #define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
11505 using Catch::Detail::Approx;
11507 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED