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