00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
00012 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
00013
00014 #define TWOBLUECUBES_CATCH_HPP_INCLUDED
00015
00016 #ifdef __clang__
00017 # pragma clang system_header
00018 #elif defined __GNUC__
00019 # pragma GCC system_header
00020 #endif
00021
00022
00023
00024 #define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
00025
00026 #ifdef __clang__
00027 # ifdef __ICC // icpc defines the __clang__ macro
00028 # pragma warning(push)
00029 # pragma warning(disable: 161 1682)
00030 # else // __ICC
00031 # pragma clang diagnostic ignored "-Wglobal-constructors"
00032 # pragma clang diagnostic ignored "-Wvariadic-macros"
00033 # pragma clang diagnostic ignored "-Wc99-extensions"
00034 # pragma clang diagnostic ignored "-Wunused-variable"
00035 # pragma clang diagnostic push
00036 # pragma clang diagnostic ignored "-Wpadded"
00037 # pragma clang diagnostic ignored "-Wc++98-compat"
00038 # pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
00039 # pragma clang diagnostic ignored "-Wswitch-enum"
00040 # endif
00041 #elif defined __GNUC__
00042 # pragma GCC diagnostic ignored "-Wvariadic-macros"
00043 # pragma GCC diagnostic ignored "-Wunused-variable"
00044 # pragma GCC diagnostic push
00045 # pragma GCC diagnostic ignored "-Wpadded"
00046 #endif
00047
00048 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
00049 # define CATCH_IMPL
00050 #endif
00051
00052 #ifdef CATCH_IMPL
00053 # ifndef CLARA_CONFIG_MAIN
00054 # define CLARA_CONFIG_MAIN_NOT_DEFINED
00055 # define CLARA_CONFIG_MAIN
00056 # endif
00057 #endif
00058
00059
00060 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
00061
00062
00063 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
00064
00065 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
00066 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
00067 #define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
00068
00069 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
00070 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
00071
00072 #include <sstream>
00073 #include <stdexcept>
00074 #include <algorithm>
00075
00076
00077 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 #ifdef __clang__
00100
00101 # if __has_feature(cxx_nullptr)
00102 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
00103 # endif
00104
00105 # if __has_feature(cxx_noexcept)
00106 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
00107 # endif
00108
00109 #endif // __clang__
00110
00112
00113 #ifdef __BORLANDC__
00114
00115 #endif // __BORLANDC__
00116
00118
00119 #ifdef __EDG_VERSION__
00120
00121 #endif // __EDG_VERSION__
00122
00124
00125 #ifdef __DMC__
00126
00127 #endif // __DMC__
00128
00130
00131 #ifdef __GNUC__
00132
00133 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
00134 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
00135 #endif
00136
00137 #endif // __GNUC__
00138
00140
00141 #ifdef _MSC_VER
00142
00143 #if (_MSC_VER >= 1600)
00144 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
00145 #endif
00146
00147 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
00148 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
00149 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
00150 #endif
00151
00152 #endif // _MSC_VER
00153
00154
00155 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
00156 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
00157 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
00158 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
00159
00160 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
00161
00162 #endif
00163
00165
00166
00167
00168 #if (__cplusplus >= 201103L)
00169
00170 # define CATCH_CPP11_OR_GREATER
00171
00172 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
00173 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
00174 # endif
00175
00176 # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
00177 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
00178 # endif
00179
00180 # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
00181 # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
00182 # endif
00183
00184 # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
00185 # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
00186 # endif
00187
00188 # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
00189 # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
00190 # endif
00191
00192 # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
00193 # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
00194 # endif
00195
00196 #endif // __cplusplus >= 201103L
00197
00198
00199 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
00200 # define CATCH_CONFIG_CPP11_NULLPTR
00201 #endif
00202 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
00203 # define CATCH_CONFIG_CPP11_NOEXCEPT
00204 #endif
00205 #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)
00206 # define CATCH_CONFIG_CPP11_GENERATED_METHODS
00207 #endif
00208 #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)
00209 # define CATCH_CONFIG_CPP11_IS_ENUM
00210 #endif
00211 #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
00212 # define CATCH_CONFIG_CPP11_TUPLE
00213 #endif
00214 #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
00215 #define CATCH_CONFIG_VARIADIC_MACROS
00216 #endif
00217
00218
00219 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
00220 # define CATCH_NOEXCEPT noexcept
00221 # define CATCH_NOEXCEPT_IS(x) noexcept(x)
00222 #else
00223 # define CATCH_NOEXCEPT throw()
00224 # define CATCH_NOEXCEPT_IS(x)
00225 #endif
00226
00227 namespace Catch {
00228
00229 class NonCopyable {
00230 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
00231 NonCopyable( NonCopyable const& ) = delete;
00232 NonCopyable( NonCopyable && ) = delete;
00233 NonCopyable& operator = ( NonCopyable const& ) = delete;
00234 NonCopyable& operator = ( NonCopyable && ) = delete;
00235 #else
00236 NonCopyable( NonCopyable const& info );
00237 NonCopyable& operator = ( NonCopyable const& );
00238 #endif
00239
00240 protected:
00241 NonCopyable() {}
00242 virtual ~NonCopyable();
00243 };
00244
00245 class SafeBool {
00246 public:
00247 typedef void (SafeBool::*type)() const;
00248
00249 static type makeSafe( bool value ) {
00250 return value ? &SafeBool::trueValue : 0;
00251 }
00252 private:
00253 void trueValue() const {}
00254 };
00255
00256 template<typename ContainerT>
00257 inline void deleteAll( ContainerT& container ) {
00258 typename ContainerT::const_iterator it = container.begin();
00259 typename ContainerT::const_iterator itEnd = container.end();
00260 for(; it != itEnd; ++it )
00261 delete *it;
00262 }
00263 template<typename AssociativeContainerT>
00264 inline void deleteAllValues( AssociativeContainerT& container ) {
00265 typename AssociativeContainerT::const_iterator it = container.begin();
00266 typename AssociativeContainerT::const_iterator itEnd = container.end();
00267 for(; it != itEnd; ++it )
00268 delete it->second;
00269 }
00270
00271 bool startsWith( std::string const& s, std::string const& prefix );
00272 bool endsWith( std::string const& s, std::string const& suffix );
00273 bool contains( std::string const& s, std::string const& infix );
00274 void toLowerInPlace( std::string& s );
00275 std::string toLower( std::string const& s );
00276 std::string trim( std::string const& str );
00277 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
00278
00279 struct pluralise {
00280 pluralise( std::size_t count, std::string const& label );
00281
00282 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
00283
00284 std::size_t m_count;
00285 std::string m_label;
00286 };
00287
00288 struct SourceLineInfo {
00289
00290 SourceLineInfo();
00291 SourceLineInfo( char const* _file, std::size_t _line );
00292 SourceLineInfo( SourceLineInfo const& other );
00293 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
00294 SourceLineInfo( SourceLineInfo && ) = default;
00295 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
00296 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
00297 # endif
00298 bool empty() const;
00299 bool operator == ( SourceLineInfo const& other ) const;
00300 bool operator < ( SourceLineInfo const& other ) const;
00301
00302 std::string file;
00303 std::size_t line;
00304 };
00305
00306 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
00307
00308
00309 inline bool isTrue( bool value ){ return value; }
00310 inline bool alwaysTrue() { return true; }
00311 inline bool alwaysFalse() { return false; }
00312
00313 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
00314
00315
00316
00317
00318
00319 struct StreamEndStop {
00320 std::string operator+() {
00321 return std::string();
00322 }
00323 };
00324 template<typename T>
00325 T const& operator + ( T const& value, StreamEndStop ) {
00326 return value;
00327 }
00328 }
00329
00330 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
00331 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
00332
00333 #include <ostream>
00334
00335 namespace Catch {
00336
00337 class NotImplementedException : public std::exception
00338 {
00339 public:
00340 NotImplementedException( SourceLineInfo const& lineInfo );
00341 NotImplementedException( NotImplementedException const& ) {}
00342
00343 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
00344
00345 virtual const char* what() const CATCH_NOEXCEPT;
00346
00347 private:
00348 std::string m_what;
00349 SourceLineInfo m_lineInfo;
00350 };
00351
00352 }
00353
00355 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
00356
00357
00358 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
00359
00360
00361 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
00362
00363 #include <string>
00364
00365 namespace Catch {
00366
00367 struct IGeneratorInfo {
00368 virtual ~IGeneratorInfo();
00369 virtual bool moveNext() = 0;
00370 virtual std::size_t getCurrentIndex() const = 0;
00371 };
00372
00373 struct IGeneratorsForTest {
00374 virtual ~IGeneratorsForTest();
00375
00376 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
00377 virtual bool moveNext() = 0;
00378 };
00379
00380 IGeneratorsForTest* createGeneratorsForTest();
00381
00382 }
00383
00384
00385 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
00386
00387 #ifdef __clang__
00388 #pragma clang diagnostic push
00389 #pragma clang diagnostic ignored "-Wpadded"
00390 #endif
00391
00392 namespace Catch {
00393
00394
00395
00396
00397 template<typename T>
00398 class Ptr {
00399 public:
00400 Ptr() : m_p( NULL ){}
00401 Ptr( T* p ) : m_p( p ){
00402 if( m_p )
00403 m_p->addRef();
00404 }
00405 Ptr( Ptr const& other ) : m_p( other.m_p ){
00406 if( m_p )
00407 m_p->addRef();
00408 }
00409 ~Ptr(){
00410 if( m_p )
00411 m_p->release();
00412 }
00413 void reset() {
00414 if( m_p )
00415 m_p->release();
00416 m_p = NULL;
00417 }
00418 Ptr& operator = ( T* p ){
00419 Ptr temp( p );
00420 swap( temp );
00421 return *this;
00422 }
00423 Ptr& operator = ( Ptr const& other ){
00424 Ptr temp( other );
00425 swap( temp );
00426 return *this;
00427 }
00428 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
00429 T* get() { return m_p; }
00430 const T* get() const{ return m_p; }
00431 T& operator*() const { return *m_p; }
00432 T* operator->() const { return m_p; }
00433 bool operator !() const { return m_p == NULL; }
00434 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
00435
00436 private:
00437 T* m_p;
00438 };
00439
00440 struct IShared : NonCopyable {
00441 virtual ~IShared();
00442 virtual void addRef() const = 0;
00443 virtual void release() const = 0;
00444 };
00445
00446 template<typename T = IShared>
00447 struct SharedImpl : T {
00448
00449 SharedImpl() : m_rc( 0 ){}
00450
00451 virtual void addRef() const {
00452 ++m_rc;
00453 }
00454 virtual void release() const {
00455 if( --m_rc == 0 )
00456 delete this;
00457 }
00458
00459 mutable unsigned int m_rc;
00460 };
00461
00462 }
00463
00464 #ifdef __clang__
00465 #pragma clang diagnostic pop
00466 #endif
00467
00468 #include <memory>
00469 #include <vector>
00470 #include <stdlib.h>
00471
00472 namespace Catch {
00473
00474 class TestCase;
00475 class Stream;
00476 struct IResultCapture;
00477 struct IRunner;
00478 struct IGeneratorsForTest;
00479 struct IConfig;
00480
00481 struct IContext
00482 {
00483 virtual ~IContext();
00484
00485 virtual IResultCapture* getResultCapture() = 0;
00486 virtual IRunner* getRunner() = 0;
00487 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
00488 virtual bool advanceGeneratorsForCurrentTest() = 0;
00489 virtual Ptr<IConfig const> getConfig() const = 0;
00490 };
00491
00492 struct IMutableContext : IContext
00493 {
00494 virtual ~IMutableContext();
00495 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
00496 virtual void setRunner( IRunner* runner ) = 0;
00497 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
00498 };
00499
00500 IContext& getCurrentContext();
00501 IMutableContext& getCurrentMutableContext();
00502 void cleanUpContext();
00503 Stream createStream( std::string const& streamName );
00504
00505 }
00506
00507
00508 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
00509
00510
00511 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
00512
00513 #include <vector>
00514
00515 namespace Catch {
00516
00517 class TestSpec;
00518
00519 struct ITestCase : IShared {
00520 virtual void invoke () const = 0;
00521 protected:
00522 virtual ~ITestCase();
00523 };
00524
00525 class TestCase;
00526 struct IConfig;
00527
00528 struct ITestCaseRegistry {
00529 virtual ~ITestCaseRegistry();
00530 virtual std::vector<TestCase> const& getAllTests() const = 0;
00531 virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const = 0;
00532
00533 };
00534 }
00535
00536 namespace Catch {
00537
00538 template<typename C>
00539 class MethodTestCase : public SharedImpl<ITestCase> {
00540
00541 public:
00542 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
00543
00544 virtual void invoke() const {
00545 C obj;
00546 (obj.*m_method)();
00547 }
00548
00549 private:
00550 virtual ~MethodTestCase() {}
00551
00552 void (C::*m_method)();
00553 };
00554
00555 typedef void(*TestFunction)();
00556
00557 struct NameAndDesc {
00558 NameAndDesc( const char* _name = "", const char* _description= "" )
00559 : name( _name ), description( _description )
00560 {}
00561
00562 const char* name;
00563 const char* description;
00564 };
00565
00566 struct AutoReg {
00567
00568 AutoReg( TestFunction function,
00569 SourceLineInfo const& lineInfo,
00570 NameAndDesc const& nameAndDesc );
00571
00572 template<typename C>
00573 AutoReg( void (C::*method)(),
00574 char const* className,
00575 NameAndDesc const& nameAndDesc,
00576 SourceLineInfo const& lineInfo ) {
00577 registerTestCase( new MethodTestCase<C>( method ),
00578 className,
00579 nameAndDesc,
00580 lineInfo );
00581 }
00582
00583 void registerTestCase( ITestCase* testCase,
00584 char const* className,
00585 NameAndDesc const& nameAndDesc,
00586 SourceLineInfo const& lineInfo );
00587
00588 ~AutoReg();
00589
00590 private:
00591 AutoReg( AutoReg const& );
00592 void operator= ( AutoReg const& );
00593 };
00594
00595 }
00596
00597 #ifdef CATCH_CONFIG_VARIADIC_MACROS
00598
00599 #define INTERNAL_CATCH_TESTCASE( ... ) \
00600 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
00601 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
00602 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
00603
00605 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
00606 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
00607
00609 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
00610 namespace{ \
00611 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
00612 void test(); \
00613 }; \
00614 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
00615 } \
00616 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
00617
00618 #else
00619
00620 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
00621 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
00622 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
00623 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
00624
00626 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
00627 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
00628
00630 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
00631 namespace{ \
00632 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
00633 void test(); \
00634 }; \
00635 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
00636 } \
00637 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
00638
00639 #endif
00640
00641
00642 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
00643
00644
00645 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
00646
00647
00648 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
00649
00650 namespace Catch {
00651
00652
00653 struct ResultWas { enum OfType {
00654 Unknown = -1,
00655 Ok = 0,
00656 Info = 1,
00657 Warning = 2,
00658
00659 FailureBit = 0x10,
00660
00661 ExpressionFailed = FailureBit | 1,
00662 ExplicitFailure = FailureBit | 2,
00663
00664 Exception = 0x100 | FailureBit,
00665
00666 ThrewException = Exception | 1,
00667 DidntThrowException = Exception | 2,
00668
00669 FatalErrorCondition = 0x200 | FailureBit
00670
00671 }; };
00672
00673 inline bool isOk( ResultWas::OfType resultType ) {
00674 return ( resultType & ResultWas::FailureBit ) == 0;
00675 }
00676 inline bool isJustInfo( int flags ) {
00677 return flags == ResultWas::Info;
00678 }
00679
00680
00681 struct ResultDisposition { enum Flags {
00682 Normal = 0x01,
00683
00684 ContinueOnFailure = 0x02,
00685 FalseTest = 0x04,
00686 SuppressFail = 0x08
00687 }; };
00688
00689 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
00690 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
00691 }
00692
00693 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
00694 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
00695 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
00696
00697 }
00698
00699
00700 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
00701
00702 #include <string>
00703
00704 namespace Catch {
00705
00706 struct AssertionInfo
00707 {
00708 AssertionInfo() {}
00709 AssertionInfo( std::string const& _macroName,
00710 SourceLineInfo const& _lineInfo,
00711 std::string const& _capturedExpression,
00712 ResultDisposition::Flags _resultDisposition );
00713
00714 std::string macroName;
00715 SourceLineInfo lineInfo;
00716 std::string capturedExpression;
00717 ResultDisposition::Flags resultDisposition;
00718 };
00719
00720 struct AssertionResultData
00721 {
00722 AssertionResultData() : resultType( ResultWas::Unknown ) {}
00723
00724 std::string reconstructedExpression;
00725 std::string message;
00726 ResultWas::OfType resultType;
00727 };
00728
00729 class AssertionResult {
00730 public:
00731 AssertionResult();
00732 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
00733 ~AssertionResult();
00734 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
00735 AssertionResult( AssertionResult const& ) = default;
00736 AssertionResult( AssertionResult && ) = default;
00737 AssertionResult& operator = ( AssertionResult const& ) = default;
00738 AssertionResult& operator = ( AssertionResult && ) = default;
00739 # endif
00740
00741 bool isOk() const;
00742 bool succeeded() const;
00743 ResultWas::OfType getResultType() const;
00744 bool hasExpression() const;
00745 bool hasMessage() const;
00746 std::string getExpression() const;
00747 std::string getExpressionInMacro() const;
00748 bool hasExpandedExpression() const;
00749 std::string getExpandedExpression() const;
00750 std::string getMessage() const;
00751 SourceLineInfo getSourceInfo() const;
00752 std::string getTestMacroName() const;
00753
00754 protected:
00755 AssertionInfo m_info;
00756 AssertionResultData m_resultData;
00757 };
00758
00759 }
00760
00761 namespace Catch {
00762
00763 struct TestFailureException{};
00764
00765 template<typename T> class ExpressionLhs;
00766
00767 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
00768
00769 struct CopyableStream {
00770 CopyableStream() {}
00771 CopyableStream( CopyableStream const& other ) {
00772 oss << other.oss.str();
00773 }
00774 CopyableStream& operator=( CopyableStream const& other ) {
00775 oss.str("");
00776 oss << other.oss.str();
00777 return *this;
00778 }
00779 std::ostringstream oss;
00780 };
00781
00782 class ResultBuilder {
00783 public:
00784 ResultBuilder( char const* macroName,
00785 SourceLineInfo const& lineInfo,
00786 char const* capturedExpression,
00787 ResultDisposition::Flags resultDisposition );
00788
00789 template<typename T>
00790 ExpressionLhs<T const&> operator <= ( T const& operand );
00791 ExpressionLhs<bool> operator <= ( bool value );
00792
00793 template<typename T>
00794 ResultBuilder& operator << ( T const& value ) {
00795 m_stream.oss << value;
00796 return *this;
00797 }
00798
00799 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
00800 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
00801
00802 ResultBuilder& setResultType( ResultWas::OfType result );
00803 ResultBuilder& setResultType( bool result );
00804 ResultBuilder& setLhs( std::string const& lhs );
00805 ResultBuilder& setRhs( std::string const& rhs );
00806 ResultBuilder& setOp( std::string const& op );
00807
00808 void endExpression();
00809
00810 std::string reconstructExpression() const;
00811 AssertionResult build() const;
00812
00813 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
00814 void captureResult( ResultWas::OfType resultType );
00815 void captureExpression();
00816 void react();
00817 bool shouldDebugBreak() const;
00818 bool allowThrows() const;
00819
00820 private:
00821 AssertionInfo m_assertionInfo;
00822 AssertionResultData m_data;
00823 struct ExprComponents {
00824 ExprComponents() : testFalse( false ) {}
00825 bool testFalse;
00826 std::string lhs, rhs, op;
00827 } m_exprComponents;
00828 CopyableStream m_stream;
00829
00830 bool m_shouldDebugBreak;
00831 bool m_shouldThrow;
00832 };
00833
00834 }
00835
00836
00837
00838 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
00839
00840
00841 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
00842
00843 #ifdef _MSC_VER
00844 #pragma warning(push)
00845 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
00846 #endif
00847
00848 #include <cstddef>
00849
00850 namespace Catch {
00851 namespace Internal {
00852
00853 enum Operator {
00854 IsEqualTo,
00855 IsNotEqualTo,
00856 IsLessThan,
00857 IsGreaterThan,
00858 IsLessThanOrEqualTo,
00859 IsGreaterThanOrEqualTo
00860 };
00861
00862 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
00863 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
00864 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
00865 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
00866 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
00867 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
00868 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
00869
00870 template<typename T>
00871 inline T& opCast(T const& t) { return const_cast<T&>(t); }
00872
00873
00874 #ifdef CATCH_CONFIG_CPP11_NULLPTR
00875 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
00876 #endif // CATCH_CONFIG_CPP11_NULLPTR
00877
00878
00879
00880 template<typename T1, typename T2, Operator Op>
00881 class Evaluator{};
00882
00883 template<typename T1, typename T2>
00884 struct Evaluator<T1, T2, IsEqualTo> {
00885 static bool evaluate( T1 const& lhs, T2 const& rhs) {
00886 return opCast( lhs ) == opCast( rhs );
00887 }
00888 };
00889 template<typename T1, typename T2>
00890 struct Evaluator<T1, T2, IsNotEqualTo> {
00891 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
00892 return opCast( lhs ) != opCast( rhs );
00893 }
00894 };
00895 template<typename T1, typename T2>
00896 struct Evaluator<T1, T2, IsLessThan> {
00897 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
00898 return opCast( lhs ) < opCast( rhs );
00899 }
00900 };
00901 template<typename T1, typename T2>
00902 struct Evaluator<T1, T2, IsGreaterThan> {
00903 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
00904 return opCast( lhs ) > opCast( rhs );
00905 }
00906 };
00907 template<typename T1, typename T2>
00908 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
00909 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
00910 return opCast( lhs ) >= opCast( rhs );
00911 }
00912 };
00913 template<typename T1, typename T2>
00914 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
00915 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
00916 return opCast( lhs ) <= opCast( rhs );
00917 }
00918 };
00919
00920 template<Operator Op, typename T1, typename T2>
00921 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
00922 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
00923 }
00924
00925
00926
00927
00928
00929 template<Operator Op, typename T1, typename T2>
00930 bool compare( T1 const& lhs, T2 const& rhs ) {
00931 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
00932 }
00933
00934
00935 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
00936 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
00937 }
00938 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
00939 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
00940 }
00941 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
00942 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
00943 }
00944
00945
00946 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
00947 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
00948 }
00949 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
00950 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
00951 }
00952 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
00953 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
00954 }
00955
00956
00957 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
00958 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
00959 }
00960 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
00961 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
00962 }
00963 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
00964 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
00965 }
00966
00967
00968 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
00969 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
00970 }
00971 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
00972 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
00973 }
00974 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
00975 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
00976 }
00977
00978
00979 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
00980 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
00981 }
00982 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
00983 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
00984 }
00985
00986
00987 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
00988 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
00989 }
00990 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
00991 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
00992 }
00993
00994 #ifdef CATCH_CONFIG_CPP11_NULLPTR
00995
00996 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
00997 return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
00998 }
00999 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
01000 return Evaluator<T*, T*, Op>::evaluate( lhs, NULL );
01001 }
01002 #endif // CATCH_CONFIG_CPP11_NULLPTR
01003
01004 }
01005 }
01006
01007 #ifdef _MSC_VER
01008 #pragma warning(pop)
01009 #endif
01010
01011
01012 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
01013
01014 #include <sstream>
01015 #include <iomanip>
01016 #include <limits>
01017 #include <vector>
01018 #include <cstddef>
01019
01020 #ifdef __OBJC__
01021
01022 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
01023
01024 #import <Foundation/Foundation.h>
01025
01026 #ifdef __has_feature
01027 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
01028 #else
01029 #define CATCH_ARC_ENABLED 0
01030 #endif
01031
01032 void arcSafeRelease( NSObject* obj );
01033 id performOptionalSelector( id obj, SEL sel );
01034
01035 #if !CATCH_ARC_ENABLED
01036 inline void arcSafeRelease( NSObject* obj ) {
01037 [obj release];
01038 }
01039 inline id performOptionalSelector( id obj, SEL sel ) {
01040 if( [obj respondsToSelector: sel] )
01041 return [obj performSelector: sel];
01042 return nil;
01043 }
01044 #define CATCH_UNSAFE_UNRETAINED
01045 #define CATCH_ARC_STRONG
01046 #else
01047 inline void arcSafeRelease( NSObject* ){}
01048 inline id performOptionalSelector( id obj, SEL sel ) {
01049 #ifdef __clang__
01050 #pragma clang diagnostic push
01051 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
01052 #endif
01053 if( [obj respondsToSelector: sel] )
01054 return [obj performSelector: sel];
01055 #ifdef __clang__
01056 #pragma clang diagnostic pop
01057 #endif
01058 return nil;
01059 }
01060 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
01061 #define CATCH_ARC_STRONG __strong
01062 #endif
01063
01064 #endif
01065
01066 #ifdef CATCH_CONFIG_CPP11_TUPLE
01067 #include <tuple>
01068 #endif
01069
01070 #ifdef CATCH_CONFIG_CPP11_IS_ENUM
01071 #include <type_traits>
01072 #endif
01073
01074 namespace Catch {
01075
01076
01077 template<typename T>
01078 std::string toString( T const& value );
01079
01080
01081
01082 std::string toString( std::string const& value );
01083 std::string toString( std::wstring const& value );
01084 std::string toString( const char* const value );
01085 std::string toString( char* const value );
01086 std::string toString( const wchar_t* const value );
01087 std::string toString( wchar_t* const value );
01088 std::string toString( int value );
01089 std::string toString( unsigned long value );
01090 std::string toString( unsigned int value );
01091 std::string toString( const double value );
01092 std::string toString( const float value );
01093 std::string toString( bool value );
01094 std::string toString( char value );
01095 std::string toString( signed char value );
01096 std::string toString( unsigned char value );
01097
01098 #ifdef CATCH_CONFIG_CPP11_NULLPTR
01099 std::string toString( std::nullptr_t );
01100 #endif
01101
01102 #ifdef __OBJC__
01103 std::string toString( NSString const * const& nsstring );
01104 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
01105 std::string toString( NSObject* const& nsObject );
01106 #endif
01107
01108 namespace Detail {
01109
01110 extern std::string unprintableString;
01111
01112 struct BorgType {
01113 template<typename T> BorgType( T const& );
01114 };
01115
01116 struct TrueType { char sizer[1]; };
01117 struct FalseType { char sizer[2]; };
01118
01119 TrueType& testStreamable( std::ostream& );
01120 FalseType testStreamable( FalseType );
01121
01122 FalseType operator<<( std::ostream const&, BorgType const& );
01123
01124 template<typename T>
01125 struct IsStreamInsertable {
01126 static std::ostream &s;
01127 static T const&t;
01128 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
01129 };
01130
01131 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
01132 template<typename T,
01133 bool IsEnum = std::is_enum<T>::value
01134 >
01135 struct EnumStringMaker
01136 {
01137 static std::string convert( T const& ) { return unprintableString; }
01138 };
01139
01140 template<typename T>
01141 struct EnumStringMaker<T,true>
01142 {
01143 static std::string convert( T const& v )
01144 {
01145 return ::Catch::toString(
01146 static_cast<typename std::underlying_type<T>::type>(v)
01147 );
01148 }
01149 };
01150 #endif
01151 template<bool C>
01152 struct StringMakerBase {
01153 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
01154 template<typename T>
01155 static std::string convert( T const& v )
01156 {
01157 return EnumStringMaker<T>::convert( v );
01158 }
01159 #else
01160 template<typename T>
01161 static std::string convert( T const& ) { return unprintableString; }
01162 #endif
01163 };
01164
01165 template<>
01166 struct StringMakerBase<true> {
01167 template<typename T>
01168 static std::string convert( T const& _value ) {
01169 std::ostringstream oss;
01170 oss << _value;
01171 return oss.str();
01172 }
01173 };
01174
01175 std::string rawMemoryToString( const void *object, std::size_t size );
01176
01177 template<typename T>
01178 inline std::string rawMemoryToString( const T& object ) {
01179 return rawMemoryToString( &object, sizeof(object) );
01180 }
01181
01182 }
01183
01184 template<typename T>
01185 struct StringMaker :
01186 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
01187
01188 template<typename T>
01189 struct StringMaker<T*> {
01190 template<typename U>
01191 static std::string convert( U* p ) {
01192 if( !p )
01193 return INTERNAL_CATCH_STRINGIFY( NULL );
01194 else
01195 return Detail::rawMemoryToString( p );
01196 }
01197 };
01198
01199 template<typename R, typename C>
01200 struct StringMaker<R C::*> {
01201 static std::string convert( R C::* p ) {
01202 if( !p )
01203 return INTERNAL_CATCH_STRINGIFY( NULL );
01204 else
01205 return Detail::rawMemoryToString( p );
01206 }
01207 };
01208
01209 namespace Detail {
01210 template<typename InputIterator>
01211 std::string rangeToString( InputIterator first, InputIterator last );
01212 }
01213
01214
01215
01216
01217
01218
01219
01220
01221 template<typename T, typename Allocator>
01222 std::string toString( std::vector<T,Allocator> const& v ) {
01223 return Detail::rangeToString( v.begin(), v.end() );
01224 }
01225
01226 #ifdef CATCH_CONFIG_CPP11_TUPLE
01227
01228
01229 namespace TupleDetail {
01230 template<
01231 typename Tuple,
01232 std::size_t N = 0,
01233 bool = (N < std::tuple_size<Tuple>::value)
01234 >
01235 struct ElementPrinter {
01236 static void print( const Tuple& tuple, std::ostream& os )
01237 {
01238 os << ( N ? ", " : " " )
01239 << Catch::toString(std::get<N>(tuple));
01240 ElementPrinter<Tuple,N+1>::print(tuple,os);
01241 }
01242 };
01243
01244 template<
01245 typename Tuple,
01246 std::size_t N
01247 >
01248 struct ElementPrinter<Tuple,N,false> {
01249 static void print( const Tuple&, std::ostream& ) {}
01250 };
01251
01252 }
01253
01254 template<typename ...Types>
01255 struct StringMaker<std::tuple<Types...>> {
01256
01257 static std::string convert( const std::tuple<Types...>& tuple )
01258 {
01259 std::ostringstream os;
01260 os << '{';
01261 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
01262 os << " }";
01263 return os.str();
01264 }
01265 };
01266 #endif // CATCH_CONFIG_CPP11_TUPLE
01267
01268 namespace Detail {
01269 template<typename T>
01270 std::string makeString( T const& value ) {
01271 return StringMaker<T>::convert( value );
01272 }
01273 }
01274
01282 template<typename T>
01283 std::string toString( T const& value ) {
01284 return StringMaker<T>::convert( value );
01285 }
01286
01287 namespace Detail {
01288 template<typename InputIterator>
01289 std::string rangeToString( InputIterator first, InputIterator last ) {
01290 std::ostringstream oss;
01291 oss << "{ ";
01292 if( first != last ) {
01293 oss << Catch::toString( *first );
01294 for( ++first ; first != last ; ++first )
01295 oss << ", " << Catch::toString( *first );
01296 }
01297 oss << " }";
01298 return oss.str();
01299 }
01300 }
01301
01302 }
01303
01304 namespace Catch {
01305
01306
01307
01308 template<typename T>
01309 class ExpressionLhs {
01310 ExpressionLhs& operator = ( ExpressionLhs const& );
01311 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
01312 ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
01313 # endif
01314
01315 public:
01316 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {}
01317 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
01318 ExpressionLhs( ExpressionLhs const& ) = default;
01319 ExpressionLhs( ExpressionLhs && ) = default;
01320 # endif
01321
01322 template<typename RhsT>
01323 ResultBuilder& operator == ( RhsT const& rhs ) {
01324 return captureExpression<Internal::IsEqualTo>( rhs );
01325 }
01326
01327 template<typename RhsT>
01328 ResultBuilder& operator != ( RhsT const& rhs ) {
01329 return captureExpression<Internal::IsNotEqualTo>( rhs );
01330 }
01331
01332 template<typename RhsT>
01333 ResultBuilder& operator < ( RhsT const& rhs ) {
01334 return captureExpression<Internal::IsLessThan>( rhs );
01335 }
01336
01337 template<typename RhsT>
01338 ResultBuilder& operator > ( RhsT const& rhs ) {
01339 return captureExpression<Internal::IsGreaterThan>( rhs );
01340 }
01341
01342 template<typename RhsT>
01343 ResultBuilder& operator <= ( RhsT const& rhs ) {
01344 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
01345 }
01346
01347 template<typename RhsT>
01348 ResultBuilder& operator >= ( RhsT const& rhs ) {
01349 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
01350 }
01351
01352 ResultBuilder& operator == ( bool rhs ) {
01353 return captureExpression<Internal::IsEqualTo>( rhs );
01354 }
01355
01356 ResultBuilder& operator != ( bool rhs ) {
01357 return captureExpression<Internal::IsNotEqualTo>( rhs );
01358 }
01359
01360 void endExpression() {
01361 bool value = m_lhs ? true : false;
01362 m_rb
01363 .setLhs( Catch::toString( value ) )
01364 .setResultType( value )
01365 .endExpression();
01366 }
01367
01368
01369
01370 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
01371 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
01372 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
01373 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
01374 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
01375 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
01376
01377 private:
01378 template<Internal::Operator Op, typename RhsT>
01379 ResultBuilder& captureExpression( RhsT const& rhs ) {
01380 return m_rb
01381 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
01382 .setLhs( Catch::toString( m_lhs ) )
01383 .setRhs( Catch::toString( rhs ) )
01384 .setOp( Internal::OperatorTraits<Op>::getName() );
01385 }
01386
01387 private:
01388 ResultBuilder& m_rb;
01389 T m_lhs;
01390 };
01391
01392 }
01393
01394
01395 namespace Catch {
01396
01397 template<typename T>
01398 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
01399 return ExpressionLhs<T const&>( *this, operand );
01400 }
01401
01402 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
01403 return ExpressionLhs<bool>( *this, value );
01404 }
01405
01406 }
01407
01408
01409 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
01410
01411 #include <string>
01412
01413 namespace Catch {
01414
01415 struct MessageInfo {
01416 MessageInfo( std::string const& _macroName,
01417 SourceLineInfo const& _lineInfo,
01418 ResultWas::OfType _type );
01419
01420 std::string macroName;
01421 SourceLineInfo lineInfo;
01422 ResultWas::OfType type;
01423 std::string message;
01424 unsigned int sequence;
01425
01426 bool operator == ( MessageInfo const& other ) const {
01427 return sequence == other.sequence;
01428 }
01429 bool operator < ( MessageInfo const& other ) const {
01430 return sequence < other.sequence;
01431 }
01432 private:
01433 static unsigned int globalCount;
01434 };
01435
01436 struct MessageBuilder {
01437 MessageBuilder( std::string const& macroName,
01438 SourceLineInfo const& lineInfo,
01439 ResultWas::OfType type )
01440 : m_info( macroName, lineInfo, type )
01441 {}
01442
01443 template<typename T>
01444 MessageBuilder& operator << ( T const& value ) {
01445 m_stream << value;
01446 return *this;
01447 }
01448
01449 MessageInfo m_info;
01450 std::ostringstream m_stream;
01451 };
01452
01453 class ScopedMessage {
01454 public:
01455 ScopedMessage( MessageBuilder const& builder );
01456 ScopedMessage( ScopedMessage const& other );
01457 ~ScopedMessage();
01458
01459 MessageInfo m_info;
01460 };
01461
01462 }
01463
01464
01465 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
01466
01467 #include <string>
01468
01469 namespace Catch {
01470
01471 class TestCase;
01472 class AssertionResult;
01473 struct AssertionInfo;
01474 struct SectionInfo;
01475 struct MessageInfo;
01476 class ScopedMessageBuilder;
01477 struct Counts;
01478
01479 struct IResultCapture {
01480
01481 virtual ~IResultCapture();
01482
01483 virtual void assertionEnded( AssertionResult const& result ) = 0;
01484 virtual bool sectionStarted( SectionInfo const& sectionInfo,
01485 Counts& assertions ) = 0;
01486 virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0;
01487 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
01488 virtual void popScopedMessage( MessageInfo const& message ) = 0;
01489
01490 virtual std::string getCurrentTestName() const = 0;
01491 virtual const AssertionResult* getLastResult() const = 0;
01492
01493 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
01494 };
01495
01496 IResultCapture& getResultCapture();
01497 }
01498
01499
01500 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
01501
01502
01503 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
01504
01505 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
01506 #define CATCH_PLATFORM_MAC
01507 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
01508 #define CATCH_PLATFORM_IPHONE
01509 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
01510 #define CATCH_PLATFORM_WINDOWS
01511 #endif
01512
01513 #include <string>
01514
01515 namespace Catch{
01516
01517 bool isDebuggerActive();
01518 void writeToDebugConsole( std::string const& text );
01519 }
01520
01521 #ifdef CATCH_PLATFORM_MAC
01522
01523
01524
01525 #ifdef DEBUG
01526 #if defined(__ppc64__) || defined(__ppc__)
01527 #define CATCH_BREAK_INTO_DEBUGGER() \
01528 if( Catch::isDebuggerActive() ) { \
01529 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
01530 : : : "memory","r0","r3","r4" ); \
01531 }
01532 #else
01533 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
01534 #endif
01535 #endif
01536
01537 #elif defined(_MSC_VER)
01538 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
01539 #elif defined(__MINGW32__)
01540 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
01541 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
01542 #endif
01543
01544 #ifndef CATCH_BREAK_INTO_DEBUGGER
01545 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
01546 #endif
01547
01548
01549 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
01550
01551 namespace Catch {
01552 class TestCase;
01553
01554 struct IRunner {
01555 virtual ~IRunner();
01556 virtual bool aborting() const = 0;
01557 };
01558 }
01559
01561
01562
01563
01564
01565 #define INTERNAL_CATCH_REACT( resultBuilder ) \
01566 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
01567 resultBuilder.react();
01568
01570 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
01571 do { \
01572 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
01573 try { \
01574 ( __catchResult <= expr ).endExpression(); \
01575 } \
01576 catch( ... ) { \
01577 __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
01578 } \
01579 INTERNAL_CATCH_REACT( __catchResult ) \
01580 } while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
01581
01583 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
01584 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
01585 if( Catch::getResultCapture().getLastResult()->succeeded() )
01586
01588 #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
01589 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
01590 if( !Catch::getResultCapture().getLastResult()->succeeded() )
01591
01593 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
01594 do { \
01595 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
01596 try { \
01597 expr; \
01598 __catchResult.captureResult( Catch::ResultWas::Ok ); \
01599 } \
01600 catch( ... ) { \
01601 __catchResult.useActiveException( resultDisposition ); \
01602 } \
01603 INTERNAL_CATCH_REACT( __catchResult ) \
01604 } while( Catch::alwaysFalse() )
01605
01607 #define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \
01608 do { \
01609 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
01610 if( __catchResult.allowThrows() ) \
01611 try { \
01612 expr; \
01613 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
01614 } \
01615 catch( ... ) { \
01616 __catchResult.captureResult( Catch::ResultWas::Ok ); \
01617 } \
01618 else \
01619 __catchResult.captureResult( Catch::ResultWas::Ok ); \
01620 INTERNAL_CATCH_REACT( __catchResult ) \
01621 } while( Catch::alwaysFalse() )
01622
01624 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
01625 do { \
01626 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
01627 if( __catchResult.allowThrows() ) \
01628 try { \
01629 expr; \
01630 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
01631 } \
01632 catch( exceptionType ) { \
01633 __catchResult.captureResult( Catch::ResultWas::Ok ); \
01634 } \
01635 catch( ... ) { \
01636 __catchResult.useActiveException( resultDisposition ); \
01637 } \
01638 else \
01639 __catchResult.captureResult( Catch::ResultWas::Ok ); \
01640 INTERNAL_CATCH_REACT( __catchResult ) \
01641 } while( Catch::alwaysFalse() )
01642
01644 #ifdef CATCH_CONFIG_VARIADIC_MACROS
01645 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
01646 do { \
01647 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
01648 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
01649 __catchResult.captureResult( messageType ); \
01650 INTERNAL_CATCH_REACT( __catchResult ) \
01651 } while( Catch::alwaysFalse() )
01652 #else
01653 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
01654 do { \
01655 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
01656 __catchResult << log + ::Catch::StreamEndStop(); \
01657 __catchResult.captureResult( messageType ); \
01658 INTERNAL_CATCH_REACT( __catchResult ) \
01659 } while( Catch::alwaysFalse() )
01660 #endif
01661
01663 #define INTERNAL_CATCH_INFO( log, macroName ) \
01664 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
01665
01667 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
01668 do { \
01669 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
01670 try { \
01671 std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
01672 __catchResult \
01673 .setLhs( Catch::toString( arg ) ) \
01674 .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
01675 .setOp( "matches" ) \
01676 .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
01677 __catchResult.captureExpression(); \
01678 } catch( ... ) { \
01679 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
01680 } \
01681 INTERNAL_CATCH_REACT( __catchResult ) \
01682 } while( Catch::alwaysFalse() )
01683
01684
01685 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
01686
01687
01688 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
01689
01690 namespace Catch {
01691
01692 struct SectionInfo {
01693 SectionInfo
01694 ( SourceLineInfo const& _lineInfo,
01695 std::string const& _name,
01696 std::string const& _description = std::string() );
01697
01698 std::string name;
01699 std::string description;
01700 SourceLineInfo lineInfo;
01701 };
01702
01703 }
01704
01705
01706 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
01707
01708 #include <cstddef>
01709
01710 namespace Catch {
01711
01712 struct Counts {
01713 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
01714
01715 Counts operator - ( Counts const& other ) const {
01716 Counts diff;
01717 diff.passed = passed - other.passed;
01718 diff.failed = failed - other.failed;
01719 diff.failedButOk = failedButOk - other.failedButOk;
01720 return diff;
01721 }
01722 Counts& operator += ( Counts const& other ) {
01723 passed += other.passed;
01724 failed += other.failed;
01725 failedButOk += other.failedButOk;
01726 return *this;
01727 }
01728
01729 std::size_t total() const {
01730 return passed + failed + failedButOk;
01731 }
01732 bool allPassed() const {
01733 return failed == 0 && failedButOk == 0;
01734 }
01735 bool allOk() const {
01736 return failed == 0;
01737 }
01738
01739 std::size_t passed;
01740 std::size_t failed;
01741 std::size_t failedButOk;
01742 };
01743
01744 struct Totals {
01745
01746 Totals operator - ( Totals const& other ) const {
01747 Totals diff;
01748 diff.assertions = assertions - other.assertions;
01749 diff.testCases = testCases - other.testCases;
01750 return diff;
01751 }
01752
01753 Totals delta( Totals const& prevTotals ) const {
01754 Totals diff = *this - prevTotals;
01755 if( diff.assertions.failed > 0 )
01756 ++diff.testCases.failed;
01757 else if( diff.assertions.failedButOk > 0 )
01758 ++diff.testCases.failedButOk;
01759 else
01760 ++diff.testCases.passed;
01761 return diff;
01762 }
01763
01764 Totals& operator += ( Totals const& other ) {
01765 assertions += other.assertions;
01766 testCases += other.testCases;
01767 return *this;
01768 }
01769
01770 Counts assertions;
01771 Counts testCases;
01772 };
01773 }
01774
01775
01776 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
01777
01778 #ifdef CATCH_PLATFORM_WINDOWS
01779 typedef unsigned long long uint64_t;
01780 #else
01781 #include <stdint.h>
01782 #endif
01783
01784 namespace Catch {
01785
01786 class Timer {
01787 public:
01788 Timer() : m_ticks( 0 ) {}
01789 void start();
01790 unsigned int getElapsedMicroseconds() const;
01791 unsigned int getElapsedMilliseconds() const;
01792 double getElapsedSeconds() const;
01793
01794 private:
01795 uint64_t m_ticks;
01796 };
01797
01798 }
01799
01800 #include <string>
01801
01802 namespace Catch {
01803
01804 class Section : NonCopyable {
01805 public:
01806 Section( SectionInfo const& info );
01807 ~Section();
01808
01809
01810 operator bool() const;
01811
01812 private:
01813 SectionInfo m_info;
01814
01815 std::string m_name;
01816 Counts m_assertions;
01817 bool m_sectionIncluded;
01818 Timer m_timer;
01819 };
01820
01821 }
01822
01823 #ifdef CATCH_CONFIG_VARIADIC_MACROS
01824 #define INTERNAL_CATCH_SECTION( ... ) \
01825 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
01826 #else
01827 #define INTERNAL_CATCH_SECTION( name, desc ) \
01828 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
01829 #endif
01830
01831
01832 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
01833
01834 #include <iterator>
01835 #include <vector>
01836 #include <string>
01837 #include <stdlib.h>
01838
01839 namespace Catch {
01840
01841 template<typename T>
01842 struct IGenerator {
01843 virtual ~IGenerator() {}
01844 virtual T getValue( std::size_t index ) const = 0;
01845 virtual std::size_t size () const = 0;
01846 };
01847
01848 template<typename T>
01849 class BetweenGenerator : public IGenerator<T> {
01850 public:
01851 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
01852
01853 virtual T getValue( std::size_t index ) const {
01854 return m_from+static_cast<int>( index );
01855 }
01856
01857 virtual std::size_t size() const {
01858 return static_cast<std::size_t>( 1+m_to-m_from );
01859 }
01860
01861 private:
01862
01863 T m_from;
01864 T m_to;
01865 };
01866
01867 template<typename T>
01868 class ValuesGenerator : public IGenerator<T> {
01869 public:
01870 ValuesGenerator(){}
01871
01872 void add( T value ) {
01873 m_values.push_back( value );
01874 }
01875
01876 virtual T getValue( std::size_t index ) const {
01877 return m_values[index];
01878 }
01879
01880 virtual std::size_t size() const {
01881 return m_values.size();
01882 }
01883
01884 private:
01885 std::vector<T> m_values;
01886 };
01887
01888 template<typename T>
01889 class CompositeGenerator {
01890 public:
01891 CompositeGenerator() : m_totalSize( 0 ) {}
01892
01893
01894 CompositeGenerator( CompositeGenerator& other )
01895 : m_fileInfo( other.m_fileInfo ),
01896 m_totalSize( 0 )
01897 {
01898 move( other );
01899 }
01900
01901 CompositeGenerator& setFileInfo( const char* fileInfo ) {
01902 m_fileInfo = fileInfo;
01903 return *this;
01904 }
01905
01906 ~CompositeGenerator() {
01907 deleteAll( m_composed );
01908 }
01909
01910 operator T () const {
01911 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
01912
01913 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
01914 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
01915 for( size_t index = 0; it != itEnd; ++it )
01916 {
01917 const IGenerator<T>* generator = *it;
01918 if( overallIndex >= index && overallIndex < index + generator->size() )
01919 {
01920 return generator->getValue( overallIndex-index );
01921 }
01922 index += generator->size();
01923 }
01924 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
01925 return T();
01926 }
01927
01928 void add( const IGenerator<T>* generator ) {
01929 m_totalSize += generator->size();
01930 m_composed.push_back( generator );
01931 }
01932
01933 CompositeGenerator& then( CompositeGenerator& other ) {
01934 move( other );
01935 return *this;
01936 }
01937
01938 CompositeGenerator& then( T value ) {
01939 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
01940 valuesGen->add( value );
01941 add( valuesGen );
01942 return *this;
01943 }
01944
01945 private:
01946
01947 void move( CompositeGenerator& other ) {
01948 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
01949 m_totalSize += other.m_totalSize;
01950 other.m_composed.clear();
01951 }
01952
01953 std::vector<const IGenerator<T>*> m_composed;
01954 std::string m_fileInfo;
01955 size_t m_totalSize;
01956 };
01957
01958 namespace Generators
01959 {
01960 template<typename T>
01961 CompositeGenerator<T> between( T from, T to ) {
01962 CompositeGenerator<T> generators;
01963 generators.add( new BetweenGenerator<T>( from, to ) );
01964 return generators;
01965 }
01966
01967 template<typename T>
01968 CompositeGenerator<T> values( T val1, T val2 ) {
01969 CompositeGenerator<T> generators;
01970 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
01971 valuesGen->add( val1 );
01972 valuesGen->add( val2 );
01973 generators.add( valuesGen );
01974 return generators;
01975 }
01976
01977 template<typename T>
01978 CompositeGenerator<T> values( T val1, T val2, T val3 ){
01979 CompositeGenerator<T> generators;
01980 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
01981 valuesGen->add( val1 );
01982 valuesGen->add( val2 );
01983 valuesGen->add( val3 );
01984 generators.add( valuesGen );
01985 return generators;
01986 }
01987
01988 template<typename T>
01989 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
01990 CompositeGenerator<T> generators;
01991 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
01992 valuesGen->add( val1 );
01993 valuesGen->add( val2 );
01994 valuesGen->add( val3 );
01995 valuesGen->add( val4 );
01996 generators.add( valuesGen );
01997 return generators;
01998 }
01999
02000 }
02001
02002 using namespace Generators;
02003
02004 }
02005
02006 #define INTERNAL_CATCH_LINESTR2( line ) #line
02007 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
02008
02009 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
02010
02011
02012 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
02013
02014 #include <string>
02015
02016 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
02017
02018 #include <string>
02019
02020 namespace Catch {
02021
02022 class TestCase;
02023 struct ITestCaseRegistry;
02024 struct IExceptionTranslatorRegistry;
02025 struct IExceptionTranslator;
02026 struct IReporterRegistry;
02027 struct IReporterFactory;
02028
02029 struct IRegistryHub {
02030 virtual ~IRegistryHub();
02031
02032 virtual IReporterRegistry const& getReporterRegistry() const = 0;
02033 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
02034 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
02035 };
02036
02037 struct IMutableRegistryHub {
02038 virtual ~IMutableRegistryHub();
02039 virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
02040 virtual void registerTest( TestCase const& testInfo ) = 0;
02041 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
02042 };
02043
02044 IRegistryHub& getRegistryHub();
02045 IMutableRegistryHub& getMutableRegistryHub();
02046 void cleanUp();
02047 std::string translateActiveException();
02048
02049 }
02050
02051
02052 namespace Catch {
02053
02054 typedef std::string(*exceptionTranslateFunction)();
02055
02056 struct IExceptionTranslator {
02057 virtual ~IExceptionTranslator();
02058 virtual std::string translate() const = 0;
02059 };
02060
02061 struct IExceptionTranslatorRegistry {
02062 virtual ~IExceptionTranslatorRegistry();
02063
02064 virtual std::string translateActiveException() const = 0;
02065 };
02066
02067 class ExceptionTranslatorRegistrar {
02068 template<typename T>
02069 class ExceptionTranslator : public IExceptionTranslator {
02070 public:
02071
02072 ExceptionTranslator( std::string(*translateFunction)( T& ) )
02073 : m_translateFunction( translateFunction )
02074 {}
02075
02076 virtual std::string translate() const {
02077 try {
02078 throw;
02079 }
02080 catch( T& ex ) {
02081 return m_translateFunction( ex );
02082 }
02083 }
02084
02085 protected:
02086 std::string(*m_translateFunction)( T& );
02087 };
02088
02089 public:
02090 template<typename T>
02091 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
02092 getMutableRegistryHub().registerTranslator
02093 ( new ExceptionTranslator<T>( translateFunction ) );
02094 }
02095 };
02096 }
02097
02099 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
02100 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
02101 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
02102 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
02103
02104
02105 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
02106
02107 #include <cmath>
02108 #include <limits>
02109
02110 namespace Catch {
02111 namespace Detail {
02112
02113 class Approx {
02114 public:
02115 explicit Approx ( double value )
02116 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
02117 m_scale( 1.0 ),
02118 m_value( value )
02119 {}
02120
02121 Approx( Approx const& other )
02122 : m_epsilon( other.m_epsilon ),
02123 m_scale( other.m_scale ),
02124 m_value( other.m_value )
02125 {}
02126
02127 static Approx custom() {
02128 return Approx( 0 );
02129 }
02130
02131 Approx operator()( double value ) {
02132 Approx approx( value );
02133 approx.epsilon( m_epsilon );
02134 approx.scale( m_scale );
02135 return approx;
02136 }
02137
02138 friend bool operator == ( double lhs, Approx const& rhs ) {
02139
02140 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
02141 }
02142
02143 friend bool operator == ( Approx const& lhs, double rhs ) {
02144 return operator==( rhs, lhs );
02145 }
02146
02147 friend bool operator != ( double lhs, Approx const& rhs ) {
02148 return !operator==( lhs, rhs );
02149 }
02150
02151 friend bool operator != ( Approx const& lhs, double rhs ) {
02152 return !operator==( rhs, lhs );
02153 }
02154
02155 Approx& epsilon( double newEpsilon ) {
02156 m_epsilon = newEpsilon;
02157 return *this;
02158 }
02159
02160 Approx& scale( double newScale ) {
02161 m_scale = newScale;
02162 return *this;
02163 }
02164
02165 std::string toString() const {
02166 std::ostringstream oss;
02167 oss << "Approx( " << Catch::toString( m_value ) << " )";
02168 return oss.str();
02169 }
02170
02171 private:
02172 double m_epsilon;
02173 double m_scale;
02174 double m_value;
02175 };
02176 }
02177
02178 template<>
02179 inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
02180 return value.toString();
02181 }
02182
02183 }
02184
02185
02186 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
02187
02188 namespace Catch {
02189 namespace Matchers {
02190 namespace Impl {
02191
02192 template<typename ExpressionT>
02193 struct Matcher : SharedImpl<IShared>
02194 {
02195 typedef ExpressionT ExpressionType;
02196
02197 virtual ~Matcher() {}
02198 virtual Ptr<Matcher> clone() const = 0;
02199 virtual bool match( ExpressionT const& expr ) const = 0;
02200 virtual std::string toString() const = 0;
02201 };
02202
02203 template<typename DerivedT, typename ExpressionT>
02204 struct MatcherImpl : Matcher<ExpressionT> {
02205
02206 virtual Ptr<Matcher<ExpressionT> > clone() const {
02207 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
02208 }
02209 };
02210
02211 namespace Generic {
02212
02213 template<typename ExpressionT>
02214 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
02215 public:
02216
02217 AllOf() {}
02218 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
02219
02220 AllOf& add( Matcher<ExpressionT> const& matcher ) {
02221 m_matchers.push_back( matcher.clone() );
02222 return *this;
02223 }
02224 virtual bool match( ExpressionT const& expr ) const
02225 {
02226 for( std::size_t i = 0; i < m_matchers.size(); ++i )
02227 if( !m_matchers[i]->match( expr ) )
02228 return false;
02229 return true;
02230 }
02231 virtual std::string toString() const {
02232 std::ostringstream oss;
02233 oss << "( ";
02234 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
02235 if( i != 0 )
02236 oss << " and ";
02237 oss << m_matchers[i]->toString();
02238 }
02239 oss << " )";
02240 return oss.str();
02241 }
02242
02243 private:
02244 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
02245 };
02246
02247 template<typename ExpressionT>
02248 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
02249 public:
02250
02251 AnyOf() {}
02252 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
02253
02254 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
02255 m_matchers.push_back( matcher.clone() );
02256 return *this;
02257 }
02258 virtual bool match( ExpressionT const& expr ) const
02259 {
02260 for( std::size_t i = 0; i < m_matchers.size(); ++i )
02261 if( m_matchers[i]->match( expr ) )
02262 return true;
02263 return false;
02264 }
02265 virtual std::string toString() const {
02266 std::ostringstream oss;
02267 oss << "( ";
02268 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
02269 if( i != 0 )
02270 oss << " or ";
02271 oss << m_matchers[i]->toString();
02272 }
02273 oss << " )";
02274 return oss.str();
02275 }
02276
02277 private:
02278 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
02279 };
02280
02281 }
02282
02283 namespace StdString {
02284
02285 inline std::string makeString( std::string const& str ) { return str; }
02286 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
02287
02288 struct Equals : MatcherImpl<Equals, std::string> {
02289 Equals( std::string const& str ) : m_str( str ){}
02290 Equals( Equals const& other ) : m_str( other.m_str ){}
02291
02292 virtual ~Equals();
02293
02294 virtual bool match( std::string const& expr ) const {
02295 return m_str == expr;
02296 }
02297 virtual std::string toString() const {
02298 return "equals: \"" + m_str + "\"";
02299 }
02300
02301 std::string m_str;
02302 };
02303
02304 struct Contains : MatcherImpl<Contains, std::string> {
02305 Contains( std::string const& substr ) : m_substr( substr ){}
02306 Contains( Contains const& other ) : m_substr( other.m_substr ){}
02307
02308 virtual ~Contains();
02309
02310 virtual bool match( std::string const& expr ) const {
02311 return expr.find( m_substr ) != std::string::npos;
02312 }
02313 virtual std::string toString() const {
02314 return "contains: \"" + m_substr + "\"";
02315 }
02316
02317 std::string m_substr;
02318 };
02319
02320 struct StartsWith : MatcherImpl<StartsWith, std::string> {
02321 StartsWith( std::string const& substr ) : m_substr( substr ){}
02322 StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){}
02323
02324 virtual ~StartsWith();
02325
02326 virtual bool match( std::string const& expr ) const {
02327 return expr.find( m_substr ) == 0;
02328 }
02329 virtual std::string toString() const {
02330 return "starts with: \"" + m_substr + "\"";
02331 }
02332
02333 std::string m_substr;
02334 };
02335
02336 struct EndsWith : MatcherImpl<EndsWith, std::string> {
02337 EndsWith( std::string const& substr ) : m_substr( substr ){}
02338 EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){}
02339
02340 virtual ~EndsWith();
02341
02342 virtual bool match( std::string const& expr ) const {
02343 return expr.find( m_substr ) == expr.size() - m_substr.size();
02344 }
02345 virtual std::string toString() const {
02346 return "ends with: \"" + m_substr + "\"";
02347 }
02348
02349 std::string m_substr;
02350 };
02351 }
02352 }
02353
02354
02355
02356 template<typename ExpressionT>
02357 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
02358 Impl::Matcher<ExpressionT> const& m2 ) {
02359 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
02360 }
02361 template<typename ExpressionT>
02362 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
02363 Impl::Matcher<ExpressionT> const& m2,
02364 Impl::Matcher<ExpressionT> const& m3 ) {
02365 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
02366 }
02367 template<typename ExpressionT>
02368 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
02369 Impl::Matcher<ExpressionT> const& m2 ) {
02370 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
02371 }
02372 template<typename ExpressionT>
02373 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
02374 Impl::Matcher<ExpressionT> const& m2,
02375 Impl::Matcher<ExpressionT> const& m3 ) {
02376 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
02377 }
02378
02379 inline Impl::StdString::Equals Equals( std::string const& str ) {
02380 return Impl::StdString::Equals( str );
02381 }
02382 inline Impl::StdString::Equals Equals( const char* str ) {
02383 return Impl::StdString::Equals( Impl::StdString::makeString( str ) );
02384 }
02385 inline Impl::StdString::Contains Contains( std::string const& substr ) {
02386 return Impl::StdString::Contains( substr );
02387 }
02388 inline Impl::StdString::Contains Contains( const char* substr ) {
02389 return Impl::StdString::Contains( Impl::StdString::makeString( substr ) );
02390 }
02391 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
02392 return Impl::StdString::StartsWith( substr );
02393 }
02394 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
02395 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
02396 }
02397 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
02398 return Impl::StdString::EndsWith( substr );
02399 }
02400 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
02401 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
02402 }
02403
02404 }
02405
02406 using namespace Matchers;
02407
02408 }
02409
02410
02411 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
02412
02413
02414 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
02415
02416 #include <string>
02417
02418 namespace Catch {
02419
02420 struct TagAlias {
02421 TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
02422
02423 std::string tag;
02424 SourceLineInfo lineInfo;
02425 };
02426
02427 struct RegistrarForTagAliases {
02428 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
02429 };
02430
02431 }
02432
02433 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
02434
02435 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
02436
02437 namespace Catch {
02438
02439
02440 template<typename T>
02441 class Option {
02442 public:
02443 Option() : nullableValue( NULL ) {}
02444 Option( T const& _value )
02445 : nullableValue( new( storage ) T( _value ) )
02446 {}
02447 Option( Option const& _other )
02448 : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
02449 {}
02450
02451 ~Option() {
02452 reset();
02453 }
02454
02455 Option& operator= ( Option const& _other ) {
02456 if( &_other != this ) {
02457 reset();
02458 if( _other )
02459 nullableValue = new( storage ) T( *_other );
02460 }
02461 return *this;
02462 }
02463 Option& operator = ( T const& _value ) {
02464 reset();
02465 nullableValue = new( storage ) T( _value );
02466 return *this;
02467 }
02468
02469 void reset() {
02470 if( nullableValue )
02471 nullableValue->~T();
02472 nullableValue = NULL;
02473 }
02474
02475 T& operator*() { return *nullableValue; }
02476 T const& operator*() const { return *nullableValue; }
02477 T* operator->() { return nullableValue; }
02478 const T* operator->() const { return nullableValue; }
02479
02480 T valueOr( T const& defaultValue ) const {
02481 return nullableValue ? *nullableValue : defaultValue;
02482 }
02483
02484 bool some() const { return nullableValue != NULL; }
02485 bool none() const { return nullableValue == NULL; }
02486
02487 bool operator !() const { return nullableValue == NULL; }
02488 operator SafeBool::type() const {
02489 return SafeBool::makeSafe( some() );
02490 }
02491
02492 private:
02493 T* nullableValue;
02494 char storage[sizeof(T)];
02495 };
02496
02497 }
02498
02499 namespace Catch {
02500
02501 struct ITagAliasRegistry {
02502 virtual ~ITagAliasRegistry();
02503 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
02504 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
02505
02506 static ITagAliasRegistry const& get();
02507 };
02508
02509 }
02510
02511
02512
02513
02514 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
02515
02516 #include <string>
02517 #include <set>
02518
02519 #ifdef __clang__
02520 #pragma clang diagnostic push
02521 #pragma clang diagnostic ignored "-Wpadded"
02522 #endif
02523
02524 namespace Catch {
02525
02526 struct ITestCase;
02527
02528 struct TestCaseInfo {
02529 enum SpecialProperties{
02530 None = 0,
02531 IsHidden = 1 << 1,
02532 ShouldFail = 1 << 2,
02533 MayFail = 1 << 3,
02534 Throws = 1 << 4
02535 };
02536
02537 TestCaseInfo( std::string const& _name,
02538 std::string const& _className,
02539 std::string const& _description,
02540 std::set<std::string> const& _tags,
02541 SourceLineInfo const& _lineInfo );
02542
02543 TestCaseInfo( TestCaseInfo const& other );
02544
02545 bool isHidden() const;
02546 bool throws() const;
02547 bool okToFail() const;
02548 bool expectedToFail() const;
02549
02550 std::string name;
02551 std::string className;
02552 std::string description;
02553 std::set<std::string> tags;
02554 std::set<std::string> lcaseTags;
02555 std::string tagsAsString;
02556 SourceLineInfo lineInfo;
02557 SpecialProperties properties;
02558 };
02559
02560 class TestCase : public TestCaseInfo {
02561 public:
02562
02563 TestCase( ITestCase* testCase, TestCaseInfo const& info );
02564 TestCase( TestCase const& other );
02565
02566 TestCase withName( std::string const& _newName ) const;
02567
02568 void invoke() const;
02569
02570 TestCaseInfo const& getTestCaseInfo() const;
02571
02572 void swap( TestCase& other );
02573 bool operator == ( TestCase const& other ) const;
02574 bool operator < ( TestCase const& other ) const;
02575 TestCase& operator = ( TestCase const& other );
02576
02577 private:
02578 Ptr<ITestCase> test;
02579 };
02580
02581 TestCase makeTestCase( ITestCase* testCase,
02582 std::string const& className,
02583 std::string const& name,
02584 std::string const& description,
02585 SourceLineInfo const& lineInfo );
02586 }
02587
02588 #ifdef __clang__
02589 #pragma clang diagnostic pop
02590 #endif
02591
02592
02593 #ifdef __OBJC__
02594
02595 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
02596
02597 #import <objc/runtime.h>
02598
02599 #include <string>
02600
02601
02602
02603
02604
02606
02607
02608 @protocol OcFixture
02609
02610 @optional
02611
02612 -(void) setUp;
02613 -(void) tearDown;
02614
02615 @end
02616
02617 namespace Catch {
02618
02619 class OcMethod : public SharedImpl<ITestCase> {
02620
02621 public:
02622 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
02623
02624 virtual void invoke() const {
02625 id obj = [[m_cls alloc] init];
02626
02627 performOptionalSelector( obj, @selector(setUp) );
02628 performOptionalSelector( obj, m_sel );
02629 performOptionalSelector( obj, @selector(tearDown) );
02630
02631 arcSafeRelease( obj );
02632 }
02633 private:
02634 virtual ~OcMethod() {}
02635
02636 Class m_cls;
02637 SEL m_sel;
02638 };
02639
02640 namespace Detail{
02641
02642 inline std::string getAnnotation( Class cls,
02643 std::string const& annotationName,
02644 std::string const& testCaseName ) {
02645 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
02646 SEL sel = NSSelectorFromString( selStr );
02647 arcSafeRelease( selStr );
02648 id value = performOptionalSelector( cls, sel );
02649 if( value )
02650 return [(NSString*)value UTF8String];
02651 return "";
02652 }
02653 }
02654
02655 inline size_t registerTestMethods() {
02656 size_t noTestMethods = 0;
02657 int noClasses = objc_getClassList( NULL, 0 );
02658
02659 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
02660 objc_getClassList( classes, noClasses );
02661
02662 for( int c = 0; c < noClasses; c++ ) {
02663 Class cls = classes[c];
02664 {
02665 u_int count;
02666 Method* methods = class_copyMethodList( cls, &count );
02667 for( u_int m = 0; m < count ; m++ ) {
02668 SEL selector = method_getName(methods[m]);
02669 std::string methodName = sel_getName(selector);
02670 if( startsWith( methodName, "Catch_TestCase_" ) ) {
02671 std::string testCaseName = methodName.substr( 15 );
02672 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
02673 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
02674 const char* className = class_getName( cls );
02675
02676 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
02677 noTestMethods++;
02678 }
02679 }
02680 free(methods);
02681 }
02682 }
02683 return noTestMethods;
02684 }
02685
02686 namespace Matchers {
02687 namespace Impl {
02688 namespace NSStringMatchers {
02689
02690 template<typename MatcherT>
02691 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
02692 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
02693 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
02694 StringHolder() {
02695 arcSafeRelease( m_substr );
02696 }
02697
02698 NSString* m_substr;
02699 };
02700
02701 struct Equals : StringHolder<Equals> {
02702 Equals( NSString* substr ) : StringHolder( substr ){}
02703
02704 virtual bool match( ExpressionType const& str ) const {
02705 return (str != nil || m_substr == nil ) &&
02706 [str isEqualToString:m_substr];
02707 }
02708
02709 virtual std::string toString() const {
02710 return "equals string: " + Catch::toString( m_substr );
02711 }
02712 };
02713
02714 struct Contains : StringHolder<Contains> {
02715 Contains( NSString* substr ) : StringHolder( substr ){}
02716
02717 virtual bool match( ExpressionType const& str ) const {
02718 return (str != nil || m_substr == nil ) &&
02719 [str rangeOfString:m_substr].location != NSNotFound;
02720 }
02721
02722 virtual std::string toString() const {
02723 return "contains string: " + Catch::toString( m_substr );
02724 }
02725 };
02726
02727 struct StartsWith : StringHolder<StartsWith> {
02728 StartsWith( NSString* substr ) : StringHolder( substr ){}
02729
02730 virtual bool match( ExpressionType const& str ) const {
02731 return (str != nil || m_substr == nil ) &&
02732 [str rangeOfString:m_substr].location == 0;
02733 }
02734
02735 virtual std::string toString() const {
02736 return "starts with: " + Catch::toString( m_substr );
02737 }
02738 };
02739 struct EndsWith : StringHolder<EndsWith> {
02740 EndsWith( NSString* substr ) : StringHolder( substr ){}
02741
02742 virtual bool match( ExpressionType const& str ) const {
02743 return (str != nil || m_substr == nil ) &&
02744 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
02745 }
02746
02747 virtual std::string toString() const {
02748 return "ends with: " + Catch::toString( m_substr );
02749 }
02750 };
02751
02752 }
02753 }
02754
02755 inline Impl::NSStringMatchers::Equals
02756 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
02757
02758 inline Impl::NSStringMatchers::Contains
02759 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
02760
02761 inline Impl::NSStringMatchers::StartsWith
02762 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
02763
02764 inline Impl::NSStringMatchers::EndsWith
02765 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
02766
02767 }
02768
02769 using namespace Matchers;
02770
02771 }
02772
02774 #define OC_TEST_CASE( name, desc )\
02775 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
02776 {\
02777 return @ name; \
02778 }\
02779 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
02780 { \
02781 return @ desc; \
02782 } \
02783 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
02784
02785 #endif
02786
02787 #ifdef CATCH_IMPL
02788
02789 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
02790
02791
02792
02793
02794 #ifdef __clang__
02795 #pragma clang diagnostic push
02796 #pragma clang diagnostic ignored "-Wweak-vtables"
02797 #endif
02798
02799
02800 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
02801
02802
02803 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
02804
02805
02806 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
02807
02808
02809 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
02810
02811 #ifdef __clang__
02812 #pragma clang diagnostic push
02813 #pragma clang diagnostic ignored "-Wpadded"
02814 #endif
02815
02816
02817 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
02818
02819 #ifdef __clang__
02820 #pragma clang diagnostic push
02821 #pragma clang diagnostic ignored "-Wpadded"
02822 #endif
02823
02824 #include <string>
02825 #include <vector>
02826
02827 namespace Catch {
02828
02829 class TestSpec {
02830 struct Pattern : SharedImpl<> {
02831 virtual ~Pattern();
02832 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
02833 };
02834 class NamePattern : public Pattern {
02835 enum WildcardPosition {
02836 NoWildcard = 0,
02837 WildcardAtStart = 1,
02838 WildcardAtEnd = 2,
02839 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
02840 };
02841
02842 public:
02843 NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) {
02844 if( startsWith( m_name, "*" ) ) {
02845 m_name = m_name.substr( 1 );
02846 m_wildcard = WildcardAtStart;
02847 }
02848 if( endsWith( m_name, "*" ) ) {
02849 m_name = m_name.substr( 0, m_name.size()-1 );
02850 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
02851 }
02852 }
02853 virtual ~NamePattern();
02854 virtual bool matches( TestCaseInfo const& testCase ) const {
02855 switch( m_wildcard ) {
02856 case NoWildcard:
02857 return m_name == toLower( testCase.name );
02858 case WildcardAtStart:
02859 return endsWith( toLower( testCase.name ), m_name );
02860 case WildcardAtEnd:
02861 return startsWith( toLower( testCase.name ), m_name );
02862 case WildcardAtBothEnds:
02863 return contains( toLower( testCase.name ), m_name );
02864 }
02865
02866 #ifdef __clang__
02867 #pragma clang diagnostic push
02868 #pragma clang diagnostic ignored "-Wunreachable-code"
02869 #endif
02870 throw std::logic_error( "Unknown enum" );
02871 #ifdef __clang__
02872 #pragma clang diagnostic pop
02873 #endif
02874 }
02875 private:
02876 std::string m_name;
02877 WildcardPosition m_wildcard;
02878 };
02879 class TagPattern : public Pattern {
02880 public:
02881 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
02882 virtual ~TagPattern();
02883 virtual bool matches( TestCaseInfo const& testCase ) const {
02884 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
02885 }
02886 private:
02887 std::string m_tag;
02888 };
02889 class ExcludedPattern : public Pattern {
02890 public:
02891 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
02892 virtual ~ExcludedPattern();
02893 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
02894 private:
02895 Ptr<Pattern> m_underlyingPattern;
02896 };
02897
02898 struct Filter {
02899 std::vector<Ptr<Pattern> > m_patterns;
02900
02901 bool matches( TestCaseInfo const& testCase ) const {
02902
02903 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
02904 if( !(*it)->matches( testCase ) )
02905 return false;
02906 return true;
02907 }
02908 };
02909
02910 public:
02911 bool hasFilters() const {
02912 return !m_filters.empty();
02913 }
02914 bool matches( TestCaseInfo const& testCase ) const {
02915
02916 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
02917 if( it->matches( testCase ) )
02918 return true;
02919 return false;
02920 }
02921
02922 private:
02923 std::vector<Filter> m_filters;
02924
02925 friend class TestSpecParser;
02926 };
02927 }
02928
02929 #ifdef __clang__
02930 #pragma clang diagnostic pop
02931 #endif
02932
02933 namespace Catch {
02934
02935 class TestSpecParser {
02936 enum Mode{ None, Name, QuotedName, Tag };
02937 Mode m_mode;
02938 bool m_exclusion;
02939 std::size_t m_start, m_pos;
02940 std::string m_arg;
02941 TestSpec::Filter m_currentFilter;
02942 TestSpec m_testSpec;
02943 ITagAliasRegistry const* m_tagAliases;
02944
02945 public:
02946 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
02947
02948 TestSpecParser& parse( std::string const& arg ) {
02949 m_mode = None;
02950 m_exclusion = false;
02951 m_start = std::string::npos;
02952 m_arg = m_tagAliases->expandAliases( arg );
02953 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
02954 visitChar( m_arg[m_pos] );
02955 if( m_mode == Name )
02956 addPattern<TestSpec::NamePattern>();
02957 return *this;
02958 }
02959 TestSpec testSpec() {
02960 addFilter();
02961 return m_testSpec;
02962 }
02963 private:
02964 void visitChar( char c ) {
02965 if( m_mode == None ) {
02966 switch( c ) {
02967 case ' ': return;
02968 case '~': m_exclusion = true; return;
02969 case '[': return startNewMode( Tag, ++m_pos );
02970 case '"': return startNewMode( QuotedName, ++m_pos );
02971 default: startNewMode( Name, m_pos ); break;
02972 }
02973 }
02974 if( m_mode == Name ) {
02975 if( c == ',' ) {
02976 addPattern<TestSpec::NamePattern>();
02977 addFilter();
02978 }
02979 else if( c == '[' ) {
02980 if( subString() == "exclude:" )
02981 m_exclusion = true;
02982 else
02983 addPattern<TestSpec::NamePattern>();
02984 startNewMode( Tag, ++m_pos );
02985 }
02986 }
02987 else if( m_mode == QuotedName && c == '"' )
02988 addPattern<TestSpec::NamePattern>();
02989 else if( m_mode == Tag && c == ']' )
02990 addPattern<TestSpec::TagPattern>();
02991 }
02992 void startNewMode( Mode mode, std::size_t start ) {
02993 m_mode = mode;
02994 m_start = start;
02995 }
02996 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
02997 template<typename T>
02998 void addPattern() {
02999 std::string token = subString();
03000 if( startsWith( token, "exclude:" ) ) {
03001 m_exclusion = true;
03002 token = token.substr( 8 );
03003 }
03004 if( !token.empty() ) {
03005 Ptr<TestSpec::Pattern> pattern = new T( token );
03006 if( m_exclusion )
03007 pattern = new TestSpec::ExcludedPattern( pattern );
03008 m_currentFilter.m_patterns.push_back( pattern );
03009 }
03010 m_exclusion = false;
03011 m_mode = None;
03012 }
03013 void addFilter() {
03014 if( !m_currentFilter.m_patterns.empty() ) {
03015 m_testSpec.m_filters.push_back( m_currentFilter );
03016 m_currentFilter = TestSpec::Filter();
03017 }
03018 }
03019 };
03020 inline TestSpec parseTestSpec( std::string const& arg ) {
03021 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
03022 }
03023
03024 }
03025
03026 #ifdef __clang__
03027 #pragma clang diagnostic pop
03028 #endif
03029
03030
03031 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
03032
03033 #include <iostream>
03034 #include <string>
03035 #include <vector>
03036
03037 namespace Catch {
03038
03039 struct Verbosity { enum Level {
03040 NoOutput = 0,
03041 Quiet,
03042 Normal
03043 }; };
03044
03045 struct WarnAbout { enum What {
03046 Nothing = 0x00,
03047 NoAssertions = 0x01
03048 }; };
03049
03050 struct ShowDurations { enum OrNot {
03051 DefaultForReporter,
03052 Always,
03053 Never
03054 }; };
03055 struct RunTests { enum InWhatOrder {
03056 InDeclarationOrder,
03057 InLexicographicalOrder,
03058 InRandomOrder
03059 }; };
03060
03061 class TestSpec;
03062
03063 struct IConfig : IShared {
03064
03065 virtual ~IConfig();
03066
03067 virtual bool allowThrows() const = 0;
03068 virtual std::ostream& stream() const = 0;
03069 virtual std::string name() const = 0;
03070 virtual bool includeSuccessfulResults() const = 0;
03071 virtual bool shouldDebugBreak() const = 0;
03072 virtual bool warnAboutMissingAssertions() const = 0;
03073 virtual int abortAfter() const = 0;
03074 virtual bool showInvisibles() const = 0;
03075 virtual ShowDurations::OrNot showDurations() const = 0;
03076 virtual TestSpec const& testSpec() const = 0;
03077 virtual RunTests::InWhatOrder runOrder() const = 0;
03078 virtual unsigned int rngSeed() const = 0;
03079 virtual bool forceColour() const = 0;
03080 };
03081 }
03082
03083
03084 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
03085
03086 #include <streambuf>
03087
03088 #ifdef __clang__
03089 #pragma clang diagnostic ignored "-Wpadded"
03090 #endif
03091
03092 namespace Catch {
03093
03094 class Stream {
03095 public:
03096 Stream();
03097 Stream( std::streambuf* _streamBuf, bool _isOwned );
03098 void release();
03099
03100 std::streambuf* streamBuf;
03101
03102 private:
03103 bool isOwned;
03104 };
03105
03106 std::ostream& cout();
03107 std::ostream& cerr();
03108 }
03109
03110 #include <memory>
03111 #include <vector>
03112 #include <string>
03113 #include <iostream>
03114 #include <ctime>
03115
03116 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
03117 #define CATCH_CONFIG_CONSOLE_WIDTH 80
03118 #endif
03119
03120 namespace Catch {
03121
03122 struct ConfigData {
03123
03124 ConfigData()
03125 : listTests( false ),
03126 listTags( false ),
03127 listReporters( false ),
03128 listTestNamesOnly( false ),
03129 showSuccessfulTests( false ),
03130 shouldDebugBreak( false ),
03131 noThrow( false ),
03132 showHelp( false ),
03133 showInvisibles( false ),
03134 forceColour( false ),
03135 abortAfter( -1 ),
03136 rngSeed( 0 ),
03137 verbosity( Verbosity::Normal ),
03138 warnings( WarnAbout::Nothing ),
03139 showDurations( ShowDurations::DefaultForReporter ),
03140 runOrder( RunTests::InDeclarationOrder )
03141 {}
03142
03143 bool listTests;
03144 bool listTags;
03145 bool listReporters;
03146 bool listTestNamesOnly;
03147
03148 bool showSuccessfulTests;
03149 bool shouldDebugBreak;
03150 bool noThrow;
03151 bool showHelp;
03152 bool showInvisibles;
03153 bool forceColour;
03154
03155 int abortAfter;
03156 unsigned int rngSeed;
03157
03158 Verbosity::Level verbosity;
03159 WarnAbout::What warnings;
03160 ShowDurations::OrNot showDurations;
03161 RunTests::InWhatOrder runOrder;
03162
03163 std::string reporterName;
03164 std::string outputFilename;
03165 std::string name;
03166 std::string processName;
03167
03168 std::vector<std::string> testsOrTags;
03169 };
03170
03171 class Config : public SharedImpl<IConfig> {
03172 private:
03173 Config( Config const& other );
03174 Config& operator = ( Config const& other );
03175 virtual void dummy();
03176 public:
03177
03178 Config()
03179 : m_os( Catch::cout().rdbuf() )
03180 {}
03181
03182 Config( ConfigData const& data )
03183 : m_data( data ),
03184 m_os( Catch::cout().rdbuf() )
03185 {
03186 if( !data.testsOrTags.empty() ) {
03187 TestSpecParser parser( ITagAliasRegistry::get() );
03188 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
03189 parser.parse( data.testsOrTags[i] );
03190 m_testSpec = parser.testSpec();
03191 }
03192 }
03193
03194 virtual ~Config() {
03195 m_os.rdbuf( Catch::cout().rdbuf() );
03196 m_stream.release();
03197 }
03198
03199 void setFilename( std::string const& filename ) {
03200 m_data.outputFilename = filename;
03201 }
03202
03203 std::string const& getFilename() const {
03204 return m_data.outputFilename ;
03205 }
03206
03207 bool listTests() const { return m_data.listTests; }
03208 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
03209 bool listTags() const { return m_data.listTags; }
03210 bool listReporters() const { return m_data.listReporters; }
03211
03212 std::string getProcessName() const { return m_data.processName; }
03213
03214 bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
03215
03216 void setStreamBuf( std::streambuf* buf ) {
03217 m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() );
03218 }
03219
03220 void useStream( std::string const& streamName ) {
03221 Stream stream = createStream( streamName );
03222 setStreamBuf( stream.streamBuf );
03223 m_stream.release();
03224 m_stream = stream;
03225 }
03226
03227 std::string getReporterName() const { return m_data.reporterName; }
03228
03229 int abortAfter() const { return m_data.abortAfter; }
03230
03231 TestSpec const& testSpec() const { return m_testSpec; }
03232
03233 bool showHelp() const { return m_data.showHelp; }
03234 bool showInvisibles() const { return m_data.showInvisibles; }
03235
03236
03237 virtual bool allowThrows() const { return !m_data.noThrow; }
03238 virtual std::ostream& stream() const { return m_os; }
03239 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
03240 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
03241 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
03242 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
03243 virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
03244 virtual unsigned int rngSeed() const { return m_data.rngSeed; }
03245 virtual bool forceColour() const { return m_data.forceColour; }
03246
03247 private:
03248 ConfigData m_data;
03249
03250 Stream m_stream;
03251 mutable std::ostream m_os;
03252 TestSpec m_testSpec;
03253 };
03254
03255 }
03256
03257
03258 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
03259
03260
03261 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
03262 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
03263 #undef CLARA_CONFIG_CONSOLE_WIDTH
03264 #endif
03265 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
03266
03267
03268 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
03269
03270
03271
03272 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
03273
03274 #ifndef STITCH_CLARA_OPEN_NAMESPACE
03275 #define TWOBLUECUBES_CLARA_H_INCLUDED
03276 #define STITCH_CLARA_OPEN_NAMESPACE
03277 #define STITCH_CLARA_CLOSE_NAMESPACE
03278 #else
03279 #define STITCH_CLARA_CLOSE_NAMESPACE }
03280 #endif
03281
03282 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
03283
03284
03285
03286
03287 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
03288 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
03289 #define TBC_TEXT_FORMAT_H_INCLUDED
03290 #endif
03291
03292 #include <string>
03293 #include <vector>
03294 #include <sstream>
03295
03296
03297 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
03298 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
03299 #endif
03300
03301 namespace Tbc {
03302
03303 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
03304 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
03305 #else
03306 const unsigned int consoleWidth = 80;
03307 #endif
03308
03309 struct TextAttributes {
03310 TextAttributes()
03311 : initialIndent( std::string::npos ),
03312 indent( 0 ),
03313 width( consoleWidth-1 ),
03314 tabChar( '\t' )
03315 {}
03316
03317 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
03318 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
03319 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
03320 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
03321
03322 std::size_t initialIndent;
03323 std::size_t indent;
03324 std::size_t width;
03325 char tabChar;
03326 };
03327
03328 class Text {
03329 public:
03330 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
03331 : attr( _attr )
03332 {
03333 std::string wrappableChars = " [({.,/|\\-";
03334 std::size_t indent = _attr.initialIndent != std::string::npos
03335 ? _attr.initialIndent
03336 : _attr.indent;
03337 std::string remainder = _str;
03338
03339 while( !remainder.empty() ) {
03340 if( lines.size() >= 1000 ) {
03341 lines.push_back( "... message truncated due to excessive size" );
03342 return;
03343 }
03344 std::size_t tabPos = std::string::npos;
03345 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
03346 std::size_t pos = remainder.find_first_of( '\n' );
03347 if( pos <= width ) {
03348 width = pos;
03349 }
03350 pos = remainder.find_last_of( _attr.tabChar, width );
03351 if( pos != std::string::npos ) {
03352 tabPos = pos;
03353 if( remainder[width] == '\n' )
03354 width--;
03355 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
03356 }
03357
03358 if( width == remainder.size() ) {
03359 spliceLine( indent, remainder, width );
03360 }
03361 else if( remainder[width] == '\n' ) {
03362 spliceLine( indent, remainder, width );
03363 if( width <= 1 || remainder.size() != 1 )
03364 remainder = remainder.substr( 1 );
03365 indent = _attr.indent;
03366 }
03367 else {
03368 pos = remainder.find_last_of( wrappableChars, width );
03369 if( pos != std::string::npos && pos > 0 ) {
03370 spliceLine( indent, remainder, pos );
03371 if( remainder[0] == ' ' )
03372 remainder = remainder.substr( 1 );
03373 }
03374 else {
03375 spliceLine( indent, remainder, width-1 );
03376 lines.back() += "-";
03377 }
03378 if( lines.size() == 1 )
03379 indent = _attr.indent;
03380 if( tabPos != std::string::npos )
03381 indent += tabPos;
03382 }
03383 }
03384 }
03385
03386 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
03387 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
03388 _remainder = _remainder.substr( _pos );
03389 }
03390
03391 typedef std::vector<std::string>::const_iterator const_iterator;
03392
03393 const_iterator begin() const { return lines.begin(); }
03394 const_iterator end() const { return lines.end(); }
03395 std::string const& last() const { return lines.back(); }
03396 std::size_t size() const { return lines.size(); }
03397 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
03398 std::string toString() const {
03399 std::ostringstream oss;
03400 oss << *this;
03401 return oss.str();
03402 }
03403
03404 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
03405 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
03406 it != itEnd; ++it ) {
03407 if( it != _text.begin() )
03408 _stream << "\n";
03409 _stream << *it;
03410 }
03411 return _stream;
03412 }
03413
03414 private:
03415 std::string str;
03416 TextAttributes attr;
03417 std::vector<std::string> lines;
03418 };
03419
03420 }
03421
03422 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
03423 }
03424 #endif
03425
03426 #endif // TBC_TEXT_FORMAT_H_INCLUDED
03427
03428
03429
03430
03431 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
03432
03433 #include <map>
03434 #include <algorithm>
03435 #include <stdexcept>
03436 #include <memory>
03437
03438
03439 #ifdef STITCH_CLARA_OPEN_NAMESPACE
03440 STITCH_CLARA_OPEN_NAMESPACE
03441 #endif
03442
03443 namespace Clara {
03444
03445 struct UnpositionalTag {};
03446
03447 extern UnpositionalTag _;
03448
03449 #ifdef CLARA_CONFIG_MAIN
03450 UnpositionalTag _;
03451 #endif
03452
03453 namespace Detail {
03454
03455 #ifdef CLARA_CONSOLE_WIDTH
03456 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
03457 #else
03458 const unsigned int consoleWidth = 80;
03459 #endif
03460
03461 using namespace Tbc;
03462
03463 inline bool startsWith( std::string const& str, std::string const& prefix ) {
03464 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
03465 }
03466
03467 template<typename T> struct RemoveConstRef{ typedef T type; };
03468 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
03469 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
03470 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
03471
03472 template<typename T> struct IsBool { static const bool value = false; };
03473 template<> struct IsBool<bool> { static const bool value = true; };
03474
03475 template<typename T>
03476 void convertInto( std::string const& _source, T& _dest ) {
03477 std::stringstream ss;
03478 ss << _source;
03479 ss >> _dest;
03480 if( ss.fail() )
03481 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
03482 }
03483 inline void convertInto( std::string const& _source, std::string& _dest ) {
03484 _dest = _source;
03485 }
03486 inline void convertInto( std::string const& _source, bool& _dest ) {
03487 std::string sourceLC = _source;
03488 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
03489 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
03490 _dest = true;
03491 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
03492 _dest = false;
03493 else
03494 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
03495 }
03496 inline void convertInto( bool _source, bool& _dest ) {
03497 _dest = _source;
03498 }
03499 template<typename T>
03500 inline void convertInto( bool, T& ) {
03501 throw std::runtime_error( "Invalid conversion" );
03502 }
03503
03504 template<typename ConfigT>
03505 struct IArgFunction {
03506 virtual ~IArgFunction() {}
03507 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
03508 IArgFunction() = default;
03509 IArgFunction( IArgFunction const& ) = default;
03510 # endif
03511 virtual void set( ConfigT& config, std::string const& value ) const = 0;
03512 virtual void setFlag( ConfigT& config ) const = 0;
03513 virtual bool takesArg() const = 0;
03514 virtual IArgFunction* clone() const = 0;
03515 };
03516
03517 template<typename ConfigT>
03518 class BoundArgFunction {
03519 public:
03520 BoundArgFunction() : functionObj( NULL ) {}
03521 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
03522 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}
03523 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
03524 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL;
03525 delete functionObj;
03526 functionObj = newFunctionObj;
03527 return *this;
03528 }
03529 ~BoundArgFunction() { delete functionObj; }
03530
03531 void set( ConfigT& config, std::string const& value ) const {
03532 functionObj->set( config, value );
03533 }
03534 void setFlag( ConfigT& config ) const {
03535 functionObj->setFlag( config );
03536 }
03537 bool takesArg() const { return functionObj->takesArg(); }
03538
03539 bool isSet() const {
03540 return functionObj != NULL;
03541 }
03542 private:
03543 IArgFunction<ConfigT>* functionObj;
03544 };
03545
03546 template<typename C>
03547 struct NullBinder : IArgFunction<C>{
03548 virtual void set( C&, std::string const& ) const {}
03549 virtual void setFlag( C& ) const {}
03550 virtual bool takesArg() const { return true; }
03551 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
03552 };
03553
03554 template<typename C, typename M>
03555 struct BoundDataMember : IArgFunction<C>{
03556 BoundDataMember( M C::* _member ) : member( _member ) {}
03557 virtual void set( C& p, std::string const& stringValue ) const {
03558 convertInto( stringValue, p.*member );
03559 }
03560 virtual void setFlag( C& p ) const {
03561 convertInto( true, p.*member );
03562 }
03563 virtual bool takesArg() const { return !IsBool<M>::value; }
03564 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
03565 M C::* member;
03566 };
03567 template<typename C, typename M>
03568 struct BoundUnaryMethod : IArgFunction<C>{
03569 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
03570 virtual void set( C& p, std::string const& stringValue ) const {
03571 typename RemoveConstRef<M>::type value;
03572 convertInto( stringValue, value );
03573 (p.*member)( value );
03574 }
03575 virtual void setFlag( C& p ) const {
03576 typename RemoveConstRef<M>::type value;
03577 convertInto( true, value );
03578 (p.*member)( value );
03579 }
03580 virtual bool takesArg() const { return !IsBool<M>::value; }
03581 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
03582 void (C::*member)( M );
03583 };
03584 template<typename C>
03585 struct BoundNullaryMethod : IArgFunction<C>{
03586 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
03587 virtual void set( C& p, std::string const& stringValue ) const {
03588 bool value;
03589 convertInto( stringValue, value );
03590 if( value )
03591 (p.*member)();
03592 }
03593 virtual void setFlag( C& p ) const {
03594 (p.*member)();
03595 }
03596 virtual bool takesArg() const { return false; }
03597 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
03598 void (C::*member)();
03599 };
03600
03601 template<typename C>
03602 struct BoundUnaryFunction : IArgFunction<C>{
03603 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
03604 virtual void set( C& obj, std::string const& stringValue ) const {
03605 bool value;
03606 convertInto( stringValue, value );
03607 if( value )
03608 function( obj );
03609 }
03610 virtual void setFlag( C& p ) const {
03611 function( p );
03612 }
03613 virtual bool takesArg() const { return false; }
03614 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
03615 void (*function)( C& );
03616 };
03617
03618 template<typename C, typename T>
03619 struct BoundBinaryFunction : IArgFunction<C>{
03620 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
03621 virtual void set( C& obj, std::string const& stringValue ) const {
03622 typename RemoveConstRef<T>::type value;
03623 convertInto( stringValue, value );
03624 function( obj, value );
03625 }
03626 virtual void setFlag( C& obj ) const {
03627 typename RemoveConstRef<T>::type value;
03628 convertInto( true, value );
03629 function( obj, value );
03630 }
03631 virtual bool takesArg() const { return !IsBool<T>::value; }
03632 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
03633 void (*function)( C&, T );
03634 };
03635
03636 }
03637
03638 struct Parser {
03639 Parser() : separators( " \t=:" ) {}
03640
03641 struct Token {
03642 enum Type { Positional, ShortOpt, LongOpt };
03643 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
03644 Type type;
03645 std::string data;
03646 };
03647
03648 void parseIntoTokens( int argc, char const * const * argv, std::vector<Parser::Token>& tokens ) const {
03649 const std::string doubleDash = "--";
03650 for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
03651 parseIntoTokens( argv[i] , tokens);
03652 }
03653 void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
03654 while( !arg.empty() ) {
03655 Parser::Token token( Parser::Token::Positional, arg );
03656 arg = "";
03657 if( token.data[0] == '-' ) {
03658 if( token.data.size() > 1 && token.data[1] == '-' ) {
03659 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
03660 }
03661 else {
03662 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
03663 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
03664 arg = "-" + token.data.substr( 1 );
03665 token.data = token.data.substr( 0, 1 );
03666 }
03667 }
03668 }
03669 if( token.type != Parser::Token::Positional ) {
03670 std::size_t pos = token.data.find_first_of( separators );
03671 if( pos != std::string::npos ) {
03672 arg = token.data.substr( pos+1 );
03673 token.data = token.data.substr( 0, pos );
03674 }
03675 }
03676 tokens.push_back( token );
03677 }
03678 }
03679 std::string separators;
03680 };
03681
03682 template<typename ConfigT>
03683 struct CommonArgProperties {
03684 CommonArgProperties() {}
03685 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
03686
03687 Detail::BoundArgFunction<ConfigT> boundField;
03688 std::string description;
03689 std::string detail;
03690 std::string placeholder;
03691
03692 bool takesArg() const {
03693 return !placeholder.empty();
03694 }
03695 void validate() const {
03696 if( !boundField.isSet() )
03697 throw std::logic_error( "option not bound" );
03698 }
03699 };
03700 struct OptionArgProperties {
03701 std::vector<std::string> shortNames;
03702 std::string longName;
03703
03704 bool hasShortName( std::string const& shortName ) const {
03705 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
03706 }
03707 bool hasLongName( std::string const& _longName ) const {
03708 return _longName == longName;
03709 }
03710 };
03711 struct PositionalArgProperties {
03712 PositionalArgProperties() : position( -1 ) {}
03713 int position;
03714
03715 bool isFixedPositional() const {
03716 return position != -1;
03717 }
03718 };
03719
03720 template<typename ConfigT>
03721 class CommandLine {
03722
03723 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
03724 Arg() {}
03725 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
03726
03727 using CommonArgProperties<ConfigT>::placeholder;
03728
03729 std::string dbgName() const {
03730 if( !longName.empty() )
03731 return "--" + longName;
03732 if( !shortNames.empty() )
03733 return "-" + shortNames[0];
03734 return "positional args";
03735 }
03736 std::string commands() const {
03737 std::ostringstream oss;
03738 bool first = true;
03739 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
03740 for(; it != itEnd; ++it ) {
03741 if( first )
03742 first = false;
03743 else
03744 oss << ", ";
03745 oss << "-" << *it;
03746 }
03747 if( !longName.empty() ) {
03748 if( !first )
03749 oss << ", ";
03750 oss << "--" << longName;
03751 }
03752 if( !placeholder.empty() )
03753 oss << " <" << placeholder << ">";
03754 return oss.str();
03755 }
03756 };
03757
03758
03759 #if defined(__cplusplus) && __cplusplus > 199711L
03760 typedef std::unique_ptr<Arg> ArgAutoPtr;
03761 #else
03762 typedef std::auto_ptr<Arg> ArgAutoPtr;
03763 #endif
03764
03765 friend void addOptName( Arg& arg, std::string const& optName )
03766 {
03767 if( optName.empty() )
03768 return;
03769 if( Detail::startsWith( optName, "--" ) ) {
03770 if( !arg.longName.empty() )
03771 throw std::logic_error( "Only one long opt may be specified. '"
03772 + arg.longName
03773 + "' already specified, now attempting to add '"
03774 + optName + "'" );
03775 arg.longName = optName.substr( 2 );
03776 }
03777 else if( Detail::startsWith( optName, "-" ) )
03778 arg.shortNames.push_back( optName.substr( 1 ) );
03779 else
03780 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
03781 }
03782 friend void setPositionalArg( Arg& arg, int position )
03783 {
03784 arg.position = position;
03785 }
03786
03787 class ArgBuilder {
03788 public:
03789 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
03790
03791
03792 template<typename C, typename M>
03793 void bind( M C::* field, std::string const& placeholder ) {
03794 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
03795 m_arg->placeholder = placeholder;
03796 }
03797
03798 template<typename C>
03799 void bind( bool C::* field ) {
03800 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
03801 }
03802
03803
03804 template<typename C, typename M>
03805 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
03806 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
03807 m_arg->placeholder = placeholder;
03808 }
03809
03810
03811 template<typename C>
03812 void bind( void (C::* unaryMethod)( bool ) ) {
03813 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
03814 }
03815
03816
03817 template<typename C>
03818 void bind( void (C::* nullaryMethod)() ) {
03819 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
03820 }
03821
03822
03823 template<typename C>
03824 void bind( void (* unaryFunction)( C& ) ) {
03825 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
03826 }
03827
03828
03829 template<typename C, typename T>
03830 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
03831 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
03832 m_arg->placeholder = placeholder;
03833 }
03834
03835 ArgBuilder& describe( std::string const& description ) {
03836 m_arg->description = description;
03837 return *this;
03838 }
03839 ArgBuilder& detail( std::string const& detail ) {
03840 m_arg->detail = detail;
03841 return *this;
03842 }
03843
03844 protected:
03845 Arg* m_arg;
03846 };
03847
03848 class OptBuilder : public ArgBuilder {
03849 public:
03850 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
03851 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
03852
03853 OptBuilder& operator[]( std::string const& optName ) {
03854 addOptName( *ArgBuilder::m_arg, optName );
03855 return *this;
03856 }
03857 };
03858
03859 public:
03860
03861 CommandLine()
03862 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
03863 m_highestSpecifiedArgPosition( 0 ),
03864 m_throwOnUnrecognisedTokens( false )
03865 {}
03866 CommandLine( CommandLine const& other )
03867 : m_boundProcessName( other.m_boundProcessName ),
03868 m_options ( other.m_options ),
03869 m_positionalArgs( other.m_positionalArgs ),
03870 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
03871 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
03872 {
03873 if( other.m_floatingArg.get() )
03874 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
03875 }
03876
03877 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
03878 m_throwOnUnrecognisedTokens = shouldThrow;
03879 return *this;
03880 }
03881
03882 OptBuilder operator[]( std::string const& optName ) {
03883 m_options.push_back( Arg() );
03884 addOptName( m_options.back(), optName );
03885 OptBuilder builder( &m_options.back() );
03886 return builder;
03887 }
03888
03889 ArgBuilder operator[]( int position ) {
03890 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
03891 if( position > m_highestSpecifiedArgPosition )
03892 m_highestSpecifiedArgPosition = position;
03893 setPositionalArg( m_positionalArgs[position], position );
03894 ArgBuilder builder( &m_positionalArgs[position] );
03895 return builder;
03896 }
03897
03898
03899 ArgBuilder operator[]( UnpositionalTag ) {
03900 if( m_floatingArg.get() )
03901 throw std::logic_error( "Only one unpositional argument can be added" );
03902 m_floatingArg.reset( new Arg() );
03903 ArgBuilder builder( m_floatingArg.get() );
03904 return builder;
03905 }
03906
03907 template<typename C, typename M>
03908 void bindProcessName( M C::* field ) {
03909 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
03910 }
03911 template<typename C, typename M>
03912 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
03913 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
03914 }
03915
03916 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
03917 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
03918 std::size_t maxWidth = 0;
03919 for( it = itBegin; it != itEnd; ++it )
03920 maxWidth = (std::max)( maxWidth, it->commands().size() );
03921
03922 for( it = itBegin; it != itEnd; ++it ) {
03923 Detail::Text usage( it->commands(), Detail::TextAttributes()
03924 .setWidth( maxWidth+indent )
03925 .setIndent( indent ) );
03926 Detail::Text desc( it->description, Detail::TextAttributes()
03927 .setWidth( width - maxWidth - 3 ) );
03928
03929 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
03930 std::string usageCol = i < usage.size() ? usage[i] : "";
03931 os << usageCol;
03932
03933 if( i < desc.size() && !desc[i].empty() )
03934 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
03935 << desc[i];
03936 os << "\n";
03937 }
03938 }
03939 }
03940 std::string optUsage() const {
03941 std::ostringstream oss;
03942 optUsage( oss );
03943 return oss.str();
03944 }
03945
03946 void argSynopsis( std::ostream& os ) const {
03947 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
03948 if( i > 1 )
03949 os << " ";
03950 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
03951 if( it != m_positionalArgs.end() )
03952 os << "<" << it->second.placeholder << ">";
03953 else if( m_floatingArg.get() )
03954 os << "<" << m_floatingArg->placeholder << ">";
03955 else
03956 throw std::logic_error( "non consecutive positional arguments with no floating args" );
03957 }
03958
03959 if( m_floatingArg.get() ) {
03960 if( m_highestSpecifiedArgPosition > 1 )
03961 os << " ";
03962 os << "[<" << m_floatingArg->placeholder << "> ...]";
03963 }
03964 }
03965 std::string argSynopsis() const {
03966 std::ostringstream oss;
03967 argSynopsis( oss );
03968 return oss.str();
03969 }
03970
03971 void usage( std::ostream& os, std::string const& procName ) const {
03972 validate();
03973 os << "usage:\n " << procName << " ";
03974 argSynopsis( os );
03975 if( !m_options.empty() ) {
03976 os << " [options]\n\nwhere options are: \n";
03977 optUsage( os, 2 );
03978 }
03979 os << "\n";
03980 }
03981 std::string usage( std::string const& procName ) const {
03982 std::ostringstream oss;
03983 usage( oss, procName );
03984 return oss.str();
03985 }
03986
03987 ConfigT parse( int argc, char const * const * argv ) const {
03988 ConfigT config;
03989 parseInto( argc, argv, config );
03990 return config;
03991 }
03992
03993 std::vector<Parser::Token> parseInto( int argc, char const * const * argv, ConfigT& config ) const {
03994 std::string processName = argv[0];
03995 std::size_t lastSlash = processName.find_last_of( "/\\" );
03996 if( lastSlash != std::string::npos )
03997 processName = processName.substr( lastSlash+1 );
03998 m_boundProcessName.set( config, processName );
03999 std::vector<Parser::Token> tokens;
04000 Parser parser;
04001 parser.parseIntoTokens( argc, argv, tokens );
04002 return populate( tokens, config );
04003 }
04004
04005 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
04006 validate();
04007 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
04008 unusedTokens = populateFixedArgs( unusedTokens, config );
04009 unusedTokens = populateFloatingArgs( unusedTokens, config );
04010 return unusedTokens;
04011 }
04012
04013 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
04014 std::vector<Parser::Token> unusedTokens;
04015 std::vector<std::string> errors;
04016 for( std::size_t i = 0; i < tokens.size(); ++i ) {
04017 Parser::Token const& token = tokens[i];
04018 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
04019 for(; it != itEnd; ++it ) {
04020 Arg const& arg = *it;
04021
04022 try {
04023 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
04024 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
04025 if( arg.takesArg() ) {
04026 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
04027 errors.push_back( "Expected argument to option: " + token.data );
04028 else
04029 arg.boundField.set( config, tokens[++i].data );
04030 }
04031 else {
04032 arg.boundField.setFlag( config );
04033 }
04034 break;
04035 }
04036 }
04037 catch( std::exception& ex ) {
04038 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
04039 }
04040 }
04041 if( it == itEnd ) {
04042 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
04043 unusedTokens.push_back( token );
04044 else if( errors.empty() && m_throwOnUnrecognisedTokens )
04045 errors.push_back( "unrecognised option: " + token.data );
04046 }
04047 }
04048 if( !errors.empty() ) {
04049 std::ostringstream oss;
04050 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
04051 it != itEnd;
04052 ++it ) {
04053 if( it != errors.begin() )
04054 oss << "\n";
04055 oss << *it;
04056 }
04057 throw std::runtime_error( oss.str() );
04058 }
04059 return unusedTokens;
04060 }
04061 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
04062 std::vector<Parser::Token> unusedTokens;
04063 int position = 1;
04064 for( std::size_t i = 0; i < tokens.size(); ++i ) {
04065 Parser::Token const& token = tokens[i];
04066 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
04067 if( it != m_positionalArgs.end() )
04068 it->second.boundField.set( config, token.data );
04069 else
04070 unusedTokens.push_back( token );
04071 if( token.type == Parser::Token::Positional )
04072 position++;
04073 }
04074 return unusedTokens;
04075 }
04076 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
04077 if( !m_floatingArg.get() )
04078 return tokens;
04079 std::vector<Parser::Token> unusedTokens;
04080 for( std::size_t i = 0; i < tokens.size(); ++i ) {
04081 Parser::Token const& token = tokens[i];
04082 if( token.type == Parser::Token::Positional )
04083 m_floatingArg->boundField.set( config, token.data );
04084 else
04085 unusedTokens.push_back( token );
04086 }
04087 return unusedTokens;
04088 }
04089
04090 void validate() const
04091 {
04092 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
04093 throw std::logic_error( "No options or arguments specified" );
04094
04095 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
04096 itEnd = m_options.end();
04097 it != itEnd; ++it )
04098 it->validate();
04099 }
04100
04101 private:
04102 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
04103 std::vector<Arg> m_options;
04104 std::map<int, Arg> m_positionalArgs;
04105 ArgAutoPtr m_floatingArg;
04106 int m_highestSpecifiedArgPosition;
04107 bool m_throwOnUnrecognisedTokens;
04108 };
04109
04110 }
04111
04112 STITCH_CLARA_CLOSE_NAMESPACE
04113 #undef STITCH_CLARA_OPEN_NAMESPACE
04114 #undef STITCH_CLARA_CLOSE_NAMESPACE
04115
04116 #endif // TWOBLUECUBES_CLARA_H_INCLUDED
04117 #undef STITCH_CLARA_OPEN_NAMESPACE
04118
04119
04120 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
04121 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
04122 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
04123 #endif
04124
04125 #include <fstream>
04126
04127 namespace Catch {
04128
04129 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
04130 inline void abortAfterX( ConfigData& config, int x ) {
04131 if( x < 1 )
04132 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
04133 config.abortAfter = x;
04134 }
04135 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
04136
04137 inline void addWarning( ConfigData& config, std::string const& _warning ) {
04138 if( _warning == "NoAssertions" )
04139 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
04140 else
04141 throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
04142 }
04143 inline void setOrder( ConfigData& config, std::string const& order ) {
04144 if( startsWith( "declared", order ) )
04145 config.runOrder = RunTests::InDeclarationOrder;
04146 else if( startsWith( "lexical", order ) )
04147 config.runOrder = RunTests::InLexicographicalOrder;
04148 else if( startsWith( "random", order ) )
04149 config.runOrder = RunTests::InRandomOrder;
04150 else
04151 throw std::runtime_error( "Unrecognised ordering: '" + order + "'" );
04152 }
04153 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
04154 if( seed == "time" ) {
04155 config.rngSeed = static_cast<unsigned int>( std::time(0) );
04156 }
04157 else {
04158 std::stringstream ss;
04159 ss << seed;
04160 ss >> config.rngSeed;
04161 if( ss.fail() )
04162 throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" );
04163 }
04164 }
04165 inline void setVerbosity( ConfigData& config, int level ) {
04166
04167 config.verbosity = static_cast<Verbosity::Level>( level );
04168 }
04169 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
04170 config.showDurations = _showDurations
04171 ? ShowDurations::Always
04172 : ShowDurations::Never;
04173 }
04174 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
04175 std::ifstream f( _filename.c_str() );
04176 if( !f.is_open() )
04177 throw std::domain_error( "Unable to load input file: " + _filename );
04178
04179 std::string line;
04180 while( std::getline( f, line ) ) {
04181 line = trim(line);
04182 if( !line.empty() && !startsWith( line, "#" ) )
04183 addTestOrTags( config, "\"" + line + "\"," );
04184 }
04185 }
04186
04187 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
04188
04189 using namespace Clara;
04190 CommandLine<ConfigData> cli;
04191
04192 cli.bindProcessName( &ConfigData::processName );
04193
04194 cli["-?"]["-h"]["--help"]
04195 .describe( "display usage information" )
04196 .bind( &ConfigData::showHelp );
04197
04198 cli["-l"]["--list-tests"]
04199 .describe( "list all/matching test cases" )
04200 .bind( &ConfigData::listTests );
04201
04202 cli["-t"]["--list-tags"]
04203 .describe( "list all/matching tags" )
04204 .bind( &ConfigData::listTags );
04205
04206 cli["-s"]["--success"]
04207 .describe( "include successful tests in output" )
04208 .bind( &ConfigData::showSuccessfulTests );
04209
04210 cli["-b"]["--break"]
04211 .describe( "break into debugger on failure" )
04212 .bind( &ConfigData::shouldDebugBreak );
04213
04214 cli["-e"]["--nothrow"]
04215 .describe( "skip exception tests" )
04216 .bind( &ConfigData::noThrow );
04217
04218 cli["-i"]["--invisibles"]
04219 .describe( "show invisibles (tabs, newlines)" )
04220 .bind( &ConfigData::showInvisibles );
04221
04222 cli["-o"]["--out"]
04223 .describe( "output filename" )
04224 .bind( &ConfigData::outputFilename, "filename" );
04225
04226 cli["-r"]["--reporter"]
04227
04228 .describe( "reporter to use (defaults to console)" )
04229 .bind( &ConfigData::reporterName, "name" );
04230
04231 cli["-n"]["--name"]
04232 .describe( "suite name" )
04233 .bind( &ConfigData::name, "name" );
04234
04235 cli["-a"]["--abort"]
04236 .describe( "abort at first failure" )
04237 .bind( &abortAfterFirst );
04238
04239 cli["-x"]["--abortx"]
04240 .describe( "abort after x failures" )
04241 .bind( &abortAfterX, "no. failures" );
04242
04243 cli["-w"]["--warn"]
04244 .describe( "enable warnings" )
04245 .bind( &addWarning, "warning name" );
04246
04247
04248
04249
04250
04251
04252
04253
04254 cli[_]
04255 .describe( "which test or tests to use" )
04256 .bind( &addTestOrTags, "test name, pattern or tags" );
04257
04258 cli["-d"]["--durations"]
04259 .describe( "show test durations" )
04260 .bind( &setShowDurations, "yes/no" );
04261
04262 cli["-f"]["--input-file"]
04263 .describe( "load test names to run from a file" )
04264 .bind( &loadTestNamesFromFile, "filename" );
04265
04266
04267 cli["--list-test-names-only"]
04268 .describe( "list all/matching test cases names only" )
04269 .bind( &ConfigData::listTestNamesOnly );
04270
04271 cli["--list-reporters"]
04272 .describe( "list all reporters" )
04273 .bind( &ConfigData::listReporters );
04274
04275 cli["--order"]
04276 .describe( "test case order (defaults to decl)" )
04277 .bind( &setOrder, "decl|lex|rand" );
04278
04279 cli["--rng-seed"]
04280 .describe( "set a specific seed for random numbers" )
04281 .bind( &setRngSeed, "'time'|number" );
04282
04283 cli["--force-colour"]
04284 .describe( "force colourised output" )
04285 .bind( &ConfigData::forceColour );
04286
04287 return cli;
04288 }
04289
04290 }
04291
04292
04293 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
04294
04295
04296 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
04297
04298 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
04299
04300 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
04301
04302
04303 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
04304 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
04305 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
04306 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
04307 # endif
04308 # else
04309 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
04310 # endif
04311 #endif
04312 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
04313 #include <string>
04314 #include <vector>
04315 #include <sstream>
04316
04317
04318 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
04319 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
04320 #endif
04321
04322 namespace Tbc {
04323
04324 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
04325 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
04326 #else
04327 const unsigned int consoleWidth = 80;
04328 #endif
04329
04330 struct TextAttributes {
04331 TextAttributes()
04332 : initialIndent( std::string::npos ),
04333 indent( 0 ),
04334 width( consoleWidth-1 ),
04335 tabChar( '\t' )
04336 {}
04337
04338 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
04339 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
04340 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
04341 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
04342
04343 std::size_t initialIndent;
04344 std::size_t indent;
04345 std::size_t width;
04346 char tabChar;
04347 };
04348
04349 class Text {
04350 public:
04351 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
04352 : attr( _attr )
04353 {
04354 std::string wrappableChars = " [({.,/|\\-";
04355 std::size_t indent = _attr.initialIndent != std::string::npos
04356 ? _attr.initialIndent
04357 : _attr.indent;
04358 std::string remainder = _str;
04359
04360 while( !remainder.empty() ) {
04361 if( lines.size() >= 1000 ) {
04362 lines.push_back( "... message truncated due to excessive size" );
04363 return;
04364 }
04365 std::size_t tabPos = std::string::npos;
04366 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
04367 std::size_t pos = remainder.find_first_of( '\n' );
04368 if( pos <= width ) {
04369 width = pos;
04370 }
04371 pos = remainder.find_last_of( _attr.tabChar, width );
04372 if( pos != std::string::npos ) {
04373 tabPos = pos;
04374 if( remainder[width] == '\n' )
04375 width--;
04376 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
04377 }
04378
04379 if( width == remainder.size() ) {
04380 spliceLine( indent, remainder, width );
04381 }
04382 else if( remainder[width] == '\n' ) {
04383 spliceLine( indent, remainder, width );
04384 if( width <= 1 || remainder.size() != 1 )
04385 remainder = remainder.substr( 1 );
04386 indent = _attr.indent;
04387 }
04388 else {
04389 pos = remainder.find_last_of( wrappableChars, width );
04390 if( pos != std::string::npos && pos > 0 ) {
04391 spliceLine( indent, remainder, pos );
04392 if( remainder[0] == ' ' )
04393 remainder = remainder.substr( 1 );
04394 }
04395 else {
04396 spliceLine( indent, remainder, width-1 );
04397 lines.back() += "-";
04398 }
04399 if( lines.size() == 1 )
04400 indent = _attr.indent;
04401 if( tabPos != std::string::npos )
04402 indent += tabPos;
04403 }
04404 }
04405 }
04406
04407 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
04408 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
04409 _remainder = _remainder.substr( _pos );
04410 }
04411
04412 typedef std::vector<std::string>::const_iterator const_iterator;
04413
04414 const_iterator begin() const { return lines.begin(); }
04415 const_iterator end() const { return lines.end(); }
04416 std::string const& last() const { return lines.back(); }
04417 std::size_t size() const { return lines.size(); }
04418 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
04419 std::string toString() const {
04420 std::ostringstream oss;
04421 oss << *this;
04422 return oss.str();
04423 }
04424
04425 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
04426 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
04427 it != itEnd; ++it ) {
04428 if( it != _text.begin() )
04429 _stream << "\n";
04430 _stream << *it;
04431 }
04432 return _stream;
04433 }
04434
04435 private:
04436 std::string str;
04437 TextAttributes attr;
04438 std::vector<std::string> lines;
04439 };
04440
04441 }
04442
04443 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
04444 }
04445 #endif
04446
04447 #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
04448 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
04449
04450 namespace Catch {
04451 using Tbc::Text;
04452 using Tbc::TextAttributes;
04453 }
04454
04455
04456 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
04457
04458 namespace Catch {
04459
04460 struct Colour {
04461 enum Code {
04462 None = 0,
04463
04464 White,
04465 Red,
04466 Green,
04467 Blue,
04468 Cyan,
04469 Yellow,
04470 Grey,
04471
04472 Bright = 0x10,
04473
04474 BrightRed = Bright | Red,
04475 BrightGreen = Bright | Green,
04476 LightGrey = Bright | Grey,
04477 BrightWhite = Bright | White,
04478
04479
04480 FileName = LightGrey,
04481 Warning = Yellow,
04482 ResultError = BrightRed,
04483 ResultSuccess = BrightGreen,
04484 ResultExpectedFailure = Warning,
04485
04486 Error = BrightRed,
04487 Success = Green,
04488
04489 OriginalExpression = Cyan,
04490 ReconstructedExpression = Yellow,
04491
04492 SecondaryText = LightGrey,
04493 Headers = White
04494 };
04495
04496
04497 Colour( Code _colourCode );
04498 Colour( Colour const& other );
04499 ~Colour();
04500
04501
04502 static void use( Code _colourCode );
04503
04504 private:
04505 bool m_moved;
04506 };
04507
04508 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
04509
04510 }
04511
04512
04513 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
04514
04515 #include <string>
04516 #include <ostream>
04517 #include <map>
04518 #include <assert.h>
04519
04520 namespace Catch
04521 {
04522 struct ReporterConfig {
04523 explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
04524 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
04525
04526 ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
04527 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
04528
04529 std::ostream& stream() const { return *m_stream; }
04530 Ptr<IConfig> fullConfig() const { return m_fullConfig; }
04531
04532 private:
04533 std::ostream* m_stream;
04534 Ptr<IConfig> m_fullConfig;
04535 };
04536
04537 struct ReporterPreferences {
04538 ReporterPreferences()
04539 : shouldRedirectStdOut( false )
04540 {}
04541
04542 bool shouldRedirectStdOut;
04543 };
04544
04545 template<typename T>
04546 struct LazyStat : Option<T> {
04547 LazyStat() : used( false ) {}
04548 LazyStat& operator=( T const& _value ) {
04549 Option<T>::operator=( _value );
04550 used = false;
04551 return *this;
04552 }
04553 void reset() {
04554 Option<T>::reset();
04555 used = false;
04556 }
04557 bool used;
04558 };
04559
04560 struct TestRunInfo {
04561 TestRunInfo( std::string const& _name ) : name( _name ) {}
04562 std::string name;
04563 };
04564 struct GroupInfo {
04565 GroupInfo( std::string const& _name,
04566 std::size_t _groupIndex,
04567 std::size_t _groupsCount )
04568 : name( _name ),
04569 groupIndex( _groupIndex ),
04570 groupsCounts( _groupsCount )
04571 {}
04572
04573 std::string name;
04574 std::size_t groupIndex;
04575 std::size_t groupsCounts;
04576 };
04577
04578 struct AssertionStats {
04579 AssertionStats( AssertionResult const& _assertionResult,
04580 std::vector<MessageInfo> const& _infoMessages,
04581 Totals const& _totals )
04582 : assertionResult( _assertionResult ),
04583 infoMessages( _infoMessages ),
04584 totals( _totals )
04585 {
04586 if( assertionResult.hasMessage() ) {
04587
04588
04589 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
04590 builder << assertionResult.getMessage();
04591 builder.m_info.message = builder.m_stream.str();
04592
04593 infoMessages.push_back( builder.m_info );
04594 }
04595 }
04596 virtual ~AssertionStats();
04597
04598 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
04599 AssertionStats( AssertionStats const& ) = default;
04600 AssertionStats( AssertionStats && ) = default;
04601 AssertionStats& operator = ( AssertionStats const& ) = default;
04602 AssertionStats& operator = ( AssertionStats && ) = default;
04603 # endif
04604
04605 AssertionResult assertionResult;
04606 std::vector<MessageInfo> infoMessages;
04607 Totals totals;
04608 };
04609
04610 struct SectionStats {
04611 SectionStats( SectionInfo const& _sectionInfo,
04612 Counts const& _assertions,
04613 double _durationInSeconds,
04614 bool _missingAssertions )
04615 : sectionInfo( _sectionInfo ),
04616 assertions( _assertions ),
04617 durationInSeconds( _durationInSeconds ),
04618 missingAssertions( _missingAssertions )
04619 {}
04620 virtual ~SectionStats();
04621 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
04622 SectionStats( SectionStats const& ) = default;
04623 SectionStats( SectionStats && ) = default;
04624 SectionStats& operator = ( SectionStats const& ) = default;
04625 SectionStats& operator = ( SectionStats && ) = default;
04626 # endif
04627
04628 SectionInfo sectionInfo;
04629 Counts assertions;
04630 double durationInSeconds;
04631 bool missingAssertions;
04632 };
04633
04634 struct TestCaseStats {
04635 TestCaseStats( TestCaseInfo const& _testInfo,
04636 Totals const& _totals,
04637 std::string const& _stdOut,
04638 std::string const& _stdErr,
04639 bool _aborting )
04640 : testInfo( _testInfo ),
04641 totals( _totals ),
04642 stdOut( _stdOut ),
04643 stdErr( _stdErr ),
04644 aborting( _aborting )
04645 {}
04646 virtual ~TestCaseStats();
04647
04648 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
04649 TestCaseStats( TestCaseStats const& ) = default;
04650 TestCaseStats( TestCaseStats && ) = default;
04651 TestCaseStats& operator = ( TestCaseStats const& ) = default;
04652 TestCaseStats& operator = ( TestCaseStats && ) = default;
04653 # endif
04654
04655 TestCaseInfo testInfo;
04656 Totals totals;
04657 std::string stdOut;
04658 std::string stdErr;
04659 bool aborting;
04660 };
04661
04662 struct TestGroupStats {
04663 TestGroupStats( GroupInfo const& _groupInfo,
04664 Totals const& _totals,
04665 bool _aborting )
04666 : groupInfo( _groupInfo ),
04667 totals( _totals ),
04668 aborting( _aborting )
04669 {}
04670 TestGroupStats( GroupInfo const& _groupInfo )
04671 : groupInfo( _groupInfo ),
04672 aborting( false )
04673 {}
04674 virtual ~TestGroupStats();
04675
04676 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
04677 TestGroupStats( TestGroupStats const& ) = default;
04678 TestGroupStats( TestGroupStats && ) = default;
04679 TestGroupStats& operator = ( TestGroupStats const& ) = default;
04680 TestGroupStats& operator = ( TestGroupStats && ) = default;
04681 # endif
04682
04683 GroupInfo groupInfo;
04684 Totals totals;
04685 bool aborting;
04686 };
04687
04688 struct TestRunStats {
04689 TestRunStats( TestRunInfo const& _runInfo,
04690 Totals const& _totals,
04691 bool _aborting )
04692 : runInfo( _runInfo ),
04693 totals( _totals ),
04694 aborting( _aborting )
04695 {}
04696 virtual ~TestRunStats();
04697
04698 # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
04699 TestRunStats( TestRunStats const& _other )
04700 : runInfo( _other.runInfo ),
04701 totals( _other.totals ),
04702 aborting( _other.aborting )
04703 {}
04704 # else
04705 TestRunStats( TestRunStats const& ) = default;
04706 TestRunStats( TestRunStats && ) = default;
04707 TestRunStats& operator = ( TestRunStats const& ) = default;
04708 TestRunStats& operator = ( TestRunStats && ) = default;
04709 # endif
04710
04711 TestRunInfo runInfo;
04712 Totals totals;
04713 bool aborting;
04714 };
04715
04716 struct IStreamingReporter : IShared {
04717 virtual ~IStreamingReporter();
04718
04719
04720
04721
04722 virtual ReporterPreferences getPreferences() const = 0;
04723
04724 virtual void noMatchingTestCases( std::string const& spec ) = 0;
04725
04726 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
04727 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
04728
04729 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
04730 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
04731
04732 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
04733
04734
04735 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
04736 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
04737 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
04738 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
04739 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
04740
04741 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
04742 };
04743
04744 struct IReporterFactory {
04745 virtual ~IReporterFactory();
04746 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
04747 virtual std::string getDescription() const = 0;
04748 };
04749
04750 struct IReporterRegistry {
04751 typedef std::map<std::string, IReporterFactory*> FactoryMap;
04752
04753 virtual ~IReporterRegistry();
04754 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
04755 virtual FactoryMap const& getFactories() const = 0;
04756 };
04757
04758 }
04759
04760 #include <limits>
04761 #include <algorithm>
04762
04763 namespace Catch {
04764
04765 inline std::size_t listTests( Config const& config ) {
04766
04767 TestSpec testSpec = config.testSpec();
04768 if( config.testSpec().hasFilters() )
04769 Catch::cout() << "Matching test cases:\n";
04770 else {
04771 Catch::cout() << "All available test cases:\n";
04772 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
04773 }
04774
04775 std::size_t matchedTests = 0;
04776 TextAttributes nameAttr, tagsAttr;
04777 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
04778 tagsAttr.setIndent( 6 );
04779
04780 std::vector<TestCase> matchedTestCases;
04781 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
04782 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
04783 it != itEnd;
04784 ++it ) {
04785 matchedTests++;
04786 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
04787 Colour::Code colour = testCaseInfo.isHidden()
04788 ? Colour::SecondaryText
04789 : Colour::None;
04790 Colour colourGuard( colour );
04791
04792 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
04793 if( !testCaseInfo.tags.empty() )
04794 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
04795 }
04796
04797 if( !config.testSpec().hasFilters() )
04798 Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
04799 else
04800 Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
04801 return matchedTests;
04802 }
04803
04804 inline std::size_t listTestsNamesOnly( Config const& config ) {
04805 TestSpec testSpec = config.testSpec();
04806 if( !config.testSpec().hasFilters() )
04807 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
04808 std::size_t matchedTests = 0;
04809 std::vector<TestCase> matchedTestCases;
04810 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
04811 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
04812 it != itEnd;
04813 ++it ) {
04814 matchedTests++;
04815 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
04816 Catch::cout() << testCaseInfo.name << std::endl;
04817 }
04818 return matchedTests;
04819 }
04820
04821 struct TagInfo {
04822 TagInfo() : count ( 0 ) {}
04823 void add( std::string const& spelling ) {
04824 ++count;
04825 spellings.insert( spelling );
04826 }
04827 std::string all() const {
04828 std::string out;
04829 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
04830 it != itEnd;
04831 ++it )
04832 out += "[" + *it + "]";
04833 return out;
04834 }
04835 std::set<std::string> spellings;
04836 std::size_t count;
04837 };
04838
04839 inline std::size_t listTags( Config const& config ) {
04840 TestSpec testSpec = config.testSpec();
04841 if( config.testSpec().hasFilters() )
04842 Catch::cout() << "Tags for matching test cases:\n";
04843 else {
04844 Catch::cout() << "All available tags:\n";
04845 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
04846 }
04847
04848 std::map<std::string, TagInfo> tagCounts;
04849
04850 std::vector<TestCase> matchedTestCases;
04851 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
04852 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
04853 it != itEnd;
04854 ++it ) {
04855 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
04856 tagItEnd = it->getTestCaseInfo().tags.end();
04857 tagIt != tagItEnd;
04858 ++tagIt ) {
04859 std::string tagName = *tagIt;
04860 std::string lcaseTagName = toLower( tagName );
04861 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
04862 if( countIt == tagCounts.end() )
04863 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
04864 countIt->second.add( tagName );
04865 }
04866 }
04867
04868 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
04869 countItEnd = tagCounts.end();
04870 countIt != countItEnd;
04871 ++countIt ) {
04872 std::ostringstream oss;
04873 oss << " " << std::setw(2) << countIt->second.count << " ";
04874 Text wrapper( countIt->second.all(), TextAttributes()
04875 .setInitialIndent( 0 )
04876 .setIndent( oss.str().size() )
04877 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
04878 Catch::cout() << oss.str() << wrapper << "\n";
04879 }
04880 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
04881 return tagCounts.size();
04882 }
04883
04884 inline std::size_t listReporters( Config const& ) {
04885 Catch::cout() << "Available reporters:\n";
04886 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
04887 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
04888 std::size_t maxNameLen = 0;
04889 for(it = itBegin; it != itEnd; ++it )
04890 maxNameLen = (std::max)( maxNameLen, it->first.size() );
04891
04892 for(it = itBegin; it != itEnd; ++it ) {
04893 Text wrapper( it->second->getDescription(), TextAttributes()
04894 .setInitialIndent( 0 )
04895 .setIndent( 7+maxNameLen )
04896 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
04897 Catch::cout() << " "
04898 << it->first
04899 << ":"
04900 << std::string( maxNameLen - it->first.size() + 2, ' ' )
04901 << wrapper << "\n";
04902 }
04903 Catch::cout() << std::endl;
04904 return factories.size();
04905 }
04906
04907 inline Option<std::size_t> list( Config const& config ) {
04908 Option<std::size_t> listedCount;
04909 if( config.listTests() )
04910 listedCount = listedCount.valueOr(0) + listTests( config );
04911 if( config.listTestNamesOnly() )
04912 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
04913 if( config.listTags() )
04914 listedCount = listedCount.valueOr(0) + listTags( config );
04915 if( config.listReporters() )
04916 listedCount = listedCount.valueOr(0) + listReporters( config );
04917 return listedCount;
04918 }
04919
04920 }
04921
04922
04923 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
04924
04925
04926 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
04927
04928 #include <map>
04929 #include <string>
04930 #include <assert.h>
04931
04932 namespace Catch {
04933 namespace SectionTracking {
04934
04935 class TrackedSection {
04936
04937 typedef std::map<std::string, TrackedSection> TrackedSections;
04938
04939 public:
04940 enum RunState {
04941 NotStarted,
04942 Executing,
04943 ExecutingChildren,
04944 Completed
04945 };
04946
04947 TrackedSection( std::string const& name, TrackedSection* parent )
04948 : m_name( name ), m_runState( NotStarted ), m_parent( parent )
04949 {}
04950
04951 RunState runState() const { return m_runState; }
04952
04953 TrackedSection* findChild( std::string const& childName );
04954 TrackedSection* acquireChild( std::string const& childName );
04955
04956 void enter() {
04957 if( m_runState == NotStarted )
04958 m_runState = Executing;
04959 }
04960 void leave();
04961
04962 TrackedSection* getParent() {
04963 return m_parent;
04964 }
04965 bool hasChildren() const {
04966 return !m_children.empty();
04967 }
04968
04969 private:
04970 std::string m_name;
04971 RunState m_runState;
04972 TrackedSections m_children;
04973 TrackedSection* m_parent;
04974 };
04975
04976 inline TrackedSection* TrackedSection::findChild( std::string const& childName ) {
04977 TrackedSections::iterator it = m_children.find( childName );
04978 return it != m_children.end()
04979 ? &it->second
04980 : NULL;
04981 }
04982 inline TrackedSection* TrackedSection::acquireChild( std::string const& childName ) {
04983 if( TrackedSection* child = findChild( childName ) )
04984 return child;
04985 m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
04986 return findChild( childName );
04987 }
04988 inline void TrackedSection::leave() {
04989 for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
04990 it != itEnd;
04991 ++it )
04992 if( it->second.runState() != Completed ) {
04993 m_runState = ExecutingChildren;
04994 return;
04995 }
04996 m_runState = Completed;
04997 }
04998
04999 class TestCaseTracker {
05000 public:
05001 TestCaseTracker( std::string const& testCaseName )
05002 : m_testCase( testCaseName, NULL ),
05003 m_currentSection( &m_testCase ),
05004 m_completedASectionThisRun( false )
05005 {}
05006
05007 bool enterSection( std::string const& name ) {
05008 TrackedSection* child = m_currentSection->acquireChild( name );
05009 if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )
05010 return false;
05011
05012 m_currentSection = child;
05013 m_currentSection->enter();
05014 return true;
05015 }
05016 void leaveSection() {
05017 m_currentSection->leave();
05018 m_currentSection = m_currentSection->getParent();
05019 assert( m_currentSection != NULL );
05020 m_completedASectionThisRun = true;
05021 }
05022
05023 bool currentSectionHasChildren() const {
05024 return m_currentSection->hasChildren();
05025 }
05026 bool isCompleted() const {
05027 return m_testCase.runState() == TrackedSection::Completed;
05028 }
05029
05030 class Guard {
05031 public:
05032 Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {
05033 m_tracker.enterTestCase();
05034 }
05035 ~Guard() {
05036 m_tracker.leaveTestCase();
05037 }
05038 private:
05039 Guard( Guard const& );
05040 void operator = ( Guard const& );
05041 TestCaseTracker& m_tracker;
05042 };
05043
05044 private:
05045 void enterTestCase() {
05046 m_currentSection = &m_testCase;
05047 m_completedASectionThisRun = false;
05048 m_testCase.enter();
05049 }
05050 void leaveTestCase() {
05051 m_testCase.leave();
05052 }
05053
05054 TrackedSection m_testCase;
05055 TrackedSection* m_currentSection;
05056 bool m_completedASectionThisRun;
05057 };
05058
05059 }
05060
05061 using SectionTracking::TestCaseTracker;
05062
05063 }
05064
05065
05066 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
05067
05068 namespace Catch {
05069
05070
05071 inline void fatal( std::string const& message, int exitCode ) {
05072 IContext& context = Catch::getCurrentContext();
05073 IResultCapture* resultCapture = context.getResultCapture();
05074 resultCapture->handleFatalErrorCondition( message );
05075
05076 if( Catch::alwaysTrue() )
05077 exit( exitCode );
05078 }
05079
05080 }
05081
05082 #if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
05083
05084 namespace Catch {
05085
05086 struct FatalConditionHandler {
05087 void reset() {}
05088 };
05089
05090 }
05091
05092 #else // Not Windows - assumed to be POSIX compatible //////////////////////////
05093
05094 #include <signal.h>
05095
05096 namespace Catch {
05097
05098 struct SignalDefs { int id; const char* name; };
05099 extern SignalDefs signalDefs[];
05100 SignalDefs signalDefs[] = {
05101 { SIGINT, "SIGINT - Terminal interrupt signal" },
05102 { SIGILL, "SIGILL - Illegal instruction signal" },
05103 { SIGFPE, "SIGFPE - Floating point error signal" },
05104 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
05105 { SIGTERM, "SIGTERM - Termination request signal" },
05106 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
05107 };
05108
05109 struct FatalConditionHandler {
05110
05111 static void handleSignal( int sig ) {
05112 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
05113 if( sig == signalDefs[i].id )
05114 fatal( signalDefs[i].name, -sig );
05115 fatal( "<unknown signal>", -sig );
05116 }
05117
05118 FatalConditionHandler() : m_isSet( true ) {
05119 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
05120 signal( signalDefs[i].id, handleSignal );
05121 }
05122 ~FatalConditionHandler() {
05123 reset();
05124 }
05125 void reset() {
05126 if( m_isSet ) {
05127 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
05128 signal( signalDefs[i].id, SIG_DFL );
05129 m_isSet = false;
05130 }
05131 }
05132
05133 bool m_isSet;
05134 };
05135
05136 }
05137
05138 #endif // not Windows
05139
05140 #include <set>
05141 #include <string>
05142
05143 namespace Catch {
05144
05145 class StreamRedirect {
05146
05147 public:
05148 StreamRedirect( std::ostream& stream, std::string& targetString )
05149 : m_stream( stream ),
05150 m_prevBuf( stream.rdbuf() ),
05151 m_targetString( targetString )
05152 {
05153 stream.rdbuf( m_oss.rdbuf() );
05154 }
05155
05156 ~StreamRedirect() {
05157 m_targetString += m_oss.str();
05158 m_stream.rdbuf( m_prevBuf );
05159 }
05160
05161 private:
05162 std::ostream& m_stream;
05163 std::streambuf* m_prevBuf;
05164 std::ostringstream m_oss;
05165 std::string& m_targetString;
05166 };
05167
05169
05170 class RunContext : public IResultCapture, public IRunner {
05171
05172 RunContext( RunContext const& );
05173 void operator =( RunContext const& );
05174
05175 public:
05176
05177 explicit RunContext( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> const& reporter )
05178 : m_runInfo( config->name() ),
05179 m_context( getCurrentMutableContext() ),
05180 m_activeTestCase( NULL ),
05181 m_config( config ),
05182 m_reporter( reporter ),
05183 m_prevRunner( m_context.getRunner() ),
05184 m_prevResultCapture( m_context.getResultCapture() ),
05185 m_prevConfig( m_context.getConfig() )
05186 {
05187 m_context.setRunner( this );
05188 m_context.setConfig( m_config );
05189 m_context.setResultCapture( this );
05190 m_reporter->testRunStarting( m_runInfo );
05191 }
05192
05193 virtual ~RunContext() {
05194 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
05195 m_context.setRunner( m_prevRunner );
05196 m_context.setConfig( NULL );
05197 m_context.setResultCapture( m_prevResultCapture );
05198 m_context.setConfig( m_prevConfig );
05199 }
05200
05201 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
05202 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
05203 }
05204 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
05205 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
05206 }
05207
05208 Totals runTest( TestCase const& testCase ) {
05209 Totals prevTotals = m_totals;
05210
05211 std::string redirectedCout;
05212 std::string redirectedCerr;
05213
05214 TestCaseInfo testInfo = testCase.getTestCaseInfo();
05215
05216 m_reporter->testCaseStarting( testInfo );
05217
05218 m_activeTestCase = &testCase;
05219 m_testCaseTracker = TestCaseTracker( testInfo.name );
05220
05221 do {
05222 do {
05223 runCurrentTest( redirectedCout, redirectedCerr );
05224 }
05225 while( !m_testCaseTracker->isCompleted() && !aborting() );
05226 }
05227 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
05228
05229 Totals deltaTotals = m_totals.delta( prevTotals );
05230 m_totals.testCases += deltaTotals.testCases;
05231 m_reporter->testCaseEnded( TestCaseStats( testInfo,
05232 deltaTotals,
05233 redirectedCout,
05234 redirectedCerr,
05235 aborting() ) );
05236
05237 m_activeTestCase = NULL;
05238 m_testCaseTracker.reset();
05239
05240 return deltaTotals;
05241 }
05242
05243 Ptr<IConfig const> config() const {
05244 return m_config;
05245 }
05246
05247 private:
05248
05249 virtual void assertionEnded( AssertionResult const& result ) {
05250 if( result.getResultType() == ResultWas::Ok ) {
05251 m_totals.assertions.passed++;
05252 }
05253 else if( !result.isOk() ) {
05254 m_totals.assertions.failed++;
05255 }
05256
05257 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
05258 m_messages.clear();
05259
05260
05261 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
05262 m_lastResult = result;
05263 }
05264
05265 virtual bool sectionStarted (
05266 SectionInfo const& sectionInfo,
05267 Counts& assertions
05268 )
05269 {
05270 std::ostringstream oss;
05271 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
05272
05273 if( !m_testCaseTracker->enterSection( oss.str() ) )
05274 return false;
05275
05276 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
05277
05278 m_reporter->sectionStarting( sectionInfo );
05279
05280 assertions = m_totals.assertions;
05281
05282 return true;
05283 }
05284 bool testForMissingAssertions( Counts& assertions ) {
05285 if( assertions.total() != 0 ||
05286 !m_config->warnAboutMissingAssertions() ||
05287 m_testCaseTracker->currentSectionHasChildren() )
05288 return false;
05289 m_totals.assertions.failed++;
05290 assertions.failed++;
05291 return true;
05292 }
05293
05294 virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
05295 if( std::uncaught_exception() ) {
05296 m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
05297 return;
05298 }
05299
05300 Counts assertions = m_totals.assertions - prevAssertions;
05301 bool missingAssertions = testForMissingAssertions( assertions );
05302
05303 m_testCaseTracker->leaveSection();
05304
05305 m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
05306 m_messages.clear();
05307 }
05308
05309 virtual void pushScopedMessage( MessageInfo const& message ) {
05310 m_messages.push_back( message );
05311 }
05312
05313 virtual void popScopedMessage( MessageInfo const& message ) {
05314 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
05315 }
05316
05317 virtual std::string getCurrentTestName() const {
05318 return m_activeTestCase
05319 ? m_activeTestCase->getTestCaseInfo().name
05320 : "";
05321 }
05322
05323 virtual const AssertionResult* getLastResult() const {
05324 return &m_lastResult;
05325 }
05326
05327 virtual void handleFatalErrorCondition( std::string const& message ) {
05328 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
05329 resultBuilder.setResultType( ResultWas::FatalErrorCondition );
05330 resultBuilder << message;
05331 resultBuilder.captureExpression();
05332
05333 handleUnfinishedSections();
05334
05335
05336 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
05337 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
05338
05339 Counts assertions;
05340 assertions.failed = 1;
05341 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
05342 m_reporter->sectionEnded( testCaseSectionStats );
05343
05344 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
05345
05346 Totals deltaTotals;
05347 deltaTotals.testCases.failed = 1;
05348 m_reporter->testCaseEnded( TestCaseStats( testInfo,
05349 deltaTotals,
05350 "",
05351 "",
05352 false ) );
05353 m_totals.testCases.failed++;
05354 testGroupEnded( "", m_totals, 1, 1 );
05355 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
05356 }
05357
05358 public:
05359
05360 bool aborting() const {
05361 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
05362 }
05363
05364 private:
05365
05366 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
05367 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
05368 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
05369 m_reporter->sectionStarting( testCaseSection );
05370 Counts prevAssertions = m_totals.assertions;
05371 double duration = 0;
05372 try {
05373 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
05374 TestCaseTracker::Guard guard( *m_testCaseTracker );
05375
05376 Timer timer;
05377 timer.start();
05378 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
05379 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
05380 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
05381 invokeActiveTestCase();
05382 }
05383 else {
05384 invokeActiveTestCase();
05385 }
05386 duration = timer.getElapsedSeconds();
05387 }
05388 catch( TestFailureException& ) {
05389
05390 }
05391 catch(...) {
05392 makeUnexpectedResultBuilder().useActiveException();
05393 }
05394 handleUnfinishedSections();
05395 m_messages.clear();
05396
05397 Counts assertions = m_totals.assertions - prevAssertions;
05398 bool missingAssertions = testForMissingAssertions( assertions );
05399
05400 if( testCaseInfo.okToFail() ) {
05401 std::swap( assertions.failedButOk, assertions.failed );
05402 m_totals.assertions.failed -= assertions.failedButOk;
05403 m_totals.assertions.failedButOk += assertions.failedButOk;
05404 }
05405
05406 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
05407 m_reporter->sectionEnded( testCaseSectionStats );
05408 }
05409
05410 void invokeActiveTestCase() {
05411 FatalConditionHandler fatalConditionHandler;
05412 m_activeTestCase->invoke();
05413 fatalConditionHandler.reset();
05414 }
05415
05416 private:
05417
05418 ResultBuilder makeUnexpectedResultBuilder() const {
05419 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
05420 m_lastAssertionInfo.lineInfo,
05421 m_lastAssertionInfo.capturedExpression.c_str(),
05422 m_lastAssertionInfo.resultDisposition );
05423 }
05424
05425 void handleUnfinishedSections() {
05426
05427
05428 for( std::vector<UnfinishedSections>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
05429 itEnd = m_unfinishedSections.rend();
05430 it != itEnd;
05431 ++it )
05432 sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
05433 m_unfinishedSections.clear();
05434 }
05435
05436 struct UnfinishedSections {
05437 UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
05438 : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
05439 {}
05440
05441 SectionInfo info;
05442 Counts prevAssertions;
05443 double durationInSeconds;
05444 };
05445
05446 TestRunInfo m_runInfo;
05447 IMutableContext& m_context;
05448 TestCase const* m_activeTestCase;
05449 Option<TestCaseTracker> m_testCaseTracker;
05450 AssertionResult m_lastResult;
05451
05452 Ptr<IConfig const> m_config;
05453 Totals m_totals;
05454 Ptr<IStreamingReporter> m_reporter;
05455 std::vector<MessageInfo> m_messages;
05456 IRunner* m_prevRunner;
05457 IResultCapture* m_prevResultCapture;
05458 Ptr<IConfig const> m_prevConfig;
05459 AssertionInfo m_lastAssertionInfo;
05460 std::vector<UnfinishedSections> m_unfinishedSections;
05461 };
05462
05463 IResultCapture& getResultCapture() {
05464 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
05465 return *capture;
05466 else
05467 throw std::logic_error( "No result capture instance" );
05468 }
05469
05470 }
05471
05472
05473 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
05474
05475 namespace Catch {
05476
05477
05478 struct Version {
05479 Version( unsigned int _majorVersion,
05480 unsigned int _minorVersion,
05481 unsigned int _patchNumber,
05482 std::string const& _branchName,
05483 unsigned int _buildNumber );
05484
05485 unsigned int const majorVersion;
05486 unsigned int const minorVersion;
05487 unsigned int const patchNumber;
05488
05489
05490 std::string const branchName;
05491 unsigned int const buildNumber;
05492
05493 friend std::ostream& operator << ( std::ostream& os, Version const& version );
05494
05495 private:
05496 void operator=( Version const& );
05497 };
05498
05499 extern Version libraryVersion;
05500 }
05501
05502 #include <fstream>
05503 #include <stdlib.h>
05504 #include <limits>
05505
05506 namespace Catch {
05507
05508 class Runner {
05509
05510 public:
05511 Runner( Ptr<Config> const& config )
05512 : m_config( config )
05513 {
05514 openStream();
05515 makeReporter();
05516 }
05517
05518 Totals runTests() {
05519
05520 RunContext context( m_config.get(), m_reporter );
05521
05522 Totals totals;
05523
05524 context.testGroupStarting( "all tests", 1, 1 );
05525
05526 TestSpec testSpec = m_config->testSpec();
05527 if( !testSpec.hasFilters() )
05528 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec();
05529
05530 std::vector<TestCase> testCases;
05531 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases );
05532
05533 int testsRunForGroup = 0;
05534 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
05535 it != itEnd;
05536 ++it ) {
05537 testsRunForGroup++;
05538 if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
05539
05540 if( context.aborting() )
05541 break;
05542
05543 totals += context.runTest( *it );
05544 m_testsAlreadyRun.insert( *it );
05545 }
05546 }
05547 std::vector<TestCase> skippedTestCases;
05548 getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, skippedTestCases, true );
05549
05550 for( std::vector<TestCase>::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end();
05551 it != itEnd;
05552 ++it )
05553 m_reporter->skipTest( *it );
05554
05555 context.testGroupEnded( "all tests", totals, 1, 1 );
05556 return totals;
05557 }
05558
05559 private:
05560 void openStream() {
05561
05562 if( !m_config->getFilename().empty() ) {
05563 m_ofs.open( m_config->getFilename().c_str() );
05564 if( m_ofs.fail() ) {
05565 std::ostringstream oss;
05566 oss << "Unable to open file: '" << m_config->getFilename() << "'";
05567 throw std::domain_error( oss.str() );
05568 }
05569 m_config->setStreamBuf( m_ofs.rdbuf() );
05570 }
05571 }
05572 void makeReporter() {
05573 std::string reporterName = m_config->getReporterName().empty()
05574 ? "console"
05575 : m_config->getReporterName();
05576
05577 m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() );
05578 if( !m_reporter ) {
05579 std::ostringstream oss;
05580 oss << "No reporter registered with name: '" << reporterName << "'";
05581 throw std::domain_error( oss.str() );
05582 }
05583 }
05584
05585 private:
05586 Ptr<Config> m_config;
05587 std::ofstream m_ofs;
05588 Ptr<IStreamingReporter> m_reporter;
05589 std::set<TestCase> m_testsAlreadyRun;
05590 };
05591
05592 class Session : NonCopyable {
05593 static bool alreadyInstantiated;
05594
05595 public:
05596
05597 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
05598
05599 Session()
05600 : m_cli( makeCommandLineParser() ) {
05601 if( alreadyInstantiated ) {
05602 std::string msg = "Only one instance of Catch::Session can ever be used";
05603 Catch::cerr() << msg << std::endl;
05604 throw std::logic_error( msg );
05605 }
05606 alreadyInstantiated = true;
05607 }
05608 ~Session() {
05609 Catch::cleanUp();
05610 }
05611
05612 void showHelp( std::string const& processName ) {
05613 Catch::cout() << "\nCatch v" << libraryVersion << "\n";
05614
05615 m_cli.usage( Catch::cout(), processName );
05616 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
05617 }
05618
05619 int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
05620 try {
05621 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
05622 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
05623 if( m_configData.showHelp )
05624 showHelp( m_configData.processName );
05625 m_config.reset();
05626 }
05627 catch( std::exception& ex ) {
05628 {
05629 Colour colourGuard( Colour::Red );
05630 Catch::cerr()
05631 << "\nError(s) in input:\n"
05632 << Text( ex.what(), TextAttributes().setIndent(2) )
05633 << "\n\n";
05634 }
05635 m_cli.usage( Catch::cout(), m_configData.processName );
05636 return (std::numeric_limits<int>::max)();
05637 }
05638 return 0;
05639 }
05640
05641 void useConfigData( ConfigData const& _configData ) {
05642 m_configData = _configData;
05643 m_config.reset();
05644 }
05645
05646 int run( int argc, char* const argv[] ) {
05647
05648 int returnCode = applyCommandLine( argc, argv );
05649 if( returnCode == 0 )
05650 returnCode = run();
05651 return returnCode;
05652 }
05653
05654 int run() {
05655 if( m_configData.showHelp )
05656 return 0;
05657
05658 try
05659 {
05660 config();
05661
05662 std::srand( m_configData.rngSeed );
05663
05664 Runner runner( m_config );
05665
05666
05667 if( Option<std::size_t> listed = list( config() ) )
05668 return static_cast<int>( *listed );
05669
05670 return static_cast<int>( runner.runTests().assertions.failed );
05671 }
05672 catch( std::exception& ex ) {
05673 Catch::cerr() << ex.what() << std::endl;
05674 return (std::numeric_limits<int>::max)();
05675 }
05676 }
05677
05678 Clara::CommandLine<ConfigData> const& cli() const {
05679 return m_cli;
05680 }
05681 std::vector<Clara::Parser::Token> const& unusedTokens() const {
05682 return m_unusedTokens;
05683 }
05684 ConfigData& configData() {
05685 return m_configData;
05686 }
05687 Config& config() {
05688 if( !m_config )
05689 m_config = new Config( m_configData );
05690 return *m_config;
05691 }
05692
05693 private:
05694 Clara::CommandLine<ConfigData> m_cli;
05695 std::vector<Clara::Parser::Token> m_unusedTokens;
05696 ConfigData m_configData;
05697 Ptr<Config> m_config;
05698 };
05699
05700 bool Session::alreadyInstantiated = false;
05701
05702 }
05703
05704
05705 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
05706
05707
05708 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
05709
05710 #include <vector>
05711 #include <set>
05712 #include <sstream>
05713 #include <iostream>
05714 #include <algorithm>
05715
05716 namespace Catch {
05717
05718 class TestRegistry : public ITestCaseRegistry {
05719 struct LexSort {
05720 bool operator() (TestCase i,TestCase j) const { return (i<j);}
05721 };
05722 struct RandomNumberGenerator {
05723 int operator()( int n ) const { return std::rand() % n; }
05724 };
05725
05726 public:
05727 TestRegistry() : m_unnamedCount( 0 ) {}
05728 virtual ~TestRegistry();
05729
05730 virtual void registerTest( TestCase const& testCase ) {
05731 std::string name = testCase.getTestCaseInfo().name;
05732 if( name == "" ) {
05733 std::ostringstream oss;
05734 oss << "Anonymous test case " << ++m_unnamedCount;
05735 return registerTest( testCase.withName( oss.str() ) );
05736 }
05737
05738 if( m_functions.find( testCase ) == m_functions.end() ) {
05739 m_functions.insert( testCase );
05740 m_functionsInOrder.push_back( testCase );
05741 if( !testCase.isHidden() )
05742 m_nonHiddenFunctions.push_back( testCase );
05743 }
05744 else {
05745 TestCase const& prev = *m_functions.find( testCase );
05746 {
05747 Colour colourGuard( Colour::Red );
05748 Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
05749 << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
05750 << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
05751 }
05752 exit(1);
05753 }
05754 }
05755
05756 virtual std::vector<TestCase> const& getAllTests() const {
05757 return m_functionsInOrder;
05758 }
05759
05760 virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
05761 return m_nonHiddenFunctions;
05762 }
05763
05764 virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const {
05765
05766 for( std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(),
05767 itEnd = m_functionsInOrder.end();
05768 it != itEnd;
05769 ++it ) {
05770 bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() );
05771 if( includeTest != negated )
05772 matchingTestCases.push_back( *it );
05773 }
05774 sortTests( config, matchingTestCases );
05775 }
05776
05777 private:
05778
05779 static void sortTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) {
05780
05781 switch( config.runOrder() ) {
05782 case RunTests::InLexicographicalOrder:
05783 std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() );
05784 break;
05785 case RunTests::InRandomOrder:
05786 {
05787 RandomNumberGenerator rng;
05788 std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng );
05789 }
05790 break;
05791 case RunTests::InDeclarationOrder:
05792
05793 break;
05794 }
05795 }
05796 std::set<TestCase> m_functions;
05797 std::vector<TestCase> m_functionsInOrder;
05798 std::vector<TestCase> m_nonHiddenFunctions;
05799 size_t m_unnamedCount;
05800 };
05801
05803
05804 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
05805 public:
05806
05807 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
05808
05809 virtual void invoke() const {
05810 m_fun();
05811 }
05812
05813 private:
05814 virtual ~FreeFunctionTestCase();
05815
05816 TestFunction m_fun;
05817 };
05818
05819 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
05820 std::string className = classOrQualifiedMethodName;
05821 if( startsWith( className, "&" ) )
05822 {
05823 std::size_t lastColons = className.rfind( "::" );
05824 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
05825 if( penultimateColons == std::string::npos )
05826 penultimateColons = 1;
05827 className = className.substr( penultimateColons, lastColons-penultimateColons );
05828 }
05829 return className;
05830 }
05831
05833
05834 AutoReg::AutoReg( TestFunction function,
05835 SourceLineInfo const& lineInfo,
05836 NameAndDesc const& nameAndDesc ) {
05837 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
05838 }
05839
05840 AutoReg::~AutoReg() {}
05841
05842 void AutoReg::registerTestCase( ITestCase* testCase,
05843 char const* classOrQualifiedMethodName,
05844 NameAndDesc const& nameAndDesc,
05845 SourceLineInfo const& lineInfo ) {
05846
05847 getMutableRegistryHub().registerTest
05848 ( makeTestCase( testCase,
05849 extractClassName( classOrQualifiedMethodName ),
05850 nameAndDesc.name,
05851 nameAndDesc.description,
05852 lineInfo ) );
05853 }
05854
05855 }
05856
05857
05858 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
05859
05860 #include <map>
05861
05862 namespace Catch {
05863
05864 class ReporterRegistry : public IReporterRegistry {
05865
05866 public:
05867
05868 virtual ~ReporterRegistry() {
05869 deleteAllValues( m_factories );
05870 }
05871
05872 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const {
05873 FactoryMap::const_iterator it = m_factories.find( name );
05874 if( it == m_factories.end() )
05875 return NULL;
05876 return it->second->create( ReporterConfig( config ) );
05877 }
05878
05879 void registerReporter( std::string const& name, IReporterFactory* factory ) {
05880 m_factories.insert( std::make_pair( name, factory ) );
05881 }
05882
05883 FactoryMap const& getFactories() const {
05884 return m_factories;
05885 }
05886
05887 private:
05888 FactoryMap m_factories;
05889 };
05890 }
05891
05892
05893 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
05894
05895 #ifdef __OBJC__
05896 #import "Foundation/Foundation.h"
05897 #endif
05898
05899 namespace Catch {
05900
05901 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
05902 public:
05903 ~ExceptionTranslatorRegistry() {
05904 deleteAll( m_translators );
05905 }
05906
05907 virtual void registerTranslator( const IExceptionTranslator* translator ) {
05908 m_translators.push_back( translator );
05909 }
05910
05911 virtual std::string translateActiveException() const {
05912 try {
05913 #ifdef __OBJC__
05914
05915 @try {
05916 throw;
05917 }
05918 @catch (NSException *exception) {
05919 return Catch::toString( [exception description] );
05920 }
05921 #else
05922 throw;
05923 #endif
05924 }
05925 catch( TestFailureException& ) {
05926 throw;
05927 }
05928 catch( std::exception& ex ) {
05929 return ex.what();
05930 }
05931 catch( std::string& msg ) {
05932 return msg;
05933 }
05934 catch( const char* msg ) {
05935 return msg;
05936 }
05937 catch(...) {
05938 return tryTranslators( m_translators.begin() );
05939 }
05940 }
05941
05942 std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
05943 if( it == m_translators.end() )
05944 return "Unknown exception";
05945
05946 try {
05947 return (*it)->translate();
05948 }
05949 catch(...) {
05950 return tryTranslators( it+1 );
05951 }
05952 }
05953
05954 private:
05955 std::vector<const IExceptionTranslator*> m_translators;
05956 };
05957 }
05958
05959 namespace Catch {
05960
05961 namespace {
05962
05963 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
05964
05965 RegistryHub( RegistryHub const& );
05966 void operator=( RegistryHub const& );
05967
05968 public:
05969 RegistryHub() {
05970 }
05971 virtual IReporterRegistry const& getReporterRegistry() const {
05972 return m_reporterRegistry;
05973 }
05974 virtual ITestCaseRegistry const& getTestCaseRegistry() const {
05975 return m_testCaseRegistry;
05976 }
05977 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
05978 return m_exceptionTranslatorRegistry;
05979 }
05980
05981 public:
05982 virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
05983 m_reporterRegistry.registerReporter( name, factory );
05984 }
05985 virtual void registerTest( TestCase const& testInfo ) {
05986 m_testCaseRegistry.registerTest( testInfo );
05987 }
05988 virtual void registerTranslator( const IExceptionTranslator* translator ) {
05989 m_exceptionTranslatorRegistry.registerTranslator( translator );
05990 }
05991
05992 private:
05993 TestRegistry m_testCaseRegistry;
05994 ReporterRegistry m_reporterRegistry;
05995 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
05996 };
05997
05998
05999 inline RegistryHub*& getTheRegistryHub() {
06000 static RegistryHub* theRegistryHub = NULL;
06001 if( !theRegistryHub )
06002 theRegistryHub = new RegistryHub();
06003 return theRegistryHub;
06004 }
06005 }
06006
06007 IRegistryHub& getRegistryHub() {
06008 return *getTheRegistryHub();
06009 }
06010 IMutableRegistryHub& getMutableRegistryHub() {
06011 return *getTheRegistryHub();
06012 }
06013 void cleanUp() {
06014 delete getTheRegistryHub();
06015 getTheRegistryHub() = NULL;
06016 cleanUpContext();
06017 }
06018 std::string translateActiveException() {
06019 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
06020 }
06021
06022 }
06023
06024
06025 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
06026
06027 #include <ostream>
06028
06029 namespace Catch {
06030
06031 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
06032 : m_lineInfo( lineInfo ) {
06033 std::ostringstream oss;
06034 oss << lineInfo << ": function ";
06035 oss << "not implemented";
06036 m_what = oss.str();
06037 }
06038
06039 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
06040 return m_what.c_str();
06041 }
06042
06043 }
06044
06045
06046 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
06047
06048
06049 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
06050
06051
06052 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
06053
06054 #include <streambuf>
06055
06056 namespace Catch {
06057
06058 class StreamBufBase : public std::streambuf {
06059 public:
06060 virtual ~StreamBufBase() CATCH_NOEXCEPT;
06061 };
06062 }
06063
06064 #include <stdexcept>
06065 #include <cstdio>
06066 #include <iostream>
06067
06068 namespace Catch {
06069
06070 template<typename WriterF, size_t bufferSize=256>
06071 class StreamBufImpl : public StreamBufBase {
06072 char data[bufferSize];
06073 WriterF m_writer;
06074
06075 public:
06076 StreamBufImpl() {
06077 setp( data, data + sizeof(data) );
06078 }
06079
06080 ~StreamBufImpl() CATCH_NOEXCEPT {
06081 sync();
06082 }
06083
06084 private:
06085 int overflow( int c ) {
06086 sync();
06087
06088 if( c != EOF ) {
06089 if( pbase() == epptr() )
06090 m_writer( std::string( 1, static_cast<char>( c ) ) );
06091 else
06092 sputc( static_cast<char>( c ) );
06093 }
06094 return 0;
06095 }
06096
06097 int sync() {
06098 if( pbase() != pptr() ) {
06099 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
06100 setp( pbase(), epptr() );
06101 }
06102 return 0;
06103 }
06104 };
06105
06107
06108 struct OutputDebugWriter {
06109
06110 void operator()( std::string const&str ) {
06111 writeToDebugConsole( str );
06112 }
06113 };
06114
06115 Stream::Stream()
06116 : streamBuf( NULL ), isOwned( false )
06117 {}
06118
06119 Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
06120 : streamBuf( _streamBuf ), isOwned( _isOwned )
06121 {}
06122
06123 void Stream::release() {
06124 if( isOwned ) {
06125 delete streamBuf;
06126 streamBuf = NULL;
06127 isOwned = false;
06128 }
06129 }
06130
06131 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions
06132 std::ostream& cout() {
06133 return std::cout;
06134 }
06135 std::ostream& cerr() {
06136 return std::cerr;
06137 }
06138 #endif
06139 }
06140
06141 namespace Catch {
06142
06143 class Context : public IMutableContext {
06144
06145 Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
06146 Context( Context const& );
06147 void operator=( Context const& );
06148
06149 public:
06150 virtual IResultCapture* getResultCapture() {
06151 return m_resultCapture;
06152 }
06153 virtual IRunner* getRunner() {
06154 return m_runner;
06155 }
06156 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
06157 return getGeneratorsForCurrentTest()
06158 .getGeneratorInfo( fileInfo, totalSize )
06159 .getCurrentIndex();
06160 }
06161 virtual bool advanceGeneratorsForCurrentTest() {
06162 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
06163 return generators && generators->moveNext();
06164 }
06165
06166 virtual Ptr<IConfig const> getConfig() const {
06167 return m_config;
06168 }
06169
06170 public:
06171 virtual void setResultCapture( IResultCapture* resultCapture ) {
06172 m_resultCapture = resultCapture;
06173 }
06174 virtual void setRunner( IRunner* runner ) {
06175 m_runner = runner;
06176 }
06177 virtual void setConfig( Ptr<IConfig const> const& config ) {
06178 m_config = config;
06179 }
06180
06181 friend IMutableContext& getCurrentMutableContext();
06182
06183 private:
06184 IGeneratorsForTest* findGeneratorsForCurrentTest() {
06185 std::string testName = getResultCapture()->getCurrentTestName();
06186
06187 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
06188 m_generatorsByTestName.find( testName );
06189 return it != m_generatorsByTestName.end()
06190 ? it->second
06191 : NULL;
06192 }
06193
06194 IGeneratorsForTest& getGeneratorsForCurrentTest() {
06195 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
06196 if( !generators ) {
06197 std::string testName = getResultCapture()->getCurrentTestName();
06198 generators = createGeneratorsForTest();
06199 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
06200 }
06201 return *generators;
06202 }
06203
06204 private:
06205 Ptr<IConfig const> m_config;
06206 IRunner* m_runner;
06207 IResultCapture* m_resultCapture;
06208 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
06209 };
06210
06211 namespace {
06212 Context* currentContext = NULL;
06213 }
06214 IMutableContext& getCurrentMutableContext() {
06215 if( !currentContext )
06216 currentContext = new Context();
06217 return *currentContext;
06218 }
06219 IContext& getCurrentContext() {
06220 return getCurrentMutableContext();
06221 }
06222
06223 Stream createStream( std::string const& streamName ) {
06224 if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false );
06225 if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false );
06226 if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
06227
06228 throw std::domain_error( "Unknown stream: " + streamName );
06229 }
06230
06231 void cleanUpContext() {
06232 delete currentContext;
06233 currentContext = NULL;
06234 }
06235 }
06236
06237
06238 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
06239
06240 namespace Catch {
06241 namespace {
06242
06243 struct IColourImpl {
06244 virtual ~IColourImpl() {}
06245 virtual void use( Colour::Code _colourCode ) = 0;
06246 };
06247
06248 struct NoColourImpl : IColourImpl {
06249 void use( Colour::Code ) {}
06250
06251 static IColourImpl* instance() {
06252 static NoColourImpl s_instance;
06253 return &s_instance;
06254 }
06255 };
06256
06257 }
06258 }
06259
06260 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
06261 # ifdef CATCH_PLATFORM_WINDOWS
06262 # define CATCH_CONFIG_COLOUR_WINDOWS
06263 # else
06264 # define CATCH_CONFIG_COLOUR_ANSI
06265 # endif
06266 #endif
06267
06268 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
06269
06270 #ifndef NOMINMAX
06271 #define NOMINMAX
06272 #endif
06273
06274 #ifdef __AFXDLL
06275 #include <AfxWin.h>
06276 #else
06277 #include <windows.h>
06278 #endif
06279
06280 namespace Catch {
06281 namespace {
06282
06283 class Win32ColourImpl : public IColourImpl {
06284 public:
06285 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
06286 {
06287 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
06288 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
06289 originalAttributes = csbiInfo.wAttributes;
06290 }
06291
06292 virtual void use( Colour::Code _colourCode ) {
06293 switch( _colourCode ) {
06294 case Colour::None: return setTextAttribute( originalAttributes );
06295 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
06296 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
06297 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
06298 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
06299 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
06300 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
06301 case Colour::Grey: return setTextAttribute( 0 );
06302
06303 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
06304 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
06305 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
06306 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
06307
06308 case Colour::Bright: throw std::logic_error( "not a colour" );
06309 }
06310 }
06311
06312 private:
06313 void setTextAttribute( WORD _textAttribute ) {
06314 SetConsoleTextAttribute( stdoutHandle, _textAttribute );
06315 }
06316 HANDLE stdoutHandle;
06317 WORD originalAttributes;
06318 };
06319
06320 IColourImpl* platformColourInstance() {
06321 static Win32ColourImpl s_instance;
06322 return &s_instance;
06323 }
06324
06325 }
06326 }
06327
06328 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
06329
06330 #include <unistd.h>
06331
06332 namespace Catch {
06333 namespace {
06334
06335
06336
06337
06338
06339 class PosixColourImpl : public IColourImpl {
06340 public:
06341 virtual void use( Colour::Code _colourCode ) {
06342 switch( _colourCode ) {
06343 case Colour::None:
06344 case Colour::White: return setColour( "[0m" );
06345 case Colour::Red: return setColour( "[0;31m" );
06346 case Colour::Green: return setColour( "[0;32m" );
06347 case Colour::Blue: return setColour( "[0:34m" );
06348 case Colour::Cyan: return setColour( "[0;36m" );
06349 case Colour::Yellow: return setColour( "[0;33m" );
06350 case Colour::Grey: return setColour( "[1;30m" );
06351
06352 case Colour::LightGrey: return setColour( "[0;37m" );
06353 case Colour::BrightRed: return setColour( "[1;31m" );
06354 case Colour::BrightGreen: return setColour( "[1;32m" );
06355 case Colour::BrightWhite: return setColour( "[1;37m" );
06356
06357 case Colour::Bright: throw std::logic_error( "not a colour" );
06358 }
06359 }
06360 static IColourImpl* instance() {
06361 static PosixColourImpl s_instance;
06362 return &s_instance;
06363 }
06364
06365 private:
06366 void setColour( const char* _escapeCode ) {
06367 Catch::cout() << '\033' << _escapeCode;
06368 }
06369 };
06370
06371 IColourImpl* platformColourInstance() {
06372 Ptr<IConfig const> config = getCurrentContext().getConfig();
06373 return (config && config->forceColour()) || isatty(STDOUT_FILENO)
06374 ? PosixColourImpl::instance()
06375 : NoColourImpl::instance();
06376 }
06377
06378 }
06379 }
06380
06381 #else // not Windows or ANSI ///////////////////////////////////////////////
06382
06383 namespace Catch {
06384
06385 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
06386
06387 }
06388
06389 #endif // Windows/ ANSI/ None
06390
06391 namespace Catch {
06392
06393 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
06394 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
06395 Colour::~Colour(){ if( !m_moved ) use( None ); }
06396
06397 void Colour::use( Code _colourCode ) {
06398 static IColourImpl* impl = isDebuggerActive()
06399 ? NoColourImpl::instance()
06400 : platformColourInstance();
06401 impl->use( _colourCode );
06402 }
06403
06404 }
06405
06406
06407 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
06408
06409 #include <vector>
06410 #include <string>
06411 #include <map>
06412
06413 namespace Catch {
06414
06415 struct GeneratorInfo : IGeneratorInfo {
06416
06417 GeneratorInfo( std::size_t size )
06418 : m_size( size ),
06419 m_currentIndex( 0 )
06420 {}
06421
06422 bool moveNext() {
06423 if( ++m_currentIndex == m_size ) {
06424 m_currentIndex = 0;
06425 return false;
06426 }
06427 return true;
06428 }
06429
06430 std::size_t getCurrentIndex() const {
06431 return m_currentIndex;
06432 }
06433
06434 std::size_t m_size;
06435 std::size_t m_currentIndex;
06436 };
06437
06439
06440 class GeneratorsForTest : public IGeneratorsForTest {
06441
06442 public:
06443 ~GeneratorsForTest() {
06444 deleteAll( m_generatorsInOrder );
06445 }
06446
06447 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
06448 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
06449 if( it == m_generatorsByName.end() ) {
06450 IGeneratorInfo* info = new GeneratorInfo( size );
06451 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
06452 m_generatorsInOrder.push_back( info );
06453 return *info;
06454 }
06455 return *it->second;
06456 }
06457
06458 bool moveNext() {
06459 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
06460 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
06461 for(; it != itEnd; ++it ) {
06462 if( (*it)->moveNext() )
06463 return true;
06464 }
06465 return false;
06466 }
06467
06468 private:
06469 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
06470 std::vector<IGeneratorInfo*> m_generatorsInOrder;
06471 };
06472
06473 IGeneratorsForTest* createGeneratorsForTest()
06474 {
06475 return new GeneratorsForTest();
06476 }
06477
06478 }
06479
06480
06481 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
06482
06483 namespace Catch {
06484
06485 AssertionInfo::AssertionInfo( std::string const& _macroName,
06486 SourceLineInfo const& _lineInfo,
06487 std::string const& _capturedExpression,
06488 ResultDisposition::Flags _resultDisposition )
06489 : macroName( _macroName ),
06490 lineInfo( _lineInfo ),
06491 capturedExpression( _capturedExpression ),
06492 resultDisposition( _resultDisposition )
06493 {}
06494
06495 AssertionResult::AssertionResult() {}
06496
06497 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
06498 : m_info( info ),
06499 m_resultData( data )
06500 {}
06501
06502 AssertionResult::~AssertionResult() {}
06503
06504
06505 bool AssertionResult::succeeded() const {
06506 return Catch::isOk( m_resultData.resultType );
06507 }
06508
06509
06510 bool AssertionResult::isOk() const {
06511 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
06512 }
06513
06514 ResultWas::OfType AssertionResult::getResultType() const {
06515 return m_resultData.resultType;
06516 }
06517
06518 bool AssertionResult::hasExpression() const {
06519 return !m_info.capturedExpression.empty();
06520 }
06521
06522 bool AssertionResult::hasMessage() const {
06523 return !m_resultData.message.empty();
06524 }
06525
06526 std::string AssertionResult::getExpression() const {
06527 if( isFalseTest( m_info.resultDisposition ) )
06528 return "!" + m_info.capturedExpression;
06529 else
06530 return m_info.capturedExpression;
06531 }
06532 std::string AssertionResult::getExpressionInMacro() const {
06533 if( m_info.macroName.empty() )
06534 return m_info.capturedExpression;
06535 else
06536 return m_info.macroName + "( " + m_info.capturedExpression + " )";
06537 }
06538
06539 bool AssertionResult::hasExpandedExpression() const {
06540 return hasExpression() && getExpandedExpression() != getExpression();
06541 }
06542
06543 std::string AssertionResult::getExpandedExpression() const {
06544 return m_resultData.reconstructedExpression;
06545 }
06546
06547 std::string AssertionResult::getMessage() const {
06548 return m_resultData.message;
06549 }
06550 SourceLineInfo AssertionResult::getSourceInfo() const {
06551 return m_info.lineInfo;
06552 }
06553
06554 std::string AssertionResult::getTestMacroName() const {
06555 return m_info.macroName;
06556 }
06557
06558 }
06559
06560
06561 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
06562
06563 namespace Catch {
06564
06565 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
06566 if( startsWith( tag, "." ) ||
06567 tag == "hide" ||
06568 tag == "!hide" )
06569 return TestCaseInfo::IsHidden;
06570 else if( tag == "!throws" )
06571 return TestCaseInfo::Throws;
06572 else if( tag == "!shouldfail" )
06573 return TestCaseInfo::ShouldFail;
06574 else if( tag == "!mayfail" )
06575 return TestCaseInfo::MayFail;
06576 else
06577 return TestCaseInfo::None;
06578 }
06579 inline bool isReservedTag( std::string const& tag ) {
06580 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
06581 }
06582 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
06583 if( isReservedTag( tag ) ) {
06584 {
06585 Colour colourGuard( Colour::Red );
06586 Catch::cerr()
06587 << "Tag name [" << tag << "] not allowed.\n"
06588 << "Tag names starting with non alpha-numeric characters are reserved\n";
06589 }
06590 {
06591 Colour colourGuard( Colour::FileName );
06592 Catch::cerr() << _lineInfo << std::endl;
06593 }
06594 exit(1);
06595 }
06596 }
06597
06598 TestCase makeTestCase( ITestCase* _testCase,
06599 std::string const& _className,
06600 std::string const& _name,
06601 std::string const& _descOrTags,
06602 SourceLineInfo const& _lineInfo )
06603 {
06604 bool isHidden( startsWith( _name, "./" ) );
06605
06606
06607 std::set<std::string> tags;
06608 std::string desc, tag;
06609 bool inTag = false;
06610 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
06611 char c = _descOrTags[i];
06612 if( !inTag ) {
06613 if( c == '[' )
06614 inTag = true;
06615 else
06616 desc += c;
06617 }
06618 else {
06619 if( c == ']' ) {
06620 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
06621 if( prop == TestCaseInfo::IsHidden )
06622 isHidden = true;
06623 else if( prop == TestCaseInfo::None )
06624 enforceNotReservedTag( tag, _lineInfo );
06625
06626 tags.insert( tag );
06627 tag.clear();
06628 inTag = false;
06629 }
06630 else
06631 tag += c;
06632 }
06633 }
06634 if( isHidden ) {
06635 tags.insert( "hide" );
06636 tags.insert( "." );
06637 }
06638
06639 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
06640 return TestCase( _testCase, info );
06641 }
06642
06643 TestCaseInfo::TestCaseInfo( std::string const& _name,
06644 std::string const& _className,
06645 std::string const& _description,
06646 std::set<std::string> const& _tags,
06647 SourceLineInfo const& _lineInfo )
06648 : name( _name ),
06649 className( _className ),
06650 description( _description ),
06651 tags( _tags ),
06652 lineInfo( _lineInfo ),
06653 properties( None )
06654 {
06655 std::ostringstream oss;
06656 for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) {
06657 oss << "[" << *it << "]";
06658 std::string lcaseTag = toLower( *it );
06659 properties = static_cast<SpecialProperties>( properties | parseSpecialTag( lcaseTag ) );
06660 lcaseTags.insert( lcaseTag );
06661 }
06662 tagsAsString = oss.str();
06663 }
06664
06665 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
06666 : name( other.name ),
06667 className( other.className ),
06668 description( other.description ),
06669 tags( other.tags ),
06670 lcaseTags( other.lcaseTags ),
06671 tagsAsString( other.tagsAsString ),
06672 lineInfo( other.lineInfo ),
06673 properties( other.properties )
06674 {}
06675
06676 bool TestCaseInfo::isHidden() const {
06677 return ( properties & IsHidden ) != 0;
06678 }
06679 bool TestCaseInfo::throws() const {
06680 return ( properties & Throws ) != 0;
06681 }
06682 bool TestCaseInfo::okToFail() const {
06683 return ( properties & (ShouldFail | MayFail ) ) != 0;
06684 }
06685 bool TestCaseInfo::expectedToFail() const {
06686 return ( properties & (ShouldFail ) ) != 0;
06687 }
06688
06689 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
06690
06691 TestCase::TestCase( TestCase const& other )
06692 : TestCaseInfo( other ),
06693 test( other.test )
06694 {}
06695
06696 TestCase TestCase::withName( std::string const& _newName ) const {
06697 TestCase other( *this );
06698 other.name = _newName;
06699 return other;
06700 }
06701
06702 void TestCase::swap( TestCase& other ) {
06703 test.swap( other.test );
06704 name.swap( other.name );
06705 className.swap( other.className );
06706 description.swap( other.description );
06707 tags.swap( other.tags );
06708 lcaseTags.swap( other.lcaseTags );
06709 tagsAsString.swap( other.tagsAsString );
06710 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
06711 std::swap( lineInfo, other.lineInfo );
06712 }
06713
06714 void TestCase::invoke() const {
06715 test->invoke();
06716 }
06717
06718 bool TestCase::operator == ( TestCase const& other ) const {
06719 return test.get() == other.test.get() &&
06720 name == other.name &&
06721 className == other.className;
06722 }
06723
06724 bool TestCase::operator < ( TestCase const& other ) const {
06725 return name < other.name;
06726 }
06727 TestCase& TestCase::operator = ( TestCase const& other ) {
06728 TestCase temp( other );
06729 swap( temp );
06730 return *this;
06731 }
06732
06733 TestCaseInfo const& TestCase::getTestCaseInfo() const
06734 {
06735 return *this;
06736 }
06737
06738 }
06739
06740
06741 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
06742
06743 namespace Catch {
06744
06745 Version::Version
06746 ( unsigned int _majorVersion,
06747 unsigned int _minorVersion,
06748 unsigned int _patchNumber,
06749 std::string const& _branchName,
06750 unsigned int _buildNumber )
06751 : majorVersion( _majorVersion ),
06752 minorVersion( _minorVersion ),
06753 patchNumber( _patchNumber ),
06754 branchName( _branchName ),
06755 buildNumber( _buildNumber )
06756 {}
06757
06758 std::ostream& operator << ( std::ostream& os, Version const& version ) {
06759 os << version.majorVersion << "."
06760 << version.minorVersion << "."
06761 << version.patchNumber;
06762
06763 if( !version.branchName.empty() ) {
06764 os << "-" << version.branchName
06765 << "." << version.buildNumber;
06766 }
06767 return os;
06768 }
06769
06770 Version libraryVersion( 1, 2, 1, "", 0 );
06771
06772 }
06773
06774
06775 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
06776
06777 namespace Catch {
06778
06779 MessageInfo::MessageInfo( std::string const& _macroName,
06780 SourceLineInfo const& _lineInfo,
06781 ResultWas::OfType _type )
06782 : macroName( _macroName ),
06783 lineInfo( _lineInfo ),
06784 type( _type ),
06785 sequence( ++globalCount )
06786 {}
06787
06788
06789 unsigned int MessageInfo::globalCount = 0;
06790
06792
06793 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
06794 : m_info( builder.m_info )
06795 {
06796 m_info.message = builder.m_stream.str();
06797 getResultCapture().pushScopedMessage( m_info );
06798 }
06799 ScopedMessage::ScopedMessage( ScopedMessage const& other )
06800 : m_info( other.m_info )
06801 {}
06802
06803 ScopedMessage::~ScopedMessage() {
06804 getResultCapture().popScopedMessage( m_info );
06805 }
06806
06807 }
06808
06809
06810 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
06811
06812
06813 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
06814
06815 namespace Catch
06816 {
06817
06818 struct IReporter : IShared {
06819 virtual ~IReporter();
06820
06821 virtual bool shouldRedirectStdout() const = 0;
06822
06823 virtual void StartTesting() = 0;
06824 virtual void EndTesting( Totals const& totals ) = 0;
06825 virtual void StartGroup( std::string const& groupName ) = 0;
06826 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
06827 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
06828 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
06829 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
06830 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
06831 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
06832 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
06833 virtual void Aborted() = 0;
06834 virtual void Result( AssertionResult const& result ) = 0;
06835 };
06836
06837 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
06838 {
06839 public:
06840 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
06841 virtual ~LegacyReporterAdapter();
06842
06843 virtual ReporterPreferences getPreferences() const;
06844 virtual void noMatchingTestCases( std::string const& );
06845 virtual void testRunStarting( TestRunInfo const& );
06846 virtual void testGroupStarting( GroupInfo const& groupInfo );
06847 virtual void testCaseStarting( TestCaseInfo const& testInfo );
06848 virtual void sectionStarting( SectionInfo const& sectionInfo );
06849 virtual void assertionStarting( AssertionInfo const& );
06850 virtual bool assertionEnded( AssertionStats const& assertionStats );
06851 virtual void sectionEnded( SectionStats const& sectionStats );
06852 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
06853 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
06854 virtual void testRunEnded( TestRunStats const& testRunStats );
06855 virtual void skipTest( TestCaseInfo const& );
06856
06857 private:
06858 Ptr<IReporter> m_legacyReporter;
06859 };
06860 }
06861
06862 namespace Catch
06863 {
06864 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
06865 : m_legacyReporter( legacyReporter )
06866 {}
06867 LegacyReporterAdapter::~LegacyReporterAdapter() {}
06868
06869 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
06870 ReporterPreferences prefs;
06871 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
06872 return prefs;
06873 }
06874
06875 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
06876 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
06877 m_legacyReporter->StartTesting();
06878 }
06879 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
06880 m_legacyReporter->StartGroup( groupInfo.name );
06881 }
06882 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
06883 m_legacyReporter->StartTestCase( testInfo );
06884 }
06885 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
06886 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
06887 }
06888 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
06889
06890 }
06891
06892 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
06893 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
06894 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
06895 it != itEnd;
06896 ++it ) {
06897 if( it->type == ResultWas::Info ) {
06898 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
06899 rb << it->message;
06900 rb.setResultType( ResultWas::Info );
06901 AssertionResult result = rb.build();
06902 m_legacyReporter->Result( result );
06903 }
06904 }
06905 }
06906 m_legacyReporter->Result( assertionStats.assertionResult );
06907 return true;
06908 }
06909 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
06910 if( sectionStats.missingAssertions )
06911 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
06912 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
06913 }
06914 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
06915 m_legacyReporter->EndTestCase
06916 ( testCaseStats.testInfo,
06917 testCaseStats.totals,
06918 testCaseStats.stdOut,
06919 testCaseStats.stdErr );
06920 }
06921 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
06922 if( testGroupStats.aborting )
06923 m_legacyReporter->Aborted();
06924 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
06925 }
06926 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
06927 m_legacyReporter->EndTesting( testRunStats.totals );
06928 }
06929 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
06930 }
06931 }
06932
06933
06934
06935 #ifdef __clang__
06936 #pragma clang diagnostic push
06937 #pragma clang diagnostic ignored "-Wc++11-long-long"
06938 #endif
06939
06940 #ifdef CATCH_PLATFORM_WINDOWS
06941 #include <windows.h>
06942 #else
06943 #include <sys/time.h>
06944 #endif
06945
06946 namespace Catch {
06947
06948 namespace {
06949 #ifdef CATCH_PLATFORM_WINDOWS
06950 uint64_t getCurrentTicks() {
06951 static uint64_t hz=0, hzo=0;
06952 if (!hz) {
06953 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
06954 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
06955 }
06956 uint64_t t;
06957 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
06958 return ((t-hzo)*1000000)/hz;
06959 }
06960 #else
06961 uint64_t getCurrentTicks() {
06962 timeval t;
06963 gettimeofday(&t,NULL);
06964 return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
06965 }
06966 #endif
06967 }
06968
06969 void Timer::start() {
06970 m_ticks = getCurrentTicks();
06971 }
06972 unsigned int Timer::getElapsedMicroseconds() const {
06973 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
06974 }
06975 unsigned int Timer::getElapsedMilliseconds() const {
06976 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
06977 }
06978 double Timer::getElapsedSeconds() const {
06979 return getElapsedMicroseconds()/1000000.0;
06980 }
06981
06982 }
06983
06984 #ifdef __clang__
06985 #pragma clang diagnostic pop
06986 #endif
06987
06988 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
06989
06990 namespace Catch {
06991
06992 bool startsWith( std::string const& s, std::string const& prefix ) {
06993 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
06994 }
06995 bool endsWith( std::string const& s, std::string const& suffix ) {
06996 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
06997 }
06998 bool contains( std::string const& s, std::string const& infix ) {
06999 return s.find( infix ) != std::string::npos;
07000 }
07001 void toLowerInPlace( std::string& s ) {
07002 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
07003 }
07004 std::string toLower( std::string const& s ) {
07005 std::string lc = s;
07006 toLowerInPlace( lc );
07007 return lc;
07008 }
07009 std::string trim( std::string const& str ) {
07010 static char const* whitespaceChars = "\n\r\t ";
07011 std::string::size_type start = str.find_first_not_of( whitespaceChars );
07012 std::string::size_type end = str.find_last_not_of( whitespaceChars );
07013
07014 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
07015 }
07016
07017 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
07018 bool replaced = false;
07019 std::size_t i = str.find( replaceThis );
07020 while( i != std::string::npos ) {
07021 replaced = true;
07022 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
07023 if( i < str.size()-withThis.size() )
07024 i = str.find( replaceThis, i+withThis.size() );
07025 else
07026 i = std::string::npos;
07027 }
07028 return replaced;
07029 }
07030
07031 pluralise::pluralise( std::size_t count, std::string const& label )
07032 : m_count( count ),
07033 m_label( label )
07034 {}
07035
07036 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
07037 os << pluraliser.m_count << " " << pluraliser.m_label;
07038 if( pluraliser.m_count != 1 )
07039 os << "s";
07040 return os;
07041 }
07042
07043 SourceLineInfo::SourceLineInfo() : line( 0 ){}
07044 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
07045 : file( _file ),
07046 line( _line )
07047 {}
07048 SourceLineInfo::SourceLineInfo( SourceLineInfo const& other )
07049 : file( other.file ),
07050 line( other.line )
07051 {}
07052 bool SourceLineInfo::empty() const {
07053 return file.empty();
07054 }
07055 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
07056 return line == other.line && file == other.file;
07057 }
07058 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
07059 return line < other.line || ( line == other.line && file < other.file );
07060 }
07061
07062 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
07063 #ifndef __GNUG__
07064 os << info.file << "(" << info.line << ")";
07065 #else
07066 os << info.file << ":" << info.line;
07067 #endif
07068 return os;
07069 }
07070
07071 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
07072 std::ostringstream oss;
07073 oss << locationInfo << ": Internal Catch error: '" << message << "'";
07074 if( alwaysTrue() )
07075 throw std::logic_error( oss.str() );
07076 }
07077 }
07078
07079
07080 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
07081
07082 namespace Catch {
07083
07084 SectionInfo::SectionInfo
07085 ( SourceLineInfo const& _lineInfo,
07086 std::string const& _name,
07087 std::string const& _description )
07088 : name( _name ),
07089 description( _description ),
07090 lineInfo( _lineInfo )
07091 {}
07092
07093 Section::Section( SectionInfo const& info )
07094 : m_info( info ),
07095 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
07096 {
07097 m_timer.start();
07098 }
07099
07100 Section::~Section() {
07101 if( m_sectionIncluded )
07102 getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
07103 }
07104
07105
07106 Section::operator bool() const {
07107 return m_sectionIncluded;
07108 }
07109
07110 }
07111
07112
07113 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
07114
07115 #include <iostream>
07116
07117 #ifdef CATCH_PLATFORM_MAC
07118
07119 #include <assert.h>
07120 #include <stdbool.h>
07121 #include <sys/types.h>
07122 #include <unistd.h>
07123 #include <sys/sysctl.h>
07124
07125 namespace Catch{
07126
07127
07128
07129
07130
07131
07132 bool isDebuggerActive(){
07133
07134 int mib[4];
07135 struct kinfo_proc info;
07136 size_t size;
07137
07138
07139
07140
07141 info.kp_proc.p_flag = 0;
07142
07143
07144
07145
07146 mib[0] = CTL_KERN;
07147 mib[1] = KERN_PROC;
07148 mib[2] = KERN_PROC_PID;
07149 mib[3] = getpid();
07150
07151
07152
07153 size = sizeof(info);
07154 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) {
07155 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
07156 return false;
07157 }
07158
07159
07160
07161 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
07162 }
07163 }
07164
07165 #elif defined(_MSC_VER)
07166 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
07167 namespace Catch {
07168 bool isDebuggerActive() {
07169 return IsDebuggerPresent() != 0;
07170 }
07171 }
07172 #elif defined(__MINGW32__)
07173 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
07174 namespace Catch {
07175 bool isDebuggerActive() {
07176 return IsDebuggerPresent() != 0;
07177 }
07178 }
07179 #else
07180 namespace Catch {
07181 inline bool isDebuggerActive() { return false; }
07182 }
07183 #endif // Platform
07184
07185 #ifdef CATCH_PLATFORM_WINDOWS
07186 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
07187 namespace Catch {
07188 void writeToDebugConsole( std::string const& text ) {
07189 ::OutputDebugStringA( text.c_str() );
07190 }
07191 }
07192 #else
07193 namespace Catch {
07194 void writeToDebugConsole( std::string const& text ) {
07195
07196 Catch::cout() << text;
07197 }
07198 }
07199 #endif // Platform
07200
07201
07202 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
07203
07204 namespace Catch {
07205
07206 namespace Detail {
07207
07208 std::string unprintableString = "{?}";
07209
07210 namespace {
07211 struct Endianness {
07212 enum Arch { Big, Little };
07213
07214 static Arch which() {
07215 union _{
07216 int asInt;
07217 char asChar[sizeof (int)];
07218 } u;
07219
07220 u.asInt = 1;
07221 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
07222 }
07223 };
07224 }
07225
07226 std::string rawMemoryToString( const void *object, std::size_t size )
07227 {
07228
07229 int i = 0, end = static_cast<int>( size ), inc = 1;
07230 if( Endianness::which() == Endianness::Little ) {
07231 i = end-1;
07232 end = inc = -1;
07233 }
07234
07235 unsigned char const *bytes = static_cast<unsigned char const *>(object);
07236 std::ostringstream os;
07237 os << "0x" << std::setfill('0') << std::hex;
07238 for( ; i != end; i += inc )
07239 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
07240 return os.str();
07241 }
07242 }
07243
07244 std::string toString( std::string const& value ) {
07245 std::string s = value;
07246 if( getCurrentContext().getConfig()->showInvisibles() ) {
07247 for(size_t i = 0; i < s.size(); ++i ) {
07248 std::string subs;
07249 switch( s[i] ) {
07250 case '\n': subs = "\\n"; break;
07251 case '\t': subs = "\\t"; break;
07252 default: break;
07253 }
07254 if( !subs.empty() ) {
07255 s = s.substr( 0, i ) + subs + s.substr( i+1 );
07256 ++i;
07257 }
07258 }
07259 }
07260 return "\"" + s + "\"";
07261 }
07262 std::string toString( std::wstring const& value ) {
07263
07264 std::string s;
07265 s.reserve( value.size() );
07266 for(size_t i = 0; i < value.size(); ++i )
07267 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
07268 return Catch::toString( s );
07269 }
07270
07271 std::string toString( const char* const value ) {
07272 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
07273 }
07274
07275 std::string toString( char* const value ) {
07276 return Catch::toString( static_cast<const char*>( value ) );
07277 }
07278
07279 std::string toString( const wchar_t* const value )
07280 {
07281 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
07282 }
07283
07284 std::string toString( wchar_t* const value )
07285 {
07286 return Catch::toString( static_cast<const wchar_t*>( value ) );
07287 }
07288
07289 std::string toString( int value ) {
07290 std::ostringstream oss;
07291 oss << value;
07292 if( value >= 255 )
07293 oss << " (0x" << std::hex << value << ")";
07294 return oss.str();
07295 }
07296
07297 std::string toString( unsigned long value ) {
07298 std::ostringstream oss;
07299 oss << value;
07300 if( value >= 255 )
07301 oss << " (0x" << std::hex << value << ")";
07302 return oss.str();
07303 }
07304
07305 std::string toString( unsigned int value ) {
07306 return Catch::toString( static_cast<unsigned long>( value ) );
07307 }
07308
07309 template<typename T>
07310 std::string fpToString( T value, int precision ) {
07311 std::ostringstream oss;
07312 oss << std::setprecision( precision )
07313 << std::fixed
07314 << value;
07315 std::string d = oss.str();
07316 std::size_t i = d.find_last_not_of( '0' );
07317 if( i != std::string::npos && i != d.size()-1 ) {
07318 if( d[i] == '.' )
07319 i++;
07320 d = d.substr( 0, i+1 );
07321 }
07322 return d;
07323 }
07324
07325 std::string toString( const double value ) {
07326 return fpToString( value, 10 );
07327 }
07328 std::string toString( const float value ) {
07329 return fpToString( value, 5 ) + "f";
07330 }
07331
07332 std::string toString( bool value ) {
07333 return value ? "true" : "false";
07334 }
07335
07336 std::string toString( char value ) {
07337 return value < ' '
07338 ? toString( static_cast<unsigned int>( value ) )
07339 : Detail::makeString( value );
07340 }
07341
07342 std::string toString( signed char value ) {
07343 return toString( static_cast<char>( value ) );
07344 }
07345
07346 std::string toString( unsigned char value ) {
07347 return toString( static_cast<char>( value ) );
07348 }
07349
07350 #ifdef CATCH_CONFIG_CPP11_NULLPTR
07351 std::string toString( std::nullptr_t ) {
07352 return "nullptr";
07353 }
07354 #endif
07355
07356 #ifdef __OBJC__
07357 std::string toString( NSString const * const& nsstring ) {
07358 if( !nsstring )
07359 return "nil";
07360 return "@" + toString([nsstring UTF8String]);
07361 }
07362 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
07363 if( !nsstring )
07364 return "nil";
07365 return "@" + toString([nsstring UTF8String]);
07366 }
07367 std::string toString( NSObject* const& nsObject ) {
07368 return toString( [nsObject description] );
07369 }
07370 #endif
07371
07372 }
07373
07374
07375 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
07376
07377 namespace Catch {
07378
07379 ResultBuilder::ResultBuilder( char const* macroName,
07380 SourceLineInfo const& lineInfo,
07381 char const* capturedExpression,
07382 ResultDisposition::Flags resultDisposition )
07383 : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ),
07384 m_shouldDebugBreak( false ),
07385 m_shouldThrow( false )
07386 {}
07387
07388 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
07389 m_data.resultType = result;
07390 return *this;
07391 }
07392 ResultBuilder& ResultBuilder::setResultType( bool result ) {
07393 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
07394 return *this;
07395 }
07396 ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) {
07397 m_exprComponents.lhs = lhs;
07398 return *this;
07399 }
07400 ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) {
07401 m_exprComponents.rhs = rhs;
07402 return *this;
07403 }
07404 ResultBuilder& ResultBuilder::setOp( std::string const& op ) {
07405 m_exprComponents.op = op;
07406 return *this;
07407 }
07408
07409 void ResultBuilder::endExpression() {
07410 m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition );
07411 captureExpression();
07412 }
07413
07414 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
07415 m_assertionInfo.resultDisposition = resultDisposition;
07416 m_stream.oss << Catch::translateActiveException();
07417 captureResult( ResultWas::ThrewException );
07418 }
07419
07420 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
07421 setResultType( resultType );
07422 captureExpression();
07423 }
07424
07425 void ResultBuilder::captureExpression() {
07426 AssertionResult result = build();
07427 getResultCapture().assertionEnded( result );
07428
07429 if( !result.isOk() ) {
07430 if( getCurrentContext().getConfig()->shouldDebugBreak() )
07431 m_shouldDebugBreak = true;
07432 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
07433 m_shouldThrow = true;
07434 }
07435 }
07436 void ResultBuilder::react() {
07437 if( m_shouldThrow )
07438 throw Catch::TestFailureException();
07439 }
07440
07441 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
07442 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
07443
07444 AssertionResult ResultBuilder::build() const
07445 {
07446 assert( m_data.resultType != ResultWas::Unknown );
07447
07448 AssertionResultData data = m_data;
07449
07450
07451 if( m_exprComponents.testFalse ) {
07452 if( data.resultType == ResultWas::Ok )
07453 data.resultType = ResultWas::ExpressionFailed;
07454 else if( data.resultType == ResultWas::ExpressionFailed )
07455 data.resultType = ResultWas::Ok;
07456 }
07457
07458 data.message = m_stream.oss.str();
07459 data.reconstructedExpression = reconstructExpression();
07460 if( m_exprComponents.testFalse ) {
07461 if( m_exprComponents.op == "" )
07462 data.reconstructedExpression = "!" + data.reconstructedExpression;
07463 else
07464 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
07465 }
07466 return AssertionResult( m_assertionInfo, data );
07467 }
07468 std::string ResultBuilder::reconstructExpression() const {
07469 if( m_exprComponents.op == "" )
07470 return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
07471 else if( m_exprComponents.op == "matches" )
07472 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
07473 else if( m_exprComponents.op != "!" ) {
07474 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
07475 m_exprComponents.lhs.find("\n") == std::string::npos &&
07476 m_exprComponents.rhs.find("\n") == std::string::npos )
07477 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
07478 else
07479 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
07480 }
07481 else
07482 return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}";
07483 }
07484
07485 }
07486
07487
07488 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
07489
07490
07491 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
07492
07493 #include <map>
07494
07495 namespace Catch {
07496
07497 class TagAliasRegistry : public ITagAliasRegistry {
07498 public:
07499 virtual ~TagAliasRegistry();
07500 virtual Option<TagAlias> find( std::string const& alias ) const;
07501 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
07502 void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
07503 static TagAliasRegistry& get();
07504
07505 private:
07506 std::map<std::string, TagAlias> m_registry;
07507 };
07508
07509 }
07510
07511 #include <map>
07512 #include <iostream>
07513
07514 namespace Catch {
07515
07516 TagAliasRegistry::~TagAliasRegistry() {}
07517
07518 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
07519 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
07520 if( it != m_registry.end() )
07521 return it->second;
07522 else
07523 return Option<TagAlias>();
07524 }
07525
07526 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
07527 std::string expandedTestSpec = unexpandedTestSpec;
07528 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
07529 it != itEnd;
07530 ++it ) {
07531 std::size_t pos = expandedTestSpec.find( it->first );
07532 if( pos != std::string::npos ) {
07533 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
07534 it->second.tag +
07535 expandedTestSpec.substr( pos + it->first.size() );
07536 }
07537 }
07538 return expandedTestSpec;
07539 }
07540
07541 void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
07542
07543 if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) {
07544 std::ostringstream oss;
07545 oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
07546 throw std::domain_error( oss.str().c_str() );
07547 }
07548 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
07549 std::ostringstream oss;
07550 oss << "error: tag alias, \"" << alias << "\" already registered.\n"
07551 << "\tFirst seen at " << find(alias)->lineInfo << "\n"
07552 << "\tRedefined at " << lineInfo;
07553 throw std::domain_error( oss.str().c_str() );
07554 }
07555 }
07556
07557 TagAliasRegistry& TagAliasRegistry::get() {
07558 static TagAliasRegistry instance;
07559 return instance;
07560
07561 }
07562
07563 ITagAliasRegistry::~ITagAliasRegistry() {}
07564 ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); }
07565
07566 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
07567 try {
07568 TagAliasRegistry::get().add( alias, tag, lineInfo );
07569 }
07570 catch( std::exception& ex ) {
07571 Colour colourGuard( Colour::Red );
07572 Catch::cerr() << ex.what() << std::endl;
07573 exit(1);
07574 }
07575 }
07576
07577 }
07578
07579
07580 #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
07581
07582
07583 #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
07584
07585 #include <cstring>
07586
07587 namespace Catch {
07588
07589 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
07590
07591 StreamingReporterBase( ReporterConfig const& _config )
07592 : m_config( _config.fullConfig() ),
07593 stream( _config.stream() )
07594 {}
07595
07596 virtual ~StreamingReporterBase();
07597
07598 virtual void noMatchingTestCases( std::string const& ) {}
07599
07600 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
07601 currentTestRunInfo = _testRunInfo;
07602 }
07603 virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
07604 currentGroupInfo = _groupInfo;
07605 }
07606
07607 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
07608 currentTestCaseInfo = _testInfo;
07609 }
07610 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
07611 m_sectionStack.push_back( _sectionInfo );
07612 }
07613
07614 virtual void sectionEnded( SectionStats const& ) {
07615 m_sectionStack.pop_back();
07616 }
07617 virtual void testCaseEnded( TestCaseStats const& ) {
07618 currentTestCaseInfo.reset();
07619 }
07620 virtual void testGroupEnded( TestGroupStats const& ) {
07621 currentGroupInfo.reset();
07622 }
07623 virtual void testRunEnded( TestRunStats const& ) {
07624 currentTestCaseInfo.reset();
07625 currentGroupInfo.reset();
07626 currentTestRunInfo.reset();
07627 }
07628
07629 virtual void skipTest( TestCaseInfo const& ) {
07630
07631
07632 }
07633
07634 Ptr<IConfig> m_config;
07635 std::ostream& stream;
07636
07637 LazyStat<TestRunInfo> currentTestRunInfo;
07638 LazyStat<GroupInfo> currentGroupInfo;
07639 LazyStat<TestCaseInfo> currentTestCaseInfo;
07640
07641 std::vector<SectionInfo> m_sectionStack;
07642 };
07643
07644 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
07645 template<typename T, typename ChildNodeT>
07646 struct Node : SharedImpl<> {
07647 explicit Node( T const& _value ) : value( _value ) {}
07648 virtual ~Node() {}
07649
07650 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
07651 T value;
07652 ChildNodes children;
07653 };
07654 struct SectionNode : SharedImpl<> {
07655 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
07656 virtual ~SectionNode();
07657
07658 bool operator == ( SectionNode const& other ) const {
07659 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
07660 }
07661 bool operator == ( Ptr<SectionNode> const& other ) const {
07662 return operator==( *other );
07663 }
07664
07665 SectionStats stats;
07666 typedef std::vector<Ptr<SectionNode> > ChildSections;
07667 typedef std::vector<AssertionStats> Assertions;
07668 ChildSections childSections;
07669 Assertions assertions;
07670 std::string stdOut;
07671 std::string stdErr;
07672 };
07673
07674 struct BySectionInfo {
07675 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
07676 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
07677 bool operator() ( Ptr<SectionNode> const& node ) const {
07678 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
07679 }
07680 private:
07681 void operator=( BySectionInfo const& );
07682 SectionInfo const& m_other;
07683 };
07684
07685 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
07686 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
07687 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
07688
07689 CumulativeReporterBase( ReporterConfig const& _config )
07690 : m_config( _config.fullConfig() ),
07691 stream( _config.stream() )
07692 {}
07693 ~CumulativeReporterBase();
07694
07695 virtual void testRunStarting( TestRunInfo const& ) {}
07696 virtual void testGroupStarting( GroupInfo const& ) {}
07697
07698 virtual void testCaseStarting( TestCaseInfo const& ) {}
07699
07700 virtual void sectionStarting( SectionInfo const& sectionInfo ) {
07701 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
07702 Ptr<SectionNode> node;
07703 if( m_sectionStack.empty() ) {
07704 if( !m_rootSection )
07705 m_rootSection = new SectionNode( incompleteStats );
07706 node = m_rootSection;
07707 }
07708 else {
07709 SectionNode& parentNode = *m_sectionStack.back();
07710 SectionNode::ChildSections::const_iterator it =
07711 std::find_if( parentNode.childSections.begin(),
07712 parentNode.childSections.end(),
07713 BySectionInfo( sectionInfo ) );
07714 if( it == parentNode.childSections.end() ) {
07715 node = new SectionNode( incompleteStats );
07716 parentNode.childSections.push_back( node );
07717 }
07718 else
07719 node = *it;
07720 }
07721 m_sectionStack.push_back( node );
07722 m_deepestSection = node;
07723 }
07724
07725 virtual void assertionStarting( AssertionInfo const& ) {}
07726
07727 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
07728 assert( !m_sectionStack.empty() );
07729 SectionNode& sectionNode = *m_sectionStack.back();
07730 sectionNode.assertions.push_back( assertionStats );
07731 return true;
07732 }
07733 virtual void sectionEnded( SectionStats const& sectionStats ) {
07734 assert( !m_sectionStack.empty() );
07735 SectionNode& node = *m_sectionStack.back();
07736 node.stats = sectionStats;
07737 m_sectionStack.pop_back();
07738 }
07739 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
07740 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
07741 assert( m_sectionStack.size() == 0 );
07742 node->children.push_back( m_rootSection );
07743 m_testCases.push_back( node );
07744 m_rootSection.reset();
07745
07746 assert( m_deepestSection );
07747 m_deepestSection->stdOut = testCaseStats.stdOut;
07748 m_deepestSection->stdErr = testCaseStats.stdErr;
07749 }
07750 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
07751 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
07752 node->children.swap( m_testCases );
07753 m_testGroups.push_back( node );
07754 }
07755 virtual void testRunEnded( TestRunStats const& testRunStats ) {
07756 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
07757 node->children.swap( m_testGroups );
07758 m_testRuns.push_back( node );
07759 testRunEndedCumulative();
07760 }
07761 virtual void testRunEndedCumulative() = 0;
07762
07763 virtual void skipTest( TestCaseInfo const& ) {}
07764
07765 Ptr<IConfig> m_config;
07766 std::ostream& stream;
07767 std::vector<AssertionStats> m_assertions;
07768 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
07769 std::vector<Ptr<TestCaseNode> > m_testCases;
07770 std::vector<Ptr<TestGroupNode> > m_testGroups;
07771
07772 std::vector<Ptr<TestRunNode> > m_testRuns;
07773
07774 Ptr<SectionNode> m_rootSection;
07775 Ptr<SectionNode> m_deepestSection;
07776 std::vector<Ptr<SectionNode> > m_sectionStack;
07777
07778 };
07779
07780 template<char C>
07781 char const* getLineOfChars() {
07782 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
07783 if( !*line ) {
07784 memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
07785 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
07786 }
07787 return line;
07788 }
07789
07790 }
07791
07792
07793 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
07794
07795 namespace Catch {
07796
07797 template<typename T>
07798 class LegacyReporterRegistrar {
07799
07800 class ReporterFactory : public IReporterFactory {
07801 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
07802 return new LegacyReporterAdapter( new T( config ) );
07803 }
07804
07805 virtual std::string getDescription() const {
07806 return T::getDescription();
07807 }
07808 };
07809
07810 public:
07811
07812 LegacyReporterRegistrar( std::string const& name ) {
07813 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
07814 }
07815 };
07816
07817 template<typename T>
07818 class ReporterRegistrar {
07819
07820 class ReporterFactory : public IReporterFactory {
07821
07822
07823
07824
07825
07826
07827
07828
07829
07830
07831
07832
07833 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
07834 return new T( config );
07835 }
07836
07837 virtual std::string getDescription() const {
07838 return T::getDescription();
07839 }
07840 };
07841
07842 public:
07843
07844 ReporterRegistrar( std::string const& name ) {
07845 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
07846 }
07847 };
07848 }
07849
07850 #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
07851 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
07852 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
07853 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
07854
07855
07856 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
07857
07858 #include <sstream>
07859 #include <string>
07860 #include <vector>
07861
07862 namespace Catch {
07863
07864 class XmlWriter {
07865 public:
07866
07867 class ScopedElement {
07868 public:
07869 ScopedElement( XmlWriter* writer )
07870 : m_writer( writer )
07871 {}
07872
07873 ScopedElement( ScopedElement const& other )
07874 : m_writer( other.m_writer ){
07875 other.m_writer = NULL;
07876 }
07877
07878 ~ScopedElement() {
07879 if( m_writer )
07880 m_writer->endElement();
07881 }
07882
07883 ScopedElement& writeText( std::string const& text, bool indent = true ) {
07884 m_writer->writeText( text, indent );
07885 return *this;
07886 }
07887
07888 template<typename T>
07889 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
07890 m_writer->writeAttribute( name, attribute );
07891 return *this;
07892 }
07893
07894 private:
07895 mutable XmlWriter* m_writer;
07896 };
07897
07898 XmlWriter()
07899 : m_tagIsOpen( false ),
07900 m_needsNewline( false ),
07901 m_os( &Catch::cout() )
07902 {}
07903
07904 XmlWriter( std::ostream& os )
07905 : m_tagIsOpen( false ),
07906 m_needsNewline( false ),
07907 m_os( &os )
07908 {}
07909
07910 ~XmlWriter() {
07911 while( !m_tags.empty() )
07912 endElement();
07913 }
07914
07915 XmlWriter& startElement( std::string const& name ) {
07916 ensureTagClosed();
07917 newlineIfNecessary();
07918 stream() << m_indent << "<" << name;
07919 m_tags.push_back( name );
07920 m_indent += " ";
07921 m_tagIsOpen = true;
07922 return *this;
07923 }
07924
07925 ScopedElement scopedElement( std::string const& name ) {
07926 ScopedElement scoped( this );
07927 startElement( name );
07928 return scoped;
07929 }
07930
07931 XmlWriter& endElement() {
07932 newlineIfNecessary();
07933 m_indent = m_indent.substr( 0, m_indent.size()-2 );
07934 if( m_tagIsOpen ) {
07935 stream() << "/>\n";
07936 m_tagIsOpen = false;
07937 }
07938 else {
07939 stream() << m_indent << "</" << m_tags.back() << ">\n";
07940 }
07941 m_tags.pop_back();
07942 return *this;
07943 }
07944
07945 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
07946 if( !name.empty() && !attribute.empty() ) {
07947 stream() << " " << name << "=\"";
07948 writeEncodedText( attribute );
07949 stream() << "\"";
07950 }
07951 return *this;
07952 }
07953
07954 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
07955 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
07956 return *this;
07957 }
07958
07959 template<typename T>
07960 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
07961 if( !name.empty() )
07962 stream() << " " << name << "=\"" << attribute << "\"";
07963 return *this;
07964 }
07965
07966 XmlWriter& writeText( std::string const& text, bool indent = true ) {
07967 if( !text.empty() ){
07968 bool tagWasOpen = m_tagIsOpen;
07969 ensureTagClosed();
07970 if( tagWasOpen && indent )
07971 stream() << m_indent;
07972 writeEncodedText( text );
07973 m_needsNewline = true;
07974 }
07975 return *this;
07976 }
07977
07978 XmlWriter& writeComment( std::string const& text ) {
07979 ensureTagClosed();
07980 stream() << m_indent << "<!--" << text << "-->";
07981 m_needsNewline = true;
07982 return *this;
07983 }
07984
07985 XmlWriter& writeBlankLine() {
07986 ensureTagClosed();
07987 stream() << "\n";
07988 return *this;
07989 }
07990
07991 void setStream( std::ostream& os ) {
07992 m_os = &os;
07993 }
07994
07995 private:
07996 XmlWriter( XmlWriter const& );
07997 void operator=( XmlWriter const& );
07998
07999 std::ostream& stream() {
08000 return *m_os;
08001 }
08002
08003 void ensureTagClosed() {
08004 if( m_tagIsOpen ) {
08005 stream() << ">\n";
08006 m_tagIsOpen = false;
08007 }
08008 }
08009
08010 void newlineIfNecessary() {
08011 if( m_needsNewline ) {
08012 stream() << "\n";
08013 m_needsNewline = false;
08014 }
08015 }
08016
08017 void writeEncodedText( std::string const& text ) {
08018 static const char* charsToEncode = "<&\"";
08019 std::string mtext = text;
08020 std::string::size_type pos = mtext.find_first_of( charsToEncode );
08021 while( pos != std::string::npos ) {
08022 stream() << mtext.substr( 0, pos );
08023
08024 switch( mtext[pos] ) {
08025 case '<':
08026 stream() << "<";
08027 break;
08028 case '&':
08029 stream() << "&";
08030 break;
08031 case '\"':
08032 stream() << """;
08033 break;
08034 }
08035 mtext = mtext.substr( pos+1 );
08036 pos = mtext.find_first_of( charsToEncode );
08037 }
08038 stream() << mtext;
08039 }
08040
08041 bool m_tagIsOpen;
08042 bool m_needsNewline;
08043 std::vector<std::string> m_tags;
08044 std::string m_indent;
08045 std::ostream* m_os;
08046 };
08047
08048 }
08049 namespace Catch {
08050 class XmlReporter : public StreamingReporterBase {
08051 public:
08052 XmlReporter( ReporterConfig const& _config )
08053 : StreamingReporterBase( _config ),
08054 m_sectionDepth( 0 )
08055 {}
08056
08057 virtual ~XmlReporter();
08058
08059 static std::string getDescription() {
08060 return "Reports test results as an XML document";
08061 }
08062
08063 public:
08064 virtual ReporterPreferences getPreferences() const {
08065 ReporterPreferences prefs;
08066 prefs.shouldRedirectStdOut = true;
08067 return prefs;
08068 }
08069
08070 virtual void noMatchingTestCases( std::string const& s ) {
08071 StreamingReporterBase::noMatchingTestCases( s );
08072 }
08073
08074 virtual void testRunStarting( TestRunInfo const& testInfo ) {
08075 StreamingReporterBase::testRunStarting( testInfo );
08076 m_xml.setStream( stream );
08077 m_xml.startElement( "Catch" );
08078 if( !m_config->name().empty() )
08079 m_xml.writeAttribute( "name", m_config->name() );
08080 }
08081
08082 virtual void testGroupStarting( GroupInfo const& groupInfo ) {
08083 StreamingReporterBase::testGroupStarting( groupInfo );
08084 m_xml.startElement( "Group" )
08085 .writeAttribute( "name", groupInfo.name );
08086 }
08087
08088 virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
08089 StreamingReporterBase::testCaseStarting(testInfo);
08090 m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
08091
08092 if ( m_config->showDurations() == ShowDurations::Always )
08093 m_testCaseTimer.start();
08094 }
08095
08096 virtual void sectionStarting( SectionInfo const& sectionInfo ) {
08097 StreamingReporterBase::sectionStarting( sectionInfo );
08098 if( m_sectionDepth++ > 0 ) {
08099 m_xml.startElement( "Section" )
08100 .writeAttribute( "name", trim( sectionInfo.name ) )
08101 .writeAttribute( "description", sectionInfo.description );
08102 }
08103 }
08104
08105 virtual void assertionStarting( AssertionInfo const& ) { }
08106
08107 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
08108 const AssertionResult& assertionResult = assertionStats.assertionResult;
08109
08110
08111 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
08112 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
08113 it != itEnd;
08114 ++it ) {
08115 if( it->type == ResultWas::Info ) {
08116 m_xml.scopedElement( "Info" )
08117 .writeText( it->message );
08118 } else if ( it->type == ResultWas::Warning ) {
08119 m_xml.scopedElement( "Warning" )
08120 .writeText( it->message );
08121 }
08122 }
08123 }
08124
08125
08126 if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
08127 return true;
08128
08129
08130 if( assertionResult.hasExpression() ) {
08131 m_xml.startElement( "Expression" )
08132 .writeAttribute( "success", assertionResult.succeeded() )
08133 .writeAttribute( "type", assertionResult.getTestMacroName() )
08134 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
08135 .writeAttribute( "line", assertionResult.getSourceInfo().line );
08136
08137 m_xml.scopedElement( "Original" )
08138 .writeText( assertionResult.getExpression() );
08139 m_xml.scopedElement( "Expanded" )
08140 .writeText( assertionResult.getExpandedExpression() );
08141 }
08142
08143
08144 switch( assertionResult.getResultType() ) {
08145 case ResultWas::ThrewException:
08146 m_xml.scopedElement( "Exception" )
08147 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
08148 .writeAttribute( "line", assertionResult.getSourceInfo().line )
08149 .writeText( assertionResult.getMessage() );
08150 break;
08151 case ResultWas::FatalErrorCondition:
08152 m_xml.scopedElement( "Fatal Error Condition" )
08153 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
08154 .writeAttribute( "line", assertionResult.getSourceInfo().line )
08155 .writeText( assertionResult.getMessage() );
08156 break;
08157 case ResultWas::Info:
08158 m_xml.scopedElement( "Info" )
08159 .writeText( assertionResult.getMessage() );
08160 break;
08161 case ResultWas::Warning:
08162
08163 break;
08164 case ResultWas::ExplicitFailure:
08165 m_xml.scopedElement( "Failure" )
08166 .writeText( assertionResult.getMessage() );
08167 break;
08168 default:
08169 break;
08170 }
08171
08172 if( assertionResult.hasExpression() )
08173 m_xml.endElement();
08174
08175 return true;
08176 }
08177
08178 virtual void sectionEnded( SectionStats const& sectionStats ) {
08179 StreamingReporterBase::sectionEnded( sectionStats );
08180 if( --m_sectionDepth > 0 ) {
08181 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
08182 e.writeAttribute( "successes", sectionStats.assertions.passed );
08183 e.writeAttribute( "failures", sectionStats.assertions.failed );
08184 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
08185
08186 if ( m_config->showDurations() == ShowDurations::Always )
08187 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
08188
08189 m_xml.endElement();
08190 }
08191 }
08192
08193 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
08194 StreamingReporterBase::testCaseEnded( testCaseStats );
08195 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
08196 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
08197
08198 if ( m_config->showDurations() == ShowDurations::Always )
08199 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
08200
08201 m_xml.endElement();
08202 }
08203
08204 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
08205 StreamingReporterBase::testGroupEnded( testGroupStats );
08206
08207 m_xml.scopedElement( "OverallResults" )
08208 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
08209 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
08210 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
08211 m_xml.endElement();
08212 }
08213
08214 virtual void testRunEnded( TestRunStats const& testRunStats ) {
08215 StreamingReporterBase::testRunEnded( testRunStats );
08216 m_xml.scopedElement( "OverallResults" )
08217 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
08218 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
08219 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
08220 m_xml.endElement();
08221 }
08222
08223 private:
08224 Timer m_testCaseTimer;
08225 XmlWriter m_xml;
08226 int m_sectionDepth;
08227 };
08228
08229 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
08230
08231 }
08232
08233
08234 #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
08235
08236 #include <assert.h>
08237
08238 namespace Catch {
08239
08240 class JunitReporter : public CumulativeReporterBase {
08241 public:
08242 JunitReporter( ReporterConfig const& _config )
08243 : CumulativeReporterBase( _config ),
08244 xml( _config.stream() )
08245 {}
08246
08247 ~JunitReporter();
08248
08249 static std::string getDescription() {
08250 return "Reports test results in an XML format that looks like Ant's junitreport target";
08251 }
08252
08253 virtual void noMatchingTestCases( std::string const& ) {}
08254
08255 virtual ReporterPreferences getPreferences() const {
08256 ReporterPreferences prefs;
08257 prefs.shouldRedirectStdOut = true;
08258 return prefs;
08259 }
08260
08261 virtual void testRunStarting( TestRunInfo const& runInfo ) {
08262 CumulativeReporterBase::testRunStarting( runInfo );
08263 xml.startElement( "testsuites" );
08264 }
08265
08266 virtual void testGroupStarting( GroupInfo const& groupInfo ) {
08267 suiteTimer.start();
08268 stdOutForSuite.str("");
08269 stdErrForSuite.str("");
08270 unexpectedExceptions = 0;
08271 CumulativeReporterBase::testGroupStarting( groupInfo );
08272 }
08273
08274 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
08275 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
08276 unexpectedExceptions++;
08277 return CumulativeReporterBase::assertionEnded( assertionStats );
08278 }
08279
08280 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
08281 stdOutForSuite << testCaseStats.stdOut;
08282 stdErrForSuite << testCaseStats.stdErr;
08283 CumulativeReporterBase::testCaseEnded( testCaseStats );
08284 }
08285
08286 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
08287 double suiteTime = suiteTimer.getElapsedSeconds();
08288 CumulativeReporterBase::testGroupEnded( testGroupStats );
08289 writeGroup( *m_testGroups.back(), suiteTime );
08290 }
08291
08292 virtual void testRunEndedCumulative() {
08293 xml.endElement();
08294 }
08295
08296 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
08297 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
08298 TestGroupStats const& stats = groupNode.value;
08299 xml.writeAttribute( "name", stats.groupInfo.name );
08300 xml.writeAttribute( "errors", unexpectedExceptions );
08301 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
08302 xml.writeAttribute( "tests", stats.totals.assertions.total() );
08303 xml.writeAttribute( "hostname", "tbd" );
08304 if( m_config->showDurations() == ShowDurations::Never )
08305 xml.writeAttribute( "time", "" );
08306 else
08307 xml.writeAttribute( "time", suiteTime );
08308 xml.writeAttribute( "timestamp", "tbd" );
08309
08310
08311 for( TestGroupNode::ChildNodes::const_iterator
08312 it = groupNode.children.begin(), itEnd = groupNode.children.end();
08313 it != itEnd;
08314 ++it )
08315 writeTestCase( **it );
08316
08317 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
08318 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
08319 }
08320
08321 void writeTestCase( TestCaseNode const& testCaseNode ) {
08322 TestCaseStats const& stats = testCaseNode.value;
08323
08324
08325
08326 assert( testCaseNode.children.size() == 1 );
08327 SectionNode const& rootSection = *testCaseNode.children.front();
08328
08329 std::string className = stats.testInfo.className;
08330
08331 if( className.empty() ) {
08332 if( rootSection.childSections.empty() )
08333 className = "global";
08334 }
08335 writeSection( className, "", rootSection );
08336 }
08337
08338 void writeSection( std::string const& className,
08339 std::string const& rootName,
08340 SectionNode const& sectionNode ) {
08341 std::string name = trim( sectionNode.stats.sectionInfo.name );
08342 if( !rootName.empty() )
08343 name = rootName + "/" + name;
08344
08345 if( !sectionNode.assertions.empty() ||
08346 !sectionNode.stdOut.empty() ||
08347 !sectionNode.stdErr.empty() ) {
08348 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
08349 if( className.empty() ) {
08350 xml.writeAttribute( "classname", name );
08351 xml.writeAttribute( "name", "root" );
08352 }
08353 else {
08354 xml.writeAttribute( "classname", className );
08355 xml.writeAttribute( "name", name );
08356 }
08357 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
08358
08359 writeAssertions( sectionNode );
08360
08361 if( !sectionNode.stdOut.empty() )
08362 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
08363 if( !sectionNode.stdErr.empty() )
08364 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
08365 }
08366 for( SectionNode::ChildSections::const_iterator
08367 it = sectionNode.childSections.begin(),
08368 itEnd = sectionNode.childSections.end();
08369 it != itEnd;
08370 ++it )
08371 if( className.empty() )
08372 writeSection( name, "", **it );
08373 else
08374 writeSection( className, name, **it );
08375 }
08376
08377 void writeAssertions( SectionNode const& sectionNode ) {
08378 for( SectionNode::Assertions::const_iterator
08379 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
08380 it != itEnd;
08381 ++it )
08382 writeAssertion( *it );
08383 }
08384 void writeAssertion( AssertionStats const& stats ) {
08385 AssertionResult const& result = stats.assertionResult;
08386 if( !result.isOk() ) {
08387 std::string elementName;
08388 switch( result.getResultType() ) {
08389 case ResultWas::ThrewException:
08390 case ResultWas::FatalErrorCondition:
08391 elementName = "error";
08392 break;
08393 case ResultWas::ExplicitFailure:
08394 elementName = "failure";
08395 break;
08396 case ResultWas::ExpressionFailed:
08397 elementName = "failure";
08398 break;
08399 case ResultWas::DidntThrowException:
08400 elementName = "failure";
08401 break;
08402
08403
08404 case ResultWas::Info:
08405 case ResultWas::Warning:
08406 case ResultWas::Ok:
08407 case ResultWas::Unknown:
08408 case ResultWas::FailureBit:
08409 case ResultWas::Exception:
08410 elementName = "internalError";
08411 break;
08412 }
08413
08414 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
08415
08416 xml.writeAttribute( "message", result.getExpandedExpression() );
08417 xml.writeAttribute( "type", result.getTestMacroName() );
08418
08419 std::ostringstream oss;
08420 if( !result.getMessage().empty() )
08421 oss << result.getMessage() << "\n";
08422 for( std::vector<MessageInfo>::const_iterator
08423 it = stats.infoMessages.begin(),
08424 itEnd = stats.infoMessages.end();
08425 it != itEnd;
08426 ++it )
08427 if( it->type == ResultWas::Info )
08428 oss << it->message << "\n";
08429
08430 oss << "at " << result.getSourceInfo();
08431 xml.writeText( oss.str(), false );
08432 }
08433 }
08434
08435 XmlWriter xml;
08436 Timer suiteTimer;
08437 std::ostringstream stdOutForSuite;
08438 std::ostringstream stdErrForSuite;
08439 unsigned int unexpectedExceptions;
08440 };
08441
08442 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
08443
08444 }
08445
08446
08447 #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
08448
08449 namespace Catch {
08450
08451 struct ConsoleReporter : StreamingReporterBase {
08452 ConsoleReporter( ReporterConfig const& _config )
08453 : StreamingReporterBase( _config ),
08454 m_headerPrinted( false )
08455 {}
08456
08457 virtual ~ConsoleReporter();
08458 static std::string getDescription() {
08459 return "Reports test results as plain lines of text";
08460 }
08461 virtual ReporterPreferences getPreferences() const {
08462 ReporterPreferences prefs;
08463 prefs.shouldRedirectStdOut = false;
08464 return prefs;
08465 }
08466
08467 virtual void noMatchingTestCases( std::string const& spec ) {
08468 stream << "No test cases matched '" << spec << "'" << std::endl;
08469 }
08470
08471 virtual void assertionStarting( AssertionInfo const& ) {
08472 }
08473
08474 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
08475 AssertionResult const& result = _assertionStats.assertionResult;
08476
08477 bool printInfoMessages = true;
08478
08479
08480 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
08481 if( result.getResultType() != ResultWas::Warning )
08482 return false;
08483 printInfoMessages = false;
08484 }
08485
08486 lazyPrint();
08487
08488 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
08489 printer.print();
08490 stream << std::endl;
08491 return true;
08492 }
08493
08494 virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
08495 m_headerPrinted = false;
08496 StreamingReporterBase::sectionStarting( _sectionInfo );
08497 }
08498 virtual void sectionEnded( SectionStats const& _sectionStats ) {
08499 if( _sectionStats.missingAssertions ) {
08500 lazyPrint();
08501 Colour colour( Colour::ResultError );
08502 if( m_sectionStack.size() > 1 )
08503 stream << "\nNo assertions in section";
08504 else
08505 stream << "\nNo assertions in test case";
08506 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
08507 }
08508 if( m_headerPrinted ) {
08509 if( m_config->showDurations() == ShowDurations::Always )
08510 stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
08511 m_headerPrinted = false;
08512 }
08513 else {
08514 if( m_config->showDurations() == ShowDurations::Always )
08515 stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
08516 }
08517 StreamingReporterBase::sectionEnded( _sectionStats );
08518 }
08519
08520 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) {
08521 StreamingReporterBase::testCaseEnded( _testCaseStats );
08522 m_headerPrinted = false;
08523 }
08524 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) {
08525 if( currentGroupInfo.used ) {
08526 printSummaryDivider();
08527 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
08528 printTotals( _testGroupStats.totals );
08529 stream << "\n" << std::endl;
08530 }
08531 StreamingReporterBase::testGroupEnded( _testGroupStats );
08532 }
08533 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
08534 printTotalsDivider( _testRunStats.totals );
08535 printTotals( _testRunStats.totals );
08536 stream << std::endl;
08537 StreamingReporterBase::testRunEnded( _testRunStats );
08538 }
08539
08540 private:
08541
08542 class AssertionPrinter {
08543 void operator= ( AssertionPrinter const& );
08544 public:
08545 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
08546 : stream( _stream ),
08547 stats( _stats ),
08548 result( _stats.assertionResult ),
08549 colour( Colour::None ),
08550 message( result.getMessage() ),
08551 messages( _stats.infoMessages ),
08552 printInfoMessages( _printInfoMessages )
08553 {
08554 switch( result.getResultType() ) {
08555 case ResultWas::Ok:
08556 colour = Colour::Success;
08557 passOrFail = "PASSED";
08558
08559 if( _stats.infoMessages.size() == 1 )
08560 messageLabel = "with message";
08561 if( _stats.infoMessages.size() > 1 )
08562 messageLabel = "with messages";
08563 break;
08564 case ResultWas::ExpressionFailed:
08565 if( result.isOk() ) {
08566 colour = Colour::Success;
08567 passOrFail = "FAILED - but was ok";
08568 }
08569 else {
08570 colour = Colour::Error;
08571 passOrFail = "FAILED";
08572 }
08573 if( _stats.infoMessages.size() == 1 )
08574 messageLabel = "with message";
08575 if( _stats.infoMessages.size() > 1 )
08576 messageLabel = "with messages";
08577 break;
08578 case ResultWas::ThrewException:
08579 colour = Colour::Error;
08580 passOrFail = "FAILED";
08581 messageLabel = "due to unexpected exception with message";
08582 break;
08583 case ResultWas::FatalErrorCondition:
08584 colour = Colour::Error;
08585 passOrFail = "FAILED";
08586 messageLabel = "due to a fatal error condition";
08587 break;
08588 case ResultWas::DidntThrowException:
08589 colour = Colour::Error;
08590 passOrFail = "FAILED";
08591 messageLabel = "because no exception was thrown where one was expected";
08592 break;
08593 case ResultWas::Info:
08594 messageLabel = "info";
08595 break;
08596 case ResultWas::Warning:
08597 messageLabel = "warning";
08598 break;
08599 case ResultWas::ExplicitFailure:
08600 passOrFail = "FAILED";
08601 colour = Colour::Error;
08602 if( _stats.infoMessages.size() == 1 )
08603 messageLabel = "explicitly with message";
08604 if( _stats.infoMessages.size() > 1 )
08605 messageLabel = "explicitly with messages";
08606 break;
08607
08608 case ResultWas::Unknown:
08609 case ResultWas::FailureBit:
08610 case ResultWas::Exception:
08611 passOrFail = "** internal error **";
08612 colour = Colour::Error;
08613 break;
08614 }
08615 }
08616
08617 void print() const {
08618 printSourceInfo();
08619 if( stats.totals.assertions.total() > 0 ) {
08620 if( result.isOk() )
08621 stream << "\n";
08622 printResultType();
08623 printOriginalExpression();
08624 printReconstructedExpression();
08625 }
08626 else {
08627 stream << "\n";
08628 }
08629 printMessage();
08630 }
08631
08632 private:
08633 void printResultType() const {
08634 if( !passOrFail.empty() ) {
08635 Colour colourGuard( colour );
08636 stream << passOrFail << ":\n";
08637 }
08638 }
08639 void printOriginalExpression() const {
08640 if( result.hasExpression() ) {
08641 Colour colourGuard( Colour::OriginalExpression );
08642 stream << " ";
08643 stream << result.getExpressionInMacro();
08644 stream << "\n";
08645 }
08646 }
08647 void printReconstructedExpression() const {
08648 if( result.hasExpandedExpression() ) {
08649 stream << "with expansion:\n";
08650 Colour colourGuard( Colour::ReconstructedExpression );
08651 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n";
08652 }
08653 }
08654 void printMessage() const {
08655 if( !messageLabel.empty() )
08656 stream << messageLabel << ":" << "\n";
08657 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
08658 it != itEnd;
08659 ++it ) {
08660
08661 if( printInfoMessages || it->type != ResultWas::Info )
08662 stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
08663 }
08664 }
08665 void printSourceInfo() const {
08666 Colour colourGuard( Colour::FileName );
08667 stream << result.getSourceInfo() << ": ";
08668 }
08669
08670 std::ostream& stream;
08671 AssertionStats const& stats;
08672 AssertionResult const& result;
08673 Colour::Code colour;
08674 std::string passOrFail;
08675 std::string messageLabel;
08676 std::string message;
08677 std::vector<MessageInfo> messages;
08678 bool printInfoMessages;
08679 };
08680
08681 void lazyPrint() {
08682
08683 if( !currentTestRunInfo.used )
08684 lazyPrintRunInfo();
08685 if( !currentGroupInfo.used )
08686 lazyPrintGroupInfo();
08687
08688 if( !m_headerPrinted ) {
08689 printTestCaseAndSectionHeader();
08690 m_headerPrinted = true;
08691 }
08692 }
08693 void lazyPrintRunInfo() {
08694 stream << "\n" << getLineOfChars<'~'>() << "\n";
08695 Colour colour( Colour::SecondaryText );
08696 stream << currentTestRunInfo->name
08697 << " is a Catch v" << libraryVersion << " host application.\n"
08698 << "Run with -? for options\n\n";
08699
08700 if( m_config->rngSeed() != 0 )
08701 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
08702
08703 currentTestRunInfo.used = true;
08704 }
08705 void lazyPrintGroupInfo() {
08706 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
08707 printClosedHeader( "Group: " + currentGroupInfo->name );
08708 currentGroupInfo.used = true;
08709 }
08710 }
08711 void printTestCaseAndSectionHeader() {
08712 assert( !m_sectionStack.empty() );
08713 printOpenHeader( currentTestCaseInfo->name );
08714
08715 if( m_sectionStack.size() > 1 ) {
08716 Colour colourGuard( Colour::Headers );
08717
08718 std::vector<SectionInfo>::const_iterator
08719 it = m_sectionStack.begin()+1,
08720 itEnd = m_sectionStack.end();
08721 for( ; it != itEnd; ++it )
08722 printHeaderString( it->name, 2 );
08723 }
08724
08725 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
08726
08727 if( !lineInfo.empty() ){
08728 stream << getLineOfChars<'-'>() << "\n";
08729 Colour colourGuard( Colour::FileName );
08730 stream << lineInfo << "\n";
08731 }
08732 stream << getLineOfChars<'.'>() << "\n" << std::endl;
08733 }
08734
08735 void printClosedHeader( std::string const& _name ) {
08736 printOpenHeader( _name );
08737 stream << getLineOfChars<'.'>() << "\n";
08738 }
08739 void printOpenHeader( std::string const& _name ) {
08740 stream << getLineOfChars<'-'>() << "\n";
08741 {
08742 Colour colourGuard( Colour::Headers );
08743 printHeaderString( _name );
08744 }
08745 }
08746
08747
08748
08749 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
08750 std::size_t i = _string.find( ": " );
08751 if( i != std::string::npos )
08752 i+=2;
08753 else
08754 i = 0;
08755 stream << Text( _string, TextAttributes()
08756 .setIndent( indent+i)
08757 .setInitialIndent( indent ) ) << "\n";
08758 }
08759
08760 struct SummaryColumn {
08761
08762 SummaryColumn( std::string const& _label, Colour::Code _colour )
08763 : label( _label ),
08764 colour( _colour )
08765 {}
08766 SummaryColumn addRow( std::size_t count ) {
08767 std::ostringstream oss;
08768 oss << count;
08769 std::string row = oss.str();
08770 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
08771 while( it->size() < row.size() )
08772 *it = " " + *it;
08773 while( it->size() > row.size() )
08774 row = " " + row;
08775 }
08776 rows.push_back( row );
08777 return *this;
08778 }
08779
08780 std::string label;
08781 Colour::Code colour;
08782 std::vector<std::string> rows;
08783
08784 };
08785
08786 void printTotals( Totals const& totals ) {
08787 if( totals.testCases.total() == 0 ) {
08788 stream << Colour( Colour::Warning ) << "No tests ran\n";
08789 }
08790 else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) {
08791 stream << Colour( Colour::ResultSuccess ) << "All tests passed";
08792 stream << " ("
08793 << pluralise( totals.assertions.passed, "assertion" ) << " in "
08794 << pluralise( totals.testCases.passed, "test case" ) << ")"
08795 << "\n";
08796 }
08797 else {
08798
08799 std::vector<SummaryColumn> columns;
08800 columns.push_back( SummaryColumn( "", Colour::None )
08801 .addRow( totals.testCases.total() )
08802 .addRow( totals.assertions.total() ) );
08803 columns.push_back( SummaryColumn( "passed", Colour::Success )
08804 .addRow( totals.testCases.passed )
08805 .addRow( totals.assertions.passed ) );
08806 columns.push_back( SummaryColumn( "failed", Colour::ResultError )
08807 .addRow( totals.testCases.failed )
08808 .addRow( totals.assertions.failed ) );
08809 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
08810 .addRow( totals.testCases.failedButOk )
08811 .addRow( totals.assertions.failedButOk ) );
08812
08813 printSummaryRow( "test cases", columns, 0 );
08814 printSummaryRow( "assertions", columns, 1 );
08815 }
08816 }
08817 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
08818 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
08819 std::string value = it->rows[row];
08820 if( it->label.empty() ) {
08821 stream << label << ": ";
08822 if( value != "0" )
08823 stream << value;
08824 else
08825 stream << Colour( Colour::Warning ) << "- none -";
08826 }
08827 else if( value != "0" ) {
08828 stream << Colour( Colour::LightGrey ) << " | ";
08829 stream << Colour( it->colour )
08830 << value << " " << it->label;
08831 }
08832 }
08833 stream << "\n";
08834 }
08835
08836 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
08837 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
08838 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
08839 }
08840 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
08841 if( i > j && i > k )
08842 return i;
08843 else if( j > k )
08844 return j;
08845 else
08846 return k;
08847 }
08848
08849 void printTotalsDivider( Totals const& totals ) {
08850 if( totals.testCases.total() > 0 ) {
08851 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
08852 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
08853 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
08854 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
08855 findMax( failedRatio, failedButOkRatio, passedRatio )++;
08856 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
08857 findMax( failedRatio, failedButOkRatio, passedRatio )--;
08858
08859 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
08860 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
08861 if( totals.testCases.allPassed() )
08862 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
08863 else
08864 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
08865 }
08866 else {
08867 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
08868 }
08869 stream << "\n";
08870 }
08871 void printSummaryDivider() {
08872 stream << getLineOfChars<'-'>() << "\n";
08873 }
08874
08875 private:
08876 bool m_headerPrinted;
08877 };
08878
08879 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
08880
08881 }
08882
08883
08884 #define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
08885
08886 namespace Catch {
08887
08888 struct CompactReporter : StreamingReporterBase {
08889
08890 CompactReporter( ReporterConfig const& _config )
08891 : StreamingReporterBase( _config )
08892 {}
08893
08894 virtual ~CompactReporter();
08895
08896 static std::string getDescription() {
08897 return "Reports test results on a single line, suitable for IDEs";
08898 }
08899
08900 virtual ReporterPreferences getPreferences() const {
08901 ReporterPreferences prefs;
08902 prefs.shouldRedirectStdOut = false;
08903 return prefs;
08904 }
08905
08906 virtual void noMatchingTestCases( std::string const& spec ) {
08907 stream << "No test cases matched '" << spec << "'" << std::endl;
08908 }
08909
08910 virtual void assertionStarting( AssertionInfo const& ) {
08911 }
08912
08913 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
08914 AssertionResult const& result = _assertionStats.assertionResult;
08915
08916 bool printInfoMessages = true;
08917
08918
08919 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
08920 if( result.getResultType() != ResultWas::Warning )
08921 return false;
08922 printInfoMessages = false;
08923 }
08924
08925 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
08926 printer.print();
08927
08928 stream << std::endl;
08929 return true;
08930 }
08931
08932 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
08933 printTotals( _testRunStats.totals );
08934 stream << "\n" << std::endl;
08935 StreamingReporterBase::testRunEnded( _testRunStats );
08936 }
08937
08938 private:
08939 class AssertionPrinter {
08940 void operator= ( AssertionPrinter const& );
08941 public:
08942 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
08943 : stream( _stream )
08944 , stats( _stats )
08945 , result( _stats.assertionResult )
08946 , messages( _stats.infoMessages )
08947 , itMessage( _stats.infoMessages.begin() )
08948 , printInfoMessages( _printInfoMessages )
08949 {}
08950
08951 void print() {
08952 printSourceInfo();
08953
08954 itMessage = messages.begin();
08955
08956 switch( result.getResultType() ) {
08957 case ResultWas::Ok:
08958 printResultType( Colour::ResultSuccess, passedString() );
08959 printOriginalExpression();
08960 printReconstructedExpression();
08961 if ( ! result.hasExpression() )
08962 printRemainingMessages( Colour::None );
08963 else
08964 printRemainingMessages();
08965 break;
08966 case ResultWas::ExpressionFailed:
08967 if( result.isOk() )
08968 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
08969 else
08970 printResultType( Colour::Error, failedString() );
08971 printOriginalExpression();
08972 printReconstructedExpression();
08973 printRemainingMessages();
08974 break;
08975 case ResultWas::ThrewException:
08976 printResultType( Colour::Error, failedString() );
08977 printIssue( "unexpected exception with message:" );
08978 printMessage();
08979 printExpressionWas();
08980 printRemainingMessages();
08981 break;
08982 case ResultWas::FatalErrorCondition:
08983 printResultType( Colour::Error, failedString() );
08984 printIssue( "fatal error condition with message:" );
08985 printMessage();
08986 printExpressionWas();
08987 printRemainingMessages();
08988 break;
08989 case ResultWas::DidntThrowException:
08990 printResultType( Colour::Error, failedString() );
08991 printIssue( "expected exception, got none" );
08992 printExpressionWas();
08993 printRemainingMessages();
08994 break;
08995 case ResultWas::Info:
08996 printResultType( Colour::None, "info" );
08997 printMessage();
08998 printRemainingMessages();
08999 break;
09000 case ResultWas::Warning:
09001 printResultType( Colour::None, "warning" );
09002 printMessage();
09003 printRemainingMessages();
09004 break;
09005 case ResultWas::ExplicitFailure:
09006 printResultType( Colour::Error, failedString() );
09007 printIssue( "explicitly" );
09008 printRemainingMessages( Colour::None );
09009 break;
09010
09011 case ResultWas::Unknown:
09012 case ResultWas::FailureBit:
09013 case ResultWas::Exception:
09014 printResultType( Colour::Error, "** internal error **" );
09015 break;
09016 }
09017 }
09018
09019 private:
09020
09021
09022 static Colour::Code dimColour() { return Colour::FileName; }
09023
09024 #ifdef CATCH_PLATFORM_MAC
09025 static const char* failedString() { return "FAILED"; }
09026 static const char* passedString() { return "PASSED"; }
09027 #else
09028 static const char* failedString() { return "failed"; }
09029 static const char* passedString() { return "passed"; }
09030 #endif
09031
09032 void printSourceInfo() const {
09033 Colour colourGuard( Colour::FileName );
09034 stream << result.getSourceInfo() << ":";
09035 }
09036
09037 void printResultType( Colour::Code colour, std::string passOrFail ) const {
09038 if( !passOrFail.empty() ) {
09039 {
09040 Colour colourGuard( colour );
09041 stream << " " << passOrFail;
09042 }
09043 stream << ":";
09044 }
09045 }
09046
09047 void printIssue( std::string issue ) const {
09048 stream << " " << issue;
09049 }
09050
09051 void printExpressionWas() {
09052 if( result.hasExpression() ) {
09053 stream << ";";
09054 {
09055 Colour colour( dimColour() );
09056 stream << " expression was:";
09057 }
09058 printOriginalExpression();
09059 }
09060 }
09061
09062 void printOriginalExpression() const {
09063 if( result.hasExpression() ) {
09064 stream << " " << result.getExpression();
09065 }
09066 }
09067
09068 void printReconstructedExpression() const {
09069 if( result.hasExpandedExpression() ) {
09070 {
09071 Colour colour( dimColour() );
09072 stream << " for: ";
09073 }
09074 stream << result.getExpandedExpression();
09075 }
09076 }
09077
09078 void printMessage() {
09079 if ( itMessage != messages.end() ) {
09080 stream << " '" << itMessage->message << "'";
09081 ++itMessage;
09082 }
09083 }
09084
09085 void printRemainingMessages( Colour::Code colour = dimColour() ) {
09086 if ( itMessage == messages.end() )
09087 return;
09088
09089
09090 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
09091 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
09092
09093 {
09094 Colour colourGuard( colour );
09095 stream << " with " << pluralise( N, "message" ) << ":";
09096 }
09097
09098 for(; itMessage != itEnd; ) {
09099
09100 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
09101 stream << " '" << itMessage->message << "'";
09102 if ( ++itMessage != itEnd ) {
09103 Colour colourGuard( dimColour() );
09104 stream << " and";
09105 }
09106 }
09107 }
09108 }
09109
09110 private:
09111 std::ostream& stream;
09112 AssertionStats const& stats;
09113 AssertionResult const& result;
09114 std::vector<MessageInfo> messages;
09115 std::vector<MessageInfo>::const_iterator itMessage;
09116 bool printInfoMessages;
09117 };
09118
09119
09120
09121
09122
09123
09124
09125
09126 std::string bothOrAll( std::size_t count ) const {
09127 return count == 1 ? "" : count == 2 ? "both " : "all " ;
09128 }
09129
09130 void printTotals( const Totals& totals ) const {
09131 if( totals.testCases.total() == 0 ) {
09132 stream << "No tests ran.";
09133 }
09134 else if( totals.testCases.failed == totals.testCases.total() ) {
09135 Colour colour( Colour::ResultError );
09136 const std::string qualify_assertions_failed =
09137 totals.assertions.failed == totals.assertions.total() ?
09138 bothOrAll( totals.assertions.failed ) : "";
09139 stream <<
09140 "Failed " << bothOrAll( totals.testCases.failed )
09141 << pluralise( totals.testCases.failed, "test case" ) << ", "
09142 "failed " << qualify_assertions_failed <<
09143 pluralise( totals.assertions.failed, "assertion" ) << ".";
09144 }
09145 else if( totals.assertions.total() == 0 ) {
09146 stream <<
09147 "Passed " << bothOrAll( totals.testCases.total() )
09148 << pluralise( totals.testCases.total(), "test case" )
09149 << " (no assertions).";
09150 }
09151 else if( totals.assertions.failed ) {
09152 Colour colour( Colour::ResultError );
09153 stream <<
09154 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
09155 "failed " << pluralise( totals.assertions.failed, "assertion" ) << ".";
09156 }
09157 else {
09158 Colour colour( Colour::ResultSuccess );
09159 stream <<
09160 "Passed " << bothOrAll( totals.testCases.passed )
09161 << pluralise( totals.testCases.passed, "test case" ) <<
09162 " with " << pluralise( totals.assertions.passed, "assertion" ) << ".";
09163 }
09164 }
09165 };
09166
09167 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
09168
09169 }
09170
09171 namespace Catch {
09172 NonCopyable::~NonCopyable() {}
09173 IShared::~IShared() {}
09174 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
09175 IContext::~IContext() {}
09176 IResultCapture::~IResultCapture() {}
09177 ITestCase::~ITestCase() {}
09178 ITestCaseRegistry::~ITestCaseRegistry() {}
09179 IRegistryHub::~IRegistryHub() {}
09180 IMutableRegistryHub::~IMutableRegistryHub() {}
09181 IExceptionTranslator::~IExceptionTranslator() {}
09182 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
09183 IReporter::~IReporter() {}
09184 IReporterFactory::~IReporterFactory() {}
09185 IReporterRegistry::~IReporterRegistry() {}
09186 IStreamingReporter::~IStreamingReporter() {}
09187 AssertionStats::~AssertionStats() {}
09188 SectionStats::~SectionStats() {}
09189 TestCaseStats::~TestCaseStats() {}
09190 TestGroupStats::~TestGroupStats() {}
09191 TestRunStats::~TestRunStats() {}
09192 CumulativeReporterBase::SectionNode::~SectionNode() {}
09193 CumulativeReporterBase::~CumulativeReporterBase() {}
09194
09195 StreamingReporterBase::~StreamingReporterBase() {}
09196 ConsoleReporter::~ConsoleReporter() {}
09197 CompactReporter::~CompactReporter() {}
09198 IRunner::~IRunner() {}
09199 IMutableContext::~IMutableContext() {}
09200 IConfig::~IConfig() {}
09201 XmlReporter::~XmlReporter() {}
09202 JunitReporter::~JunitReporter() {}
09203 TestRegistry::~TestRegistry() {}
09204 FreeFunctionTestCase::~FreeFunctionTestCase() {}
09205 IGeneratorInfo::~IGeneratorInfo() {}
09206 IGeneratorsForTest::~IGeneratorsForTest() {}
09207 TestSpec::Pattern::~Pattern() {}
09208 TestSpec::NamePattern::~NamePattern() {}
09209 TestSpec::TagPattern::~TagPattern() {}
09210 TestSpec::ExcludedPattern::~ExcludedPattern() {}
09211
09212 Matchers::Impl::StdString::Equals::~Equals() {}
09213 Matchers::Impl::StdString::Contains::~Contains() {}
09214 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
09215 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
09216
09217 void Config::dummy() {}
09218 }
09219
09220 #ifdef __clang__
09221 #pragma clang diagnostic pop
09222 #endif
09223
09224 #endif
09225
09226 #ifdef CATCH_CONFIG_MAIN
09227
09228 #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
09229
09230 #ifndef __OBJC__
09231
09232
09233 int main (int argc, char * const argv[]) {
09234 return Catch::Session().run( argc, argv );
09235 }
09236
09237 #else // __OBJC__
09238
09239
09240 int main (int argc, char * const argv[]) {
09241 #if !CATCH_ARC_ENABLED
09242 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
09243 #endif
09244
09245 Catch::registerTestMethods();
09246 int result = Catch::Session().run( argc, (char* const*)argv );
09247
09248 #if !CATCH_ARC_ENABLED
09249 [pool drain];
09250 #endif
09251
09252 return result;
09253 }
09254
09255 #endif // __OBJC__
09256
09257 #endif
09258
09259 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
09260 # undef CLARA_CONFIG_MAIN
09261 #endif
09262
09264
09265
09266 #ifdef CATCH_CONFIG_PREFIX_ALL
09267
09268 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
09269 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
09270
09271 #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
09272 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
09273 #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
09274
09275 #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
09276 #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
09277 #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
09278 #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
09279 #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
09280
09281 #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
09282 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
09283 #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
09284
09285 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
09286 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
09287
09288 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
09289 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
09290 #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
09291 #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
09292 #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
09293
09294 #ifdef CATCH_CONFIG_VARIADIC_MACROS
09295 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
09296 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
09297 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
09298 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
09299 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
09300 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
09301 #else
09302 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
09303 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
09304 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
09305 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
09306 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
09307 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
09308 #endif
09309 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
09310
09311 #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
09312 #define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
09313
09314 #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
09315
09316
09317 #ifdef CATCH_CONFIG_VARIADIC_MACROS
09318 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
09319 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
09320 #else
09321 #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
09322 #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
09323 #endif
09324 #define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" )
09325 #define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" )
09326 #define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" )
09327 #define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" )
09328 #define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" )
09329
09330
09331 #else
09332
09333 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
09334 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
09335
09336 #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
09337 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
09338 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
09339
09340 #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
09341 #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
09342 #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
09343 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
09344 #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
09345
09346 #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
09347 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
09348 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
09349
09350 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
09351 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
09352
09353 #define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
09354 #define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
09355 #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
09356 #define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
09357 #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
09358
09359 #ifdef CATCH_CONFIG_VARIADIC_MACROS
09360 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
09361 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
09362 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
09363 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
09364 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
09365 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
09366 #else
09367 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
09368 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
09369 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
09370 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
09371 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
09372 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
09373 #endif
09374 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
09375
09376 #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
09377 #define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
09378
09379 #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
09380
09381 #endif
09382
09383 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
09384
09385
09386 #ifdef CATCH_CONFIG_VARIADIC_MACROS
09387 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
09388 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
09389 #else
09390 #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
09391 #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
09392 #endif
09393 #define GIVEN( desc ) SECTION( " Given: " desc, "" )
09394 #define WHEN( desc ) SECTION( " When: " desc, "" )
09395 #define AND_WHEN( desc ) SECTION( "And when: " desc, "" )
09396 #define THEN( desc ) SECTION( " Then: " desc, "" )
09397 #define AND_THEN( desc ) SECTION( " And: " desc, "" )
09398
09399 using Catch::Detail::Approx;
09400
09401
09402
09403 #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
09404
09405 #ifdef __clang__
09406 # ifdef __ICC // icpc defines the __clang__ macro
09407 # pragma warning(pop)
09408 # else
09409 # pragma clang diagnostic pop
09410 # endif
09411 #elif defined __GNUC__
09412 # pragma GCC diagnostic pop
09413 #endif
09414
09415 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
09416