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