From 805de43a3dfc14b03927afb66d3856e9a72eaa64 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 1 Jul 2015 07:33:27 +0100 Subject: [PATCH 01/87] Use CATCH_NULL instead of NULL - expands to nullptr if CATCH_CONFIG_CPP11_NULLPTR is defined (see #444) --- include/external/clara.h | 8 ++-- .../internal/catch_compiler_capabilities.h | 6 +++ include/internal/catch_context_impl.hpp | 8 ++-- include/internal/catch_debugger.hpp | 2 +- include/internal/catch_evaluate.hpp | 4 +- include/internal/catch_objc.hpp | 2 +- include/internal/catch_option.hpp | 12 ++--- include/internal/catch_ptr.hpp | 8 ++-- include/internal/catch_registry_hub.hpp | 4 +- include/internal/catch_reporter_registry.hpp | 2 +- include/internal/catch_runner_impl.hpp | 6 +-- include/internal/catch_section_info.hpp | 2 +- include/internal/catch_stream.hpp | 4 +- include/internal/catch_test_case_tracker.hpp | 8 ++-- include/internal/catch_timer.hpp | 2 +- include/internal/catch_tostring.h | 4 +- include/internal/catch_xmlwriter.hpp | 5 ++- .../Baselines/console.sw.approved.txt | 44 +++++++++---------- .../SelfTest/Baselines/xml.sw.approved.txt | 44 +++++++++---------- projects/SelfTest/CmdLineTests.cpp | 2 +- projects/SelfTest/ConditionTests.cpp | 22 +++++----- projects/SelfTest/MiscTests.cpp | 8 ++-- projects/SelfTest/TestMain.cpp | 2 +- projects/SelfTest/ToStringTuple.cpp | 2 + projects/SelfTest/TrickyTests.cpp | 2 +- 25 files changed, 112 insertions(+), 101 deletions(-) diff --git a/include/external/clara.h b/include/external/clara.h index bc162806..0971ebf5 100644 --- a/include/external/clara.h +++ b/include/external/clara.h @@ -264,11 +264,11 @@ namespace Clara { template class BoundArgFunction { public: - BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction() : functionObj( CATCH_NULL ) {} BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CATCH_NULL ) {} BoundArgFunction& operator = ( BoundArgFunction const& other ) { - IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CATCH_NULL; delete functionObj; functionObj = newFunctionObj; return *this; @@ -284,7 +284,7 @@ namespace Clara { bool takesArg() const { return functionObj->takesArg(); } bool isSet() const { - return functionObj != NULL; + return functionObj != CATCH_NULL; } private: IArgFunction* functionObj; diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index 20528c29..db8100f0 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -162,6 +162,12 @@ # define CATCH_NOEXCEPT_IS(x) #endif +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif #endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED diff --git a/include/internal/catch_context_impl.hpp b/include/internal/catch_context_impl.hpp index a495503c..3c97fcb1 100644 --- a/include/internal/catch_context_impl.hpp +++ b/include/internal/catch_context_impl.hpp @@ -17,7 +17,7 @@ namespace Catch { class Context : public IMutableContext { - Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} Context( Context const& ); void operator=( Context const& ); @@ -63,7 +63,7 @@ namespace Catch { m_generatorsByTestName.find( testName ); return it != m_generatorsByTestName.end() ? it->second - : NULL; + : CATCH_NULL; } IGeneratorsForTest& getGeneratorsForCurrentTest() { @@ -84,7 +84,7 @@ namespace Catch { }; namespace { - Context* currentContext = NULL; + Context* currentContext = CATCH_NULL; } IMutableContext& getCurrentMutableContext() { if( !currentContext ) @@ -105,7 +105,7 @@ namespace Catch { void cleanUpContext() { delete currentContext; - currentContext = NULL; + currentContext = CATCH_NULL; } } diff --git a/include/internal/catch_debugger.hpp b/include/internal/catch_debugger.hpp index 4151aec7..8c552661 100644 --- a/include/internal/catch_debugger.hpp +++ b/include/internal/catch_debugger.hpp @@ -50,7 +50,7 @@ // Call sysctl. size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; return false; } diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index 2f85a2b9..ab9db784 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -163,10 +163,10 @@ namespace Internal { #ifdef CATCH_CONFIG_CPP11_NULLPTR // pointer to nullptr_t (when comparing against nullptr) template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( NULL, rhs ); + return Evaluator::evaluate( CATCH_NULL, rhs ); } template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, NULL ); + return Evaluator::evaluate( lhs, CATCH_NULL ); } #endif // CATCH_CONFIG_CPP11_NULLPTR diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp index 7e315c22..489cf558 100644 --- a/include/internal/catch_objc.hpp +++ b/include/internal/catch_objc.hpp @@ -72,7 +72,7 @@ namespace Catch { inline size_t registerTestMethods() { size_t noTestMethods = 0; - int noClasses = objc_getClassList( NULL, 0 ); + int noClasses = objc_getClassList( CATCH_NULL, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); objc_getClassList( classes, noClasses ); diff --git a/include/internal/catch_option.hpp b/include/internal/catch_option.hpp index bf3bce3d..5413abf0 100644 --- a/include/internal/catch_option.hpp +++ b/include/internal/catch_option.hpp @@ -16,12 +16,12 @@ namespace Catch { template class Option { public: - Option() : nullableValue( NULL ) {} + Option() : nullableValue( CATCH_NULL ) {} Option( T const& _value ) : nullableValue( new( storage ) T( _value ) ) {} Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) {} ~Option() { @@ -45,7 +45,7 @@ namespace Catch { void reset() { if( nullableValue ) nullableValue->~T(); - nullableValue = NULL; + nullableValue = CATCH_NULL; } T& operator*() { return *nullableValue; } @@ -57,10 +57,10 @@ namespace Catch { return nullableValue ? *nullableValue : defaultValue; } - bool some() const { return nullableValue != NULL; } - bool none() const { return nullableValue == NULL; } + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } - bool operator !() const { return nullableValue == NULL; } + bool operator !() const { return nullableValue == CATCH_NULL; } operator SafeBool::type() const { return SafeBool::makeSafe( some() ); } diff --git a/include/internal/catch_ptr.hpp b/include/internal/catch_ptr.hpp index 3d76e328..e37da385 100644 --- a/include/internal/catch_ptr.hpp +++ b/include/internal/catch_ptr.hpp @@ -23,7 +23,7 @@ namespace Catch { template class Ptr { public: - Ptr() : m_p( NULL ){} + Ptr() : m_p( CATCH_NULL ){} Ptr( T* p ) : m_p( p ){ if( m_p ) m_p->addRef(); @@ -39,7 +39,7 @@ namespace Catch { void reset() { if( m_p ) m_p->release(); - m_p = NULL; + m_p = CATCH_NULL; } Ptr& operator = ( T* p ){ Ptr temp( p ); @@ -56,8 +56,8 @@ namespace Catch { const T* get() const{ return m_p; } T& operator*() const { return *m_p; } T* operator->() const { return m_p; } - bool operator !() const { return m_p == NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } private: T* m_p; diff --git a/include/internal/catch_registry_hub.hpp b/include/internal/catch_registry_hub.hpp index 303a843a..cd6a4e07 100644 --- a/include/internal/catch_registry_hub.hpp +++ b/include/internal/catch_registry_hub.hpp @@ -55,7 +55,7 @@ namespace Catch { // Single, global, instance inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = NULL; + static RegistryHub* theRegistryHub = CATCH_NULL; if( !theRegistryHub ) theRegistryHub = new RegistryHub(); return theRegistryHub; @@ -70,7 +70,7 @@ namespace Catch { } void cleanUp() { delete getTheRegistryHub(); - getTheRegistryHub() = NULL; + getTheRegistryHub() = CATCH_NULL; cleanUpContext(); } std::string translateActiveException() { diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index 2ce24bef..3e2ae4c9 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -25,7 +25,7 @@ namespace Catch { virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) - return NULL; + return CATCH_NULL; return it->second->create( ReporterConfig( config ) ); } diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index e6893518..5c39bcb2 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -62,7 +62,7 @@ namespace Catch { explicit RunContext( Ptr const& config, Ptr const& reporter ) : m_runInfo( config->name() ), m_context( getCurrentMutableContext() ), - m_activeTestCase( NULL ), + m_activeTestCase( CATCH_NULL ), m_config( config ), m_reporter( reporter ), m_prevRunner( m_context.getRunner() ), @@ -78,7 +78,7 @@ namespace Catch { virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); m_context.setRunner( m_prevRunner ); - m_context.setConfig( NULL ); + m_context.setConfig( CATCH_NULL ); m_context.setResultCapture( m_prevResultCapture ); m_context.setConfig( m_prevConfig ); } @@ -119,7 +119,7 @@ namespace Catch { redirectedCerr, aborting() ) ); - m_activeTestCase = NULL; + m_activeTestCase = CATCH_NULL; m_testCaseTracker.reset(); return deltaTotals; diff --git a/include/internal/catch_section_info.hpp b/include/internal/catch_section_info.hpp index f60896c4..6258a281 100644 --- a/include/internal/catch_section_info.hpp +++ b/include/internal/catch_section_info.hpp @@ -36,7 +36,7 @@ namespace Catch { RunningSection( std::string const& name ) : m_state( Root ), - m_parent( NULL ), + m_parent( CATCH_NULL ), m_name( name ) {} diff --git a/include/internal/catch_stream.hpp b/include/internal/catch_stream.hpp index 604ed97b..42933487 100644 --- a/include/internal/catch_stream.hpp +++ b/include/internal/catch_stream.hpp @@ -65,7 +65,7 @@ namespace Catch { }; Stream::Stream() - : streamBuf( NULL ), isOwned( false ) + : streamBuf( CATCH_NULL ), isOwned( false ) {} Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) @@ -75,7 +75,7 @@ namespace Catch { void Stream::release() { if( isOwned ) { delete streamBuf; - streamBuf = NULL; + streamBuf = CATCH_NULL; isOwned = false; } } diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index 86b6be50..eb2616e0 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -8,6 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED +#include "catch_compiler_capabilities.h" + #include #include #include @@ -60,7 +62,7 @@ namespace SectionTracking { TrackedSections::iterator it = m_children.find( childName ); return it != m_children.end() ? &it->second - : NULL; + : CATCH_NULL; } inline TrackedSection* TrackedSection::acquireChild( std::string const& childName ) { if( TrackedSection* child = findChild( childName ) ) @@ -82,7 +84,7 @@ namespace SectionTracking { class TestCaseTracker { public: TestCaseTracker( std::string const& testCaseName ) - : m_testCase( testCaseName, NULL ), + : m_testCase( testCaseName, CATCH_NULL ), m_currentSection( &m_testCase ), m_completedASectionThisRun( false ) {} @@ -99,7 +101,7 @@ namespace SectionTracking { void leaveSection() { m_currentSection->leave(); m_currentSection = m_currentSection->getParent(); - assert( m_currentSection != NULL ); + assert( m_currentSection != CATCH_NULL ); m_completedASectionThisRun = true; } diff --git a/include/internal/catch_timer.hpp b/include/internal/catch_timer.hpp index 47d9536b..2ba709e3 100644 --- a/include/internal/catch_timer.hpp +++ b/include/internal/catch_timer.hpp @@ -37,7 +37,7 @@ namespace Catch { #else uint64_t getCurrentTicks() { timeval t; - gettimeofday(&t,NULL); + gettimeofday(&t,CATCH_NULL); return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); } #endif diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 120619be..8efb9be3 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -148,7 +148,7 @@ struct StringMaker { template static std::string convert( U* p ) { if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); + return "NULL"; else return Detail::rawMemoryToString( p ); } @@ -158,7 +158,7 @@ template struct StringMaker { static std::string convert( R C::* p ) { if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); + return "NULL"; else return Detail::rawMemoryToString( p ); } diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.hpp index 553c5a79..3355f4d3 100644 --- a/include/internal/catch_xmlwriter.hpp +++ b/include/internal/catch_xmlwriter.hpp @@ -8,7 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED -#include "../internal/catch_stream.h" +#include "catch_stream.h" +#include "catch_compiler_capabilities.h" #include #include @@ -27,7 +28,7 @@ namespace Catch { ScopedElement( ScopedElement const& other ) : m_writer( other.m_writer ){ - other.m_writer = NULL; + other.m_writer = CATCH_NULL; } ~ScopedElement() { diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 744fab67..2023c59b 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -973,51 +973,51 @@ ConditionTests.cpp: ConditionTests.cpp:: PASSED: - REQUIRE( p == __null ) + REQUIRE( p == nullptr ) with expansion: - __null == 0 + NULL == nullptr ConditionTests.cpp:: PASSED: REQUIRE( p == pNULL ) with expansion: - __null == __null + NULL == NULL ConditionTests.cpp:: PASSED: - REQUIRE( p != __null ) + REQUIRE( p != nullptr ) with expansion: - 0x != 0 + 0x != nullptr ConditionTests.cpp:: PASSED: - REQUIRE( cp != __null ) + REQUIRE( cp != nullptr ) with expansion: - 0x != 0 + 0x != nullptr ConditionTests.cpp:: PASSED: - REQUIRE( cpc != __null ) + REQUIRE( cpc != nullptr ) with expansion: - 0x != 0 + 0x != nullptr ConditionTests.cpp:: PASSED: - REQUIRE( returnsNull() == __null ) + REQUIRE( returnsNull() == nullptr ) with expansion: - {null string} == 0 + {null string} == nullptr ConditionTests.cpp:: PASSED: - REQUIRE( returnsConstNull() == __null ) + REQUIRE( returnsConstNull() == nullptr ) with expansion: - {null string} == 0 + {null string} == nullptr ConditionTests.cpp:: PASSED: - REQUIRE( __null != p ) + REQUIRE( nullptr != p ) with expansion: - 0 != 0x + nullptr != 0x ------------------------------------------------------------------------------- 'Not' checks that should succeed @@ -3113,13 +3113,13 @@ MiscTests.cpp: MiscTests.cpp:: PASSED: - REQUIRE( makeString( false ) != static_cast(__null) ) + REQUIRE( makeString( false ) != static_cast(nullptr) ) with expansion: "valid string" != {null string} MiscTests.cpp:: PASSED: - REQUIRE( makeString( true ) == static_cast(__null) ) + REQUIRE( makeString( true ) == static_cast(nullptr) ) with expansion: {null string} == {null string} @@ -3316,7 +3316,7 @@ MiscTests.cpp: MiscTests.cpp:: PASSED: - REQUIRE_THAT( "" Equals(__null) ) + REQUIRE_THAT( "" Equals(nullptr) ) with expansion: "" equals: "" @@ -5863,9 +5863,9 @@ TrickyTests.cpp: TrickyTests.cpp:: PASSED: - REQUIRE( obj.prop != __null ) + REQUIRE( obj.prop != nullptr ) with expansion: - 0x != 0 + 0x != nullptr ------------------------------------------------------------------------------- (unimplemented) static bools can be evaluated @@ -6106,7 +6106,7 @@ TrickyTests.cpp:: PASSED: REQUIRE( p == 0 ) with expansion: - __null == 0 + NULL == 0 ------------------------------------------------------------------------------- null_ptr @@ -6118,7 +6118,7 @@ TrickyTests.cpp:: PASSED: REQUIRE( ptr.get() == nullptr ) with expansion: - __null == nullptr + NULL == nullptr ------------------------------------------------------------------------------- X/level/0/a diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index c0a75b73..974559a2 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1205,10 +1205,10 @@ - p == __null + p == nullptr - __null == 0 + NULL == nullptr @@ -1216,55 +1216,55 @@ p == pNULL - __null == __null + NULL == NULL - p != __null + p != nullptr - 0x != 0 + 0x != nullptr - cp != __null + cp != nullptr - 0x != 0 + 0x != nullptr - cpc != __null + cpc != nullptr - 0x != 0 + 0x != nullptr - returnsNull() == __null + returnsNull() == nullptr - {null string} == 0 + {null string} == nullptr - returnsConstNull() == __null + returnsConstNull() == nullptr - {null string} == 0 + {null string} == nullptr - __null != p + nullptr != p - 0 != 0x + nullptr != 0x @@ -3226,7 +3226,7 @@ - makeString( false ) != static_cast<char*>(__null) + makeString( false ) != static_cast<char*>(nullptr) "valid string" != {null string} @@ -3234,7 +3234,7 @@ - makeString( true ) == static_cast<char*>(__null) + makeString( true ) == static_cast<char*>(nullptr) {null string} == {null string} @@ -3434,7 +3434,7 @@ - "" Equals(__null) + "" Equals(nullptr) "" equals: "" @@ -6041,10 +6041,10 @@ there" - obj.prop != __null + obj.prop != nullptr - 0x != 0 + 0x != nullptr @@ -6270,7 +6270,7 @@ there" p == 0 - __null == 0 + NULL == 0 @@ -6281,7 +6281,7 @@ there" ptr.get() == nullptr - __null == nullptr + NULL == nullptr diff --git a/projects/SelfTest/CmdLineTests.cpp b/projects/SelfTest/CmdLineTests.cpp index 46aecfd0..955bcd3d 100644 --- a/projects/SelfTest/CmdLineTests.cpp +++ b/projects/SelfTest/CmdLineTests.cpp @@ -10,7 +10,7 @@ #include "catch_test_spec_parser.hpp" -inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } +inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( CATCH_NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } TEST_CASE( "Parse test names and tags", "" ) { diff --git a/projects/SelfTest/ConditionTests.cpp b/projects/SelfTest/ConditionTests.cpp index 097c3f33..910021ce 100644 --- a/projects/SelfTest/ConditionTests.cpp +++ b/projects/SelfTest/ConditionTests.cpp @@ -265,32 +265,32 @@ TEST_CASE( "Comparisons between ints where one side is computed", "" ) #pragma GCC diagnostic pop #endif -inline const char* returnsConstNull(){ return NULL; } -inline char* returnsNull(){ return NULL; } +inline const char* returnsConstNull(){ return CATCH_NULL; } +inline char* returnsNull(){ return CATCH_NULL; } TEST_CASE( "Pointers can be compared to null", "" ) { - TestData* p = NULL; - TestData* pNULL = NULL; + TestData* p = CATCH_NULL; + TestData* pNULL = CATCH_NULL; - REQUIRE( p == NULL ); + REQUIRE( p == CATCH_NULL ); REQUIRE( p == pNULL ); TestData data; p = &data; - REQUIRE( p != NULL ); + REQUIRE( p != CATCH_NULL ); const TestData* cp = p; - REQUIRE( cp != NULL ); + REQUIRE( cp != CATCH_NULL ); const TestData* const cpc = p; - REQUIRE( cpc != NULL ); + REQUIRE( cpc != CATCH_NULL ); - REQUIRE( returnsNull() == NULL ); - REQUIRE( returnsConstNull() == NULL ); + REQUIRE( returnsNull() == CATCH_NULL ); + REQUIRE( returnsConstNull() == CATCH_NULL ); - REQUIRE( NULL != p ); + REQUIRE( CATCH_NULL != p ); } // Not (!) tests diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 86bd4f39..d91db944 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -124,13 +124,13 @@ TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) inline const char* makeString( bool makeNull ) { - return makeNull ? NULL : "valid string"; + return makeNull ? CATCH_NULL : "valid string"; } TEST_CASE( "null strings", "" ) { - REQUIRE( makeString( false ) != static_cast(NULL)); - REQUIRE( makeString( true ) == static_cast(NULL)); + REQUIRE( makeString( false ) != static_cast(CATCH_NULL)); + REQUIRE( makeString( true ) == static_cast(CATCH_NULL)); } @@ -233,7 +233,7 @@ TEST_CASE("Equals string matcher", "[.][failing][matchers]") } TEST_CASE("Equals string matcher, with NULL", "[matchers]") { - REQUIRE_THAT("", Equals(NULL)); + REQUIRE_THAT("", Equals(CATCH_NULL)); } TEST_CASE("AllOf matcher", "[matchers]") { diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 7cb7ca42..dae87f0c 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -39,7 +39,7 @@ std::string parseIntoConfigAndReturnError( const char * (&argv)[size], Catch::Co return ""; } -inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } +inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( CATCH_NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { diff --git a/projects/SelfTest/ToStringTuple.cpp b/projects/SelfTest/ToStringTuple.cpp index d1ab02f2..80e54530 100644 --- a/projects/SelfTest/ToStringTuple.cpp +++ b/projects/SelfTest/ToStringTuple.cpp @@ -42,12 +42,14 @@ TEST_CASE( "tuple,tuple<>,float>", "[toString][tuple]" ) CHECK( "{ { 42 }, { }, 1.2f }" == Catch::toString(value) ); } +#ifdef CATCH_CONFIG_CPP11_NULLPTR TEST_CASE( "tuple", "[toString][tuple]" ) { typedef std::tuple type; type value { nullptr, 42, "Catch me" }; CHECK( "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) ); } +#endif #ifdef __clang__ #pragma clang diagnostic pop diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 462718db..95612022 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -234,7 +234,7 @@ struct Obj TEST_CASE("boolean member", "[Tricky]") { Obj obj; - REQUIRE( obj.prop != NULL ); + REQUIRE( obj.prop != CATCH_NULL ); } // Tests for a problem submitted by Ralph McArdell From 680b1a881be180f1d75540a163d6a1df648ef4f3 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 1 Jul 2015 07:50:53 +0100 Subject: [PATCH 02/87] Squashed some warnings about local variables shadowing members - see #444 --- include/external/clara.h | 10 +++++----- include/internal/catch_runner_impl.hpp | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/external/clara.h b/include/external/clara.h index 0971ebf5..5cd4759b 100644 --- a/include/external/clara.h +++ b/include/external/clara.h @@ -585,8 +585,8 @@ namespace Clara { m_arg->description = description; return *this; } - ArgBuilder& detail( std::string const& detail ) { - m_arg->detail = detail; + ArgBuilder& detail( std::string const& _detail ) { + m_arg->detail = _detail; return *this; } @@ -670,14 +670,14 @@ namespace Clara { maxWidth = (std::max)( maxWidth, it->commands().size() ); for( it = itBegin; it != itEnd; ++it ) { - Detail::Text usage( it->commands(), Detail::TextAttributes() + Detail::Text usageText( it->commands(), Detail::TextAttributes() .setWidth( maxWidth+indent ) .setIndent( indent ) ); Detail::Text desc( it->description, Detail::TextAttributes() .setWidth( width - maxWidth - 3 ) ); - for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { - std::string usageCol = i < usage.size() ? usage[i] : ""; + for( std::size_t i = 0; i < (std::max)( usageText.size(), desc.size() ); ++i ) { + std::string usageCol = i < usageText.size() ? usageText[i] : ""; os << usageCol; if( i < desc.size() && !desc[i].empty() ) diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index 5c39bcb2..98f3dfd1 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -59,11 +59,11 @@ namespace Catch { public: - explicit RunContext( Ptr const& config, Ptr const& reporter ) - : m_runInfo( config->name() ), + explicit RunContext( Ptr const& _config, Ptr const& reporter ) + : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), m_activeTestCase( CATCH_NULL ), - m_config( config ), + m_config( _config ), m_reporter( reporter ), m_prevRunner( m_context.getRunner() ), m_prevResultCapture( m_context.getResultCapture() ), From 088c5bc53ed22b30c15f88fbfbdb7629f8b78a53 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 2 Jul 2015 08:20:18 +0100 Subject: [PATCH 03/87] --filenames-as-tags --- include/catch_runner.hpp | 23 ++++++++++++++++ include/internal/catch_commandline.hpp | 4 +++ include/internal/catch_config.hpp | 2 ++ include/internal/catch_test_case_info.h | 2 ++ include/internal/catch_test_case_info.hpp | 27 ++++++++++++------- .../CatchSelfTest.xcodeproj/project.pbxproj | 4 +-- 6 files changed, 49 insertions(+), 13 deletions(-) diff --git a/include/catch_runner.hpp b/include/catch_runner.hpp index 8023d970..3a674148 100644 --- a/include/catch_runner.hpp +++ b/include/catch_runner.hpp @@ -104,6 +104,26 @@ namespace Catch { Ptr m_reporter; std::set m_testsAlreadyRun; }; + + void applyFilenamesAsTags() { + std::vector const& tests = getRegistryHub().getTestCaseRegistry().getAllTests(); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast( tests[i] ); + std::set tags = test.tags; + + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\//" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.insert( "@" + filename ); + setTags( test, tags ); + } + } class Session : NonCopyable { static bool alreadyInstantiated; @@ -175,6 +195,9 @@ namespace Catch { { config(); // Force config to be constructed + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags(); + std::srand( m_configData.rngSeed ); Runner runner( m_config ); diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index 8b085365..d05cee96 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -174,6 +174,10 @@ namespace Catch { .describe( "force colourised output" ) .bind( &ConfigData::forceColour ); + cli["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + return cli; } diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 1f3ca64a..b0f88fd0 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -38,6 +38,7 @@ namespace Catch { showHelp( false ), showInvisibles( false ), forceColour( false ), + filenamesAsTags( false ), abortAfter( -1 ), rngSeed( 0 ), verbosity( Verbosity::Normal ), @@ -57,6 +58,7 @@ namespace Catch { bool showHelp; bool showInvisibles; bool forceColour; + bool filenamesAsTags; int abortAfter; unsigned int rngSeed; diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index 7520fd1c..685825e1 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -40,6 +40,8 @@ namespace Catch { TestCaseInfo( TestCaseInfo const& other ); + friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + bool isHidden() const; bool throws() const; bool okToFail() const; diff --git a/include/internal/catch_test_case_info.hpp b/include/internal/catch_test_case_info.hpp index 308ddc74..2101c985 100644 --- a/include/internal/catch_test_case_info.hpp +++ b/include/internal/catch_test_case_info.hpp @@ -88,11 +88,26 @@ namespace Catch { tags.insert( "hide" ); tags.insert( "." ); } - + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); return TestCase( _testCase, info ); } + void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + TestCaseInfo::TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, @@ -101,18 +116,10 @@ namespace Catch { : name( _name ), className( _className ), description( _description ), - tags( _tags ), lineInfo( _lineInfo ), properties( None ) { - std::ostringstream oss; - for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { - oss << "[" << *it << "]"; - std::string lcaseTag = toLower( *it ); - properties = static_cast( properties | parseSpecialTag( lcaseTag ) ); - lcaseTags.insert( lcaseTag ); - } - tagsAsString = oss.str(); + setTags( *this, _tags ); } TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index b64ceef1..047fa70e 100644 --- a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -91,7 +91,6 @@ 26711C91195D47820033EDA2 /* catch_tag_alias.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_tag_alias.h; sourceTree = ""; }; 26711C92195D48F60033EDA2 /* catch_tag_alias_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_tag_alias_registry.hpp; sourceTree = ""; }; 26711C94195D4B120033EDA2 /* catch_tag_alias_registry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_tag_alias_registry.h; sourceTree = ""; }; - 26759472171C72A400A84BD1 /* catch_sfinae.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_sfinae.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 26759473171C74C200A84BD1 /* catch_compiler_capabilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_compiler_capabilities.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; 26847E5B16BBAB790043B9C1 /* catch_message.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_message.h; sourceTree = ""; }; 26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = ""; }; @@ -453,6 +452,7 @@ 266ECD8C1713614B0030D735 /* catch_legacy_reporter_adapter.hpp */, 266ECD8D1713614B0030D735 /* catch_legacy_reporter_adapter.h */, 4A6D0C49149B3E3D00DB3EAA /* catch_common.h */, + 262E739A1846759000CAC268 /* catch_common.hpp */, 4A6D0C4B149B3E3D00DB3EAA /* catch_debugger.hpp */, 261488FF184DC4A20041FBEB /* catch_debugger.h */, 4A6D0C60149B3E3D00DB3EAA /* catch_stream.hpp */, @@ -461,12 +461,10 @@ 4AB77CB51551AEA200857BF0 /* catch_ptr.hpp */, 4AEE0326161431070071E950 /* catch_streambuf.h */, 4ACE21C8166CA19700FB5509 /* catch_option.hpp */, - 26759472171C72A400A84BD1 /* catch_sfinae.hpp */, 26759473171C74C200A84BD1 /* catch_compiler_capabilities.h */, 26DACF2F17206D3400A21326 /* catch_text.h */, 263FD06117AF8DF200988A20 /* catch_timer.h */, 26AEAF1617BEA18E009E32C9 /* catch_platform.h */, - 262E739A1846759000CAC268 /* catch_common.hpp */, 261488FC184D1DC10041FBEB /* catch_stream.h */, 268F47B018A93F7800D8C14F /* catch_clara.h */, 2656C226192A77EF0040DB02 /* catch_suppress_warnings.h */, From b971fe785b2b346c2c66f84a5c9ee0681e3ee7d3 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 2 Jul 2015 08:21:38 +0100 Subject: [PATCH 04/87] develop build 1 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 159 ++++++++++++++++++----------- 3 files changed, 104 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index fade0d0a..c9d9f6c3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1* +*v1.2.1-develop.1* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 46651b72..bf57c617 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "", 0 ); + Version libraryVersion( 1, 2, 1, "develop", 1 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index de61226c..b06810f6 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1 - * Generated: 2015-06-30 18:23:27.961086 + * Catch v1.2.1-develop.1 + * Generated: 2015-07-02 08:21:11.983471 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -224,6 +224,13 @@ # define CATCH_NOEXCEPT_IS(x) #endif +// nullptr support +#ifdef CATCH_CONFIG_CPP11_NULLPTR +# define CATCH_NULL nullptr +#else +# define CATCH_NULL NULL +#endif + namespace Catch { class NonCopyable { @@ -397,7 +404,7 @@ namespace Catch { template class Ptr { public: - Ptr() : m_p( NULL ){} + Ptr() : m_p( CATCH_NULL ){} Ptr( T* p ) : m_p( p ){ if( m_p ) m_p->addRef(); @@ -413,7 +420,7 @@ namespace Catch { void reset() { if( m_p ) m_p->release(); - m_p = NULL; + m_p = CATCH_NULL; } Ptr& operator = ( T* p ){ Ptr temp( p ); @@ -430,8 +437,8 @@ namespace Catch { const T* get() const{ return m_p; } T& operator*() const { return *m_p; } T* operator->() const { return m_p; } - bool operator !() const { return m_p == NULL; } - operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); } + bool operator !() const { return m_p == CATCH_NULL; } + operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } private: T* m_p; @@ -994,10 +1001,10 @@ namespace Internal { #ifdef CATCH_CONFIG_CPP11_NULLPTR // pointer to nullptr_t (when comparing against nullptr) template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( NULL, rhs ); + return Evaluator::evaluate( CATCH_NULL, rhs ); } template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, NULL ); + return Evaluator::evaluate( lhs, CATCH_NULL ); } #endif // CATCH_CONFIG_CPP11_NULLPTR @@ -1190,7 +1197,7 @@ struct StringMaker { template static std::string convert( U* p ) { if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); + return "NULL"; else return Detail::rawMemoryToString( p ); } @@ -1200,7 +1207,7 @@ template struct StringMaker { static std::string convert( R C::* p ) { if( !p ) - return INTERNAL_CATCH_STRINGIFY( NULL ); + return "NULL"; else return Detail::rawMemoryToString( p ); } @@ -2440,12 +2447,12 @@ namespace Catch { template class Option { public: - Option() : nullableValue( NULL ) {} + Option() : nullableValue( CATCH_NULL ) {} Option( T const& _value ) : nullableValue( new( storage ) T( _value ) ) {} Option( Option const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : NULL ) + : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) {} ~Option() { @@ -2469,7 +2476,7 @@ namespace Catch { void reset() { if( nullableValue ) nullableValue->~T(); - nullableValue = NULL; + nullableValue = CATCH_NULL; } T& operator*() { return *nullableValue; } @@ -2481,10 +2488,10 @@ namespace Catch { return nullableValue ? *nullableValue : defaultValue; } - bool some() const { return nullableValue != NULL; } - bool none() const { return nullableValue == NULL; } + bool some() const { return nullableValue != CATCH_NULL; } + bool none() const { return nullableValue == CATCH_NULL; } - bool operator !() const { return nullableValue == NULL; } + bool operator !() const { return nullableValue == CATCH_NULL; } operator SafeBool::type() const { return SafeBool::makeSafe( some() ); } @@ -2542,6 +2549,8 @@ namespace Catch { TestCaseInfo( TestCaseInfo const& other ); + friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); + bool isHidden() const; bool throws() const; bool okToFail() const; @@ -2654,7 +2663,7 @@ namespace Catch { inline size_t registerTestMethods() { size_t noTestMethods = 0; - int noClasses = objc_getClassList( NULL, 0 ); + int noClasses = objc_getClassList( CATCH_NULL, 0 ); Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); objc_getClassList( classes, noClasses ); @@ -3132,6 +3141,7 @@ namespace Catch { showHelp( false ), showInvisibles( false ), forceColour( false ), + filenamesAsTags( false ), abortAfter( -1 ), rngSeed( 0 ), verbosity( Verbosity::Normal ), @@ -3151,6 +3161,7 @@ namespace Catch { bool showHelp; bool showInvisibles; bool forceColour; + bool filenamesAsTags; int abortAfter; unsigned int rngSeed; @@ -3517,11 +3528,11 @@ namespace Clara { template class BoundArgFunction { public: - BoundArgFunction() : functionObj( NULL ) {} + BoundArgFunction() : functionObj( CATCH_NULL ) {} BoundArgFunction( IArgFunction* _functionObj ) : functionObj( _functionObj ) {} - BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {} + BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CATCH_NULL ) {} BoundArgFunction& operator = ( BoundArgFunction const& other ) { - IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL; + IArgFunction* newFunctionObj = other.functionObj ? other.functionObj->clone() : CATCH_NULL; delete functionObj; functionObj = newFunctionObj; return *this; @@ -3537,7 +3548,7 @@ namespace Clara { bool takesArg() const { return functionObj->takesArg(); } bool isSet() const { - return functionObj != NULL; + return functionObj != CATCH_NULL; } private: IArgFunction* functionObj; @@ -3836,8 +3847,8 @@ namespace Clara { m_arg->description = description; return *this; } - ArgBuilder& detail( std::string const& detail ) { - m_arg->detail = detail; + ArgBuilder& detail( std::string const& _detail ) { + m_arg->detail = _detail; return *this; } @@ -3920,14 +3931,14 @@ namespace Clara { maxWidth = (std::max)( maxWidth, it->commands().size() ); for( it = itBegin; it != itEnd; ++it ) { - Detail::Text usage( it->commands(), Detail::TextAttributes() + Detail::Text usageText( it->commands(), Detail::TextAttributes() .setWidth( maxWidth+indent ) .setIndent( indent ) ); Detail::Text desc( it->description, Detail::TextAttributes() .setWidth( width - maxWidth - 3 ) ); - for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { - std::string usageCol = i < usage.size() ? usage[i] : ""; + for( std::size_t i = 0; i < (std::max)( usageText.size(), desc.size() ); ++i ) { + std::string usageCol = i < usageText.size() ? usageText[i] : ""; os << usageCol; if( i < desc.size() && !desc[i].empty() ) @@ -4284,6 +4295,10 @@ namespace Catch { .describe( "force colourised output" ) .bind( &ConfigData::forceColour ); + cli["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + return cli; } @@ -4977,7 +4992,7 @@ namespace SectionTracking { TrackedSections::iterator it = m_children.find( childName ); return it != m_children.end() ? &it->second - : NULL; + : CATCH_NULL; } inline TrackedSection* TrackedSection::acquireChild( std::string const& childName ) { if( TrackedSection* child = findChild( childName ) ) @@ -4999,7 +5014,7 @@ namespace SectionTracking { class TestCaseTracker { public: TestCaseTracker( std::string const& testCaseName ) - : m_testCase( testCaseName, NULL ), + : m_testCase( testCaseName, CATCH_NULL ), m_currentSection( &m_testCase ), m_completedASectionThisRun( false ) {} @@ -5016,7 +5031,7 @@ namespace SectionTracking { void leaveSection() { m_currentSection->leave(); m_currentSection = m_currentSection->getParent(); - assert( m_currentSection != NULL ); + assert( m_currentSection != CATCH_NULL ); m_completedASectionThisRun = true; } @@ -5174,11 +5189,11 @@ namespace Catch { public: - explicit RunContext( Ptr const& config, Ptr const& reporter ) - : m_runInfo( config->name() ), + explicit RunContext( Ptr const& _config, Ptr const& reporter ) + : m_runInfo( _config->name() ), m_context( getCurrentMutableContext() ), - m_activeTestCase( NULL ), - m_config( config ), + m_activeTestCase( CATCH_NULL ), + m_config( _config ), m_reporter( reporter ), m_prevRunner( m_context.getRunner() ), m_prevResultCapture( m_context.getResultCapture() ), @@ -5193,7 +5208,7 @@ namespace Catch { virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); m_context.setRunner( m_prevRunner ); - m_context.setConfig( NULL ); + m_context.setConfig( CATCH_NULL ); m_context.setResultCapture( m_prevResultCapture ); m_context.setConfig( m_prevConfig ); } @@ -5234,7 +5249,7 @@ namespace Catch { redirectedCerr, aborting() ) ); - m_activeTestCase = NULL; + m_activeTestCase = CATCH_NULL; m_testCaseTracker.reset(); return deltaTotals; @@ -5589,6 +5604,26 @@ namespace Catch { std::set m_testsAlreadyRun; }; + void applyFilenamesAsTags() { + std::vector const& tests = getRegistryHub().getTestCaseRegistry().getAllTests(); + for(std::size_t i = 0; i < tests.size(); ++i ) { + TestCase& test = const_cast( tests[i] ); + std::set tags = test.tags; + + std::string filename = test.lineInfo.file; + std::string::size_type lastSlash = filename.find_last_of( "\//" ); + if( lastSlash != std::string::npos ) + filename = filename.substr( lastSlash+1 ); + + std::string::size_type lastDot = filename.find_last_of( "." ); + if( lastDot != std::string::npos ) + filename = filename.substr( 0, lastDot ); + + tags.insert( "@" + filename ); + setTags( test, tags ); + } + } + class Session : NonCopyable { static bool alreadyInstantiated; @@ -5659,6 +5694,9 @@ namespace Catch { { config(); // Force config to be constructed + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags(); + std::srand( m_configData.rngSeed ); Runner runner( m_config ); @@ -5872,7 +5910,7 @@ namespace Catch { virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) - return NULL; + return CATCH_NULL; return it->second->create( ReporterConfig( config ) ); } @@ -5997,7 +6035,7 @@ namespace Catch { // Single, global, instance inline RegistryHub*& getTheRegistryHub() { - static RegistryHub* theRegistryHub = NULL; + static RegistryHub* theRegistryHub = CATCH_NULL; if( !theRegistryHub ) theRegistryHub = new RegistryHub(); return theRegistryHub; @@ -6012,7 +6050,7 @@ namespace Catch { } void cleanUp() { delete getTheRegistryHub(); - getTheRegistryHub() = NULL; + getTheRegistryHub() = CATCH_NULL; cleanUpContext(); } std::string translateActiveException() { @@ -6113,7 +6151,7 @@ namespace Catch { }; Stream::Stream() - : streamBuf( NULL ), isOwned( false ) + : streamBuf( CATCH_NULL ), isOwned( false ) {} Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) @@ -6123,7 +6161,7 @@ namespace Catch { void Stream::release() { if( isOwned ) { delete streamBuf; - streamBuf = NULL; + streamBuf = CATCH_NULL; isOwned = false; } } @@ -6142,7 +6180,7 @@ namespace Catch { class Context : public IMutableContext { - Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {} + Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} Context( Context const& ); void operator=( Context const& ); @@ -6188,7 +6226,7 @@ namespace Catch { m_generatorsByTestName.find( testName ); return it != m_generatorsByTestName.end() ? it->second - : NULL; + : CATCH_NULL; } IGeneratorsForTest& getGeneratorsForCurrentTest() { @@ -6209,7 +6247,7 @@ namespace Catch { }; namespace { - Context* currentContext = NULL; + Context* currentContext = CATCH_NULL; } IMutableContext& getCurrentMutableContext() { if( !currentContext ) @@ -6230,7 +6268,7 @@ namespace Catch { void cleanUpContext() { delete currentContext; - currentContext = NULL; + currentContext = CATCH_NULL; } } @@ -6640,6 +6678,21 @@ namespace Catch { return TestCase( _testCase, info ); } + void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ) + { + testCaseInfo.tags = tags; + testCaseInfo.lcaseTags.clear(); + + std::ostringstream oss; + for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { + oss << "[" << *it << "]"; + std::string lcaseTag = toLower( *it ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.insert( lcaseTag ); + } + testCaseInfo.tagsAsString = oss.str(); + } + TestCaseInfo::TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, @@ -6648,18 +6701,10 @@ namespace Catch { : name( _name ), className( _className ), description( _description ), - tags( _tags ), lineInfo( _lineInfo ), properties( None ) { - std::ostringstream oss; - for( std::set::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) { - oss << "[" << *it << "]"; - std::string lcaseTag = toLower( *it ); - properties = static_cast( properties | parseSpecialTag( lcaseTag ) ); - lcaseTags.insert( lcaseTag ); - } - tagsAsString = oss.str(); + setTags( *this, _tags ); } TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) @@ -6767,7 +6812,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "", 0 ); + Version libraryVersion( 1, 2, 1, "develop", 1 ); } @@ -6960,7 +7005,7 @@ namespace Catch { #else uint64_t getCurrentTicks() { timeval t; - gettimeofday(&t,NULL); + gettimeofday(&t,CATCH_NULL); return static_cast( t.tv_sec ) * 1000000ull + static_cast( t.tv_usec ); } #endif @@ -7151,7 +7196,7 @@ namespace Catch { // Call sysctl. size = sizeof(info); - if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; return false; } @@ -7872,7 +7917,7 @@ namespace Catch { ScopedElement( ScopedElement const& other ) : m_writer( other.m_writer ){ - other.m_writer = NULL; + other.m_writer = CATCH_NULL; } ~ScopedElement() { From d87e551efabb32bb08cd9abff51bb0c47fe6081c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 2 Jul 2015 23:02:35 +0100 Subject: [PATCH 05/87] reseeds rng before each test case and provides access to seed through Catch::rngSeed() function --- include/catch_runner.hpp | 2 +- include/internal/catch_common.h | 5 +++++ include/internal/catch_common.hpp | 8 ++++++++ include/internal/catch_runner_impl.hpp | 2 ++ include/internal/catch_test_case_registry_impl.hpp | 2 ++ 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/include/catch_runner.hpp b/include/catch_runner.hpp index 3a674148..18754483 100644 --- a/include/catch_runner.hpp +++ b/include/catch_runner.hpp @@ -198,7 +198,7 @@ namespace Catch { if( m_configData.filenamesAsTags ) applyFilenamesAsTags(); - std::srand( m_configData.rngSeed ); + seedRng( *m_config ); Runner runner( m_config ); diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 9f07e47c..cec7eba5 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -22,6 +22,8 @@ #include "catch_compiler_capabilities.h" namespace Catch { + + struct IConfig; class NonCopyable { #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS @@ -109,6 +111,9 @@ namespace Catch { void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as diff --git a/include/internal/catch_common.hpp b/include/internal/catch_common.hpp index 8a42d0a0..69a64ad1 100644 --- a/include/internal/catch_common.hpp +++ b/include/internal/catch_common.hpp @@ -82,6 +82,14 @@ namespace Catch { return line < other.line || ( line == other.line && file < other.file ); } + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { #ifndef __GNUG__ os << info.file << "(" << info.line << ")"; diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index 98f3dfd1..073f78d3 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -259,6 +259,8 @@ namespace Catch { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); TestCaseTracker::Guard guard( *m_testCaseTracker ); + seedRng( *m_config ); + Timer timer; timer.start(); if( m_reporter->getPreferences().shouldRedirectStdOut ) { diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 21165a30..b25ed9a2 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -90,6 +90,8 @@ namespace Catch { break; case RunTests::InRandomOrder: { + seedRng( config ); + RandomNumberGenerator rng; std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng ); } From 8f66e3495bd8c161683ef7dacefbce1c2ee69ddf Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 2 Jul 2015 23:03:13 +0100 Subject: [PATCH 06/87] dev build 2 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 25 +++++++++++++++++++++---- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c9d9f6c3..4fee77e6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.1* +*v1.2.1-develop.2* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index bf57c617..fbd96d49 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 1 ); + Version libraryVersion( 1, 2, 1, "develop", 2 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index b06810f6..713dc02b 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.1 - * Generated: 2015-07-02 08:21:11.983471 + * Catch v1.2.1-develop.2 + * Generated: 2015-07-02 23:02:49.715552 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -233,6 +233,8 @@ namespace Catch { + struct IConfig; + class NonCopyable { #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; @@ -319,6 +321,9 @@ namespace Catch { void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); + void seedRng( IConfig const& config ); + unsigned int rngSeed(); + // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as @@ -5388,6 +5393,8 @@ namespace Catch { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); TestCaseTracker::Guard guard( *m_testCaseTracker ); + seedRng( *m_config ); + Timer timer; timer.start(); if( m_reporter->getPreferences().shouldRedirectStdOut ) { @@ -5697,7 +5704,7 @@ namespace Catch { if( m_configData.filenamesAsTags ) applyFilenamesAsTags(); - std::srand( m_configData.rngSeed ); + seedRng( *m_config ); Runner runner( m_config ); @@ -5822,6 +5829,8 @@ namespace Catch { break; case RunTests::InRandomOrder: { + seedRng( config ); + RandomNumberGenerator rng; std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng ); } @@ -6812,7 +6821,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 1 ); + Version libraryVersion( 1, 2, 1, "develop", 2 ); } @@ -7104,6 +7113,14 @@ namespace Catch { return line < other.line || ( line == other.line && file < other.file ); } + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { #ifndef __GNUG__ os << info.file << "(" << info.line << ")"; From 6160a2b0796c73e64916f2602c9b6410c8b00bb6 Mon Sep 17 00:00:00 2001 From: csa Date: Fri, 3 Jul 2015 12:02:40 +0200 Subject: [PATCH 07/87] Fix for white background in windows powershell when using colour output. This commit fixes the white background that appears in windows powershell when catch outputs messages with colour. The previous implementation ignored the original background colour and defaulted to a white background. --- include/internal/catch_console_colour_impl.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/include/internal/catch_console_colour_impl.hpp b/include/internal/catch_console_colour_impl.hpp index 2c4b36c3..9ca915ff 100644 --- a/include/internal/catch_console_colour_impl.hpp +++ b/include/internal/catch_console_colour_impl.hpp @@ -60,12 +60,13 @@ namespace { { CONSOLE_SCREEN_BUFFER_INFO csbiInfo; GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalAttributes = csbiInfo.wAttributes; + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); } virtual void use( Colour::Code _colourCode ) { switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalAttributes ); + case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::Red: return setTextAttribute( FOREGROUND_RED ); case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); @@ -85,10 +86,11 @@ namespace { private: void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); } HANDLE stdoutHandle; - WORD originalAttributes; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; }; IColourImpl* platformColourInstance() { From 62e517f83325ece83f65b14a01283b5e5c001160 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 3 Jul 2015 18:07:13 +0100 Subject: [PATCH 08/87] Fixed backslash detection in filenames-as-tags --- include/catch_runner.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/catch_runner.hpp b/include/catch_runner.hpp index 18754483..4234f601 100644 --- a/include/catch_runner.hpp +++ b/include/catch_runner.hpp @@ -112,7 +112,7 @@ namespace Catch { std::set tags = test.tags; std::string filename = test.lineInfo.file; - std::string::size_type lastSlash = filename.find_last_of( "\//" ); + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); if( lastSlash != std::string::npos ) filename = filename.substr( lastSlash+1 ); From d6f1446e4e5dc36af5e760d41f5edd7f361abda2 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 3 Jul 2015 18:27:36 +0100 Subject: [PATCH 09/87] Fixed an issue on some compilers with implicit conversion from nullptr to Ptr - also cleaned up some warnings to do with CATCH_NULL --- include/internal/catch_runner_impl.hpp | 2 +- projects/SelfTest/CmdLineTests.cpp | 3 +++ projects/SelfTest/ConditionTests.cpp | 3 ++- projects/SelfTest/SectionTrackerTests.cpp | 3 ++- projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp | 2 ++ projects/SelfTest/TestMain.cpp | 5 +++-- 6 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index 073f78d3..39b9888b 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -78,7 +78,7 @@ namespace Catch { virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); m_context.setRunner( m_prevRunner ); - m_context.setConfig( CATCH_NULL ); + m_context.setConfig( Ptr() ); m_context.setResultCapture( m_prevResultCapture ); m_context.setConfig( m_prevConfig ); } diff --git a/projects/SelfTest/CmdLineTests.cpp b/projects/SelfTest/CmdLineTests.cpp index 955bcd3d..719c89b8 100644 --- a/projects/SelfTest/CmdLineTests.cpp +++ b/projects/SelfTest/CmdLineTests.cpp @@ -9,6 +9,9 @@ #include "catch.hpp" #include "catch_test_spec_parser.hpp" +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wc++98-compat" +#endif inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ return Catch::makeTestCase( CATCH_NULL, "", name, desc, CATCH_INTERNAL_LINEINFO ); } diff --git a/projects/SelfTest/ConditionTests.cpp b/projects/SelfTest/ConditionTests.cpp index 910021ce..195188ac 100644 --- a/projects/SelfTest/ConditionTests.cpp +++ b/projects/SelfTest/ConditionTests.cpp @@ -6,7 +6,8 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" #endif #include "catch.hpp" diff --git a/projects/SelfTest/SectionTrackerTests.cpp b/projects/SelfTest/SectionTrackerTests.cpp index 03d856d8..96e96f5e 100644 --- a/projects/SelfTest/SectionTrackerTests.cpp +++ b/projects/SelfTest/SectionTrackerTests.cpp @@ -7,7 +7,8 @@ */ #ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" #endif #include "internal/catch_test_case_tracker.hpp" diff --git a/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp b/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp index ca853847..15328efe 100644 --- a/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_xmlwriter.cpp @@ -1,2 +1,4 @@ // This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" #include "catch_xmlwriter.hpp" +#include "catch_reenable_warnings.h" diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index dae87f0c..bb2cf417 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -16,8 +16,9 @@ CATCH_REGISTER_TAG_ALIAS( "[@tricky]", "[tricky]~[.]" ) #ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" -#pragma clang diagnostic ignored "-Wweak-vtables" +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wweak-vtables" +# pragma clang diagnostic ignored "-Wc++98-compat" #endif From c1ca0fdabe8def3e67d42b275d51ac383fd5819f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 3 Jul 2015 18:30:25 +0100 Subject: [PATCH 10/87] dev build 3 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 4fee77e6..32ef40df 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.2* +*v1.2.1-develop.3* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index fbd96d49..879b671d 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 2 ); + Version libraryVersion( 1, 2, 1, "develop", 3 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 713dc02b..d5811f84 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.2 - * Generated: 2015-07-02 23:02:49.715552 + * Catch v1.2.1-develop.3 + * Generated: 2015-07-03 18:29:49.753953 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -5213,7 +5213,7 @@ namespace Catch { virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); m_context.setRunner( m_prevRunner ); - m_context.setConfig( CATCH_NULL ); + m_context.setConfig( Ptr() ); m_context.setResultCapture( m_prevResultCapture ); m_context.setConfig( m_prevConfig ); } @@ -5618,7 +5618,7 @@ namespace Catch { std::set tags = test.tags; std::string filename = test.lineInfo.file; - std::string::size_type lastSlash = filename.find_last_of( "\//" ); + std::string::size_type lastSlash = filename.find_last_of( "\\/" ); if( lastSlash != std::string::npos ) filename = filename.substr( lastSlash+1 ); @@ -6821,7 +6821,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 2 ); + Version libraryVersion( 1, 2, 1, "develop", 3 ); } From 584032dfa4b66a2610049645480fc7846d735b79 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 6 Jul 2015 06:22:28 +0100 Subject: [PATCH 11/87] dev build 4 - undisturbed background colour (windows), from PR #456 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 16 +++++++++------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 32ef40df..6c46344f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.3* +*v1.2.1-develop.4* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 879b671d..a3cac3f6 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 3 ); + Version libraryVersion( 1, 2, 1, "develop", 4 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index d5811f84..05bf3471 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.3 - * Generated: 2015-07-03 18:29:49.753953 + * Catch v1.2.1-develop.4 + * Generated: 2015-07-06 06:21:18.816844 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -6333,12 +6333,13 @@ namespace { { CONSOLE_SCREEN_BUFFER_INFO csbiInfo; GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); - originalAttributes = csbiInfo.wAttributes; + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); } virtual void use( Colour::Code _colourCode ) { switch( _colourCode ) { - case Colour::None: return setTextAttribute( originalAttributes ); + case Colour::None: return setTextAttribute( originalForegroundAttributes ); case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); case Colour::Red: return setTextAttribute( FOREGROUND_RED ); case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); @@ -6358,10 +6359,11 @@ namespace { private: void setTextAttribute( WORD _textAttribute ) { - SetConsoleTextAttribute( stdoutHandle, _textAttribute ); + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); } HANDLE stdoutHandle; - WORD originalAttributes; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; }; IColourImpl* platformColourInstance() { @@ -6821,7 +6823,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 3 ); + Version libraryVersion( 1, 2, 1, "develop", 4 ); } From 02e1966db3fc28cc7a61d731bb6dd7ed645cc9b2 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 6 Jul 2015 18:46:50 +0100 Subject: [PATCH 12/87] Changed --filenames-as-tags prefix to #, added -# as short form and updated docs --- docs/test-cases-and-sections.md | 30 ++++++++++++++++++++++++-- include/catch_runner.hpp | 2 +- include/internal/catch_commandline.hpp | 8 +++---- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/docs/test-cases-and-sections.md b/docs/test-cases-and-sections.md index 28426d78..86644f00 100644 --- a/docs/test-cases-and-sections.md +++ b/docs/test-cases-and-sections.md @@ -28,10 +28,36 @@ The tag expression, ```"[widget]"``` selects A, B & D. ```"[gadget]"``` selects For more detail on command line selection see [the command line docs](command-line.md#specifying-which-tests-to-run) -A special tag name, ```[hide]``` causes test cases to be skipped from the default list (ie when no test cases have been explicitly selected through tag expressions or name wildcards). ```[.]``` is an alias for ```[hide]```. - Tag names are not case sensitive. +### Special Tags + +All tag names beginning with non-alphanumeric characters are reserved by Catch. Catch defines a number of "special" tags, which have meaning to the test runner itself. These special tags all begin with a symbol character. Following is a list of currently defined special tags and their meanings. + +* `[!hide]` or `[.]` (or, for legacy reasons, `[hide]`) - causes test cases to be skipped from the default list (ie when no test cases have been explicitly selected through tag expressions or name wildcards). The hide tag is often combined with another, user, tag (for example `[.][integration]` - so all integration tests are excluded from the default run but can be run by passing `[integration]` on the command line). As a short-cut you can combine these by simply prefixing your user tag with a `.` - e.g. `[.integration]`. Because the hide tag has evolved to have several forms, all forms are added as tags if you use one of them. + +* `[!throws]` - lets Catch know that this test is likely to throw an exception even if successful. This causes the test to be exluded when running with `-e` or `--nothrow`. + +* `[!shouldfail]` - reverse the failing logic of the test: if the test is successful if it fails, and vice-versa. + +* `[!mayfail]` - doesn't fail the test if any given assertion fails (but still reports it). This can be useful to flag a work-in-progress, or a known issue that you don't want to immediately fix but still want to track in the your tests. + +* `[#]` - running with `-#` or `--filenames-as-tags` causes Catch to add the filename, prefixed with `#` (and with any extension stripped) as a tag. e.g. tests in testfile.cpp would all be tagged `[#testfile]`. + +* `[@]` - tag aliases all begin with `@` (see below). + +## Tag aliases + +Between tag expressions and wildcarded test names (as well as combinations of the two) quite complex patterns can be constructed to direct which test cases are run. If a complex pattern is used often it is convenient to be able to create an alias for the expression. this can be done, in code, using the following form: + + CATCH_REGISTER_TAG_ALIAS( , ) + +Aliases must begining with the `@` character. An example of a tag alias is: + + CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" ) + +Now when `[@nhf]` is used on the command line this matches all tests that are tagged `[failing]`, but which are not also hidden. + ## BDD-style test cases In addition to Catch's take on the classic style of test cases, Catch supports an alternative syntax that allow tests to be written as "executable specifications" (one of the early goals of [Behaviour Driven Development](http://dannorth.net/introducing-bdd/)). This set of macros map on to ```TEST_CASE```s and ```SECTION```s, with a little internal support to make them smoother to work with. diff --git a/include/catch_runner.hpp b/include/catch_runner.hpp index 4234f601..ac7a9148 100644 --- a/include/catch_runner.hpp +++ b/include/catch_runner.hpp @@ -120,7 +120,7 @@ namespace Catch { if( lastDot != std::string::npos ) filename = filename.substr( 0, lastDot ); - tags.insert( "@" + filename ); + tags.insert( "#" + filename ); setTags( test, tags ); } } diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index d05cee96..d48d0d14 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -153,6 +153,10 @@ namespace Catch { .describe( "load test names to run from a file" ) .bind( &loadTestNamesFromFile, "filename" ); + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + // Less common commands which don't have a short form cli["--list-test-names-only"] .describe( "list all/matching test cases names only" ) @@ -173,10 +177,6 @@ namespace Catch { cli["--force-colour"] .describe( "force colourised output" ) .bind( &ConfigData::forceColour ); - - cli["--filenames-as-tags"] - .describe( "adds a tag for the filename" ) - .bind( &ConfigData::filenamesAsTags ); return cli; } From e6b365dc8cdc40b9f7875450765d8aa26fa178f9 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 7 Jul 2015 08:25:15 +0100 Subject: [PATCH 13/87] dev build 5 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 16 ++++++++-------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6c46344f..2d0e2a8a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.4* +*v1.2.1-develop.5* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index a3cac3f6..015ebdf2 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 4 ); + Version libraryVersion( 1, 2, 1, "develop", 5 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 05bf3471..c42c72df 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.4 - * Generated: 2015-07-06 06:21:18.816844 + * Catch v1.2.1-develop.5 + * Generated: 2015-07-07 08:24:50.226161 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -4279,6 +4279,10 @@ namespace Catch { .describe( "load test names to run from a file" ) .bind( &loadTestNamesFromFile, "filename" ); + cli["-#"]["--filenames-as-tags"] + .describe( "adds a tag for the filename" ) + .bind( &ConfigData::filenamesAsTags ); + // Less common commands which don't have a short form cli["--list-test-names-only"] .describe( "list all/matching test cases names only" ) @@ -4300,10 +4304,6 @@ namespace Catch { .describe( "force colourised output" ) .bind( &ConfigData::forceColour ); - cli["--filenames-as-tags"] - .describe( "adds a tag for the filename" ) - .bind( &ConfigData::filenamesAsTags ); - return cli; } @@ -5626,7 +5626,7 @@ namespace Catch { if( lastDot != std::string::npos ) filename = filename.substr( 0, lastDot ); - tags.insert( "@" + filename ); + tags.insert( "#" + filename ); setTags( test, tags ); } } @@ -6823,7 +6823,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 4 ); + Version libraryVersion( 1, 2, 1, "develop", 5 ); } From 57df3ba9982e15e8b90a697b98a5c7b6bcf8b97e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 10 Jul 2015 07:44:37 +0100 Subject: [PATCH 14/87] Force cout/ cerr to be initialised before errors in test registry are printed - see #461 --- include/internal/catch_test_case_registry_impl.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index b25ed9a2..41170052 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -105,6 +105,7 @@ namespace Catch { std::vector m_functionsInOrder; std::vector m_nonHiddenFunctions; size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; /////////////////////////////////////////////////////////////////////////// From 5d5ed5a28356434d13b72eb5970947f6b4186059 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 10 Jul 2015 08:08:37 +0100 Subject: [PATCH 15/87] Updated approvalTests script to allow for modified version strings --- scripts/approvalTests.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/approvalTests.py b/scripts/approvalTests.py index 92e2876c..618812f8 100644 --- a/scripts/approvalTests.py +++ b/scripts/approvalTests.py @@ -15,7 +15,8 @@ pathParser = re.compile( r'(.*?)/(.*\..pp)(.*)' ) lineNumberParser = re.compile( r'(.*)line="[0-9]*"(.*)' ) hexParser = re.compile( r'(.*)\b(0[xX][0-9a-fA-F]+)\b(.*)' ) durationsParser = re.compile( r'(.*)time="[0-9]*\.[0-9]*"(.*)' ) -versionParser = re.compile( r'(.*?)Catch v[0-9]*\.[0-9]*\.[0-9].?( .*)' ) +versionParser = re.compile( r'(.*?)Catch v[0-9]*\.[0-9]*\.[0-9]*(.*)' ) +devVersionParser = re.compile( r'(.*?)Catch v[0-9]*\.[0-9]*\.[0-9]*-develop\.[0-9]*(.*)' ) if len(sys.argv) == 2: cmdPath = sys.argv[1] @@ -41,9 +42,13 @@ def filterLine( line ): if path.startswith( catchPath ): path = path[1+len(catchPath):] line = m.group(1) + path + m.group(3) - m = versionParser.match( line ) + m = devVersionParser.match( line ) if m: line = m.group(1) + "" + m.group(2) + else: + m = versionParser.match( line ) + if m: + line = m.group(1) + "" + m.group(2) while True: m = hexParser.match( line ) From 85de743d70186a9b1a18ab226389aa0af6d4abc0 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 13 Jul 2015 06:34:41 +0100 Subject: [PATCH 16/87] Added _THROWS_WITH macros - asserts on exception message --- include/catch.hpp | 10 ++++-- include/internal/catch_capture.hpp | 6 ++-- include/internal/catch_result_builder.h | 5 ++- include/internal/catch_result_builder.hpp | 33 +++++++++++++++++-- .../Baselines/console.std.approved.txt | 15 +++++++-- .../Baselines/console.sw.approved.txt | 19 +++++++++-- .../SelfTest/Baselines/junit.sw.approved.txt | 7 +++- .../SelfTest/Baselines/xml.sw.approved.txt | 23 +++++++++++-- projects/SelfTest/ExceptionTests.cpp | 5 +++ 9 files changed, 106 insertions(+), 17 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index f6359c02..505fa19b 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -70,8 +70,9 @@ #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "CATCH_REQUIRE_THROWS_WITH" ) #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) @@ -82,6 +83,7 @@ #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CATCH_CHECK_THROWS_WITH" ) #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) @@ -135,8 +137,9 @@ #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "REQUIRE_THROWS_WITH" ) #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) @@ -145,8 +148,9 @@ #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CHECK_THROWS_WITH" ) #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 7bfef0e1..3858261a 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -66,16 +66,16 @@ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \ +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, expectedMessage, macroName ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, expectedMessage ); \ if( __catchResult.allowThrows() ) \ try { \ expr; \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ + __catchResult.captureExpectedException( expectedMessage ); \ } \ else \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index b44882bb..c8cd92eb 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -38,7 +38,8 @@ namespace Catch { ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, - ResultDisposition::Flags resultDisposition ); + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); template ExpressionLhs operator <= ( T const& operand ); @@ -67,6 +68,8 @@ namespace Catch { void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); void captureResult( ResultWas::OfType resultType ); void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void handleResult( AssertionResult const& result ); void react(); bool shouldDebugBreak() const; bool allowThrows() const; diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp index 8ce4a4fb..cc083bce 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.hpp @@ -18,11 +18,17 @@ namespace Catch { + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() + ? capturedExpression + : capturedExpression + ", \"" + secondArg + "\""; + } ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, - ResultDisposition::Flags resultDisposition ) - : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ), + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), m_shouldDebugBreak( false ), m_shouldThrow( false ) {} @@ -64,10 +70,31 @@ namespace Catch { captureExpression(); } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + if( expectedMessage != "" ) { + + std::string actualMessage = Catch::translateActiveException(); + if( expectedMessage != actualMessage ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + void ResultBuilder::captureExpression() { AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { getResultCapture().assertionEnded( result ); - + if( !result.isOk() ) { if( getCurrentContext().getConfig()->shouldDebugBreak() ) m_shouldDebugBreak = true; diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 3fc76122..de86a473 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -397,6 +397,17 @@ ExceptionTests.cpp:: FAILED: due to unexpected exception with message: 3.14 +------------------------------------------------------------------------------- +Exception messages can be tested for +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) +with expansion: + expected exception + ------------------------------------------------------------------------------- INFO and WARN do not abort tests ------------------------------------------------------------------------------- @@ -786,6 +797,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 155 | 116 passed | 38 failed | 1 failed as expected -assertions: 765 | 673 passed | 79 failed | 13 failed as expected +test cases: 156 | 116 passed | 39 failed | 1 failed as expected +assertions: 767 | 674 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 2023c59b..6e191f56 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1277,6 +1277,21 @@ ExceptionTests.cpp:: PASSED: REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ) +------------------------------------------------------------------------------- +Exception messages can be tested for +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + +ExceptionTests.cpp:: FAILED: + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ) +with expansion: + expected exception + ------------------------------------------------------------------------------- Generators over two ranges ------------------------------------------------------------------------------- @@ -7944,6 +7959,6 @@ with expansion: true =============================================================================== -test cases: 155 | 100 passed | 54 failed | 1 failed as expected -assertions: 785 | 673 passed | 99 failed | 13 failed as expected +test cases: 156 | 100 passed | 55 failed | 1 failed as expected +assertions: 787 | 674 passed | 100 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 48b84679..36e31fe8 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -251,6 +251,11 @@ ExceptionTests.cpp: + + +ExceptionTests.cpp: + + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 974559a2..01144a0d 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1596,6 +1596,25 @@ + + + + thisThrows(), "expected exception" + + + thisThrows(), "expected exception" + + + + + thisThrows(), "should fail" + + + expected exception + + + + @@ -8220,7 +8239,7 @@ there" - + - + diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index 7de1d179..eb24160b 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -152,3 +152,8 @@ TEST_CASE( "NotImplemented exception", "" ) { REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ); } + +TEST_CASE( "Exception messages can be tested for", "[.][failing]" ) { + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); + REQUIRE_THROWS_WITH( thisThrows(), "should fail" ); +} From 93a842e2f0e9c51296cfbc81c27004e515643050 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 13 Jul 2015 06:36:07 +0100 Subject: [PATCH 17/87] dev build 6 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 59 ++++++++++++++++++++++++------ 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 2d0e2a8a..44ace893 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.5* +*v1.2.1-develop.6* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 015ebdf2..76210de7 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 5 ); + Version libraryVersion( 1, 2, 1, "develop", 6 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index c42c72df..7a0e758a 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.5 - * Generated: 2015-07-07 08:24:50.226161 + * Catch v1.2.1-develop.6 + * Generated: 2015-07-13 06:35:13.441019 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -796,7 +796,8 @@ namespace Catch { ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, - ResultDisposition::Flags resultDisposition ); + ResultDisposition::Flags resultDisposition, + char const* secondArg = "" ); template ExpressionLhs operator <= ( T const& operand ); @@ -825,6 +826,8 @@ namespace Catch { void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); void captureResult( ResultWas::OfType resultType ); void captureExpression(); + void captureExpectedException( std::string const& expectedMessage ); + void handleResult( AssertionResult const& result ); void react(); bool shouldDebugBreak() const; bool allowThrows() const; @@ -1616,16 +1619,16 @@ namespace Catch { } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \ +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, expectedMessage, macroName ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, expectedMessage ); \ if( __catchResult.allowThrows() ) \ try { \ expr; \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ - __catchResult.captureResult( Catch::ResultWas::Ok ); \ + __catchResult.captureExpectedException( expectedMessage ); \ } \ else \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ @@ -5844,6 +5847,7 @@ namespace Catch { std::vector m_functionsInOrder; std::vector m_nonHiddenFunctions; size_t m_unnamedCount; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; /////////////////////////////////////////////////////////////////////////// @@ -6823,7 +6827,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 5 ); + Version libraryVersion( 1, 2, 1, "develop", 6 ); } @@ -7440,11 +7444,17 @@ std::string toString( std::nullptr_t ) { namespace Catch { + std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { + return secondArg.empty() + ? capturedExpression + : capturedExpression + ", \"" + secondArg + "\""; + } ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, char const* capturedExpression, - ResultDisposition::Flags resultDisposition ) - : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ), + ResultDisposition::Flags resultDisposition, + char const* secondArg ) + : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ), m_shouldDebugBreak( false ), m_shouldThrow( false ) {} @@ -7486,8 +7496,29 @@ namespace Catch { captureExpression(); } + void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + assert( m_exprComponents.testFalse == false ); + AssertionResultData data = m_data; + data.resultType = ResultWas::Ok; + data.reconstructedExpression = m_assertionInfo.capturedExpression; + if( expectedMessage != "" ) { + + std::string actualMessage = Catch::translateActiveException(); + if( expectedMessage != actualMessage ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; + } + } + AssertionResult result( m_assertionInfo, data ); + handleResult( result ); + } + void ResultBuilder::captureExpression() { AssertionResult result = build(); + handleResult( result ); + } + void ResultBuilder::handleResult( AssertionResult const& result ) + { getResultCapture().assertionEnded( result ); if( !result.isOk() ) { @@ -9332,8 +9363,9 @@ int main (int argc, char * const argv[]) { #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" ) #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" ) -#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" ) +#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "CATCH_REQUIRE_THROWS_WITH" ) #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) @@ -9344,6 +9376,7 @@ int main (int argc, char * const argv[]) { #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) +#define CATCH_CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CATCH_CHECK_THROWS_WITH" ) #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) @@ -9397,8 +9430,9 @@ int main (int argc, char * const argv[]) { #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" ) #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" ) -#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" ) +#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) +#define REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "REQUIRE_THROWS_WITH" ) #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) @@ -9407,8 +9441,9 @@ int main (int argc, char * const argv[]) { #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" ) #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" ) -#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" ) +#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) +#define CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CHECK_THROWS_WITH" ) #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) From 2104ca2aa49712dbfac022d5afe681305b8acb3f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 13 Jul 2015 15:03:04 +0100 Subject: [PATCH 18/87] Exception message testing now supports wildcards - extracted WildcardPattern from TestSpec::NamePattern --- include/internal/catch_impl.hpp | 1 + include/internal/catch_result_builder.hpp | 5 +- include/internal/catch_test_spec.hpp | 48 +++--------- include/internal/catch_wildcard_pattern.hpp | 75 +++++++++++++++++++ .../Baselines/console.std.approved.txt | 6 +- .../Baselines/console.sw.approved.txt | 53 ++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 7 +- .../SelfTest/Baselines/xml.sw.approved.txt | 72 +++++++++++++++++- projects/SelfTest/ExceptionTests.cpp | 16 +++- .../CatchSelfTest.xcodeproj/project.pbxproj | 2 + 10 files changed, 234 insertions(+), 51 deletions(-) create mode 100644 include/internal/catch_wildcard_pattern.hpp diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 24a8c3f8..62fdcaea 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -77,6 +77,7 @@ namespace Catch { FreeFunctionTestCase::~FreeFunctionTestCase() {} IGeneratorInfo::~IGeneratorInfo() {} IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} TestSpec::Pattern::~Pattern() {} TestSpec::NamePattern::~NamePattern() {} TestSpec::TagPattern::~TagPattern() {} diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp index cc083bce..ae86d768 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.hpp @@ -14,7 +14,7 @@ #include "catch_interfaces_runner.h" #include "catch_interfaces_capture.h" #include "catch_interfaces_registry_hub.h" - +#include "catch_wildcard_pattern.hpp" namespace Catch { @@ -78,7 +78,8 @@ namespace Catch { if( expectedMessage != "" ) { std::string actualMessage = Catch::translateActiveException(); - if( expectedMessage != actualMessage ) { + WildcardPattern pattern( expectedMessage, WildcardPattern::CaseInsensitive ); + if( !pattern.matches( actualMessage ) ) { data.resultType = ResultWas::ExpressionFailed; data.reconstructedExpression = actualMessage; } diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.hpp index b5f70635..292ffce4 100644 --- a/include/internal/catch_test_spec.hpp +++ b/include/internal/catch_test_spec.hpp @@ -13,63 +13,32 @@ #pragma clang diagnostic ignored "-Wpadded" #endif +#include "catch_wildcard_pattern.hpp" #include "catch_test_case_info.h" #include #include namespace Catch { - + class TestSpec { struct Pattern : SharedImpl<> { virtual ~Pattern(); virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; class NamePattern : public Pattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - public: - NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { - if( startsWith( m_name, "*" ) ) { - m_name = m_name.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_name, "*" ) ) { - m_name = m_name.substr( 0, m_name.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), WildcardPattern::CaseInsensitive ) + {} virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_name == toLower( testCase.name ); - case WildcardAtStart: - return endsWith( toLower( testCase.name ), m_name ); - case WildcardAtEnd: - return startsWith( toLower( testCase.name ), m_name ); - case WildcardAtBothEnds: - return contains( toLower( testCase.name ), m_name ); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif + return m_wildcardPattern.matches( toLower( testCase.name ) ); } private: - std::string m_name; - WildcardPosition m_wildcard; + WildcardPattern m_wildcardPattern; }; + class TagPattern : public Pattern { public: TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} @@ -80,6 +49,7 @@ namespace Catch { private: std::string m_tag; }; + class ExcludedPattern : public Pattern { public: ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} diff --git a/include/internal/catch_wildcard_pattern.hpp b/include/internal/catch_wildcard_pattern.hpp new file mode 100644 index 00000000..f42dc5d0 --- /dev/null +++ b/include/internal/catch_wildcard_pattern.hpp @@ -0,0 +1,75 @@ +/* + * Created by Phil on 13/7/2015. + * Copyright 2015 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +#include "catch_common.h" + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + enum CaseSensitivity { + CaseSensitive, + CaseInsensitive + }; + WildcardPattern( std::string const& pattern, CaseSensitivity caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseInsensitive ? toLower( str ) : str; + } + CaseSensitivity m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + +#endif // TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index de86a473..63530052 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -398,7 +398,7 @@ due to unexpected exception with message: 3.14 ------------------------------------------------------------------------------- -Exception messages can be tested for +Mismatching exception messages failing the test ------------------------------------------------------------------------------- ExceptionTests.cpp: ............................................................................... @@ -797,6 +797,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 156 | 116 passed | 39 failed | 1 failed as expected -assertions: 767 | 674 passed | 80 failed | 13 failed as expected +test cases: 157 | 117 passed | 39 failed | 1 failed as expected +assertions: 774 | 681 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 6e191f56..1919c1c2 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1279,10 +1279,59 @@ PASSED: ------------------------------------------------------------------------------- Exception messages can be tested for + exact match ------------------------------------------------------------------------------- ExceptionTests.cpp: ............................................................................... +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + different case +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expecteD Exception" ) + +------------------------------------------------------------------------------- +Exception messages can be tested for + wildcarded +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected*" ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "*exception" ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "*except*" ) + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "*exCept*" ) + +------------------------------------------------------------------------------- +Mismatching exception messages failing the test +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: +PASSED: + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) + ExceptionTests.cpp:: PASSED: REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) @@ -7959,6 +8008,6 @@ with expansion: true =============================================================================== -test cases: 156 | 100 passed | 55 failed | 1 failed as expected -assertions: 787 | 674 passed | 100 failed | 13 failed as expected +test cases: 157 | 101 passed | 55 failed | 1 failed as expected +assertions: 794 | 681 passed | 100 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 36e31fe8..95d4f9a2 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -251,7 +251,10 @@ ExceptionTests.cpp: - + + + + ExceptionTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 01144a0d..0d06a704 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1597,6 +1597,74 @@ +
+ + + thisThrows(), "expected exception" + + + thisThrows(), "expected exception" + + + +
+
+ + + thisThrows(), "expecteD Exception" + + + thisThrows(), "expecteD Exception" + + + +
+
+ + + thisThrows(), "expected*" + + + thisThrows(), "expected*" + + + + + thisThrows(), "*exception" + + + thisThrows(), "*exception" + + + + + thisThrows(), "*except*" + + + thisThrows(), "*except*" + + + + + thisThrows(), "*exCept*" + + + thisThrows(), "*exCept*" + + + +
+ +
+ + + + thisThrows(), "expected exception" + + + thisThrows(), "expected exception" + + thisThrows(), "expected exception" @@ -8239,7 +8307,7 @@ there" - +
- + diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index eb24160b..f3b7f41d 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -153,7 +153,21 @@ TEST_CASE( "NotImplemented exception", "" ) REQUIRE_THROWS( thisFunctionNotImplemented( 7 ) ); } -TEST_CASE( "Exception messages can be tested for", "[.][failing]" ) { +TEST_CASE( "Exception messages can be tested for", "" ) { + SECTION( "exact match" ) + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); + SECTION( "different case" ) + REQUIRE_THROWS_WITH( thisThrows(), "expecteD Exception" ); + SECTION( "wildcarded" ) { + REQUIRE_THROWS_WITH( thisThrows(), "expected*" ); + REQUIRE_THROWS_WITH( thisThrows(), "*exception" ); + REQUIRE_THROWS_WITH( thisThrows(), "*except*" ); + REQUIRE_THROWS_WITH( thisThrows(), "*exCept*" ); + } +} + +TEST_CASE( "Mismatching exception messages failing the test", "[.][failing]" ) { + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); REQUIRE_THROWS_WITH( thisThrows(), "should fail" ); } diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index 047fa70e..47e8c66a 100644 --- a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -108,6 +108,7 @@ 269831E719121CA500BB0CE0 /* catch_reporter_compact.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_compact.hpp; sourceTree = ""; }; 26AEAF1617BEA18E009E32C9 /* catch_platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_platform.h; sourceTree = ""; }; 26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = ""; }; + 26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_wildcard_pattern.hpp; sourceTree = ""; }; 26E1B7D119213BC900812682 /* CmdLineTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CmdLineTests.cpp; path = ../../../SelfTest/CmdLineTests.cpp; sourceTree = ""; }; 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = ""; }; 4A3D7DD01503869D005F9203 /* catch_matchers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_matchers.hpp; sourceTree = ""; }; @@ -470,6 +471,7 @@ 2656C226192A77EF0040DB02 /* catch_suppress_warnings.h */, 2656C227192A78410040DB02 /* catch_reenable_warnings.h */, 263F7A4519A66608009474C2 /* catch_fatal_condition.hpp */, + 26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */, ); name = Infrastructure; sourceTree = ""; From 8342ae8dfb61ca5d90821a6cd0c320da25f7f0cb Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 13 Jul 2015 15:03:26 +0100 Subject: [PATCH 19/87] dev build 7 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 120 +++++++++++++++++++---------- 3 files changed, 80 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 44ace893..aa00297a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.6* +*v1.2.1-develop.7* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 76210de7..2463e4d0 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 6 ); + Version libraryVersion( 1, 2, 1, "develop", 7 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 7a0e758a..7e5a3730 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.6 - * Generated: 2015-07-13 06:35:13.441019 + * Catch v1.2.1-develop.7 + * Generated: 2015-07-13 15:03:15.644872 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -2838,6 +2838,71 @@ return @ desc; \ #pragma clang diagnostic ignored "-Wpadded" #endif +// #included from: catch_wildcard_pattern.hpp +#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + enum CaseSensitivity { + CaseSensitive, + CaseInsensitive + }; + WildcardPattern( std::string const& pattern, CaseSensitivity caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_wildcard( NoWildcard ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, "*" ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + virtual ~WildcardPattern(); + virtual bool matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + } + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunreachable-code" +#endif + throw std::logic_error( "Unknown enum" ); +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + } + private: + std::string adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseInsensitive ? toLower( str ) : str; + } + CaseSensitivity m_caseSensitivity; + WildcardPosition m_wildcard; + std::string m_pattern; + }; +} + #include #include @@ -2849,50 +2914,18 @@ namespace Catch { virtual bool matches( TestCaseInfo const& testCase ) const = 0; }; class NamePattern : public Pattern { - enum WildcardPosition { - NoWildcard = 0, - WildcardAtStart = 1, - WildcardAtEnd = 2, - WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd - }; - public: - NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) { - if( startsWith( m_name, "*" ) ) { - m_name = m_name.substr( 1 ); - m_wildcard = WildcardAtStart; - } - if( endsWith( m_name, "*" ) ) { - m_name = m_name.substr( 0, m_name.size()-1 ); - m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); - } - } + NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), WildcardPattern::CaseInsensitive ) + {} virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const { - switch( m_wildcard ) { - case NoWildcard: - return m_name == toLower( testCase.name ); - case WildcardAtStart: - return endsWith( toLower( testCase.name ), m_name ); - case WildcardAtEnd: - return startsWith( toLower( testCase.name ), m_name ); - case WildcardAtBothEnds: - return contains( toLower( testCase.name ), m_name ); - } - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunreachable-code" -#endif - throw std::logic_error( "Unknown enum" ); -#ifdef __clang__ -#pragma clang diagnostic pop -#endif + return m_wildcardPattern.matches( toLower( testCase.name ) ); } private: - std::string m_name; - WildcardPosition m_wildcard; + WildcardPattern m_wildcardPattern; }; + class TagPattern : public Pattern { public: TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} @@ -2903,6 +2936,7 @@ namespace Catch { private: std::string m_tag; }; + class ExcludedPattern : public Pattern { public: ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} @@ -6827,7 +6861,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 6 ); + Version libraryVersion( 1, 2, 1, "develop", 7 ); } @@ -7504,7 +7538,8 @@ namespace Catch { if( expectedMessage != "" ) { std::string actualMessage = Catch::translateActiveException(); - if( expectedMessage != actualMessage ) { + WildcardPattern pattern( expectedMessage, WildcardPattern::CaseInsensitive ); + if( !pattern.matches( actualMessage ) ) { data.resultType = ResultWas::ExpressionFailed; data.reconstructedExpression = actualMessage; } @@ -9299,6 +9334,7 @@ namespace Catch { FreeFunctionTestCase::~FreeFunctionTestCase() {} IGeneratorInfo::~IGeneratorInfo() {} IGeneratorsForTest::~IGeneratorsForTest() {} + WildcardPattern::~WildcardPattern() {} TestSpec::Pattern::~Pattern() {} TestSpec::NamePattern::~NamePattern() {} TestSpec::TagPattern::~TagPattern() {} From 72868920bb44c07b632ac351f05485b5b189f970 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 15 Jul 2015 23:02:25 +0100 Subject: [PATCH 20/87] Exception message assertions now work with matchers --- include/catch.hpp | 8 +- include/internal/catch_capture.hpp | 6 +- include/internal/catch_common.h | 5 ++ include/internal/catch_matchers.hpp | 84 ++++++++++++------- include/internal/catch_result_builder.h | 2 + include/internal/catch_result_builder.hpp | 26 +++--- include/internal/catch_test_spec.hpp | 2 +- include/internal/catch_wildcard_pattern.hpp | 10 +-- .../Baselines/console.std.approved.txt | 2 +- .../Baselines/console.sw.approved.txt | 16 ++-- .../SelfTest/Baselines/junit.sw.approved.txt | 2 +- .../SelfTest/Baselines/xml.sw.approved.txt | 32 +++---- projects/SelfTest/ExceptionTests.cpp | 13 +-- 13 files changed, 116 insertions(+), 92 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 505fa19b..9d81143e 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -72,7 +72,7 @@ #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) -#define CATCH_REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) @@ -83,7 +83,7 @@ #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) -#define CATCH_CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) @@ -139,7 +139,7 @@ #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) -#define REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) @@ -150,7 +150,7 @@ #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) -#define CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CHECK_THROWS_WITH" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 3858261a..544fc120 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -66,16 +66,16 @@ } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, resultDisposition, expectedMessage, macroName ) \ +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, expectedMessage ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ if( __catchResult.allowThrows() ) \ try { \ expr; \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ - __catchResult.captureExpectedException( expectedMessage ); \ + __catchResult.captureExpectedException( matcher ); \ } \ else \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index cec7eba5..2ae79b18 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -25,6 +25,11 @@ namespace Catch { struct IConfig; + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + class NonCopyable { #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 028ff678..a959095e 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -108,68 +108,96 @@ namespace Matchers { inline std::string makeString( std::string const& str ) { return str; } inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + struct Equals : MatcherImpl { - Equals( std::string const& str ) : m_str( str ){} - Equals( Equals const& other ) : m_str( other.m_str ){} + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} virtual ~Equals(); virtual bool match( std::string const& expr ) const { - return m_str == expr; + return m_data.m_str == m_data.adjustString( expr );; } virtual std::string toString() const { - return "equals: \"" + m_str + "\""; + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); } - std::string m_str; + CasedString m_data; }; struct Contains : MatcherImpl { - Contains( std::string const& substr ) : m_substr( substr ){} - Contains( Contains const& other ) : m_substr( other.m_substr ){} + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} virtual ~Contains(); virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) != std::string::npos; + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; } virtual std::string toString() const { - return "contains: \"" + m_substr + "\""; + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); } - std::string m_substr; + CasedString m_data; }; struct StartsWith : MatcherImpl { - StartsWith( std::string const& substr ) : m_substr( substr ){} - StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} virtual ~StartsWith(); virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == 0; + return m_data.adjustString( expr ).find( m_data.m_str ) == 0; } virtual std::string toString() const { - return "starts with: \"" + m_substr + "\""; + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); } - std::string m_substr; + CasedString m_data; }; struct EndsWith : MatcherImpl { - EndsWith( std::string const& substr ) : m_substr( substr ){} - EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} virtual ~EndsWith(); virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == expr.size() - m_substr.size(); + return m_data.adjustString( expr ).find( m_data.m_str ) == expr.size() - m_data.m_str.size(); } virtual std::string toString() const { - return "ends with: \"" + m_substr + "\""; + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); } - std::string m_substr; + CasedString m_data; }; } // namespace StdString } // namespace Impl @@ -199,17 +227,17 @@ namespace Matchers { return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); } - inline Impl::StdString::Equals Equals( std::string const& str ) { - return Impl::StdString::Equals( str ); + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); } - inline Impl::StdString::Equals Equals( const char* str ) { - return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); } - inline Impl::StdString::Contains Contains( std::string const& substr ) { - return Impl::StdString::Contains( substr ); + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); } - inline Impl::StdString::Contains Contains( const char* substr ) { - return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); } inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { return Impl::StdString::StartsWith( substr ); diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index c8cd92eb..c27fe5c2 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -11,6 +11,7 @@ #include "catch_result_type.h" #include "catch_assertionresult.h" #include "catch_common.h" +#include "catch_matchers.hpp" namespace Catch { @@ -69,6 +70,7 @@ namespace Catch { void captureResult( ResultWas::OfType resultType ); void captureExpression(); void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher const& matcher ); void handleResult( AssertionResult const& result ); void react(); bool shouldDebugBreak() const; diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp index ae86d768..5e2ba32b 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.hpp @@ -19,9 +19,9 @@ namespace Catch { std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { - return secondArg.empty() + return secondArg.empty() || secondArg == "\"\"" ? capturedExpression - : capturedExpression + ", \"" + secondArg + "\""; + : capturedExpression + ", " + secondArg; } ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, @@ -69,20 +69,24 @@ namespace Catch { setResultType( resultType ); captureExpression(); } - void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + assert( m_exprComponents.testFalse == false ); AssertionResultData data = m_data; data.resultType = ResultWas::Ok; data.reconstructedExpression = m_assertionInfo.capturedExpression; - if( expectedMessage != "" ) { - - std::string actualMessage = Catch::translateActiveException(); - WildcardPattern pattern( expectedMessage, WildcardPattern::CaseInsensitive ); - if( !pattern.matches( actualMessage ) ) { - data.resultType = ResultWas::ExpressionFailed; - data.reconstructedExpression = actualMessage; - } + + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; } AssertionResult result( m_assertionInfo, data ); handleResult( result ); diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.hpp index 292ffce4..8428b09d 100644 --- a/include/internal/catch_test_spec.hpp +++ b/include/internal/catch_test_spec.hpp @@ -29,7 +29,7 @@ namespace Catch { class NamePattern : public Pattern { public: NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), WildcardPattern::CaseInsensitive ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) {} virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const { diff --git a/include/internal/catch_wildcard_pattern.hpp b/include/internal/catch_wildcard_pattern.hpp index f42dc5d0..a5e89b6e 100644 --- a/include/internal/catch_wildcard_pattern.hpp +++ b/include/internal/catch_wildcard_pattern.hpp @@ -22,11 +22,7 @@ namespace Catch public: - enum CaseSensitivity { - CaseSensitive, - CaseInsensitive - }; - WildcardPattern( std::string const& pattern, CaseSensitivity caseSensitivity ) + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) : m_caseSensitivity( caseSensitivity ), m_wildcard( NoWildcard ), m_pattern( adjustCase( pattern ) ) @@ -64,9 +60,9 @@ namespace Catch } private: std::string adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseInsensitive ? toLower( str ) : str; + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; } - CaseSensitivity m_caseSensitivity; + CaseSensitive::Choice m_caseSensitivity; WildcardPosition m_wildcard; std::string m_pattern; }; diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 63530052..67fb8437 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -798,5 +798,5 @@ with expansion: =============================================================================== test cases: 157 | 117 passed | 39 failed | 1 failed as expected -assertions: 774 | 681 passed | 80 failed | 13 failed as expected +assertions: 773 | 680 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 1919c1c2..7d41c5a7 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1297,7 +1297,7 @@ ExceptionTests.cpp: ExceptionTests.cpp:: PASSED: - REQUIRE_THROWS_WITH( thisThrows(), "expecteD Exception" ) + REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ) ------------------------------------------------------------------------------- Exception messages can be tested for @@ -1308,19 +1308,19 @@ ExceptionTests.cpp: ExceptionTests.cpp:: PASSED: - REQUIRE_THROWS_WITH( thisThrows(), "expected*" ) + REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ) ExceptionTests.cpp:: PASSED: - REQUIRE_THROWS_WITH( thisThrows(), "*exception" ) + REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ) ExceptionTests.cpp:: PASSED: - REQUIRE_THROWS_WITH( thisThrows(), "*except*" ) + REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ) ExceptionTests.cpp:: PASSED: - REQUIRE_THROWS_WITH( thisThrows(), "*exCept*" ) + REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ) ------------------------------------------------------------------------------- Mismatching exception messages failing the test @@ -1328,10 +1328,6 @@ Mismatching exception messages failing the test ExceptionTests.cpp: ............................................................................... -ExceptionTests.cpp:: -PASSED: - REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) - ExceptionTests.cpp:: PASSED: REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ) @@ -8009,5 +8005,5 @@ with expansion: =============================================================================== test cases: 157 | 101 passed | 55 failed | 1 failed as expected -assertions: 794 | 681 passed | 100 failed | 13 failed as expected +assertions: 793 | 680 passed | 100 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 95d4f9a2..cd978bfb 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 0d06a704..654061f2 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1611,10 +1611,10 @@
- thisThrows(), "expecteD Exception" + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) - thisThrows(), "expecteD Exception" + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) @@ -1622,34 +1622,34 @@
- thisThrows(), "expected*" + thisThrows(), StartsWith( "expected" ) - thisThrows(), "expected*" + thisThrows(), StartsWith( "expected" ) - thisThrows(), "*exception" + thisThrows(), EndsWith( "exception" ) - thisThrows(), "*exception" + thisThrows(), EndsWith( "exception" ) - thisThrows(), "*except*" + thisThrows(), Contains( "except" ) - thisThrows(), "*except*" + thisThrows(), Contains( "except" ) - thisThrows(), "*exCept*" + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) - thisThrows(), "*exCept*" + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) @@ -1657,14 +1657,6 @@ - - - thisThrows(), "expected exception" - - - thisThrows(), "expected exception" - - thisThrows(), "expected exception" @@ -8307,7 +8299,7 @@ there"
- + - + diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index f3b7f41d..3826c58b 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -154,20 +154,21 @@ TEST_CASE( "NotImplemented exception", "" ) } TEST_CASE( "Exception messages can be tested for", "" ) { + using namespace Catch::Matchers; SECTION( "exact match" ) REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); SECTION( "different case" ) - REQUIRE_THROWS_WITH( thisThrows(), "expecteD Exception" ); + REQUIRE_THROWS_WITH( thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) ); SECTION( "wildcarded" ) { - REQUIRE_THROWS_WITH( thisThrows(), "expected*" ); - REQUIRE_THROWS_WITH( thisThrows(), "*exception" ); - REQUIRE_THROWS_WITH( thisThrows(), "*except*" ); - REQUIRE_THROWS_WITH( thisThrows(), "*exCept*" ); + REQUIRE_THROWS_WITH( thisThrows(), StartsWith( "expected" ) ); + REQUIRE_THROWS_WITH( thisThrows(), EndsWith( "exception" ) ); + REQUIRE_THROWS_WITH( thisThrows(), Contains( "except" ) ); + REQUIRE_THROWS_WITH( thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) ); } } TEST_CASE( "Mismatching exception messages failing the test", "[.][failing]" ) { - REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); REQUIRE_THROWS_WITH( thisThrows(), "should fail" ); + REQUIRE_THROWS_WITH( thisThrows(), "expected exception" ); } From 5bbdc8fd38804c55f4967c135a06aa3925c72154 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 15 Jul 2015 23:03:11 +0100 Subject: [PATCH 21/87] Dev build 8 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 540 +++++++++++++++-------------- 3 files changed, 289 insertions(+), 255 deletions(-) diff --git a/README.md b/README.md index aa00297a..8bf1c27b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.7* +*v1.2.1-develop.8* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 2463e4d0..9202fef4 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 7 ); + Version libraryVersion( 1, 2, 1, "develop", 8 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 7e5a3730..03629ecb 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.7 - * Generated: 2015-07-13 15:03:15.644872 + * Catch v1.2.1-develop.8 + * Generated: 2015-07-15 23:02:54.523106 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -235,6 +235,11 @@ namespace Catch { struct IConfig; + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + class NonCopyable { #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; @@ -770,6 +775,259 @@ namespace Catch { } // end namespace Catch +// #included from: catch_matchers.hpp +#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED + +namespace Catch { +namespace Matchers { + namespace Impl { + + template + struct Matcher : SharedImpl + { + typedef ExpressionT ExpressionType; + + virtual ~Matcher() {} + virtual Ptr clone() const = 0; + virtual bool match( ExpressionT const& expr ) const = 0; + virtual std::string toString() const = 0; + }; + + template + struct MatcherImpl : Matcher { + + virtual Ptr > clone() const { + return Ptr >( new DerivedT( static_cast( *this ) ) ); + } + }; + + namespace Generic { + + template + class AllOf : public MatcherImpl, ExpressionT> { + public: + + AllOf() {} + AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} + + AllOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( !m_matchers[i]->match( expr ) ) + return false; + return true; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " and "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + template + class AnyOf : public MatcherImpl, ExpressionT> { + public: + + AnyOf() {} + AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} + + AnyOf& add( Matcher const& matcher ) { + m_matchers.push_back( matcher.clone() ); + return *this; + } + virtual bool match( ExpressionT const& expr ) const + { + for( std::size_t i = 0; i < m_matchers.size(); ++i ) + if( m_matchers[i]->match( expr ) ) + return true; + return false; + } + virtual std::string toString() const { + std::ostringstream oss; + oss << "( "; + for( std::size_t i = 0; i < m_matchers.size(); ++i ) { + if( i != 0 ) + oss << " or "; + oss << m_matchers[i]->toString(); + } + oss << " )"; + return oss.str(); + } + + private: + std::vector > > m_matchers; + }; + + } + + namespace StdString { + + inline std::string makeString( std::string const& str ) { return str; } + inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + + } + std::string toStringSuffix() const + { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : ""; + } + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct Equals : MatcherImpl { + Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( str, caseSensitivity ) + {} + Equals( Equals const& other ) : m_data( other.m_data ){} + + virtual ~Equals(); + + virtual bool match( std::string const& expr ) const { + return m_data.m_str == m_data.adjustString( expr );; + } + virtual std::string toString() const { + return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct Contains : MatcherImpl { + Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + Contains( Contains const& other ) : m_data( other.m_data ){} + + virtual ~Contains(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos; + } + virtual std::string toString() const { + return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct StartsWith : MatcherImpl { + StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} + + virtual ~StartsWith(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) == 0; + } + virtual std::string toString() const { + return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + + struct EndsWith : MatcherImpl { + EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) + : m_data( substr, caseSensitivity ){} + EndsWith( EndsWith const& other ) : m_data( other.m_data ){} + + virtual ~EndsWith(); + + virtual bool match( std::string const& expr ) const { + return m_data.adjustString( expr ).find( m_data.m_str ) == expr.size() - m_data.m_str.size(); + } + virtual std::string toString() const { + return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix(); + } + + CasedString m_data; + }; + } // namespace StdString + } // namespace Impl + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ); + } + template + inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, + Impl::Matcher const& m2, + Impl::Matcher const& m3 ) { + return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); + } + + inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( str, caseSensitivity ); + } + inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity ); + } + inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( substr, caseSensitivity ); + } + inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) { + return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity ); + } + inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { + return Impl::StdString::StartsWith( substr ); + } + inline Impl::StdString::StartsWith StartsWith( const char* substr ) { + return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); + } + inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { + return Impl::StdString::EndsWith( substr ); + } + inline Impl::StdString::EndsWith EndsWith( const char* substr ) { + return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); + } + +} // namespace Matchers + +using namespace Matchers; + +} // namespace Catch + namespace Catch { struct TestFailureException{}; @@ -827,6 +1085,7 @@ namespace Catch { void captureResult( ResultWas::OfType resultType ); void captureExpression(); void captureExpectedException( std::string const& expectedMessage ); + void captureExpectedException( Matchers::Impl::Matcher const& matcher ); void handleResult( AssertionResult const& result ); void react(); bool shouldDebugBreak() const; @@ -1619,16 +1878,16 @@ namespace Catch { } while( Catch::alwaysFalse() ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_THROWS( expr, resultDisposition, expectedMessage, macroName ) \ +#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \ do { \ - Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, expectedMessage ); \ + Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ if( __catchResult.allowThrows() ) \ try { \ expr; \ __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ } \ catch( ... ) { \ - __catchResult.captureExpectedException( expectedMessage ); \ + __catchResult.captureExpectedException( matcher ); \ } \ else \ __catchResult.captureResult( Catch::ResultWas::Ok ); \ @@ -2197,231 +2456,6 @@ inline std::string toString( Detail::Approx const& value ) { } // end namespace Catch -// #included from: internal/catch_matchers.hpp -#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED - -namespace Catch { -namespace Matchers { - namespace Impl { - - template - struct Matcher : SharedImpl - { - typedef ExpressionT ExpressionType; - - virtual ~Matcher() {} - virtual Ptr clone() const = 0; - virtual bool match( ExpressionT const& expr ) const = 0; - virtual std::string toString() const = 0; - }; - - template - struct MatcherImpl : Matcher { - - virtual Ptr > clone() const { - return Ptr >( new DerivedT( static_cast( *this ) ) ); - } - }; - - namespace Generic { - - template - class AllOf : public MatcherImpl, ExpressionT> { - public: - - AllOf() {} - AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {} - - AllOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( !m_matchers[i]->match( expr ) ) - return false; - return true; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " and "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector > > m_matchers; - }; - - template - class AnyOf : public MatcherImpl, ExpressionT> { - public: - - AnyOf() {} - AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {} - - AnyOf& add( Matcher const& matcher ) { - m_matchers.push_back( matcher.clone() ); - return *this; - } - virtual bool match( ExpressionT const& expr ) const - { - for( std::size_t i = 0; i < m_matchers.size(); ++i ) - if( m_matchers[i]->match( expr ) ) - return true; - return false; - } - virtual std::string toString() const { - std::ostringstream oss; - oss << "( "; - for( std::size_t i = 0; i < m_matchers.size(); ++i ) { - if( i != 0 ) - oss << " or "; - oss << m_matchers[i]->toString(); - } - oss << " )"; - return oss.str(); - } - - private: - std::vector > > m_matchers; - }; - - } - - namespace StdString { - - inline std::string makeString( std::string const& str ) { return str; } - inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); } - - struct Equals : MatcherImpl { - Equals( std::string const& str ) : m_str( str ){} - Equals( Equals const& other ) : m_str( other.m_str ){} - - virtual ~Equals(); - - virtual bool match( std::string const& expr ) const { - return m_str == expr; - } - virtual std::string toString() const { - return "equals: \"" + m_str + "\""; - } - - std::string m_str; - }; - - struct Contains : MatcherImpl { - Contains( std::string const& substr ) : m_substr( substr ){} - Contains( Contains const& other ) : m_substr( other.m_substr ){} - - virtual ~Contains(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) != std::string::npos; - } - virtual std::string toString() const { - return "contains: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct StartsWith : MatcherImpl { - StartsWith( std::string const& substr ) : m_substr( substr ){} - StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){} - - virtual ~StartsWith(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == 0; - } - virtual std::string toString() const { - return "starts with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - - struct EndsWith : MatcherImpl { - EndsWith( std::string const& substr ) : m_substr( substr ){} - EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){} - - virtual ~EndsWith(); - - virtual bool match( std::string const& expr ) const { - return expr.find( m_substr ) == expr.size() - m_substr.size(); - } - virtual std::string toString() const { - return "ends with: \"" + m_substr + "\""; - } - - std::string m_substr; - }; - } // namespace StdString - } // namespace Impl - - // The following functions create the actual matcher objects. - // This allows the types to be inferred - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AllOf().add( m1 ).add( m2 ).add( m3 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ); - } - template - inline Impl::Generic::AnyOf AnyOf( Impl::Matcher const& m1, - Impl::Matcher const& m2, - Impl::Matcher const& m3 ) { - return Impl::Generic::AnyOf().add( m1 ).add( m2 ).add( m3 ); - } - - inline Impl::StdString::Equals Equals( std::string const& str ) { - return Impl::StdString::Equals( str ); - } - inline Impl::StdString::Equals Equals( const char* str ) { - return Impl::StdString::Equals( Impl::StdString::makeString( str ) ); - } - inline Impl::StdString::Contains Contains( std::string const& substr ) { - return Impl::StdString::Contains( substr ); - } - inline Impl::StdString::Contains Contains( const char* substr ) { - return Impl::StdString::Contains( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) { - return Impl::StdString::StartsWith( substr ); - } - inline Impl::StdString::StartsWith StartsWith( const char* substr ) { - return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) ); - } - inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) { - return Impl::StdString::EndsWith( substr ); - } - inline Impl::StdString::EndsWith EndsWith( const char* substr ) { - return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) ); - } - -} // namespace Matchers - -using namespace Matchers; - -} // namespace Catch - // #included from: internal/catch_interfaces_tag_alias_registry.h #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED @@ -2853,11 +2887,7 @@ namespace Catch public: - enum CaseSensitivity { - CaseSensitive, - CaseInsensitive - }; - WildcardPattern( std::string const& pattern, CaseSensitivity caseSensitivity ) + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) : m_caseSensitivity( caseSensitivity ), m_wildcard( NoWildcard ), m_pattern( adjustCase( pattern ) ) @@ -2895,9 +2925,9 @@ namespace Catch } private: std::string adjustCase( std::string const& str ) const { - return m_caseSensitivity == CaseInsensitive ? toLower( str ) : str; + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; } - CaseSensitivity m_caseSensitivity; + CaseSensitive::Choice m_caseSensitivity; WildcardPosition m_wildcard; std::string m_pattern; }; @@ -2916,7 +2946,7 @@ namespace Catch { class NamePattern : public Pattern { public: NamePattern( std::string const& name ) - : m_wildcardPattern( toLower( name ), WildcardPattern::CaseInsensitive ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) {} virtual ~NamePattern(); virtual bool matches( TestCaseInfo const& testCase ) const { @@ -6861,7 +6891,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 7 ); + Version libraryVersion( 1, 2, 1, "develop", 8 ); } @@ -7479,9 +7509,9 @@ std::string toString( std::nullptr_t ) { namespace Catch { std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) { - return secondArg.empty() + return secondArg.empty() || secondArg == "\"\"" ? capturedExpression - : capturedExpression + ", \"" + secondArg + "\""; + : capturedExpression + ", " + secondArg; } ResultBuilder::ResultBuilder( char const* macroName, SourceLineInfo const& lineInfo, @@ -7529,20 +7559,24 @@ namespace Catch { setResultType( resultType ); captureExpression(); } - void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { + if( expectedMessage.empty() ) + captureExpectedException( Matchers::Impl::Generic::AllOf() ); + else + captureExpectedException( Matchers::Equals( expectedMessage ) ); + } + + void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { + assert( m_exprComponents.testFalse == false ); AssertionResultData data = m_data; data.resultType = ResultWas::Ok; data.reconstructedExpression = m_assertionInfo.capturedExpression; - if( expectedMessage != "" ) { - std::string actualMessage = Catch::translateActiveException(); - WildcardPattern pattern( expectedMessage, WildcardPattern::CaseInsensitive ); - if( !pattern.matches( actualMessage ) ) { - data.resultType = ResultWas::ExpressionFailed; - data.reconstructedExpression = actualMessage; - } + std::string actualMessage = Catch::translateActiveException(); + if( !matcher.match( actualMessage ) ) { + data.resultType = ResultWas::ExpressionFailed; + data.reconstructedExpression = actualMessage; } AssertionResult result( m_assertionInfo, data ); handleResult( result ); @@ -9401,7 +9435,7 @@ int main (int argc, char * const argv[]) { #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" ) #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" ) -#define CATCH_REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "CATCH_REQUIRE_THROWS_WITH" ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" ) #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" ) #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" ) @@ -9412,7 +9446,7 @@ int main (int argc, char * const argv[]) { #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" ) #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" ) -#define CATCH_CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CATCH_CHECK_THROWS_WITH" ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" ) #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) @@ -9468,7 +9502,7 @@ int main (int argc, char * const argv[]) { #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" ) #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" ) -#define REQUIRE_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, expectedMessage, "REQUIRE_THROWS_WITH" ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" ) #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" ) #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" ) @@ -9479,7 +9513,7 @@ int main (int argc, char * const argv[]) { #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" ) #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" ) -#define CHECK_THROWS_WITH( expr, expectedMessage ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, expectedMessage, "CHECK_THROWS_WITH" ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" ) #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" ) #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) From 6de135c63aad8986cb28a88b988661de7fddf003 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 22 Jul 2015 18:07:28 +0100 Subject: [PATCH 22/87] Given, When, Then prefixes are now std::strings (and so can be prepended to std::strings themselves) see #455 --- include/catch.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 9d81143e..897b2959 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -125,11 +125,11 @@ #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required #else @@ -196,11 +196,11 @@ #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif -#define GIVEN( desc ) SECTION( " Given: " desc, "" ) -#define WHEN( desc ) SECTION( " When: " desc, "" ) -#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) -#define THEN( desc ) SECTION( " Then: " desc, "" ) -#define AND_THEN( desc ) SECTION( " And: " desc, "" ) +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) using Catch::Detail::Approx; From d6e59cd56f196eb40cbec3223531ee8d98e8ac8f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 23 Jul 2015 18:45:31 +0100 Subject: [PATCH 23/87] Fixed Xml encoding - don't encode apostrophes - only encode quotes in attributes - encode control characters (as in PR #465) --- include/internal/catch_xmlwriter.hpp | 95 +- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 126 ++- .../SelfTest/Baselines/junit.sw.approved.txt | 10 +- .../SelfTest/Baselines/xml.sw.approved.txt | 943 ++++++++++-------- projects/SelfTest/MiscTests.cpp | 37 + 6 files changed, 762 insertions(+), 453 deletions(-) diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.hpp index 3355f4d3..5f2e87e5 100644 --- a/include/internal/catch_xmlwriter.hpp +++ b/include/internal/catch_xmlwriter.hpp @@ -14,9 +14,65 @@ #include #include #include +#include namespace Catch { + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + class XmlWriter { public: @@ -99,11 +155,8 @@ namespace Catch { } XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) { - stream() << " " << name << "=\""; - writeEncodedText( attribute ); - stream() << "\""; - } + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; return *this; } @@ -114,9 +167,9 @@ namespace Catch { template XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - if( !name.empty() ) - stream() << " " << name << "=\"" << attribute << "\""; - return *this; + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); } XmlWriter& writeText( std::string const& text, bool indent = true ) { @@ -125,7 +178,7 @@ namespace Catch { ensureTagClosed(); if( tagWasOpen && indent ) stream() << m_indent; - writeEncodedText( text ); + stream() << XmlEncode( text ); m_needsNewline = true; } return *this; @@ -170,30 +223,6 @@ namespace Catch { } } - void writeEncodedText( std::string const& text ) { - static const char* charsToEncode = "<&\""; - std::string mtext = text; - std::string::size_type pos = mtext.find_first_of( charsToEncode ); - while( pos != std::string::npos ) { - stream() << mtext.substr( 0, pos ); - - switch( mtext[pos] ) { - case '<': - stream() << "<"; - break; - case '&': - stream() << "&"; - break; - case '\"': - stream() << """; - break; - } - mtext = mtext.substr( pos+1 ); - pos = mtext.find_first_of( charsToEncode ); - } - stream() << mtext; - } - bool m_tagIsOpen; bool m_needsNewline; std::vector m_tags; diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 67fb8437..3aa3ae86 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -797,6 +797,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 157 | 117 passed | 39 failed | 1 failed as expected -assertions: 773 | 680 passed | 80 failed | 13 failed as expected +test cases: 158 | 118 passed | 39 failed | 1 failed as expected +assertions: 783 | 690 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 7d41c5a7..238450b0 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -3762,6 +3762,128 @@ PASSED: with expansion: ""wide load"" == ""wide load"" +------------------------------------------------------------------------------- +XmlEncode + normal string +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "normal string" ) == "normal string" ) +with expansion: + "normal string" == "normal string" + +------------------------------------------------------------------------------- +XmlEncode + empty string +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "" ) == "" ) +with expansion: + "" == "" + +------------------------------------------------------------------------------- +XmlEncode + string with ampersand +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith & jones" ) == "smith & jones" ) +with expansion: + "smith & jones" == "smith & jones" + +------------------------------------------------------------------------------- +XmlEncode + string with less-than +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith < jones" ) == "smith < jones" ) +with expansion: + "smith < jones" == "smith < jones" + +------------------------------------------------------------------------------- +XmlEncode + string with greater-than +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith > jones" ) == "smith > jones" ) +with expansion: + "smith > jones" == "smith > jones" + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" ) +with expansion: + "smith ]]> jones" + == + "smith ]]> jones" + +------------------------------------------------------------------------------- +XmlEncode + string with quotes +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( stringWithQuotes ) == stringWithQuotes ) +with expansion: + "don't "quote" me on that" + == + "don't "quote" me on that" + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" ) +with expansion: + "don't "quote" me on that" + == + "don't "quote" me on that" + +------------------------------------------------------------------------------- +XmlEncode + string with control char (1) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "[\x01]" ) == "[]" ) +with expansion: + "[]" == "[]" + +------------------------------------------------------------------------------- +XmlEncode + string with control char (x7F) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( encode( "[\x7F]" ) == "[]" ) +with expansion: + "[]" == "[]" + ------------------------------------------------------------------------------- Process can be configured on command line default - no arguments @@ -8004,6 +8126,6 @@ with expansion: true =============================================================================== -test cases: 157 | 101 passed | 55 failed | 1 failed as expected -assertions: 793 | 680 passed | 100 failed | 13 failed as expected +test cases: 158 | 102 passed | 55 failed | 1 failed as expected +assertions: 803 | 690 passed | 100 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index cd978bfb..deae7529 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -463,6 +463,14 @@ MiscTests.cpp: + + + + + + + + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 654061f2..10b826c2 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -3,18 +3,18 @@ - Catch::toString(e0) == "0" + Catch::toString(e0) == "0" - "0" == "0" + "0" == "0" - Catch::toString(e1) == "1" + Catch::toString(e1) == "1" - "1" == "1" + "1" == "1" @@ -22,18 +22,18 @@ - Catch::toString(e0) == "E2{0}" + Catch::toString(e0) == "E2{0}" - "E2{0}" == "E2{0}" + "E2{0}" == "E2{0}" - Catch::toString(e1) == "E2{1}" + Catch::toString(e1) == "E2{1}" - "E2{1}" == "E2{1}" + "E2{1}" == "E2{1}" @@ -41,18 +41,18 @@ - Catch::toString(e0) == "0" + Catch::toString(e0) == "0" - "0" == "0" + "0" == "0" - Catch::toString(e1) == "1" + Catch::toString(e1) == "1" - "1" == "1" + "1" == "1" @@ -60,28 +60,28 @@ - Catch::toString(e0) == "E2/V0" + Catch::toString(e0) == "E2/V0" - "E2/V0" == "E2/V0" + "E2/V0" == "E2/V0" - Catch::toString(e1) == "E2/V1" + Catch::toString(e1) == "E2/V1" - "E2/V1" == "E2/V1" + "E2/V1" == "E2/V1" - Catch::toString(e3) == "Unknown enum value 10" + Catch::toString(e3) == "Unknown enum value 10" - "Unknown enum value 10" + "Unknown enum value 10" == -"Unknown enum value 10" +"Unknown enum value 10" @@ -326,10 +326,10 @@ - s == "hello" + s == "hello" - "hello" == "hello" + "hello" == "hello" @@ -337,10 +337,10 @@ - s == "world" + s == "world" - "hello" == "world" + "hello" == "world" @@ -394,18 +394,18 @@ - data.str_hello == "hello" + data.str_hello == "hello" - "hello" == "hello" + "hello" == "hello" - "hello" == data.str_hello + "hello" == data.str_hello - "hello" == "hello" + "hello" == "hello" @@ -493,26 +493,26 @@ - data.str_hello == "goodbye" + data.str_hello == "goodbye" - "hello" == "goodbye" + "hello" == "goodbye" - data.str_hello == "hell" + data.str_hello == "hell" - "hello" == "hell" + "hello" == "hell" - data.str_hello == "hello1" + data.str_hello == "hello1" - "hello" == "hello1" + "hello" == "hello1" @@ -592,26 +592,26 @@ - data.str_hello != "goodbye" + data.str_hello != "goodbye" - "hello" != "goodbye" + "hello" != "goodbye" - data.str_hello != "hell" + data.str_hello != "hell" - "hello" != "hell" + "hello" != "hell" - data.str_hello != "hello1" + data.str_hello != "hello1" - "hello" != "hello1" + "hello" != "hello1" @@ -651,10 +651,10 @@ - data.str_hello != "hello" + data.str_hello != "hello" - "hello" != "hello" + "hello" != "hello" @@ -758,50 +758,50 @@ - data.str_hello <= "hello" + data.str_hello <= "hello" - "hello" <= "hello" + "hello" <= "hello" - data.str_hello >= "hello" + data.str_hello >= "hello" - "hello" >= "hello" + "hello" >= "hello" - data.str_hello < "hellp" + data.str_hello < "hellp" - "hello" < "hellp" + "hello" < "hellp" - data.str_hello < "zebra" + data.str_hello < "zebra" - "hello" < "zebra" + "hello" < "zebra" - data.str_hello > "hellm" + data.str_hello > "hellm" - "hello" > "hellm" + "hello" > "hellm" - data.str_hello > "a" + data.str_hello > "a" - "hello" > "a" + "hello" > "a" @@ -897,66 +897,66 @@ - data.str_hello > "hello" + data.str_hello > "hello" - "hello" > "hello" + "hello" > "hello" - data.str_hello < "hello" + data.str_hello < "hello" - "hello" < "hello" + "hello" < "hello" - data.str_hello > "hellp" + data.str_hello > "hellp" - "hello" > "hellp" + "hello" > "hellp" - data.str_hello > "z" + data.str_hello > "z" - "hello" > "z" + "hello" > "z" - data.str_hello < "hellm" + data.str_hello < "hellm" - "hello" < "hellm" + "hello" < "hellm" - data.str_hello < "a" + data.str_hello < "a" - "hello" < "a" + "hello" < "a" - data.str_hello >= "z" + data.str_hello >= "z" - "hello" >= "z" + "hello" >= "z" - data.str_hello <= "a" + data.str_hello <= "a" - "hello" <= "a" + "hello" <= "a" @@ -1600,10 +1600,10 @@
- thisThrows(), "expected exception" + thisThrows(), "expected exception" - thisThrows(), "expected exception" + thisThrows(), "expected exception" @@ -1611,10 +1611,10 @@
- thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) - thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) + thisThrows(), Equals( "expecteD Exception", Catch::CaseSensitive::No ) @@ -1622,34 +1622,34 @@
- thisThrows(), StartsWith( "expected" ) + thisThrows(), StartsWith( "expected" ) - thisThrows(), StartsWith( "expected" ) + thisThrows(), StartsWith( "expected" ) - thisThrows(), EndsWith( "exception" ) + thisThrows(), EndsWith( "exception" ) - thisThrows(), EndsWith( "exception" ) + thisThrows(), EndsWith( "exception" ) - thisThrows(), Contains( "except" ) + thisThrows(), Contains( "except" ) - thisThrows(), Contains( "except" ) + thisThrows(), Contains( "except" ) - thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) - thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) + thisThrows(), Contains( "exCept", Catch::CaseSensitive::No ) @@ -1659,15 +1659,15 @@ - thisThrows(), "expected exception" + thisThrows(), "expected exception" - thisThrows(), "expected exception" + thisThrows(), "expected exception" - thisThrows(), "should fail" + thisThrows(), "should fail" expected exception @@ -3308,7 +3308,7 @@ makeString( false ) != static_cast<char*>(nullptr) - "valid string" != {null string} + "valid string" != {null string} @@ -3434,34 +3434,34 @@ - testStringForMatching() Contains( "string" ) + testStringForMatching() Contains( "string" ) - "this string contains 'abc' as a substring" contains: "string" + "this string contains 'abc' as a substring" contains: "string" - testStringForMatching() Contains( "abc" ) + testStringForMatching() Contains( "abc" ) - "this string contains 'abc' as a substring" contains: "abc" + "this string contains 'abc' as a substring" contains: "abc" - testStringForMatching() StartsWith( "this" ) + testStringForMatching() StartsWith( "this" ) - "this string contains 'abc' as a substring" starts with: "this" + "this string contains 'abc' as a substring" starts with: "this" - testStringForMatching() EndsWith( "substring" ) + testStringForMatching() EndsWith( "substring" ) - "this string contains 'abc' as a substring" ends with: "substring" + "this string contains 'abc' as a substring" ends with: "substring" @@ -3469,10 +3469,10 @@ - testStringForMatching() Contains( "not there" ) + testStringForMatching() Contains( "not there" ) - "this string contains 'abc' as a substring" contains: "not there" + "this string contains 'abc' as a substring" contains: "not there" @@ -3480,10 +3480,10 @@ - testStringForMatching() StartsWith( "string" ) + testStringForMatching() StartsWith( "string" ) - "this string contains 'abc' as a substring" starts with: "string" + "this string contains 'abc' as a substring" starts with: "string" @@ -3491,10 +3491,10 @@ - testStringForMatching() EndsWith( "this" ) + testStringForMatching() EndsWith( "this" ) - "this string contains 'abc' as a substring" ends with: "this" + "this string contains 'abc' as a substring" ends with: "this" @@ -3502,10 +3502,10 @@ - testStringForMatching() Equals( "something else" ) + testStringForMatching() Equals( "something else" ) - "this string contains 'abc' as a substring" equals: "something else" + "this string contains 'abc' as a substring" equals: "something else" @@ -3513,10 +3513,10 @@ - "" Equals(nullptr) + "" Equals(nullptr) - "" equals: "" + "" equals: "" @@ -3524,10 +3524,10 @@ - testStringForMatching() AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) + testStringForMatching() AllOf( Catch::Contains( "string" ), Catch::Contains( "abc" ) ) - "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" ) + "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" ) @@ -3535,18 +3535,18 @@ - testStringForMatching() AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) + testStringForMatching() AnyOf( Catch::Contains( "string" ), Catch::Contains( "not there" ) ) - "this string contains 'abc' as a substring" ( contains: "string" or contains: "not there" ) + "this string contains 'abc' as a substring" ( contains: "string" or contains: "not there" ) - testStringForMatching() AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) + testStringForMatching() AnyOf( Catch::Contains( "not there" ), Catch::Contains( "string" ) ) - "this string contains 'abc' as a substring" ( contains: "not there" or contains: "string" ) + "this string contains 'abc' as a substring" ( contains: "not there" or contains: "string" ) @@ -3554,10 +3554,10 @@ - testStringForMatching() Equals( "this string contains 'abc' as a substring" ) + testStringForMatching() Equals( "this string contains 'abc' as a substring" ) - "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" + "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" @@ -3795,14 +3795,14 @@ s1 == s2 - "if ($b == 10) { + "if ($b == 10) { $a = 20; -}" +}" == -"if ($b == 10) { +"if ($b == 10) { $a = 20; } -" +" @@ -3810,10 +3810,10 @@ - result == "\"wide load\"" + result == "\"wide load\"" - ""wide load"" == ""wide load"" + ""wide load"" == ""wide load"" @@ -3821,10 +3821,10 @@ - result == "\"wide load\"" + result == "\"wide load\"" - ""wide load"" == ""wide load"" + ""wide load"" == ""wide load"" @@ -3832,10 +3832,10 @@ - result == "\"wide load\"" + result == "\"wide load\"" - ""wide load"" == ""wide load"" + ""wide load"" == ""wide load"" @@ -3843,14 +3843,127 @@ - result == "\"wide load\"" + result == "\"wide load\"" - ""wide load"" == ""wide load"" + ""wide load"" == ""wide load"" + +
+ + + encode( "normal string" ) == "normal string" + + + "normal string" == "normal string" + + + +
+
+ + + encode( "" ) == "" + + + "" == "" + + + +
+
+ + + encode( "smith & jones" ) == "smith &amp; jones" + + + "smith &amp; jones" == "smith &amp; jones" + + + +
+
+ + + encode( "smith < jones" ) == "smith &lt; jones" + + + "smith &lt; jones" == "smith &lt; jones" + + + +
+
+ + + encode( "smith > jones" ) == "smith > jones" + + + "smith > jones" == "smith > jones" + + + + + encode( "smith ]]> jones" ) == "smith ]]&gt; jones" + + + "smith ]]&gt; jones" +== +"smith ]]&gt; jones" + + + +
+
+ + + encode( stringWithQuotes ) == stringWithQuotes + + + "don't "quote" me on that" +== +"don't "quote" me on that" + + + + + encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't &quot;quote&quot; me on that" + + + "don't &quot;quote&quot; me on that" +== +"don't &quot;quote&quot; me on that" + + + +
+
+ + + encode( "[\x01]" ) == "[&#x1]" + + + "[&#x1]" == "[&#x1]" + + + +
+
+ + + encode( "[\x7F]" ) == "[&#x7F]" + + + "[&#x7F]" == "[&#x7F]" + + + +
+ +
@@ -3907,7 +4020,7 @@ - cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false + cfg.testSpec().matches( fakeTestCase( "notIncluded" ) ) == false false == false @@ -3915,7 +4028,7 @@ - cfg.testSpec().matches( fakeTestCase( "test1" ) ) + cfg.testSpec().matches( fakeTestCase( "test1" ) ) true @@ -3937,7 +4050,7 @@ - cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false + cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false false == false @@ -3945,7 +4058,7 @@ - cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) + cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) true @@ -3967,7 +4080,7 @@ - cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false + cfg.testSpec().matches( fakeTestCase( "test1" ) ) == false false == false @@ -3975,7 +4088,7 @@ - cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) + cfg.testSpec().matches( fakeTestCase( "alwaysIncluded" ) ) true @@ -3997,10 +4110,10 @@ - config.reporterName == "console" + config.reporterName == "console" - "console" == "console" + "console" == "console" @@ -4019,10 +4132,10 @@ - config.reporterName == "xml" + config.reporterName == "xml" - "xml" == "xml" + "xml" == "xml" @@ -4041,10 +4154,10 @@ - config.reporterName == "junit" + config.reporterName == "junit" - "junit" == "junit" + "junit" == "junit" @@ -4143,11 +4256,11 @@
- parseIntoConfigAndReturnError( argv, config ) Contains( "greater than zero" ) + parseIntoConfigAndReturnError( argv, config ) Contains( "greater than zero" ) - "Value after -x or --abortAfter must be greater than zero -- while parsing: (-x, --abortx <no. failures>)" contains: "greater than zero" + "Value after -x or --abortAfter must be greater than zero +- while parsing: (-x, --abortx <no. failures>)" contains: "greater than zero" @@ -4158,11 +4271,11 @@
- parseIntoConfigAndReturnError( argv, config ) Contains( "-x" ) + parseIntoConfigAndReturnError( argv, config ) Contains( "-x" ) - "Unable to convert oops to destination type -- while parsing: (-x, --abortx <no. failures>)" contains: "-x" + "Unable to convert oops to destination type +- while parsing: (-x, --abortx <no. failures>)" contains: "-x" @@ -4225,10 +4338,10 @@ - config.outputFilename == "filename.ext" + config.outputFilename == "filename.ext" - "filename.ext" == "filename.ext" + "filename.ext" == "filename.ext" @@ -4247,10 +4360,10 @@ - config.outputFilename == "filename.ext" + config.outputFilename == "filename.ext" - "filename.ext" == "filename.ext" + "filename.ext" == "filename.ext" @@ -4349,9 +4462,9 @@ Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString - "one two three four" + "one two three four" == -"one two three four" +"one two three four" @@ -4359,9 +4472,9 @@ Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString - "one two three four" + "one two three four" == -"one two three four" +"one two three four" @@ -4372,62 +4485,62 @@
- Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" + Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" - "one two three -four" + "one two three +four" == -"one two three -four" +"one two three +four" - Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" + Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" - "one two three -four" + "one two three +four" == -"one two three -four" +"one two three +four" - Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" + Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" - "one two three -four" + "one two three +four" == -"one two three -four" +"one two three +four" - Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" + Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" - "one two three -four" + "one two three +four" == -"one two three -four" +"one two three +four" - Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" + Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" - "one two -three four" + "one two +three four" == -"one two -three four" +"one two +three four" @@ -4438,44 +4551,44 @@ three four"
- Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" + Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" - "one two + "one two three -four" +four" == -"one two +"one two three -four" +four" - Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" + Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" - "one two + "one two three -four" +four" == -"one two +"one two three -four" +four" - Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" + Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" - "one two + "one two three -four" +four" == -"one two +"one two three -four" +four" @@ -4486,34 +4599,34 @@ four"
- Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" + Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" - "one + "one two three -four" +four" == -"one +"one two three -four" +four" - Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" + Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" - "one + "one two three -four" +four" == -"one +"one two three -four" +four" @@ -4524,78 +4637,78 @@ four"
- Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" + Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" - "abc- -def" + "abc- +def" == -"abc- -def" +"abc- +def" - Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" + Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" - "abc- -defg" + "abc- +defg" == -"abc- -defg" +"abc- +defg" - Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" + Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" - "abc- + "abc- def- -gh" +gh" == -"abc- +"abc- def- -gh" +gh" - Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" + Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" - "one + "one two thr- ee -four" +four" == -"one +"one two thr- ee -four" +four" - Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" + Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" - "one + "one two th- ree fo- -ur" +ur" == -"one +"one two th- ree fo- -ur" +ur" @@ -4614,34 +4727,34 @@ ur" - text[0] == "one" + text[0] == "one" - "one" == "one" + "one" == "one" - text[1] == "two" + text[1] == "two" - "two" == "two" + "two" == "two" - text[2] == "three" + text[2] == "three" - "three" == "three" + "three" == "three" - text[3] == "four" + text[3] == "four" - "four" == "four" + "four" == "four" @@ -4652,16 +4765,16 @@ ur"
- text.toString() == " one two\n three\n four" + text.toString() == " one two\n three\n four" - " one two + " one two three - four" + four" == -" one two +" one two three - four" + four" @@ -4675,11 +4788,11 @@ ur" Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString - "one two -three four" + "one two +three four" == -"one two -three four" +"one two +three four" @@ -4687,11 +4800,11 @@ three four" Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString - "one two -three four" + "one two +three four" == -"one two -three four" +"one two +three four" @@ -4699,11 +4812,11 @@ three four" Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString - "one two -three four" + "one two +three four" == -"one two -three four" +"one two +three four" @@ -4714,34 +4827,34 @@ three four"
- Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" + Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" - "abcdef -" + "abcdef +" == -"abcdef -" +"abcdef +" - Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" + Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" - "abcdef" == "abcdef" + "abcdef" == "abcdef" - Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" + Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" - "abcdef -" + "abcdef +" == -"abcdef -" +"abcdef +" @@ -4752,44 +4865,44 @@ three four"
- Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" + Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" - "one two + "one two three -four" +four" == -"one two +"one two three -four" +four" - Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" + Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" - "one two + "one two three -four" +four" == -"one two +"one two three -four" +four" - Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" + Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" - "one two + "one two three -four" +four" == -"one two +"one two three -four" +four" @@ -4800,18 +4913,18 @@ four"
- Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" + Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" - "one + "one two three -four" +four" == -"one +"one two three -four" +four" @@ -4821,18 +4934,18 @@ four"
- Text( testString, TextAttributes().setWidth( 15 ) ).toString() == "one two three\n four\n five\n six" + Text( testString, TextAttributes().setWidth( 15 ) ).toString() == "one two three\n four\n five\n six" - "one two three + "one two three four five - six" + six" == -"one two three +"one two three four five - six" + six" @@ -4843,7 +4956,7 @@ four"
- replaceInPlace( letters, "b", "z" ) + replaceInPlace( letters, "b", "z" ) true @@ -4851,10 +4964,10 @@ four" - letters == "azcdefcg" + letters == "azcdefcg" - "azcdefcg" == "azcdefcg" + "azcdefcg" == "azcdefcg" @@ -4862,7 +4975,7 @@ four"
- replaceInPlace( letters, "c", "z" ) + replaceInPlace( letters, "c", "z" ) true @@ -4870,10 +4983,10 @@ four" - letters == "abzdefzg" + letters == "abzdefzg" - "abzdefzg" == "abzdefzg" + "abzdefzg" == "abzdefzg" @@ -4881,7 +4994,7 @@ four"
- replaceInPlace( letters, "a", "z" ) + replaceInPlace( letters, "a", "z" ) true @@ -4889,10 +5002,10 @@ four" - letters == "zbcdefcg" + letters == "zbcdefcg" - "zbcdefcg" == "zbcdefcg" + "zbcdefcg" == "zbcdefcg" @@ -4900,7 +5013,7 @@ four"
- replaceInPlace( letters, "g", "z" ) + replaceInPlace( letters, "g", "z" ) true @@ -4908,10 +5021,10 @@ four" - letters == "abcdefcz" + letters == "abcdefcz" - "abcdefcz" == "abcdefcz" + "abcdefcz" == "abcdefcz" @@ -4919,7 +5032,7 @@ four"
- replaceInPlace( letters, letters, "replaced" ) + replaceInPlace( letters, letters, "replaced" ) true @@ -4927,10 +5040,10 @@ four" - letters == "replaced" + letters == "replaced" - "replaced" == "replaced" + "replaced" == "replaced" @@ -4938,7 +5051,7 @@ four"
- !replaceInPlace( letters, "x", "z" ) + !replaceInPlace( letters, "x", "z" ) !false @@ -4949,7 +5062,7 @@ four" letters == letters - "abcdefcg" == "abcdefcg" + "abcdefcg" == "abcdefcg" @@ -4957,7 +5070,7 @@ four"
- replaceInPlace( s, "'", "|'" ) + replaceInPlace( s, "'", "|'" ) true @@ -4965,10 +5078,10 @@ four" - s == "didn|'t" + s == "didn|'t" - "didn|'t" == "didn|'t" + "didn|'t" == "didn|'t" @@ -4981,22 +5094,22 @@ four" - Text( "hi there" ).toString() == "hi there" + Text( "hi there" ).toString() == "hi there" - "hi there" == "hi there" + "hi there" == "hi there" - Text( "hi there", narrow ).toString() == "hi\nthere" + Text( "hi there", narrow ).toString() == "hi\nthere" - "hi -there" + "hi +there" == -"hi -there" +"hi +there" @@ -5004,10 +5117,10 @@ there" - t.toString() EndsWith( "... message truncated due to excessive size" ) + t.toString() EndsWith( "... message truncated due to excessive size" ) - "******************************************************************************- + "******************************************************************************- ******************************************************************************- ************************ ******************************************************************************- @@ -6007,7 +6120,7 @@ there" ******************************************************************************- ************************ ******************************************************************************- -... message truncated due to excessive size" ends with: "... message truncated due to excessive size" +... message truncated due to excessive size" ends with: "... message truncated due to excessive size" @@ -6057,10 +6170,10 @@ there" - std::string( "first" ) == "second" + std::string( "first" ) == "second" - "first" == "second" + "first" == "second" @@ -6303,10 +6416,10 @@ there" - s == "7" + s == "7" - "7" == "7" + "7" == "7" @@ -6380,12 +6493,12 @@ there" - Catch::toString( item ) == "toString( has_toString )" + Catch::toString( item ) == "toString( has_toString )" - "toString( has_toString )" + "toString( has_toString )" == -"toString( has_toString )" +"toString( has_toString )" @@ -6393,12 +6506,12 @@ there" - Catch::toString( item ) == "StringMaker<has_maker>" + Catch::toString( item ) == "StringMaker<has_maker>" - "StringMaker<has_maker>" + "StringMaker<has_maker>" == -"StringMaker<has_maker>" +"StringMaker<has_maker>" @@ -6406,12 +6519,12 @@ there" - Catch::toString( item ) == "toString( has_maker_and_toString )" + Catch::toString( item ) == "toString( has_maker_and_toString )" - "toString( has_maker_and_toString )" + "toString( has_maker_and_toString )" == -"toString( has_maker_and_toString )" +"toString( has_maker_and_toString )" @@ -6419,10 +6532,10 @@ there" - Catch::toString( v ) == "{ {?} }" + Catch::toString( v ) == "{ {?} }" - "{ {?} }" == "{ {?} }" + "{ {?} }" == "{ {?} }" @@ -6430,12 +6543,12 @@ there" - Catch::toString( v ) == "{ StringMaker<has_maker> }" + Catch::toString( v ) == "{ StringMaker<has_maker> }" - "{ StringMaker<has_maker> }" + "{ StringMaker<has_maker> }" == -"{ StringMaker<has_maker> }" +"{ StringMaker<has_maker> }" @@ -6443,12 +6556,12 @@ there" - Catch::toString( v ) == "{ StringMaker<has_maker_and_toString> }" + Catch::toString( v ) == "{ StringMaker<has_maker_and_toString> }" - "{ StringMaker<has_maker_and_toString> }" + "{ StringMaker<has_maker_and_toString> }" == -"{ StringMaker<has_maker_and_toString> }" +"{ StringMaker<has_maker_and_toString> }" @@ -6456,10 +6569,10 @@ there" - Catch::toString( value ) == "{ 34, \"xyzzy\" }" + Catch::toString( value ) == "{ 34, \"xyzzy\" }" - "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" @@ -6467,10 +6580,10 @@ there" - Catch::toString(value) == "{ 34, \"xyzzy\" }" + Catch::toString(value) == "{ 34, \"xyzzy\" }" - "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" + "{ 34, "xyzzy" }" == "{ 34, "xyzzy" }" @@ -6478,12 +6591,12 @@ there" - Catch::toString( pr ) == "{ { \"green\", 55 } }" + Catch::toString( pr ) == "{ { \"green\", 55 } }" - "{ { "green", 55 } }" + "{ { "green", 55 } }" == -"{ { "green", 55 } }" +"{ { "green", 55 } }" @@ -6491,12 +6604,12 @@ there" - Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" + Catch::toString( pair ) == "{ { 42, \"Arthur\" }, { \"Ford\", 24 } }" - "{ { 42, "Arthur" }, { "Ford", 24 } }" + "{ { 42, "Arthur" }, { "Ford", 24 } }" == -"{ { 42, "Arthur" }, { "Ford", 24 } }" +"{ { 42, "Arthur" }, { "Ford", 24 } }" @@ -6504,26 +6617,26 @@ there" - Catch::toString(vv) == "{ }" + Catch::toString(vv) == "{ }" - "{ }" == "{ }" + "{ }" == "{ }" - Catch::toString(vv) == "{ 42 }" + Catch::toString(vv) == "{ 42 }" - "{ 42 }" == "{ 42 }" + "{ 42 }" == "{ 42 }" - Catch::toString(vv) == "{ 42, 250 }" + Catch::toString(vv) == "{ 42, 250 }" - "{ 42, 250 }" == "{ 42, 250 }" + "{ 42, 250 }" == "{ 42, 250 }" @@ -6531,28 +6644,28 @@ there" - Catch::toString(vv) == "{ }" + Catch::toString(vv) == "{ }" - "{ }" == "{ }" + "{ }" == "{ }" - Catch::toString(vv) == "{ \"hello\" }" + Catch::toString(vv) == "{ \"hello\" }" - "{ "hello" }" == "{ "hello" }" + "{ "hello" }" == "{ "hello" }" - Catch::toString(vv) == "{ \"hello\", \"world\" }" + Catch::toString(vv) == "{ \"hello\", \"world\" }" - "{ "hello", "world" }" + "{ "hello", "world" }" == -"{ "hello", "world" }" +"{ "hello", "world" }" @@ -6560,26 +6673,26 @@ there" - Catch::toString(vv) == "{ }" + Catch::toString(vv) == "{ }" - "{ }" == "{ }" + "{ }" == "{ }" - Catch::toString(vv) == "{ 42 }" + Catch::toString(vv) == "{ 42 }" - "{ 42 }" == "{ 42 }" + "{ 42 }" == "{ 42 }" - Catch::toString(vv) == "{ 42, 250 }" + Catch::toString(vv) == "{ 42, 250 }" - "{ 42, 250 }" == "{ 42, 250 }" + "{ 42, 250 }" == "{ 42, 250 }" @@ -6587,20 +6700,20 @@ there" - Catch::toString(v) == "{ }" + Catch::toString(v) == "{ }" - "{ }" == "{ }" + "{ }" == "{ }" - Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" + Catch::toString(v) == "{ { \"hello\" }, { \"world\" } }" - "{ { "hello" }, { "world" } }" + "{ { "hello" }, { "world" } }" == -"{ { "hello" }, { "world" } }" +"{ { "hello" }, { "world" } }" @@ -6819,7 +6932,7 @@ there" - parseTestSpec( "*a" ).matches( tcA ) == true + parseTestSpec( "*a" ).matches( tcA ) == true true == true @@ -6870,7 +6983,7 @@ there" - parseTestSpec( "a*" ).matches( tcA ) == true + parseTestSpec( "a*" ).matches( tcA ) == true true == true @@ -6921,7 +7034,7 @@ there" - parseTestSpec( "*a*" ).matches( tcA ) == true + parseTestSpec( "*a*" ).matches( tcA ) == true true == true @@ -7784,18 +7897,18 @@ there" - "{ }" == Catch::toString(type{}) + "{ }" == Catch::toString(type{}) - "{ }" == "{ }" + "{ }" == "{ }" - "{ }" == Catch::toString(value) + "{ }" == Catch::toString(value) - "{ }" == "{ }" + "{ }" == "{ }" @@ -7803,10 +7916,10 @@ there" - "{ 0 }" == Catch::toString(type{0}) + "{ 0 }" == Catch::toString(type{0}) - "{ 0 }" == "{ 0 }" + "{ 0 }" == "{ 0 }" @@ -7814,18 +7927,18 @@ there" - "1.2f" == Catch::toString(float(1.2)) + "1.2f" == Catch::toString(float(1.2)) - "1.2f" == "1.2f" + "1.2f" == "1.2f" - "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) + "{ 1.2f, 0 }" == Catch::toString(type{1.2,0}) - "{ 1.2f, 0 }" == "{ 1.2f, 0 }" + "{ 1.2f, 0 }" == "{ 1.2f, 0 }" @@ -7833,12 +7946,12 @@ there" - "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) + "{ \"hello\", \"world\" }" == Catch::toString(type{"hello","world"}) - "{ "hello", "world" }" + "{ "hello", "world" }" == -"{ "hello", "world" }" +"{ "hello", "world" }" @@ -7846,12 +7959,12 @@ there" - "{ { 42 }, { }, 1.2f }" == Catch::toString(value) + "{ { 42 }, { }, 1.2f }" == Catch::toString(value) - "{ { 42 }, { }, 1.2f }" + "{ { 42 }, { }, 1.2f }" == -"{ { 42 }, { }, 1.2f }" +"{ { 42 }, { }, 1.2f }" @@ -7859,12 +7972,12 @@ there" - "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) + "{ nullptr, 42, \"Catch me\" }" == Catch::toString(value) - "{ nullptr, 42, "Catch me" }" + "{ nullptr, 42, "Catch me" }" == -"{ nullptr, 42, "Catch me" }" +"{ nullptr, 42, "Catch me" }" @@ -7873,42 +7986,42 @@ there"
- what Contains( "[@zzz]" ) + what Contains( "[@zzz]" ) - "error: tag alias, "[@zzz]" already registered. + "error: tag alias, "[@zzz]" already registered. First seen at file:2 - Redefined at file:10" contains: "[@zzz]" + Redefined at file:10" contains: "[@zzz]" - what Contains( "file" ) + what Contains( "file" ) - "error: tag alias, "[@zzz]" already registered. + "error: tag alias, "[@zzz]" already registered. First seen at file:2 - Redefined at file:10" contains: "file" + Redefined at file:10" contains: "file" - what Contains( "2" ) + what Contains( "2" ) - "error: tag alias, "[@zzz]" already registered. + "error: tag alias, "[@zzz]" already registered. First seen at file:2 - Redefined at file:10" contains: "2" + Redefined at file:10" contains: "2" - what Contains( "10" ) + what Contains( "10" ) - "error: tag alias, "[@zzz]" already registered. + "error: tag alias, "[@zzz]" already registered. First seen at file:2 - Redefined at file:10" contains: "10" + Redefined at file:10" contains: "10" @@ -7916,34 +8029,34 @@ there"
- registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) + registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) - registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) + registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) - registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) + registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) - registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) + registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) - registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) + registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) - registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) + registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) - registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) + registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) - registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) + registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) @@ -8299,7 +8412,7 @@ there"
- + - + diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index d91db944..04b86c81 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -7,6 +7,7 @@ */ #include "catch.hpp" +#include "catch_xmlwriter.hpp" #include @@ -381,6 +382,42 @@ TEST_CASE( "toString on wchar_t returns the string contents", "[toString]" ) { CHECK( result == "\"wide load\"" ); } +inline std::string encode( std::string const& str, Catch::XmlEncode::ForWhat forWhat = Catch::XmlEncode::ForTextNodes ) { + std::ostringstream oss; + oss << Catch::XmlEncode( str, forWhat ); + return oss.str(); +} + +TEST_CASE( "XmlEncode" ) { + SECTION( "normal string" ) { + REQUIRE( encode( "normal string" ) == "normal string" ); + } + SECTION( "empty string" ) { + REQUIRE( encode( "" ) == "" ); + } + SECTION( "string with ampersand" ) { + REQUIRE( encode( "smith & jones" ) == "smith & jones" ); + } + SECTION( "string with less-than" ) { + REQUIRE( encode( "smith < jones" ) == "smith < jones" ); + } + SECTION( "string with greater-than" ) { + REQUIRE( encode( "smith > jones" ) == "smith > jones" ); + REQUIRE( encode( "smith ]]> jones" ) == "smith ]]> jones" ); + } + SECTION( "string with quotes" ) { + std::string stringWithQuotes = "don't \"quote\" me on that"; + REQUIRE( encode( stringWithQuotes ) == stringWithQuotes ); + REQUIRE( encode( stringWithQuotes, Catch::XmlEncode::ForAttributes ) == "don't "quote" me on that" ); + } + SECTION( "string with control char (1)" ) { + REQUIRE( encode( "[\x01]" ) == "[]" ); + } + SECTION( "string with control char (x7F)" ) { + REQUIRE( encode( "[\x7F]" ) == "[]" ); + } +} + //TEST_CASE( "Divide by Zero signal handler", "[.][sig]" ) { // int i = 0; // int x = 10/i; // This should cause the signal to fire From 733ebb6024d6b6ff60ef96b9f761828e6eff6ae7 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 23 Jul 2015 19:03:33 +0100 Subject: [PATCH 24/87] Added CATCH_CONFIG_CPP11_LONG_LONG support --- .../internal/catch_compiler_capabilities.h | 10 ++++- include/internal/catch_evaluate.hpp | 42 ++++++++++++++++++- include/internal/catch_tostring.h | 7 +++- include/internal/catch_tostring.hpp | 27 ++++++++++-- include/internal/catch_xmlwriter.hpp | 3 ++ projects/SelfTest/MiscTests.cpp | 8 ++++ 6 files changed, 89 insertions(+), 8 deletions(-) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index db8100f0..a5847545 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -16,6 +16,7 @@ // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? @@ -130,6 +131,10 @@ # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS # endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + #endif // __cplusplus >= 201103L // Now set the actual defines based on the above + anything the user has configured @@ -149,7 +154,10 @@ # define CATCH_CONFIG_CPP11_TUPLE #endif #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) -#define CATCH_CONFIG_VARIADIC_MACROS +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) +# define CATCH_CONFIG_CPP11_LONG_LONG #endif diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index ab9db784..76f19e2a 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -160,13 +160,51 @@ namespace Internal { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // unsigned long long to X + template bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template bool compare( long long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + #ifdef CATCH_CONFIG_CPP11_NULLPTR // pointer to nullptr_t (when comparing against nullptr) template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( CATCH_NULL, rhs ); + return Evaluator::evaluate( nullptr, rhs ); } template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, CATCH_NULL ); + return Evaluator::evaluate( lhs, nullptr ); } #endif // CATCH_CONFIG_CPP11_NULLPTR diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 8efb9be3..91bc106a 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -52,6 +52,11 @@ std::string toString( char value ); std::string toString( signed char value ); std::string toString( unsigned char value ); +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ); #endif @@ -65,7 +70,7 @@ std::string toString( std::nullptr_t ); namespace Detail { - extern std::string unprintableString; + extern const std::string unprintableString; struct BorgType { template BorgType( T const& ); diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.hpp index 60f8f823..50b587d1 100644 --- a/include/internal/catch_tostring.hpp +++ b/include/internal/catch_tostring.hpp @@ -15,9 +15,11 @@ namespace Catch { namespace Detail { - std::string unprintableString = "{?}"; - + const std::string unprintableString = "{?}"; + namespace { + const int hexThreshold = 255; + struct Endianness { enum Arch { Big, Little }; @@ -99,7 +101,7 @@ std::string toString( wchar_t* const value ) std::string toString( int value ) { std::ostringstream oss; oss << value; - if( value >= 255 ) + if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ")"; return oss.str(); } @@ -107,7 +109,7 @@ std::string toString( int value ) { std::string toString( unsigned long value ) { std::ostringstream oss; oss << value; - if( value >= 255 ) + if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ")"; return oss.str(); } @@ -157,6 +159,23 @@ std::string toString( unsigned char value ) { return toString( static_cast( value ) ); } +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ) { return "nullptr"; diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.hpp index 5f2e87e5..738415c3 100644 --- a/include/internal/catch_xmlwriter.hpp +++ b/include/internal/catch_xmlwriter.hpp @@ -10,6 +10,7 @@ #include "catch_stream.h" #include "catch_compiler_capabilities.h" +#include "catch_suppress_warnings.h" #include #include @@ -231,4 +232,6 @@ namespace Catch { }; } +#include "catch_reenable_warnings.h" + #endif // TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 04b86c81..8dbebea7 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -418,6 +418,14 @@ TEST_CASE( "XmlEncode" ) { } } +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +TEST_CASE( "long long" ) { + long long l = std::numeric_limits::max(); + + REQUIRE( l == std::numeric_limits::max() ); +} +#endif + //TEST_CASE( "Divide by Zero signal handler", "[.][sig]" ) { // int i = 0; // int x = 10/i; // This should cause the signal to fire From 70975517b3d560d14c528a110231fe33656a89ee Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 23 Jul 2015 23:05:52 +0100 Subject: [PATCH 25/87] rebased approvals for long long test --- .../Baselines/console.std.approved.txt | 4 +-- .../Baselines/console.sw.approved.txt | 26 +++++++++++++------ .../SelfTest/Baselines/junit.sw.approved.txt | 3 ++- .../SelfTest/Baselines/xml.sw.approved.txt | 25 ++++++++++++------ 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 3aa3ae86..97293423 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -797,6 +797,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 158 | 118 passed | 39 failed | 1 failed as expected -assertions: 783 | 690 passed | 80 failed | 13 failed as expected +test cases: 159 | 119 passed | 39 failed | 1 failed as expected +assertions: 784 | 691 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 238450b0..675edc2f 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -846,9 +846,7 @@ ConditionTests.cpp:: PASSED: REQUIRE( (std::numeric_limits::max)() > ul ) with expansion: - 18446744073709551615 (0x) - > - 4 + 4294967295 (0x) > 4 ------------------------------------------------------------------------------- comparisons between int variables @@ -3884,6 +3882,20 @@ PASSED: with expansion: "[]" == "[]" +------------------------------------------------------------------------------- +long long +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( l == std::numeric_limits::max() ) +with expansion: + 9223372036854775807 (0x) + == + 9223372036854775807 (0x) + ------------------------------------------------------------------------------- Process can be configured on command line default - no arguments @@ -6274,9 +6286,7 @@ TrickyTests.cpp:: PASSED: CHECK( m == &S::f ) with expansion: - 0x - == - 0x + 0x == 0x ------------------------------------------------------------------------------- pointer to class @@ -8126,6 +8136,6 @@ with expansion: true =============================================================================== -test cases: 158 | 102 passed | 55 failed | 1 failed as expected -assertions: 803 | 690 passed | 100 failed | 13 failed as expected +test cases: 159 | 103 passed | 55 failed | 1 failed as expected +assertions: 804 | 691 passed | 100 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index deae7529..59688118 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -471,6 +471,7 @@ MiscTests.cpp: + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 10b826c2..07f7843d 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1063,9 +1063,7 @@ (std::numeric_limits<unsigned long>::max)() > ul - 18446744073709551615 (0x) -> -4 + 4294967295 (0x) > 4 @@ -3964,6 +3962,19 @@
+ + + + l == std::numeric_limits<long long>::max() + + + 9223372036854775807 (0x) +== +9223372036854775807 (0x) + + + +
@@ -6449,9 +6460,7 @@ there" m == &S::f - 0x -== -0x + 0x == 0x @@ -8412,7 +8421,7 @@ there"
- + - + From 2f6371f2eca46d8e2cfde0577fc8e8f2b789e685 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 23 Jul 2015 23:06:26 +0100 Subject: [PATCH 26/87] dev build 9 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 234 ++++++++++++++++++++--------- 3 files changed, 169 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 8bf1c27b..2144029a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.8* +*v1.2.1-develop.9* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 9202fef4..d9e59ea7 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 8 ); + Version libraryVersion( 1, 2, 1, "develop", 9 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 03629ecb..3645a672 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.8 - * Generated: 2015-07-15 23:02:54.523106 + * Catch v1.2.1-develop.9 + * Generated: 2015-07-23 23:06:03.575257 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -84,6 +84,7 @@ // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported +// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? @@ -193,6 +194,10 @@ # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS # endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) +# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG +# endif + #endif // __cplusplus >= 201103L // Now set the actual defines based on the above + anything the user has configured @@ -212,7 +217,10 @@ # define CATCH_CONFIG_CPP11_TUPLE #endif #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) -#define CATCH_CONFIG_VARIADIC_MACROS +# define CATCH_CONFIG_VARIADIC_MACROS +#endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) +# define CATCH_CONFIG_CPP11_LONG_LONG #endif // noexcept support: @@ -1265,13 +1273,51 @@ namespace Internal { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } +#ifdef CATCH_CONFIG_CPP11_LONG_LONG + // long long to unsigned X + template bool compare( long long lhs, unsigned int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( long long lhs, unsigned char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // unsigned long long to X + template bool compare( unsigned long long lhs, int rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, long long rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + template bool compare( unsigned long long lhs, char rhs ) { + return applyEvaluator( static_cast( lhs ), rhs ); + } + + // pointer to long long (when comparing against NULL) + template bool compare( long long lhs, T* rhs ) { + return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); + } + template bool compare( T* lhs, long long rhs ) { + return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); + } +#endif // CATCH_CONFIG_CPP11_LONG_LONG + #ifdef CATCH_CONFIG_CPP11_NULLPTR // pointer to nullptr_t (when comparing against nullptr) template bool compare( std::nullptr_t, T* rhs ) { - return Evaluator::evaluate( CATCH_NULL, rhs ); + return Evaluator::evaluate( nullptr, rhs ); } template bool compare( T* lhs, std::nullptr_t ) { - return Evaluator::evaluate( lhs, CATCH_NULL ); + return Evaluator::evaluate( lhs, nullptr ); } #endif // CATCH_CONFIG_CPP11_NULLPTR @@ -1369,6 +1415,11 @@ std::string toString( char value ); std::string toString( signed char value ); std::string toString( unsigned char value ); +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ); +std::string toString( unsigned long long value ); +#endif + #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ); #endif @@ -1381,7 +1432,7 @@ std::string toString( std::nullptr_t ); namespace Detail { - extern std::string unprintableString; + extern const std::string unprintableString; struct BorgType { template BorgType( T const& ); @@ -6891,7 +6942,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 8 ); + Version libraryVersion( 1, 2, 1, "develop", 9 ); } @@ -7337,9 +7388,11 @@ namespace Catch { namespace Detail { - std::string unprintableString = "{?}"; + const std::string unprintableString = "{?}"; namespace { + const int hexThreshold = 255; + struct Endianness { enum Arch { Big, Little }; @@ -7421,7 +7474,7 @@ std::string toString( wchar_t* const value ) std::string toString( int value ) { std::ostringstream oss; oss << value; - if( value >= 255 ) + if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ")"; return oss.str(); } @@ -7429,7 +7482,7 @@ std::string toString( int value ) { std::string toString( unsigned long value ) { std::ostringstream oss; oss << value; - if( value >= 255 ) + if( value > Detail::hexThreshold ) oss << " (0x" << std::hex << value << ")"; return oss.str(); } @@ -7479,6 +7532,23 @@ std::string toString( unsigned char value ) { return toString( static_cast( value ) ); } +#ifdef CATCH_CONFIG_CPP11_LONG_LONG +std::string toString( long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +std::string toString( unsigned long long value ) { + std::ostringstream oss; + oss << value; + if( value > Detail::hexThreshold ) + oss << " (0x" << std::hex << value << ")"; + return oss.str(); +} +#endif + #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ) { return "nullptr"; @@ -8022,9 +8092,65 @@ namespace Catch { #include #include #include +#include namespace Catch { + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void encodeTo( std::ostream& os ) const { + + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t i = 0; i < m_str.size(); ++ i ) { + char c = m_str[i]; + switch( c ) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) + os << ">"; + else + os << c; + break; + + case '\"': + if( m_forWhat == ForAttributes ) + os << """; + else + os << c; + break; + + default: + // Escape control chars - based on contribution by @espenalb in PR #465 + if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) + os << "&#x" << std::uppercase << std::hex << static_cast( c ); + else + os << c; + } + } + } + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + private: + std::string m_str; + ForWhat m_forWhat; + }; + class XmlWriter { public: @@ -8107,11 +8233,8 @@ namespace Catch { } XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { - if( !name.empty() && !attribute.empty() ) { - stream() << " " << name << "=\""; - writeEncodedText( attribute ); - stream() << "\""; - } + if( !name.empty() && !attribute.empty() ) + stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\""; return *this; } @@ -8122,9 +8245,9 @@ namespace Catch { template XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { - if( !name.empty() ) - stream() << " " << name << "=\"" << attribute << "\""; - return *this; + std::ostringstream oss; + oss << attribute; + return writeAttribute( name, oss.str() ); } XmlWriter& writeText( std::string const& text, bool indent = true ) { @@ -8133,7 +8256,7 @@ namespace Catch { ensureTagClosed(); if( tagWasOpen && indent ) stream() << m_indent; - writeEncodedText( text ); + stream() << XmlEncode( text ); m_needsNewline = true; } return *this; @@ -8178,30 +8301,6 @@ namespace Catch { } } - void writeEncodedText( std::string const& text ) { - static const char* charsToEncode = "<&\""; - std::string mtext = text; - std::string::size_type pos = mtext.find_first_of( charsToEncode ); - while( pos != std::string::npos ) { - stream() << mtext.substr( 0, pos ); - - switch( mtext[pos] ) { - case '<': - stream() << "<"; - break; - case '&': - stream() << "&"; - break; - case '\"': - stream() << """; - break; - } - mtext = mtext.substr( pos+1 ); - pos = mtext.find_first_of( charsToEncode ); - } - stream() << mtext; - } - bool m_tagIsOpen; bool m_needsNewline; std::vector m_tags; @@ -8210,6 +8309,21 @@ namespace Catch { }; } +// #included from: catch_reenable_warnings.h + +#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + + namespace Catch { class XmlReporter : public StreamingReporterBase { public: @@ -9488,11 +9602,11 @@ int main (int argc, char * const argv[]) { #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif -#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" ) -#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" ) -#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" ) -#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" ) -#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" ) +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required #else @@ -9559,27 +9673,13 @@ int main (int argc, char * const argv[]) { #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) #endif -#define GIVEN( desc ) SECTION( " Given: " desc, "" ) -#define WHEN( desc ) SECTION( " When: " desc, "" ) -#define AND_WHEN( desc ) SECTION( "And when: " desc, "" ) -#define THEN( desc ) SECTION( " Then: " desc, "" ) -#define AND_THEN( desc ) SECTION( " And: " desc, "" ) +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) using Catch::Detail::Approx; -// #included from: internal/catch_reenable_warnings.h - -#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(pop) -# else -# pragma clang diagnostic pop -# endif -#elif defined __GNUC__ -# pragma GCC diagnostic pop -#endif - #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED From e085d4811a4b4396091a2a59c8f0a000c8ff6d92 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 24 Jul 2015 08:13:07 +0100 Subject: [PATCH 27/87] Qualified path to xmlwriter to fix travis error --- projects/SelfTest/MiscTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 8dbebea7..b753cf46 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -7,7 +7,7 @@ */ #include "catch.hpp" -#include "catch_xmlwriter.hpp" +#include "internal/catch_xmlwriter.hpp" #include From 74eef52644102c662976b9b86fbaaafd927d9b4c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 24 Jul 2015 08:13:52 +0100 Subject: [PATCH 28/87] dev build 10 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2144029a..4a9df385 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.9* +*v1.2.1-develop.10* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index d9e59ea7..f4272a88 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 9 ); + Version libraryVersion( 1, 2, 1, "develop", 10 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 3645a672..ccfdde11 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.9 - * Generated: 2015-07-23 23:06:03.575257 + * Catch v1.2.1-develop.10 + * Generated: 2015-07-24 08:13:33.830879 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -6942,7 +6942,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 9 ); + Version libraryVersion( 1, 2, 1, "develop", 10 ); } From f3308ed7c48c7989464817d5b1f07c66122c1d85 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 27 Jul 2015 18:34:21 +0100 Subject: [PATCH 29/87] Let gcc use __cplusplus identifier to decide if nullptr supported - or, for 4.6, continue to check __GX_EXPERIMENTAL_CXX0X__ See GitHb issue #445 and PR #471 --- include/internal/catch_compiler_capabilities.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index a5847545..fb6350db 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -67,10 +67,13 @@ // GCC #ifdef __GNUC__ -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR #endif +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + #endif // __GNUC__ From 0edebf41b03e50db985d8b1a029595898b327941 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 28 Jul 2015 18:24:20 +0100 Subject: [PATCH 30/87] approvals rebase - I *think* this fixes an earlier regression, but I'm not 100% sure where that came from! --- projects/SelfTest/Baselines/console.sw.approved.txt | 8 ++++++-- projects/SelfTest/Baselines/xml.sw.approved.txt | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 675edc2f..2e81da7b 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -846,7 +846,9 @@ ConditionTests.cpp:: PASSED: REQUIRE( (std::numeric_limits::max)() > ul ) with expansion: - 4294967295 (0x) > 4 + 18446744073709551615 (0x) + > + 4 ------------------------------------------------------------------------------- comparisons between int variables @@ -6286,7 +6288,9 @@ TrickyTests.cpp:: PASSED: CHECK( m == &S::f ) with expansion: - 0x == 0x + 0x + == + 0x ------------------------------------------------------------------------------- pointer to class diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 07f7843d..9740926f 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1063,7 +1063,9 @@ (std::numeric_limits<unsigned long>::max)() > ul - 4294967295 (0x) > 4 + 18446744073709551615 (0x) +> +4
@@ -6460,7 +6462,9 @@ there" m == &S::f - 0x == 0x + 0x +== +0x From 85c807478466c026a1e56dc076c643b553ab31ff Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 28 Jul 2015 18:26:09 +0100 Subject: [PATCH 31/87] Set group name to -n parameter (or exe name) - As discussed in #469 --- include/catch_runner.hpp | 4 ++-- projects/SelfTest/Baselines/junit.sw.approved.txt | 2 +- projects/SelfTest/Baselines/xml.sw.approved.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/catch_runner.hpp b/include/catch_runner.hpp index ac7a9148..ab6cad3c 100644 --- a/include/catch_runner.hpp +++ b/include/catch_runner.hpp @@ -37,7 +37,7 @@ namespace Catch { Totals totals; - context.testGroupStarting( "all tests", 1, 1 ); // deprecated? + context.testGroupStarting( context.config()->name(), 1, 1 ); TestSpec testSpec = m_config->testSpec(); if( !testSpec.hasFilters() ) @@ -68,7 +68,7 @@ namespace Catch { ++it ) m_reporter->skipTest( *it ); - context.testGroupEnded( "all tests", totals, 1, 1 ); + context.testGroupEnded( context.config()->name(), totals, 1, 1 ); return totals; } diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 59688118..dfd77437 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 9740926f..213d8b6e 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1,5 +1,5 @@ - + From 34fa25ed2f50c1a6d235ab6fc684cc14cda6c834 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 28 Jul 2015 18:55:11 +0100 Subject: [PATCH 32/87] Removed Runner class - it served no purpose - split into functions instead --- include/catch_runner.hpp | 145 +++++++++++++++------------------ include/internal/catch_ptr.hpp | 3 +- 2 files changed, 66 insertions(+), 82 deletions(-) diff --git a/include/catch_runner.hpp b/include/catch_runner.hpp index ab6cad3c..3e08884d 100644 --- a/include/catch_runner.hpp +++ b/include/catch_runner.hpp @@ -21,89 +21,76 @@ namespace Catch { - class Runner { - - public: - Runner( Ptr const& config ) - : m_config( config ) - { - openStream(); - makeReporter(); + Ptr makeReporter( Ptr const& config ) { + std::string reporterName = config->getReporterName().empty() + ? "console" + : config->getReporterName(); + + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); } - - Totals runTests() { - - RunContext context( m_config.get(), m_reporter ); - - Totals totals; - - context.testGroupStarting( context.config()->name(), 1, 1 ); - - TestSpec testSpec = m_config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - - std::vector testCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); - - int testsRunForGroup = 0; - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); - it != itEnd; - ++it ) { - testsRunForGroup++; - if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { - - if( context.aborting() ) - break; - - totals += context.runTest( *it ); - m_testsAlreadyRun.insert( *it ); - } - } - std::vector skippedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, skippedTestCases, true ); - - for( std::vector::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end(); - it != itEnd; - ++it ) - m_reporter->skipTest( *it ); - - context.testGroupEnded( context.config()->name(), totals, 1, 1 ); - return totals; - } - - private: - void openStream() { - // Open output file, if specified - if( !m_config->getFilename().empty() ) { - m_ofs.open( m_config->getFilename().c_str() ); - if( m_ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << m_config->getFilename() << "'"; - throw std::domain_error( oss.str() ); - } - m_config->setStreamBuf( m_ofs.rdbuf() ); - } - } - void makeReporter() { - std::string reporterName = m_config->getReporterName().empty() - ? "console" - : m_config->getReporterName(); - - m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); - if( !m_reporter ) { + return reporter; + } + + void openStreamInto( Ptr const& config, std::ofstream& ofs ) { + // Open output file, if specified + if( !config->getFilename().empty() ) { + ofs.open( config->getFilename().c_str() ); + if( ofs.fail() ) { std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; + oss << "Unable to open file: '" << config->getFilename() << "'"; throw std::domain_error( oss.str() ); } + config->setStreamBuf( ofs.rdbuf() ); } + } + + Totals runTests( Ptr const& config ) { - private: - Ptr m_config; - std::ofstream m_ofs; - Ptr m_reporter; - std::set m_testsAlreadyRun; - }; + std::ofstream ofs; + openStreamInto( config, ofs ); + Ptr reporter = makeReporter( config ); + + RunContext context( config.get(), reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector testCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *config, testCases ); + + std::set testsAlreadyRun; + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) { + if( testsAlreadyRun.find( *it ) == testsAlreadyRun.end() ) { + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + testsAlreadyRun.insert( *it ); + } + } + std::vector skippedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *config, skippedTestCases, true ); + + for( std::vector::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end(); + it != itEnd; + ++it ) + reporter->skipTest( *it ); + + context.testGroupEnded( config->name(), totals, 1, 1 ); + return totals; + } void applyFilenamesAsTags() { std::vector const& tests = getRegistryHub().getTestCaseRegistry().getAllTests(); @@ -200,13 +187,11 @@ namespace Catch { seedRng( *m_config ); - Runner runner( m_config ); - // Handle list request if( Option listed = list( config() ) ) return static_cast( *listed ); - return static_cast( runner.runTests().assertions.failed ); + return static_cast( runTests( m_config ).assertions.failed ); } catch( std::exception& ex ) { Catch::cerr() << ex.what() << std::endl; diff --git a/include/internal/catch_ptr.hpp b/include/internal/catch_ptr.hpp index e37da385..940e5d19 100644 --- a/include/internal/catch_ptr.hpp +++ b/include/internal/catch_ptr.hpp @@ -52,8 +52,7 @@ namespace Catch { return *this; } void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() { return m_p; } - const T* get() const{ return m_p; } + T* get() const{ return m_p; } T& operator*() const { return *m_p; } T* operator->() const { return m_p; } bool operator !() const { return m_p == CATCH_NULL; } From 8b1b7cd66e8bc92e4056d201d8e1d88ce480a2cc Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 3 Aug 2015 07:40:52 +0100 Subject: [PATCH 33/87] dev build 11 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 155 +++++++++++++---------------- 3 files changed, 73 insertions(+), 86 deletions(-) diff --git a/README.md b/README.md index 4a9df385..3fc52b0c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.10* +*v1.2.1-develop.11* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index f4272a88..ca18ef0d 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 10 ); + Version libraryVersion( 1, 2, 1, "develop", 11 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index ccfdde11..ac4bb515 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.10 - * Generated: 2015-07-24 08:13:33.830879 + * Catch v1.2.1-develop.11 + * Generated: 2015-08-03 07:40:22.369337 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -131,10 +131,13 @@ // GCC #ifdef __GNUC__ -#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) ) +#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR #endif +// - otherwise more recent versions define __cplusplus >= 201103L +// and will get picked up below + #endif // __GNUC__ //////////////////////////////////////////////////////////////////////////////// @@ -451,8 +454,7 @@ namespace Catch { return *this; } void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } - T* get() { return m_p; } - const T* get() const{ return m_p; } + T* get() const{ return m_p; } T& operator*() const { return *m_p; } T* operator->() const { return m_p; } bool operator !() const { return m_p == CATCH_NULL; } @@ -5645,89 +5647,76 @@ namespace Catch { namespace Catch { - class Runner { + Ptr makeReporter( Ptr const& config ) { + std::string reporterName = config->getReporterName().empty() + ? "console" + : config->getReporterName(); - public: - Runner( Ptr const& config ) - : m_config( config ) - { - openStream(); - makeReporter(); + Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); + if( !reporter ) { + std::ostringstream oss; + oss << "No reporter registered with name: '" << reporterName << "'"; + throw std::domain_error( oss.str() ); } + return reporter; + } - Totals runTests() { - - RunContext context( m_config.get(), m_reporter ); - - Totals totals; - - context.testGroupStarting( "all tests", 1, 1 ); // deprecated? - - TestSpec testSpec = m_config->testSpec(); - if( !testSpec.hasFilters() ) - testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - - std::vector testCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases ); - - int testsRunForGroup = 0; - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); - it != itEnd; - ++it ) { - testsRunForGroup++; - if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) { - - if( context.aborting() ) - break; - - totals += context.runTest( *it ); - m_testsAlreadyRun.insert( *it ); - } - } - std::vector skippedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, skippedTestCases, true ); - - for( std::vector::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end(); - it != itEnd; - ++it ) - m_reporter->skipTest( *it ); - - context.testGroupEnded( "all tests", totals, 1, 1 ); - return totals; - } - - private: - void openStream() { - // Open output file, if specified - if( !m_config->getFilename().empty() ) { - m_ofs.open( m_config->getFilename().c_str() ); - if( m_ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << m_config->getFilename() << "'"; - throw std::domain_error( oss.str() ); - } - m_config->setStreamBuf( m_ofs.rdbuf() ); - } - } - void makeReporter() { - std::string reporterName = m_config->getReporterName().empty() - ? "console" - : m_config->getReporterName(); - - m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() ); - if( !m_reporter ) { + void openStreamInto( Ptr const& config, std::ofstream& ofs ) { + // Open output file, if specified + if( !config->getFilename().empty() ) { + ofs.open( config->getFilename().c_str() ); + if( ofs.fail() ) { std::ostringstream oss; - oss << "No reporter registered with name: '" << reporterName << "'"; + oss << "Unable to open file: '" << config->getFilename() << "'"; throw std::domain_error( oss.str() ); } + config->setStreamBuf( ofs.rdbuf() ); } + } - private: - Ptr m_config; - std::ofstream m_ofs; - Ptr m_reporter; - std::set m_testsAlreadyRun; - }; + Totals runTests( Ptr const& config ) { + + std::ofstream ofs; + openStreamInto( config, ofs ); + Ptr reporter = makeReporter( config ); + + RunContext context( config.get(), reporter ); + + Totals totals; + + context.testGroupStarting( config->name(), 1, 1 ); + + TestSpec testSpec = config->testSpec(); + if( !testSpec.hasFilters() ) + testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests + + std::vector testCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *config, testCases ); + + std::set testsAlreadyRun; + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) { + if( testsAlreadyRun.find( *it ) == testsAlreadyRun.end() ) { + + if( context.aborting() ) + break; + + totals += context.runTest( *it ); + testsAlreadyRun.insert( *it ); + } + } + std::vector skippedTestCases; + getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *config, skippedTestCases, true ); + + for( std::vector::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end(); + it != itEnd; + ++it ) + reporter->skipTest( *it ); + + context.testGroupEnded( config->name(), totals, 1, 1 ); + return totals; + } void applyFilenamesAsTags() { std::vector const& tests = getRegistryHub().getTestCaseRegistry().getAllTests(); @@ -5824,13 +5813,11 @@ namespace Catch { seedRng( *m_config ); - Runner runner( m_config ); - // Handle list request if( Option listed = list( config() ) ) return static_cast( *listed ); - return static_cast( runner.runTests().assertions.failed ); + return static_cast( runTests( m_config ).assertions.failed ); } catch( std::exception& ex ) { Catch::cerr() << ex.what() << std::endl; @@ -6942,7 +6929,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 10 ); + Version libraryVersion( 1, 2, 1, "develop", 11 ); } From c06e1909aecc5d628151446c84c7978eb5e8ce3e Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 4 Aug 2015 23:11:56 +0100 Subject: [PATCH 34/87] Refactored test filtering and sorting --- include/catch_runner.hpp | 34 ++--- include/internal/catch_interfaces_testcase.h | 8 +- include/internal/catch_list.hpp | 9 +- .../catch_test_case_registry_impl.hpp | 142 ++++++++++-------- 4 files changed, 99 insertions(+), 94 deletions(-) diff --git a/include/catch_runner.hpp b/include/catch_runner.hpp index 3e08884d..2b5ca8fe 100644 --- a/include/catch_runner.hpp +++ b/include/catch_runner.hpp @@ -64,36 +64,22 @@ namespace Catch { if( !testSpec.hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - std::vector testCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *config, testCases ); - - std::set testsAlreadyRun; - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + std::vector const& allTestCases = getAllTestCasesSorted( *config ); + for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); it != itEnd; ++it ) { - if( testsAlreadyRun.find( *it ) == testsAlreadyRun.end() ) { - - if( context.aborting() ) - break; - + if( !context.aborting() && matchTest( *it, testSpec, *config ) ) totals += context.runTest( *it ); - testsAlreadyRun.insert( *it ); - } + else + reporter->skipTest( *it ); } - std::vector skippedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *config, skippedTestCases, true ); - - for( std::vector::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end(); - it != itEnd; - ++it ) - reporter->skipTest( *it ); context.testGroupEnded( config->name(), totals, 1, 1 ); return totals; } - void applyFilenamesAsTags() { - std::vector const& tests = getRegistryHub().getTestCaseRegistry().getAllTests(); + void applyFilenamesAsTags( IConfig const& config ) { + std::vector const& tests = getAllTestCasesSorted( config ); for(std::size_t i = 0; i < tests.size(); ++i ) { TestCase& test = const_cast( tests[i] ); std::set tags = test.tags; @@ -181,12 +167,12 @@ namespace Catch { try { config(); // Force config to be constructed - - if( m_configData.filenamesAsTags ) - applyFilenamesAsTags(); seedRng( *m_config ); + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + // Handle list request if( Option listed = list( config() ) ) return static_cast( *listed ); diff --git a/include/internal/catch_interfaces_testcase.h b/include/internal/catch_interfaces_testcase.h index a23ff9f4..3ae412c5 100644 --- a/include/internal/catch_interfaces_testcase.h +++ b/include/internal/catch_interfaces_testcase.h @@ -28,9 +28,13 @@ namespace Catch { struct ITestCaseRegistry { virtual ~ITestCaseRegistry(); virtual std::vector const& getAllTests() const = 0; - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const = 0; - + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + } #endif // TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED diff --git a/include/internal/catch_list.hpp b/include/internal/catch_list.hpp index 1c510ef8..4c87ccf4 100644 --- a/include/internal/catch_list.hpp +++ b/include/internal/catch_list.hpp @@ -34,8 +34,7 @@ namespace Catch { nameAttr.setInitialIndent( 2 ).setIndent( 4 ); tagsAttr.setIndent( 6 ); - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -63,8 +62,7 @@ namespace Catch { if( !config.testSpec().hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); std::size_t matchedTests = 0; - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -104,8 +102,7 @@ namespace Catch { std::map tagCounts; - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 41170052..ac789a38 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -21,14 +21,75 @@ namespace Catch { - class TestRegistry : public ITestCaseRegistry { - struct LexSort { - bool operator() (TestCase i,TestCase j) const { return (i sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end(), LexSort() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + + RandomNumberGenerator rng; + std::random_shuffle( sorted.begin(), sorted.end(), rng ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + struct TestMatcher { + TestMatcher( TestSpec const& testSpec, bool allowThrows ) : m_testSpec( testSpec ), m_allowThrows( allowThrows ) {} + bool operator()( TestCase const& testCase ) const { + return m_testSpec.matches( testCase ) && ( m_allowThrows || !testCase.throws() ); + } + TestSpec m_testSpec; + bool m_allowThrows; + }; + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ){ + Catch::cerr() + << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + exit(1); + } + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + std::copy_if( testCases.begin(), testCases.end(), std::back_inserter( filtered ), TestMatcher( testSpec, config.allowThrows() ) ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { public: TestRegistry() : m_unnamedCount( 0 ) {} virtual ~TestRegistry(); @@ -40,70 +101,27 @@ namespace Catch { oss << "Anonymous test case " << ++m_unnamedCount; return registerTest( testCase.withName( oss.str() ) ); } - - if( m_functions.find( testCase ) == m_functions.end() ) { - m_functions.insert( testCase ); - m_functionsInOrder.push_back( testCase ); - if( !testCase.isHidden() ) - m_nonHiddenFunctions.push_back( testCase ); - } - else { - TestCase const& prev = *m_functions.find( testCase ); - { - Colour colourGuard( Colour::Red ); - Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; - } - exit(1); - } + m_functions.push_back( testCase ); } virtual std::vector const& getAllTests() const { - return m_functionsInOrder; + return m_functions; } + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); - virtual std::vector const& getAllNonHiddenTests() const { - return m_nonHiddenFunctions; - } - - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const { - - for( std::vector::const_iterator it = m_functionsInOrder.begin(), - itEnd = m_functionsInOrder.end(); - it != itEnd; - ++it ) { - bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ); - if( includeTest != negated ) - matchingTestCases.push_back( *it ); + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); } - sortTests( config, matchingTestCases ); + return m_sortedFunctions; } private: - - static void sortTests( IConfig const& config, std::vector& matchingTestCases ) { - - switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() ); - break; - case RunTests::InRandomOrder: - { - seedRng( config ); - - RandomNumberGenerator rng; - std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng ); - } - break; - case RunTests::InDeclarationOrder: - // already in declaration order - break; - } - } - std::set m_functions; - std::vector m_functionsInOrder; - std::vector m_nonHiddenFunctions; + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector m_sortedFunctions; size_t m_unnamedCount; std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; From 4cb74761d990be2fa65266c3e1d659a481493735 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 5 Aug 2015 19:02:17 +0100 Subject: [PATCH 35/87] Support for multiple reporters - can't (yet) specify different targets for each reporter (e.g. different files) --- .../{catch_runner.hpp => catch_session.hpp} | 21 ++- include/internal/catch_commandline.hpp | 3 +- .../internal/catch_compiler_capabilities.h | 16 ++ include/internal/catch_config.hpp | 4 +- include/internal/catch_context_impl.hpp | 2 +- include/internal/catch_impl.hpp | 3 +- include/internal/catch_interfaces_reporter.h | 2 + ..._runner_impl.hpp => catch_run_context.hpp} | 0 include/reporters/catch_reporter_multi.hpp | 147 ++++++++++++++++++ projects/SelfTest/TestMain.cpp | 16 +- .../CatchSelfTest.xcodeproj/project.pbxproj | 10 +- 11 files changed, 205 insertions(+), 19 deletions(-) rename include/{catch_runner.hpp => catch_session.hpp} (92%) rename include/internal/{catch_runner_impl.hpp => catch_run_context.hpp} (100%) create mode 100644 include/reporters/catch_reporter_multi.hpp diff --git a/include/catch_runner.hpp b/include/catch_session.hpp similarity index 92% rename from include/catch_runner.hpp rename to include/catch_session.hpp index 2b5ca8fe..db6b6bda 100644 --- a/include/catch_runner.hpp +++ b/include/catch_session.hpp @@ -10,7 +10,7 @@ #include "internal/catch_commandline.hpp" #include "internal/catch_list.hpp" -#include "internal/catch_runner_impl.hpp" +#include "internal/catch_run_context.hpp" #include "internal/catch_test_spec.hpp" #include "internal/catch_version.h" #include "internal/catch_text.h" @@ -21,11 +21,7 @@ namespace Catch { - Ptr makeReporter( Ptr const& config ) { - std::string reporterName = config->getReporterName().empty() - ? "console" - : config->getReporterName(); - + Ptr createReporter( std::string const& reporterName, Ptr const& config ) { Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); if( !reporter ) { std::ostringstream oss; @@ -35,6 +31,19 @@ namespace Catch { return reporter; } + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr reporter; + for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + void openStreamInto( Ptr const& config, std::ofstream& ofs ) { // Open output file, if specified if( !config->getFilename().empty() ) { diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index d48d0d14..f2fce31b 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -23,6 +23,7 @@ namespace Catch { config.abortAfter = x; } inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } inline void addWarning( ConfigData& config, std::string const& _warning ) { if( _warning == "NoAssertions" ) @@ -116,7 +117,7 @@ namespace Catch { cli["-r"]["--reporter"] // .placeholder( "name[:filename]" ) .describe( "reporter to use (defaults to console)" ) - .bind( &ConfigData::reporterName, "name" ); + .bind( &addReporterName, "name" ); cli["-n"]["--name"] .describe( "suite name" ) diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index fb6350db..ad9c59c5 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -17,6 +17,7 @@ // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? @@ -138,6 +139,11 @@ # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG # endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif + + #endif // __cplusplus >= 201103L // Now set the actual defines based on the above + anything the user has configured @@ -162,6 +168,9 @@ #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) # define CATCH_CONFIG_CPP11_LONG_LONG #endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif // noexcept support: @@ -180,5 +189,12 @@ # define CATCH_NULL NULL #endif +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + #endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index b0f88fd0..6b2b04a3 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -68,11 +68,11 @@ namespace Catch { ShowDurations::OrNot showDurations; RunTests::InWhatOrder runOrder; - std::string reporterName; std::string outputFilename; std::string name; std::string processName; + std::vector reporterNames; std::vector testsOrTags; }; @@ -133,7 +133,7 @@ namespace Catch { m_stream = stream; } - std::string getReporterName() const { return m_data.reporterName; } + std::vector getReporterNames() const { return m_data.reporterNames; } int abortAfter() const { return m_data.abortAfter; } diff --git a/include/internal/catch_context_impl.hpp b/include/internal/catch_context_impl.hpp index 3c97fcb1..a3ac2ae5 100644 --- a/include/internal/catch_context_impl.hpp +++ b/include/internal/catch_context_impl.hpp @@ -8,7 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED -#include "catch_runner_impl.hpp" +#include "catch_run_context.hpp" #include "catch_context.h" #include "catch_stream.hpp" diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 62fdcaea..3ff5ac00 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -16,7 +16,7 @@ #pragma clang diagnostic ignored "-Wweak-vtables" #endif -#include "../catch_runner.hpp" +#include "../catch_session.hpp" #include "catch_registry_hub.hpp" #include "catch_notimplemented_exception.hpp" #include "catch_context_impl.hpp" @@ -36,6 +36,7 @@ #include "catch_result_builder.hpp" #include "catch_tag_alias_registry.hpp" +#include "../reporters/catch_reporter_multi.hpp" #include "../reporters/catch_reporter_xml.hpp" #include "../reporters/catch_reporter_junit.hpp" #include "../reporters/catch_reporter_console.hpp" diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index ff893038..5d846d2d 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -263,6 +263,8 @@ namespace Catch virtual FactoryMap const& getFactories() const = 0; }; + Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + } #endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_run_context.hpp similarity index 100% rename from include/internal/catch_runner_impl.hpp rename to include/internal/catch_run_context.hpp diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.hpp new file mode 100644 index 00000000..63d86c38 --- /dev/null +++ b/include/reporters/catch_reporter_multi.hpp @@ -0,0 +1,147 @@ +/* + * Created by Phil on 5/08/2015. + * Copyright 2015 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +#include "../internal/catch_interfaces_reporter.h" + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } +}; + +Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { + Ptr resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = dynamic_cast( existingReporter.get() ); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index bb2cf417..57e68666 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -53,7 +53,7 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" CHECK( config.shouldDebugBreak == false ); CHECK( config.abortAfter == -1 ); CHECK( config.noThrow == false ); - CHECK( config.reporterName.empty() ); + CHECK( config.reporterNames.empty() ); } SECTION( "test lists", "" ) { @@ -90,19 +90,27 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" const char* argv[] = { "test", "-r", "console" }; CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - REQUIRE( config.reporterName == "console" ); + REQUIRE( config.reporterNames[0] == "console" ); } SECTION( "-r/xml", "" ) { const char* argv[] = { "test", "-r", "xml" }; CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - REQUIRE( config.reporterName == "xml" ); + REQUIRE( config.reporterNames[0] == "xml" ); + } + SECTION( "-r xml and junit", "" ) { + const char* argv[] = { "test", "-r", "xml", "-r", "junit" }; + CHECK_NOTHROW( parseIntoConfig( argv, config ) ); + + REQUIRE( config.reporterNames.size() == 2 ); + REQUIRE( config.reporterNames[0] == "xml" ); + REQUIRE( config.reporterNames[1] == "junit" ); } SECTION( "--reporter/junit", "" ) { const char* argv[] = { "test", "--reporter", "junit" }; CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - REQUIRE( config.reporterName == "junit" ); + REQUIRE( config.reporterNames[0] == "junit" ); } } diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index 47e8c66a..81f826b6 100644 --- a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -110,6 +110,7 @@ 26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = ""; }; 26DFD3B11B53F84700FD6F16 /* catch_wildcard_pattern.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_wildcard_pattern.hpp; sourceTree = ""; }; 26E1B7D119213BC900812682 /* CmdLineTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CmdLineTests.cpp; path = ../../../SelfTest/CmdLineTests.cpp; sourceTree = ""; }; + 26EDFBD91B72011F00B1873C /* catch_reporter_multi.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_multi.hpp; sourceTree = ""; }; 4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = ""; }; 4A3D7DD01503869D005F9203 /* catch_matchers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_matchers.hpp; sourceTree = ""; }; 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_console_colour.cpp; path = ../../../SelfTest/SurrogateCpps/catch_console_colour.cpp; sourceTree = ""; }; @@ -136,7 +137,7 @@ 4A6D0C34149B3D9E00DB3EAA /* MiscTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MiscTests.cpp; path = ../../../SelfTest/MiscTests.cpp; sourceTree = ""; }; 4A6D0C35149B3D9E00DB3EAA /* TestMain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestMain.cpp; path = ../../../SelfTest/TestMain.cpp; sourceTree = ""; }; 4A6D0C36149B3D9E00DB3EAA /* TrickyTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TrickyTests.cpp; path = ../../../SelfTest/TrickyTests.cpp; sourceTree = ""; }; - 4A6D0C42149B3E1500DB3EAA /* catch_runner.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; name = catch_runner.hpp; path = ../../../../include/catch_runner.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C42149B3E1500DB3EAA /* catch_session.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; name = catch_session.hpp; path = ../../../../include/catch_session.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4A6D0C43149B3E1500DB3EAA /* catch_with_main.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch_with_main.hpp; path = ../../../../include/catch_with_main.hpp; sourceTree = ""; }; 4A6D0C44149B3E1500DB3EAA /* catch.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = catch.hpp; path = ../../../../include/catch.hpp; sourceTree = ""; }; 4A6D0C46149B3E3D00DB3EAA /* catch_approx.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_approx.hpp; sourceTree = ""; }; @@ -163,7 +164,7 @@ 4A6D0C5B149B3E3D00DB3EAA /* catch_reporter_registry.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_reporter_registry.hpp; sourceTree = ""; }; 4A6D0C5C149B3E3D00DB3EAA /* catch_result_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_result_type.h; sourceTree = ""; }; 4A6D0C5D149B3E3D00DB3EAA /* catch_assertionresult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_assertionresult.h; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; }; - 4A6D0C5E149B3E3D00DB3EAA /* catch_runner_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_runner_impl.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; + 4A6D0C5E149B3E3D00DB3EAA /* catch_run_context.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_run_context.hpp; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.cpp; }; 4A6D0C5F149B3E3D00DB3EAA /* catch_section.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_section.hpp; sourceTree = ""; }; 4A6D0C60149B3E3D00DB3EAA /* catch_stream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_stream.hpp; sourceTree = ""; }; 4A6D0C61149B3E3D00DB3EAA /* catch_test_case_info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_test_case_info.h; sourceTree = ""; }; @@ -285,7 +286,7 @@ 4AA7B8B4165428BA003155F6 /* catch_version.hpp */, 4A8E4DCF160A34E200194CBD /* SurrogateCpps */, 4A6D0C44149B3E1500DB3EAA /* catch.hpp */, - 4A6D0C42149B3E1500DB3EAA /* catch_runner.hpp */, + 4A6D0C42149B3E1500DB3EAA /* catch_session.hpp */, 4A6D0C43149B3E1500DB3EAA /* catch_with_main.hpp */, 4A6D0C45149B3E3D00DB3EAA /* internal */, 4A6D0C65149B3E3D00DB3EAA /* reporters */, @@ -318,6 +319,7 @@ 4A6D0C68149B3E3D00DB3EAA /* catch_reporter_xml.hpp */, 4AB42F84166F3E1A0099F2C8 /* catch_reporter_console.hpp */, 2691574A1A4480C50054F1ED /* catch_reporter_teamcity.hpp */, + 26EDFBD91B72011F00B1873C /* catch_reporter_multi.hpp */, ); name = reporters; path = ../../../../include/reporters; @@ -358,7 +360,7 @@ 4A4B0F9715CE6CFB00AE2392 /* catch_registry_hub.hpp */, 4A6D0C50149B3E3D00DB3EAA /* catch_generators_impl.hpp */, 4A6D0C52149B3E3D00DB3EAA /* catch_context_impl.hpp */, - 4A6D0C5E149B3E3D00DB3EAA /* catch_runner_impl.hpp */, + 4A6D0C5E149B3E3D00DB3EAA /* catch_run_context.hpp */, 4A6D0C62149B3E3D00DB3EAA /* catch_test_case_registry_impl.hpp */, 4AB1C73514F97BDA00F31DF7 /* catch_console_colour_impl.hpp */, 4A4B0F9B15CEF8C400AE2392 /* catch_notimplemented_exception.hpp */, From 368714e7aa09656344c8ac229963eb79e63b81ff Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 7 Aug 2015 08:20:56 +0100 Subject: [PATCH 36/87] Added Listeners (programatically provided extra reporters) --- include/catch_session.hpp | 12 +++- .../internal/catch_interfaces_registry_hub.h | 5 +- include/internal/catch_interfaces_reporter.h | 7 +- include/internal/catch_registry_hub.hpp | 15 ++-- .../internal/catch_reporter_registrars.hpp | 26 ++++++- include/internal/catch_reporter_registry.hpp | 17 +++-- include/internal/catch_suppress_warnings.h | 5 -- include/reporters/catch_reporter_bases.hpp | 72 +++++++++++++------ include/reporters/catch_reporter_console.hpp | 23 +++--- include/reporters/catch_reporter_junit.hpp | 26 +++---- include/reporters/catch_reporter_teamcity.hpp | 37 +++++----- include/reporters/catch_reporter_xml.hpp | 33 ++++----- .../Baselines/console.std.approved.txt | 2 +- .../Baselines/console.sw.approved.txt | 40 +++++++++-- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +- .../SelfTest/Baselines/xml.sw.approved.txt | 50 +++++++++++-- projects/SelfTest/MiscTests.cpp | 10 +-- .../catch_interfaces_exception.cpp | 1 + .../catch_interfaces_registry_hub.cpp | 1 + 19 files changed, 256 insertions(+), 129 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index db6b6bda..50623ad4 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -43,6 +43,14 @@ namespace Catch { reporter = addReporter( reporter, createReporter( *it, config ) ); return reporter; } + Ptr addListeners( Ptr const& config, Ptr reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } void openStreamInto( Ptr const& config, std::ofstream& ofs ) { // Open output file, if specified @@ -62,7 +70,8 @@ namespace Catch { std::ofstream ofs; openStreamInto( config, ofs ); Ptr reporter = makeReporter( config ); - + reporter = addListeners( config.get(), reporter ); + RunContext context( config.get(), reporter ); Totals totals; @@ -208,7 +217,6 @@ namespace Catch { m_config = new Config( m_configData ); return *m_config; } - private: Clara::CommandLine m_cli; std::vector m_unusedTokens; diff --git a/include/internal/catch_interfaces_registry_hub.h b/include/internal/catch_interfaces_registry_hub.h index b657183b..2a420bf3 100644 --- a/include/internal/catch_interfaces_registry_hub.h +++ b/include/internal/catch_interfaces_registry_hub.h @@ -8,6 +8,8 @@ #ifndef TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED +#include + #include namespace Catch { @@ -29,7 +31,8 @@ namespace Catch { struct IMutableRegistryHub { virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; }; diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 5d846d2d..46720fbb 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -240,6 +240,7 @@ namespace Catch // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; @@ -249,18 +250,20 @@ namespace Catch }; - struct IReporterFactory { + struct IReporterFactory : IShared { virtual ~IReporterFactory(); virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; struct IReporterRegistry { - typedef std::map FactoryMap; + typedef std::map > FactoryMap; + typedef std::vector > Listeners; virtual ~IReporterRegistry(); virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; }; Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); diff --git a/include/internal/catch_registry_hub.hpp b/include/internal/catch_registry_hub.hpp index cd6a4e07..47c1bb42 100644 --- a/include/internal/catch_registry_hub.hpp +++ b/include/internal/catch_registry_hub.hpp @@ -26,24 +26,27 @@ namespace Catch { public: // IRegistryHub RegistryHub() { } - virtual IReporterRegistry const& getReporterRegistry() const { + virtual IReporterRegistry const& getReporterRegistry() const override { return m_reporterRegistry; } - virtual ITestCaseRegistry const& getTestCaseRegistry() const { + virtual ITestCaseRegistry const& getTestCaseRegistry() const override { return m_testCaseRegistry; } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { return m_exceptionTranslatorRegistry; } public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + virtual void registerReporter( std::string const& name, Ptr const& factory ) override { m_reporterRegistry.registerReporter( name, factory ); } - virtual void registerTest( TestCase const& testInfo ) { + virtual void registerListener( Ptr const& factory ) override { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) override { m_testCaseRegistry.registerTest( testInfo ); } - virtual void registerTranslator( const IExceptionTranslator* translator ) { + virtual void registerTranslator( const IExceptionTranslator* translator ) override { m_exceptionTranslatorRegistry.registerTranslator( translator ); } diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index 51465556..0aed0823 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -36,7 +36,7 @@ namespace Catch { template class ReporterRegistrar { - class ReporterFactory : public IReporterFactory { + class ReporterFactory : public SharedImpl { // *** Please Note ***: // - If you end up here looking at a compiler error because it's trying to register @@ -64,11 +64,35 @@ namespace Catch { getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; + + template + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; } #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + #endif // TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index 3e2ae4c9..b0ac2fba 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -18,27 +18,32 @@ namespace Catch { public: - virtual ~ReporterRegistry() { - deleteAllValues( m_factories ); - } + virtual ~ReporterRegistry() override {} - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const override { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return CATCH_NULL; return it->second->create( ReporterConfig( config ) ); } - void registerReporter( std::string const& name, IReporterFactory* factory ) { + void registerReporter( std::string const& name, Ptr const& factory ) { m_factories.insert( std::make_pair( name, factory ) ); } + void registerListener( Ptr const& factory ) { + m_listeners.push_back( factory ); + } - FactoryMap const& getFactories() const { + virtual FactoryMap const& getFactories() const override { return m_factories; } + virtual Listeners const& getListeners() const override { + return m_listeners; + } private: FactoryMap m_factories; + Listeners m_listeners; }; } diff --git a/include/internal/catch_suppress_warnings.h b/include/internal/catch_suppress_warnings.h index e459dfcc..094ed98b 100644 --- a/include/internal/catch_suppress_warnings.h +++ b/include/internal/catch_suppress_warnings.h @@ -5,9 +5,6 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#ifndef TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED -#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED - #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro # pragma warning(push) @@ -29,5 +26,3 @@ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpadded" #endif - -#endif // TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 865dc29e..75a2bb44 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -19,42 +19,48 @@ namespace Catch { StreamingReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = false; + } - virtual ~StreamingReporterBase(); + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } - virtual void noMatchingTestCases( std::string const& ) {} + virtual ~StreamingReporterBase() CATCH_OVERRIDE; - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { currentTestRunInfo = _testRunInfo; } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { currentGroupInfo = _groupInfo; } - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { currentTestCaseInfo = _testInfo; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_sectionStack.push_back( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { m_sectionStack.pop_back(); } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { currentGroupInfo.reset(); } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); currentGroupInfo.reset(); currentTestRunInfo.reset(); } - virtual void skipTest( TestCaseInfo const& ) { + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { // Don't do anything with this by default. // It can optionally be overridden in the derived class. } @@ -67,6 +73,7 @@ namespace Catch { LazyStat currentTestCaseInfo; std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; }; struct CumulativeReporterBase : SharedImpl { @@ -118,15 +125,21 @@ namespace Catch { CumulativeReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = false; + } ~CumulativeReporterBase(); - virtual void testRunStarting( TestRunInfo const& ) {} - virtual void testGroupStarting( GroupInfo const& ) {} + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } - virtual void testCaseStarting( TestCaseInfo const& ) {} + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} - virtual void sectionStarting( SectionInfo const& sectionInfo ) { + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); Ptr node; if( m_sectionStack.empty() ) { @@ -151,7 +164,7 @@ namespace Catch { m_deepestSection = node; } - virtual void assertionStarting( AssertionInfo const& ) {} + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} virtual bool assertionEnded( AssertionStats const& assertionStats ) { assert( !m_sectionStack.empty() ); @@ -159,13 +172,13 @@ namespace Catch { sectionNode.assertions.push_back( assertionStats ); return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) { + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { assert( !m_sectionStack.empty() ); SectionNode& node = *m_sectionStack.back(); node.stats = sectionStats; m_sectionStack.pop_back(); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { Ptr node = new TestCaseNode( testCaseStats ); assert( m_sectionStack.size() == 0 ); node->children.push_back( m_rootSection ); @@ -176,12 +189,12 @@ namespace Catch { m_deepestSection->stdOut = testCaseStats.stdOut; m_deepestSection->stdErr = testCaseStats.stdErr; } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { Ptr node = new TestGroupNode( testGroupStats ); node->children.swap( m_testCases ); m_testGroups.push_back( node ); } - virtual void testRunEnded( TestRunStats const& testRunStats ) { + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { Ptr node = new TestRunNode( testRunStats ); node->children.swap( m_testGroups ); m_testRuns.push_back( node ); @@ -189,7 +202,7 @@ namespace Catch { } virtual void testRunEndedCumulative() = 0; - virtual void skipTest( TestCaseInfo const& ) {} + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} Ptr m_config; std::ostream& stream; @@ -203,6 +216,7 @@ namespace Catch { Ptr m_rootSection; Ptr m_deepestSection; std::vector > m_sectionStack; + ReporterPreferences m_reporterPrefs; }; @@ -216,6 +230,18 @@ namespace Catch { return line; } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + return false; + } + }; + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED diff --git a/include/reporters/catch_reporter_console.hpp b/include/reporters/catch_reporter_console.hpp index 150cf52a..e7367039 100644 --- a/include/reporters/catch_reporter_console.hpp +++ b/include/reporters/catch_reporter_console.hpp @@ -21,24 +21,19 @@ namespace Catch { m_headerPrinted( false ) {} - virtual ~ConsoleReporter(); + virtual ~ConsoleReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as plain lines of text"; } - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - virtual void noMatchingTestCases( std::string const& spec ) { + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { stream << "No test cases matched '" << spec << "'" << std::endl; } - virtual void assertionStarting( AssertionInfo const& ) { + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = _assertionStats.assertionResult; bool printInfoMessages = true; @@ -58,11 +53,11 @@ namespace Catch { return true; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_headerPrinted = false; StreamingReporterBase::sectionStarting( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& _sectionStats ) { + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); @@ -84,11 +79,11 @@ namespace Catch { StreamingReporterBase::sectionEnded( _sectionStats ); } - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { if( currentGroupInfo.used ) { printSummaryDivider(); stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; @@ -97,7 +92,7 @@ namespace Catch { } StreamingReporterBase::testGroupEnded( _testGroupStats ); } - virtual void testRunEnded( TestRunStats const& _testRunStats ) { + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { printTotalsDivider( _testRunStats.totals ); printTotals( _testRunStats.totals ); stream << std::endl; diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index f9524aaf..ae27f698 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.hpp @@ -23,28 +23,24 @@ namespace Catch { JunitReporter( ReporterConfig const& _config ) : CumulativeReporterBase( _config ), xml( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = true; + } - ~JunitReporter(); + virtual ~JunitReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results in an XML format that looks like Ant's junitreport target"; } - virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - - virtual void testRunStarting( TestRunInfo const& runInfo ) { + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { CumulativeReporterBase::testRunStarting( runInfo ); xml.startElement( "testsuites" ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) { + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { suiteTimer.start(); stdOutForSuite.str(""); stdErrForSuite.str(""); @@ -52,25 +48,25 @@ namespace Catch { CumulativeReporterBase::testGroupStarting( groupInfo ); } - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) unexpectedExceptions++; return CumulativeReporterBase::assertionEnded( assertionStats ); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { stdOutForSuite << testCaseStats.stdOut; stdErrForSuite << testCaseStats.stdErr; CumulativeReporterBase::testCaseEnded( testCaseStats ); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { double suiteTime = suiteTimer.getElapsedSeconds(); CumulativeReporterBase::testGroupEnded( testGroupStats ); writeGroup( *m_testGroups.back(), suiteTime ); } - virtual void testRunEndedCumulative() { + virtual void testRunEndedCumulative() CATCH_OVERRIDE { xml.endElement(); } diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index 0647244f..2e1b008b 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -17,8 +17,10 @@ #include #ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" #endif namespace Catch { @@ -27,7 +29,9 @@ namespace Catch { TeamCityReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), m_headerPrintedForThisSection( false ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = true; + } static std::string escape( std::string const& str ) { std::string escaped = str; @@ -39,18 +43,13 @@ namespace Catch { replaceInPlace( escaped, "]", "|]" ); return escaped; } - virtual ~TeamCityReporter(); + virtual ~TeamCityReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as TeamCity service messages"; } - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - virtual void skipTest( TestCaseInfo const& testInfo ) { + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { stream << "##teamcity[testIgnored name='" << escape( testInfo.name ) << "'"; if( testInfo.isHidden() ) @@ -60,24 +59,24 @@ namespace Catch { stream << "]\n"; } - virtual void noMatchingTestCases( std::string const& /* spec */ ) {} + virtual void noMatchingTestCases( std::string const& /* spec */ ) CATCH_OVERRIDE {} - virtual void testGroupStarting( GroupInfo const& groupInfo ) { + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { StreamingReporterBase::testGroupStarting( groupInfo ); stream << "##teamcity[testSuiteStarted name='" << escape( groupInfo.name ) << "']\n"; } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { StreamingReporterBase::testGroupEnded( testGroupStats ); stream << "##teamcity[testSuiteFinished name='" << escape( testGroupStats.groupInfo.name ) << "']\n"; } - virtual void assertionStarting( AssertionInfo const& ) { + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = assertionStats.assertionResult; if( !result.isOk() ) { @@ -143,18 +142,18 @@ namespace Catch { return true; } - virtual void sectionStarting( SectionInfo const& sectionInfo ) { + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { m_headerPrintedForThisSection = false; StreamingReporterBase::sectionStarting( sectionInfo ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) { + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testCaseStarting( testInfo ); stream << "##teamcity[testStarted name='" << escape( testInfo.name ) << "']\n"; } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( testCaseStats ); if( !testCaseStats.stdOut.empty() ) stream << "##teamcity[testStdOut name='" @@ -216,7 +215,7 @@ namespace Catch { } // end namespace Catch #ifdef __clang__ -#pragma clang diagnostic pop +# pragma clang diagnostic pop #endif #endif // TWOBLUECUBES_CATCH_REPORTER_TEAMCITY_HPP_INCLUDED diff --git a/include/reporters/catch_reporter_xml.hpp b/include/reporters/catch_reporter_xml.hpp index d8cb1dd1..4268473b 100644 --- a/include/reporters/catch_reporter_xml.hpp +++ b/include/reporters/catch_reporter_xml.hpp @@ -21,26 +21,23 @@ namespace Catch { XmlReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), m_sectionDepth( 0 ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = true; + } - virtual ~XmlReporter(); + virtual ~XmlReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as an XML document"; } public: // StreamingReporterBase - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - virtual void noMatchingTestCases( std::string const& s ) { + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { StreamingReporterBase::noMatchingTestCases( s ); } - virtual void testRunStarting( TestRunInfo const& testInfo ) { + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testRunStarting( testInfo ); m_xml.setStream( stream ); m_xml.startElement( "Catch" ); @@ -48,13 +45,13 @@ namespace Catch { m_xml.writeAttribute( "name", m_config->name() ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) { + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { StreamingReporterBase::testGroupStarting( groupInfo ); m_xml.startElement( "Group" ) .writeAttribute( "name", groupInfo.name ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) { + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testCaseStarting(testInfo); m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); @@ -62,7 +59,7 @@ namespace Catch { m_testCaseTimer.start(); } - virtual void sectionStarting( SectionInfo const& sectionInfo ) { + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { StreamingReporterBase::sectionStarting( sectionInfo ); if( m_sectionDepth++ > 0 ) { m_xml.startElement( "Section" ) @@ -71,9 +68,9 @@ namespace Catch { } } - virtual void assertionStarting( AssertionInfo const& ) { } + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { const AssertionResult& assertionResult = assertionStats.assertionResult; // Print any info messages in tags. @@ -144,7 +141,7 @@ namespace Catch { return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) { + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { StreamingReporterBase::sectionEnded( sectionStats ); if( --m_sectionDepth > 0 ) { XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); @@ -159,7 +156,7 @@ namespace Catch { } } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( testCaseStats ); XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); @@ -170,7 +167,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { StreamingReporterBase::testGroupEnded( testGroupStats ); // TODO: Check testGroupStats.aborting and act accordingly. m_xml.scopedElement( "OverallResults" ) @@ -180,7 +177,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testRunEnded( TestRunStats const& testRunStats ) { + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { StreamingReporterBase::testRunEnded( testRunStats ); m_xml.scopedElement( "OverallResults" ) .writeAttribute( "successes", testRunStats.totals.assertions.passed ) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 97293423..dbaca8ba 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -798,5 +798,5 @@ with expansion: =============================================================================== test cases: 159 | 119 passed | 39 failed | 1 failed as expected -assertions: 784 | 691 passed | 80 failed | 13 failed as expected +assertions: 788 | 695 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 2e81da7b..82702ecf 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -3929,7 +3929,7 @@ with expansion: TestMain.cpp:: PASSED: - CHECK( config.reporterName.empty() ) + CHECK( config.reporterNames.empty() ) with expansion: true @@ -4019,7 +4019,7 @@ PASSED: TestMain.cpp:: PASSED: - REQUIRE( config.reporterName == "console" ) + REQUIRE( config.reporterNames[0] == "console" ) with expansion: "console" == "console" @@ -4037,10 +4037,40 @@ PASSED: TestMain.cpp:: PASSED: - REQUIRE( config.reporterName == "xml" ) + REQUIRE( config.reporterNames[0] == "xml" ) with expansion: "xml" == "xml" +------------------------------------------------------------------------------- +Process can be configured on command line + reporter + -r xml and junit +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: + CHECK_NOTHROW( parseIntoConfig( argv, config ) ) + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames.size() == 2 ) +with expansion: + 2 == 2 + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[0] == "xml" ) +with expansion: + "xml" == "xml" + +TestMain.cpp:: +PASSED: + REQUIRE( config.reporterNames[1] == "junit" ) +with expansion: + "junit" == "junit" + ------------------------------------------------------------------------------- Process can be configured on command line reporter @@ -4055,7 +4085,7 @@ PASSED: TestMain.cpp:: PASSED: - REQUIRE( config.reporterName == "junit" ) + REQUIRE( config.reporterNames[0] == "junit" ) with expansion: "junit" == "junit" @@ -8141,5 +8171,5 @@ with expansion: =============================================================================== test cases: 159 | 103 passed | 55 failed | 1 failed as expected -assertions: 804 | 691 passed | 100 failed | 13 failed as expected +assertions: 808 | 695 passed | 100 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index dfd77437..6c6e5208 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -478,6 +478,7 @@ MiscTests.cpp: + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 213d8b6e..3d20d996 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -4013,7 +4013,7 @@ - config.reporterName.empty() + config.reporterNames.empty() true @@ -4123,7 +4123,7 @@ - config.reporterName == "console" + config.reporterNames[0] == "console" "console" == "console" @@ -4145,7 +4145,7 @@ - config.reporterName == "xml" + config.reporterNames[0] == "xml" "xml" == "xml" @@ -4155,6 +4155,44 @@
+
+
+ + + parseIntoConfig( argv, config ) + + + parseIntoConfig( argv, config ) + + + + + config.reporterNames.size() == 2 + + + 2 == 2 + + + + + config.reporterNames[0] == "xml" + + + "xml" == "xml" + + + + + config.reporterNames[1] == "junit" + + + "junit" == "junit" + + + +
+ +
@@ -4167,7 +4205,7 @@ - config.reporterName == "junit" + config.reporterNames[0] == "junit" "junit" == "junit" @@ -8425,7 +8463,7 @@ there"
- + - + diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index b753cf46..4f92e30c 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -7,14 +7,16 @@ */ #include "catch.hpp" + +#ifdef __clang__ +# pragma clang diagnostic ignored "-Wc++98-compat" +# pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif + #include "internal/catch_xmlwriter.hpp" #include -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif - TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) { int a = 1; diff --git a/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp b/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp index 65709351..183d87d9 100644 --- a/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_interfaces_exception.cpp @@ -1 +1,2 @@ +#include "catch_suppress_warnings.h" #include "catch_interfaces_exception.h" diff --git a/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp b/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp index 9446c5cf..ffece3b4 100644 --- a/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_interfaces_registry_hub.cpp @@ -1,2 +1,3 @@ // This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" #include "catch_interfaces_registry_hub.h" From afcc38efc54e06360e778b3fbb778cf420165580 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 7 Aug 2015 17:28:48 +0100 Subject: [PATCH 37/87] Fixes for single include --- .../internal/catch_interfaces_registry_hub.h | 2 +- projects/SelfTest/MiscTests.cpp | 2 +- projects/SelfTest/TestMain.cpp | 2 +- .../CatchSelfTestSingle.xccheckout | 18 +++++++++--------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/internal/catch_interfaces_registry_hub.h b/include/internal/catch_interfaces_registry_hub.h index 2a420bf3..ec06ca29 100644 --- a/include/internal/catch_interfaces_registry_hub.h +++ b/include/internal/catch_interfaces_registry_hub.h @@ -8,7 +8,7 @@ #ifndef TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED -#include +#include "catch_ptr.hpp" #include diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 4f92e30c..36b8a608 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -13,7 +13,7 @@ # pragma clang diagnostic ignored "-Wc++98-compat-pedantic" #endif -#include "internal/catch_xmlwriter.hpp" +#include "../include/internal/catch_xmlwriter.hpp" #include diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index 57e68666..f4c660d6 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -8,7 +8,7 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" -#include "reporters/catch_reporter_teamcity.hpp" +#include "../include/reporters/catch_reporter_teamcity.hpp" // Some example tag aliases CATCH_REGISTER_TAG_ALIAS( "[@nhf]", "[failing]~[.]" ) diff --git a/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/xcshareddata/CatchSelfTestSingle.xccheckout b/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/xcshareddata/CatchSelfTestSingle.xccheckout index fd24e72b..cce7052b 100644 --- a/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/xcshareddata/CatchSelfTestSingle.xccheckout +++ b/projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace/xcshareddata/CatchSelfTestSingle.xccheckout @@ -10,31 +10,31 @@ CatchSelfTestSingle IDESourceControlProjectOriginsDictionary - 01DD8CA9-7DC3-46BC-B998-EFF40EA3485F - ssh://github.com/philsquared/Catch.git + 90C00904F36E6ADB57A7313E998815D255B0DEAF + https://github.com/philsquared/Catch.git IDESourceControlProjectPath - projects/XCode4/CatchSelfTest/CatchSelfTestSingle.xcodeproj/project.xcworkspace + projects/XCode/CatchSelfTest/CatchSelfTestSingle.xcodeproj IDESourceControlProjectRelativeInstallPathDictionary - 01DD8CA9-7DC3-46BC-B998-EFF40EA3485F + 90C00904F36E6ADB57A7313E998815D255B0DEAF ../../../../.. IDESourceControlProjectURL - ssh://github.com/philsquared/Catch.git + https://github.com/philsquared/Catch.git IDESourceControlProjectVersion - 110 + 111 IDESourceControlProjectWCCIdentifier - 01DD8CA9-7DC3-46BC-B998-EFF40EA3485F + 90C00904F36E6ADB57A7313E998815D255B0DEAF IDESourceControlProjectWCConfigurations IDESourceControlRepositoryExtensionIdentifierKey public.vcs.git IDESourceControlWCCIdentifierKey - 01DD8CA9-7DC3-46BC-B998-EFF40EA3485F + 90C00904F36E6ADB57A7313E998815D255B0DEAF IDESourceControlWCCName - Catch + Catch-Develop From e73583d556fc729a7d46b21765145c4f133237f6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 7 Aug 2015 17:30:34 +0100 Subject: [PATCH 38/87] dev build 12 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 611 +++++++++++++++++++---------- 3 files changed, 416 insertions(+), 199 deletions(-) diff --git a/README.md b/README.md index 3fc52b0c..6323aa63 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.11* +*v1.2.1-develop.12* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index ca18ef0d..d11a6d95 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 11 ); + Version libraryVersion( 1, 2, 1, "develop", 12 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index ac4bb515..7724e49e 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.11 - * Generated: 2015-08-03 07:40:22.369337 + * Catch v1.2.1-develop.12 + * Generated: 2015-08-07 17:29:52.878958 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -21,8 +21,6 @@ // #included from: internal/catch_suppress_warnings.h -#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED - #ifdef __clang__ # ifdef __ICC // icpc defines the __clang__ macro # pragma warning(push) @@ -44,7 +42,6 @@ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wpadded" #endif - #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) # define CATCH_IMPL #endif @@ -85,6 +82,7 @@ // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? +// CATCH_CONFIG_CPP11_OVERRIDE : is override supported? // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? @@ -201,6 +199,10 @@ # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG # endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) +# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE +# endif + #endif // __cplusplus >= 201103L // Now set the actual defines based on the above + anything the user has configured @@ -225,6 +227,9 @@ #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) # define CATCH_CONFIG_CPP11_LONG_LONG #endif +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) +# define CATCH_CONFIG_CPP11_OVERRIDE +#endif // noexcept support: #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) @@ -242,6 +247,13 @@ # define CATCH_NULL NULL #endif +// override support +#ifdef CATCH_CONFIG_CPP11_OVERRIDE +# define CATCH_OVERRIDE override +#else +# define CATCH_OVERRIDE +#endif + namespace Catch { struct IConfig; @@ -555,9 +567,13 @@ namespace Catch { struct ITestCaseRegistry { virtual ~ITestCaseRegistry(); virtual std::vector const& getAllTests() const = 0; - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const = 0; - + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + } namespace Catch { @@ -2363,7 +2379,8 @@ namespace Catch { struct IMutableRegistryHub { virtual ~IMutableRegistryHub(); - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0; + virtual void registerReporter( std::string const& name, Ptr const& factory ) = 0; + virtual void registerListener( Ptr const& factory ) = 0; virtual void registerTest( TestCase const& testInfo ) = 0; virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; }; @@ -2900,7 +2917,7 @@ return @ desc; \ #pragma clang diagnostic ignored "-Wweak-vtables" #endif -// #included from: ../catch_runner.hpp +// #included from: ../catch_session.hpp #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED // #included from: internal/catch_commandline.hpp @@ -3296,11 +3313,11 @@ namespace Catch { ShowDurations::OrNot showDurations; RunTests::InWhatOrder runOrder; - std::string reporterName; std::string outputFilename; std::string name; std::string processName; + std::vector reporterNames; std::vector testsOrTags; }; @@ -3360,7 +3377,7 @@ namespace Catch { m_stream = stream; } - std::string getReporterName() const { return m_data.reporterName; } + std::vector getReporterNames() const { return m_data.reporterNames; } int abortAfter() const { return m_data.abortAfter; } @@ -4269,6 +4286,7 @@ namespace Catch { config.abortAfter = x; } inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } + inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } inline void addWarning( ConfigData& config, std::string const& _warning ) { if( _warning == "NoAssertions" ) @@ -4362,7 +4380,7 @@ namespace Catch { cli["-r"]["--reporter"] // .placeholder( "name[:filename]" ) .describe( "reporter to use (defaults to console)" ) - .bind( &ConfigData::reporterName, "name" ); + .bind( &addReporterName, "name" ); cli["-n"]["--name"] .describe( "suite name" ) @@ -4873,6 +4891,7 @@ namespace Catch // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; @@ -4881,20 +4900,24 @@ namespace Catch virtual void skipTest( TestCaseInfo const& testInfo ) = 0; }; - struct IReporterFactory { + struct IReporterFactory : IShared { virtual ~IReporterFactory(); virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; virtual std::string getDescription() const = 0; }; struct IReporterRegistry { - typedef std::map FactoryMap; + typedef std::map > FactoryMap; + typedef std::vector > Listeners; virtual ~IReporterRegistry(); virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; }; + Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); + } #include @@ -4917,8 +4940,7 @@ namespace Catch { nameAttr.setInitialIndent( 2 ).setIndent( 4 ); tagsAttr.setIndent( 6 ); - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4946,8 +4968,7 @@ namespace Catch { if( !config.testSpec().hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); std::size_t matchedTests = 0; - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -4987,8 +5008,7 @@ namespace Catch { std::map tagCounts; - std::vector matchedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases ); + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); for( std::vector::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); it != itEnd; ++it ) { @@ -5059,7 +5079,7 @@ namespace Catch { } // end namespace Catch -// #included from: internal/catch_runner_impl.hpp +// #included from: internal/catch_run_context.hpp #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED // #included from: catch_test_case_tracker.hpp @@ -5647,11 +5667,7 @@ namespace Catch { namespace Catch { - Ptr makeReporter( Ptr const& config ) { - std::string reporterName = config->getReporterName().empty() - ? "console" - : config->getReporterName(); - + Ptr createReporter( std::string const& reporterName, Ptr const& config ) { Ptr reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); if( !reporter ) { std::ostringstream oss; @@ -5661,6 +5677,27 @@ namespace Catch { return reporter; } + Ptr makeReporter( Ptr const& config ) { + std::vector reporters = config->getReporterNames(); + if( reporters.empty() ) + reporters.push_back( "console" ); + + Ptr reporter; + for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); + it != itEnd; + ++it ) + reporter = addReporter( reporter, createReporter( *it, config ) ); + return reporter; + } + Ptr addListeners( Ptr const& config, Ptr reporters ) { + IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); + for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); + it != itEnd; + ++it ) + reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); + return reporters; + } + void openStreamInto( Ptr const& config, std::ofstream& ofs ) { // Open output file, if specified if( !config->getFilename().empty() ) { @@ -5679,6 +5716,7 @@ namespace Catch { std::ofstream ofs; openStreamInto( config, ofs ); Ptr reporter = makeReporter( config ); + reporter = addListeners( config.get(), reporter ); RunContext context( config.get(), reporter ); @@ -5690,36 +5728,22 @@ namespace Catch { if( !testSpec.hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - std::vector testCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *config, testCases ); - - std::set testsAlreadyRun; - for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + std::vector const& allTestCases = getAllTestCasesSorted( *config ); + for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); it != itEnd; ++it ) { - if( testsAlreadyRun.find( *it ) == testsAlreadyRun.end() ) { - - if( context.aborting() ) - break; - + if( !context.aborting() && matchTest( *it, testSpec, *config ) ) totals += context.runTest( *it ); - testsAlreadyRun.insert( *it ); - } + else + reporter->skipTest( *it ); } - std::vector skippedTestCases; - getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *config, skippedTestCases, true ); - - for( std::vector::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end(); - it != itEnd; - ++it ) - reporter->skipTest( *it ); context.testGroupEnded( config->name(), totals, 1, 1 ); return totals; } - void applyFilenamesAsTags() { - std::vector const& tests = getRegistryHub().getTestCaseRegistry().getAllTests(); + void applyFilenamesAsTags( IConfig const& config ) { + std::vector const& tests = getAllTestCasesSorted( config ); for(std::size_t i = 0; i < tests.size(); ++i ) { TestCase& test = const_cast( tests[i] ); std::set tags = test.tags; @@ -5808,11 +5832,11 @@ namespace Catch { { config(); // Force config to be constructed - if( m_configData.filenamesAsTags ) - applyFilenamesAsTags(); - seedRng( *m_config ); + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + // Handle list request if( Option listed = list( config() ) ) return static_cast( *listed ); @@ -5839,7 +5863,6 @@ namespace Catch { m_config = new Config( m_configData ); return *m_config; } - private: Clara::CommandLine m_cli; std::vector m_unusedTokens; @@ -5865,14 +5888,75 @@ namespace Catch { namespace Catch { - class TestRegistry : public ITestCaseRegistry { - struct LexSort { - bool operator() (TestCase i,TestCase j) const { return (i sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end(), LexSort() ); + break; + case RunTests::InRandomOrder: + { + seedRng( config ); + + RandomNumberGenerator rng; + std::random_shuffle( sorted.begin(), sorted.end(), rng ); + } + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + struct TestMatcher { + TestMatcher( TestSpec const& testSpec, bool allowThrows ) : m_testSpec( testSpec ), m_allowThrows( allowThrows ) {} + + bool operator()( TestCase const& testCase ) const { + return m_testSpec.matches( testCase ) && ( m_allowThrows || !testCase.throws() ); + } + TestSpec m_testSpec; + bool m_allowThrows; + }; + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( std::vector::const_iterator it = functions.begin(), itEnd = functions.end(); + it != itEnd; + ++it ) { + std::pair::const_iterator, bool> prev = seenFunctions.insert( *it ); + if( !prev.second ){ + Catch::cerr() + << Colour( Colour::Red ) + << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; + exit(1); + } + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + std::copy_if( testCases.begin(), testCases.end(), std::back_inserter( filtered ), TestMatcher( testSpec, config.allowThrows() ) ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + class TestRegistry : public ITestCaseRegistry { public: TestRegistry() : m_unnamedCount( 0 ) {} virtual ~TestRegistry(); @@ -5884,70 +5968,27 @@ namespace Catch { oss << "Anonymous test case " << ++m_unnamedCount; return registerTest( testCase.withName( oss.str() ) ); } - - if( m_functions.find( testCase ) == m_functions.end() ) { - m_functions.insert( testCase ); - m_functionsInOrder.push_back( testCase ); - if( !testCase.isHidden() ) - m_nonHiddenFunctions.push_back( testCase ); - } - else { - TestCase const& prev = *m_functions.find( testCase ); - { - Colour colourGuard( Colour::Red ); - Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" - << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" - << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; - } - exit(1); - } + m_functions.push_back( testCase ); } virtual std::vector const& getAllTests() const { - return m_functionsInOrder; + return m_functions; } + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); - virtual std::vector const& getAllNonHiddenTests() const { - return m_nonHiddenFunctions; - } - - virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector& matchingTestCases, bool negated = false ) const { - - for( std::vector::const_iterator it = m_functionsInOrder.begin(), - itEnd = m_functionsInOrder.end(); - it != itEnd; - ++it ) { - bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ); - if( includeTest != negated ) - matchingTestCases.push_back( *it ); + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); } - sortTests( config, matchingTestCases ); + return m_sortedFunctions; } private: - - static void sortTests( IConfig const& config, std::vector& matchingTestCases ) { - - switch( config.runOrder() ) { - case RunTests::InLexicographicalOrder: - std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() ); - break; - case RunTests::InRandomOrder: - { - seedRng( config ); - - RandomNumberGenerator rng; - std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng ); - } - break; - case RunTests::InDeclarationOrder: - // already in declaration order - break; - } - } - std::set m_functions; - std::vector m_functionsInOrder; - std::vector m_nonHiddenFunctions; + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder; + mutable std::vector m_sortedFunctions; size_t m_unnamedCount; std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised }; @@ -6018,27 +6059,32 @@ namespace Catch { public: - virtual ~ReporterRegistry() { - deleteAllValues( m_factories ); - } + virtual ~ReporterRegistry() override {} - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const { + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const override { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return CATCH_NULL; return it->second->create( ReporterConfig( config ) ); } - void registerReporter( std::string const& name, IReporterFactory* factory ) { + void registerReporter( std::string const& name, Ptr const& factory ) { m_factories.insert( std::make_pair( name, factory ) ); } + void registerListener( Ptr const& factory ) { + m_listeners.push_back( factory ); + } - FactoryMap const& getFactories() const { + virtual FactoryMap const& getFactories() const override { return m_factories; } + virtual Listeners const& getListeners() const override { + return m_listeners; + } private: FactoryMap m_factories; + Listeners m_listeners; }; } @@ -6121,24 +6167,27 @@ namespace Catch { public: // IRegistryHub RegistryHub() { } - virtual IReporterRegistry const& getReporterRegistry() const { + virtual IReporterRegistry const& getReporterRegistry() const override { return m_reporterRegistry; } - virtual ITestCaseRegistry const& getTestCaseRegistry() const { + virtual ITestCaseRegistry const& getTestCaseRegistry() const override { return m_testCaseRegistry; } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { return m_exceptionTranslatorRegistry; } public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { + virtual void registerReporter( std::string const& name, Ptr const& factory ) override { m_reporterRegistry.registerReporter( name, factory ); } - virtual void registerTest( TestCase const& testInfo ) { + virtual void registerListener( Ptr const& factory ) override { + m_reporterRegistry.registerListener( factory ); + } + virtual void registerTest( TestCase const& testInfo ) override { m_testCaseRegistry.registerTest( testInfo ); } - virtual void registerTranslator( const IExceptionTranslator* translator ) { + virtual void registerTranslator( const IExceptionTranslator* translator ) override { m_exceptionTranslatorRegistry.registerTranslator( translator ); } @@ -6929,7 +6978,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 11 ); + Version libraryVersion( 1, 2, 1, "develop", 12 ); } @@ -7797,6 +7846,137 @@ namespace Catch { } // end namespace Catch +// #included from: ../reporters/catch_reporter_multi.hpp +#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED + +namespace Catch { + +class MultipleReporters : public SharedImpl { + typedef std::vector > Reporters; + Reporters m_reporters; + +public: + void add( Ptr const& reporter ) { + m_reporters.push_back( reporter ); + } + +public: // IStreamingReporter + + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporters[0]->getPreferences(); + } + + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->noMatchingTestCases( spec ); + } + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunStarting( testRunInfo ); + } + + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupStarting( groupInfo ); + } + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseStarting( testInfo ); + } + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionStarting( sectionInfo ); + } + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { + bool clearBuffer = false; + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + clearBuffer |= (*it)->assertionEnded( assertionStats ); + return clearBuffer; + } + + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->sectionEnded( sectionStats ); + } + + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testCaseEnded( testCaseStats ); + } + + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testGroupEnded( testGroupStats ); + } + + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->testRunEnded( testRunStats ); + } + + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { + for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); + it != itEnd; + ++it ) + (*it)->skipTest( testInfo ); + } +}; + +Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { + Ptr resultingReporter; + + if( existingReporter ) { + MultipleReporters* multi = dynamic_cast( existingReporter.get() ); + if( !multi ) { + multi = new MultipleReporters; + resultingReporter = Ptr( multi ); + if( existingReporter ) + multi->add( existingReporter ); + } + else + resultingReporter = existingReporter; + multi->add( additionalReporter ); + } + else + resultingReporter = additionalReporter; + + return resultingReporter; +} + +} // end namespace Catch + // #included from: ../reporters/catch_reporter_xml.hpp #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED @@ -7812,42 +7992,48 @@ namespace Catch { StreamingReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = false; + } - virtual ~StreamingReporterBase(); + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } - virtual void noMatchingTestCases( std::string const& ) {} + virtual ~StreamingReporterBase() CATCH_OVERRIDE; - virtual void testRunStarting( TestRunInfo const& _testRunInfo ) { + virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} + + virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { currentTestRunInfo = _testRunInfo; } - virtual void testGroupStarting( GroupInfo const& _groupInfo ) { + virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { currentGroupInfo = _groupInfo; } - virtual void testCaseStarting( TestCaseInfo const& _testInfo ) { + virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { currentTestCaseInfo = _testInfo; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_sectionStack.push_back( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) { + virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { m_sectionStack.pop_back(); } - virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { + virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); } - virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { + virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { currentGroupInfo.reset(); } - virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) { + virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { currentTestCaseInfo.reset(); currentGroupInfo.reset(); currentTestRunInfo.reset(); } - virtual void skipTest( TestCaseInfo const& ) { + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { // Don't do anything with this by default. // It can optionally be overridden in the derived class. } @@ -7860,6 +8046,7 @@ namespace Catch { LazyStat currentTestCaseInfo; std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; }; struct CumulativeReporterBase : SharedImpl { @@ -7910,15 +8097,21 @@ namespace Catch { CumulativeReporterBase( ReporterConfig const& _config ) : m_config( _config.fullConfig() ), stream( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = false; + } ~CumulativeReporterBase(); - virtual void testRunStarting( TestRunInfo const& ) {} - virtual void testGroupStarting( GroupInfo const& ) {} + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { + return m_reporterPrefs; + } - virtual void testCaseStarting( TestCaseInfo const& ) {} + virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} + virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} - virtual void sectionStarting( SectionInfo const& sectionInfo ) { + virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} + + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); Ptr node; if( m_sectionStack.empty() ) { @@ -7943,7 +8136,7 @@ namespace Catch { m_deepestSection = node; } - virtual void assertionStarting( AssertionInfo const& ) {} + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} virtual bool assertionEnded( AssertionStats const& assertionStats ) { assert( !m_sectionStack.empty() ); @@ -7951,13 +8144,13 @@ namespace Catch { sectionNode.assertions.push_back( assertionStats ); return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) { + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { assert( !m_sectionStack.empty() ); SectionNode& node = *m_sectionStack.back(); node.stats = sectionStats; m_sectionStack.pop_back(); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { Ptr node = new TestCaseNode( testCaseStats ); assert( m_sectionStack.size() == 0 ); node->children.push_back( m_rootSection ); @@ -7968,12 +8161,12 @@ namespace Catch { m_deepestSection->stdOut = testCaseStats.stdOut; m_deepestSection->stdErr = testCaseStats.stdErr; } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { Ptr node = new TestGroupNode( testGroupStats ); node->children.swap( m_testCases ); m_testGroups.push_back( node ); } - virtual void testRunEnded( TestRunStats const& testRunStats ) { + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { Ptr node = new TestRunNode( testRunStats ); node->children.swap( m_testGroups ); m_testRuns.push_back( node ); @@ -7981,7 +8174,7 @@ namespace Catch { } virtual void testRunEndedCumulative() = 0; - virtual void skipTest( TestCaseInfo const& ) {} + virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} Ptr m_config; std::ostream& stream; @@ -7995,6 +8188,7 @@ namespace Catch { Ptr m_rootSection; Ptr m_deepestSection; std::vector > m_sectionStack; + ReporterPreferences m_reporterPrefs; }; @@ -8008,6 +8202,17 @@ namespace Catch { return line; } + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ) + : StreamingReporterBase( _config ) + {} + + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + return false; + } + }; + } // end namespace Catch // #included from: ../internal/catch_reporter_registrars.hpp @@ -8038,7 +8243,7 @@ namespace Catch { template class ReporterRegistrar { - class ReporterFactory : public IReporterFactory { + class ReporterFactory : public SharedImpl { // *** Please Note ***: // - If you end up here looking at a compiler error because it's trying to register @@ -8066,13 +8271,37 @@ namespace Catch { getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; + + template + class ListenerRegistrar { + + class ListenerFactory : public SharedImpl { + + virtual IStreamingReporter* create( ReporterConfig const& config ) const { + return new T( config ); + } + virtual std::string getDescription() const { + return ""; + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( new ListenerFactory() ); + } + }; } #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ namespace{ Catch::LegacyReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } + #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } +#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } + // #included from: ../internal/catch_xmlwriter.hpp #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED @@ -8317,26 +8546,23 @@ namespace Catch { XmlReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), m_sectionDepth( 0 ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = true; + } - virtual ~XmlReporter(); + virtual ~XmlReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as an XML document"; } public: // StreamingReporterBase - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - virtual void noMatchingTestCases( std::string const& s ) { + virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { StreamingReporterBase::noMatchingTestCases( s ); } - virtual void testRunStarting( TestRunInfo const& testInfo ) { + virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testRunStarting( testInfo ); m_xml.setStream( stream ); m_xml.startElement( "Catch" ); @@ -8344,13 +8570,13 @@ namespace Catch { m_xml.writeAttribute( "name", m_config->name() ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) { + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { StreamingReporterBase::testGroupStarting( groupInfo ); m_xml.startElement( "Group" ) .writeAttribute( "name", groupInfo.name ); } - virtual void testCaseStarting( TestCaseInfo const& testInfo ) { + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { StreamingReporterBase::testCaseStarting(testInfo); m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); @@ -8358,7 +8584,7 @@ namespace Catch { m_testCaseTimer.start(); } - virtual void sectionStarting( SectionInfo const& sectionInfo ) { + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { StreamingReporterBase::sectionStarting( sectionInfo ); if( m_sectionDepth++ > 0 ) { m_xml.startElement( "Section" ) @@ -8367,9 +8593,9 @@ namespace Catch { } } - virtual void assertionStarting( AssertionInfo const& ) { } + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { const AssertionResult& assertionResult = assertionStats.assertionResult; // Print any info messages in tags. @@ -8440,7 +8666,7 @@ namespace Catch { return true; } - virtual void sectionEnded( SectionStats const& sectionStats ) { + virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { StreamingReporterBase::sectionEnded( sectionStats ); if( --m_sectionDepth > 0 ) { XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); @@ -8455,7 +8681,7 @@ namespace Catch { } } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( testCaseStats ); XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); @@ -8466,7 +8692,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { StreamingReporterBase::testGroupEnded( testGroupStats ); // TODO: Check testGroupStats.aborting and act accordingly. m_xml.scopedElement( "OverallResults" ) @@ -8476,7 +8702,7 @@ namespace Catch { m_xml.endElement(); } - virtual void testRunEnded( TestRunStats const& testRunStats ) { + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { StreamingReporterBase::testRunEnded( testRunStats ); m_xml.scopedElement( "OverallResults" ) .writeAttribute( "successes", testRunStats.totals.assertions.passed ) @@ -8507,28 +8733,24 @@ namespace Catch { JunitReporter( ReporterConfig const& _config ) : CumulativeReporterBase( _config ), xml( _config.stream() ) - {} + { + m_reporterPrefs.shouldRedirectStdOut = true; + } - ~JunitReporter(); + virtual ~JunitReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results in an XML format that looks like Ant's junitreport target"; } - virtual void noMatchingTestCases( std::string const& /*spec*/ ) {} + virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = true; - return prefs; - } - - virtual void testRunStarting( TestRunInfo const& runInfo ) { + virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { CumulativeReporterBase::testRunStarting( runInfo ); xml.startElement( "testsuites" ); } - virtual void testGroupStarting( GroupInfo const& groupInfo ) { + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { suiteTimer.start(); stdOutForSuite.str(""); stdErrForSuite.str(""); @@ -8536,25 +8758,25 @@ namespace Catch { CumulativeReporterBase::testGroupStarting( groupInfo ); } - virtual bool assertionEnded( AssertionStats const& assertionStats ) { + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException ) unexpectedExceptions++; return CumulativeReporterBase::assertionEnded( assertionStats ); } - virtual void testCaseEnded( TestCaseStats const& testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { stdOutForSuite << testCaseStats.stdOut; stdErrForSuite << testCaseStats.stdErr; CumulativeReporterBase::testCaseEnded( testCaseStats ); } - virtual void testGroupEnded( TestGroupStats const& testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { double suiteTime = suiteTimer.getElapsedSeconds(); CumulativeReporterBase::testGroupEnded( testGroupStats ); writeGroup( *m_testGroups.back(), suiteTime ); } - virtual void testRunEndedCumulative() { + virtual void testRunEndedCumulative() CATCH_OVERRIDE { xml.endElement(); } @@ -8719,24 +8941,19 @@ namespace Catch { m_headerPrinted( false ) {} - virtual ~ConsoleReporter(); + virtual ~ConsoleReporter() CATCH_OVERRIDE; static std::string getDescription() { return "Reports test results as plain lines of text"; } - virtual ReporterPreferences getPreferences() const { - ReporterPreferences prefs; - prefs.shouldRedirectStdOut = false; - return prefs; - } - virtual void noMatchingTestCases( std::string const& spec ) { + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { stream << "No test cases matched '" << spec << "'" << std::endl; } - virtual void assertionStarting( AssertionInfo const& ) { + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - virtual bool assertionEnded( AssertionStats const& _assertionStats ) { + virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = _assertionStats.assertionResult; bool printInfoMessages = true; @@ -8756,11 +8973,11 @@ namespace Catch { return true; } - virtual void sectionStarting( SectionInfo const& _sectionInfo ) { + virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { m_headerPrinted = false; StreamingReporterBase::sectionStarting( _sectionInfo ); } - virtual void sectionEnded( SectionStats const& _sectionStats ) { + virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { if( _sectionStats.missingAssertions ) { lazyPrint(); Colour colour( Colour::ResultError ); @@ -8782,11 +8999,11 @@ namespace Catch { StreamingReporterBase::sectionEnded( _sectionStats ); } - virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { + virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( _testCaseStats ); m_headerPrinted = false; } - virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { + virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { if( currentGroupInfo.used ) { printSummaryDivider(); stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; @@ -8795,7 +9012,7 @@ namespace Catch { } StreamingReporterBase::testGroupEnded( _testGroupStats ); } - virtual void testRunEnded( TestRunStats const& _testRunStats ) { + virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { printTotalsDivider( _testRunStats.totals ); printTotals( _testRunStats.totals ); stream << std::endl; From 8a05f46a3710ae063ecbdc680061a37e81468f9b Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 7 Aug 2015 17:53:29 +0100 Subject: [PATCH 39/87] Removed use of std::copy_if (as it's limited to c++11) --- .../internal/catch_test_case_registry_impl.hpp | 16 ++++++---------- single_include/catch.hpp | 18 +++++++----------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index ac789a38..fda70aae 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -53,15 +53,6 @@ namespace Catch { bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); } - struct TestMatcher { - TestMatcher( TestSpec const& testSpec, bool allowThrows ) : m_testSpec( testSpec ), m_allowThrows( allowThrows ) {} - - bool operator()( TestCase const& testCase ) const { - return m_testSpec.matches( testCase ) && ( m_allowThrows || !testCase.throws() ); - } - TestSpec m_testSpec; - bool m_allowThrows; - }; void enforceNoDuplicateTestCases( std::vector const& functions ) { std::set seenFunctions; @@ -82,7 +73,12 @@ namespace Catch { std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { std::vector filtered; - std::copy_if( testCases.begin(), testCases.end(), std::back_inserter( filtered ), TestMatcher( testSpec, config.allowThrows() ) ); + filtered.reserve( testCases.size() ); + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); return filtered; } std::vector const& getAllTestCasesSorted( IConfig const& config ) { diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 7724e49e..fcffca19 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* * Catch v1.2.1-develop.12 - * Generated: 2015-08-07 17:29:52.878958 + * Generated: 2015-08-07 17:51:37.651202 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -5920,15 +5920,6 @@ namespace Catch { bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); } - struct TestMatcher { - TestMatcher( TestSpec const& testSpec, bool allowThrows ) : m_testSpec( testSpec ), m_allowThrows( allowThrows ) {} - - bool operator()( TestCase const& testCase ) const { - return m_testSpec.matches( testCase ) && ( m_allowThrows || !testCase.throws() ); - } - TestSpec m_testSpec; - bool m_allowThrows; - }; void enforceNoDuplicateTestCases( std::vector const& functions ) { std::set seenFunctions; @@ -5949,7 +5940,12 @@ namespace Catch { std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { std::vector filtered; - std::copy_if( testCases.begin(), testCases.end(), std::back_inserter( filtered ), TestMatcher( testSpec, config.allowThrows() ) ); + filtered.reserve( testCases.size() ); + for( std::vector::const_iterator it = testCases.begin(), itEnd = testCases.end(); + it != itEnd; + ++it ) + if( matchTest( *it, testSpec, config ) ) + filtered.push_back( *it ); return filtered; } std::vector const& getAllTestCasesSorted( IConfig const& config ) { From ad7edd068048af7193b1e051cc6d57983c989429 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 10 Aug 2015 07:32:21 +0100 Subject: [PATCH 40/87] Replaced some stray overrides with CATCH_OVERRIDE --- include/internal/catch_registry_hub.hpp | 14 +++++++------- include/internal/catch_reporter_registry.hpp | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/internal/catch_registry_hub.hpp b/include/internal/catch_registry_hub.hpp index 47c1bb42..35293bf5 100644 --- a/include/internal/catch_registry_hub.hpp +++ b/include/internal/catch_registry_hub.hpp @@ -26,27 +26,27 @@ namespace Catch { public: // IRegistryHub RegistryHub() { } - virtual IReporterRegistry const& getReporterRegistry() const override { + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { return m_reporterRegistry; } - virtual ITestCaseRegistry const& getTestCaseRegistry() const override { + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { return m_testCaseRegistry; } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { return m_exceptionTranslatorRegistry; } public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, Ptr const& factory ) override { + virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { m_reporterRegistry.registerReporter( name, factory ); } - virtual void registerListener( Ptr const& factory ) override { + virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { m_reporterRegistry.registerListener( factory ); } - virtual void registerTest( TestCase const& testInfo ) override { + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { m_testCaseRegistry.registerTest( testInfo ); } - virtual void registerTranslator( const IExceptionTranslator* translator ) override { + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { m_exceptionTranslatorRegistry.registerTranslator( translator ); } diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index b0ac2fba..b67252f3 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -18,9 +18,9 @@ namespace Catch { public: - virtual ~ReporterRegistry() override {} + virtual ~ReporterRegistry() CATCH_OVERRIDE {} - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const override { + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return CATCH_NULL; @@ -34,10 +34,10 @@ namespace Catch { m_listeners.push_back( factory ); } - virtual FactoryMap const& getFactories() const override { + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { return m_factories; } - virtual Listeners const& getListeners() const override { + virtual Listeners const& getListeners() const CATCH_OVERRIDE { return m_listeners; } From 19520157fb6905c8ba9cc1e0680c824b0b0c454c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 10 Aug 2015 07:32:48 +0100 Subject: [PATCH 41/87] regen single header --- single_include/catch.hpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/single_include/catch.hpp b/single_include/catch.hpp index fcffca19..82d12af2 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* * Catch v1.2.1-develop.12 - * Generated: 2015-08-07 17:51:37.651202 + * Generated: 2015-08-10 07:32:30.267995 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -6055,9 +6055,9 @@ namespace Catch { public: - virtual ~ReporterRegistry() override {} + virtual ~ReporterRegistry() CATCH_OVERRIDE {} - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const override { + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return CATCH_NULL; @@ -6071,10 +6071,10 @@ namespace Catch { m_listeners.push_back( factory ); } - virtual FactoryMap const& getFactories() const override { + virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { return m_factories; } - virtual Listeners const& getListeners() const override { + virtual Listeners const& getListeners() const CATCH_OVERRIDE { return m_listeners; } @@ -6163,27 +6163,27 @@ namespace Catch { public: // IRegistryHub RegistryHub() { } - virtual IReporterRegistry const& getReporterRegistry() const override { + virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { return m_reporterRegistry; } - virtual ITestCaseRegistry const& getTestCaseRegistry() const override { + virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { return m_testCaseRegistry; } - virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { return m_exceptionTranslatorRegistry; } public: // IMutableRegistryHub - virtual void registerReporter( std::string const& name, Ptr const& factory ) override { + virtual void registerReporter( std::string const& name, Ptr const& factory ) CATCH_OVERRIDE { m_reporterRegistry.registerReporter( name, factory ); } - virtual void registerListener( Ptr const& factory ) override { + virtual void registerListener( Ptr const& factory ) CATCH_OVERRIDE { m_reporterRegistry.registerListener( factory ); } - virtual void registerTest( TestCase const& testInfo ) override { + virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { m_testCaseRegistry.registerTest( testInfo ); } - virtual void registerTranslator( const IExceptionTranslator* translator ) override { + virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { m_exceptionTranslatorRegistry.registerTranslator( translator ); } From 40d0d2f65647bd429604cd8856e1eadb47843eb5 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 11 Aug 2015 08:09:41 +0100 Subject: [PATCH 42/87] Added unique_ptr detection to compiler_capabilities - as well as use by C++11 conformant compilers now enabled for VS2013 on too (see #479) - updated docs with this (and long long and override support) --- docs/configuration.md | 3 +++ include/external/clara.h | 7 +---- .../internal/catch_compiler_capabilities.h | 27 ++++++++++++++++--- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index d1788c34..33052190 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -58,6 +58,9 @@ This can be useful on certain platforms that do not provide ```std::cout``` and CATCH_CONFIG_CPP11_IS_ENUM // std::is_enum is supported? CATCH_CONFIG_CPP11_TUPLE // std::tuple is supported CATCH_CONFIG_VARIADIC_MACROS // Usually pre-C++11 compiler extensions are sufficient + CATCH_CONFIG_CPP11_LONG_LONG // generates overloads for the long long type + CATCH_CONFIG_CPP11_OVERRIDE // CATCH_OVERRIDE expands to override (for virtual function implementations) + CATCH_CONFIG_CPP11_UNIQUE_PTR // Use std::unique_ptr instead of std::auto_ptr Catch has some basic compiler detection that will attempt to select the appropriate mix of these macros. However being incomplete - and often without access to the respective compilers - this detection tends to be conservative. So overriding control is given to the user. If a compiler supports a feature (and Catch does not already detect it) then one or more of these may be defined to enable it (or suppress it, in some cases). If you do do this please raise an issue, specifying your compiler version (ideally with an idea of how to detect it) and stating that it has such support. diff --git a/include/external/clara.h b/include/external/clara.h index 5cd4759b..2c03f985 100644 --- a/include/external/clara.h +++ b/include/external/clara.h @@ -503,12 +503,7 @@ namespace Clara { } }; - // NOTE: std::auto_ptr is deprecated in c++11/c++0x -#if defined(__cplusplus) && __cplusplus > 199711L - typedef std::unique_ptr ArgAutoPtr; -#else - typedef std::auto_ptr ArgAutoPtr; -#endif + typedef CATCH_AUTO_PTR( Arg ) ArgAutoPtr; friend void addOptName( Arg& arg, std::string const& optName ) { diff --git a/include/internal/catch_compiler_capabilities.h b/include/internal/catch_compiler_capabilities.h index ad9c59c5..7ac7b73f 100644 --- a/include/internal/catch_compiler_capabilities.h +++ b/include/internal/catch_compiler_capabilities.h @@ -18,11 +18,16 @@ // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? // CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** // In general each macro has a _NO_ form // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. @@ -84,6 +89,7 @@ #if (_MSC_VER >= 1600) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR #endif #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) @@ -93,6 +99,8 @@ #endif // _MSC_VER +//////////////////////////////////////////////////////////////////////////////// + // Use variadic macros if the compiler supports them #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ @@ -107,7 +115,7 @@ // C++ language feature support // catch all support for C++11 -#if (__cplusplus >= 201103L) +#if defined(__cplusplus) && __cplusplus >= 201103L # define CATCH_CPP11_OR_GREATER @@ -142,6 +150,9 @@ # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE # endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif #endif // __cplusplus >= 201103L @@ -165,12 +176,15 @@ #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) # define CATCH_CONFIG_VARIADIC_MACROS #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) +#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) # define CATCH_CONFIG_CPP11_LONG_LONG #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_OVERRIDE #endif +#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) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif // noexcept support: @@ -196,5 +210,12 @@ # define CATCH_OVERRIDE #endif +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + #endif // TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED From 312b94e532100fbda8540bf4f15fb1cdc2b8cd71 Mon Sep 17 00:00:00 2001 From: Simon Warta Date: Wed, 12 Aug 2015 11:05:16 +0200 Subject: [PATCH 43/87] Add matcher: Not() --- include/internal/catch_matchers.hpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index a959095e..a2adf61f 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -32,6 +32,23 @@ namespace Matchers { }; namespace Generic { + template + struct Not : public MatcherImpl, ExpressionT> + { + Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE + { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + + Ptr< Matcher > m_matcher; + }; template class AllOf : public MatcherImpl, ExpressionT> { @@ -204,6 +221,11 @@ namespace Matchers { // The following functions create the actual matcher objects. // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + template inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, Impl::Matcher const& m2 ) { From d234ed1a67a41e2d14ddb1fbe839a4e5ab466311 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 24 Aug 2015 06:28:25 +0100 Subject: [PATCH 44/87] dev build 13 --- README.md | 2 +- include/internal/catch_matchers.hpp | 7 +--- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 62 +++++++++++++++++++++++------ 4 files changed, 53 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 6323aa63..d84793ff 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.12* +*v1.2.1-develop.13* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index a2adf61f..8b0783cc 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -33,13 +33,11 @@ namespace Matchers { namespace Generic { template - struct Not : public MatcherImpl, ExpressionT> - { + struct Not : public MatcherImpl, ExpressionT> { Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} Not( Not const& other ) : m_matcher( other.m_matcher ) {} - virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE - { + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { return !m_matcher->match( expr ); } @@ -117,7 +115,6 @@ namespace Matchers { private: std::vector > > m_matchers; }; - } namespace StdString { diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index d11a6d95..d292644c 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 12 ); + Version libraryVersion( 1, 2, 1, "develop", 13 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 82d12af2..94067d84 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.12 - * Generated: 2015-08-10 07:32:30.267995 + * Catch v1.2.1-develop.13 + * Generated: 2015-08-24 06:27:37.882342 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -83,11 +83,17 @@ // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? // CATCH_CONFIG_CPP11_OVERRIDE : is override supported? +// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + // In general each macro has a _NO_ form // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. // Many features, at point of detection, define an _INTERNAL_ macro, so they @@ -144,6 +150,7 @@ #if (_MSC_VER >= 1600) # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR #endif #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) @@ -153,6 +160,8 @@ #endif // _MSC_VER +//////////////////////////////////////////////////////////////////////////////// + // Use variadic macros if the compiler supports them #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ @@ -167,7 +176,7 @@ // C++ language feature support // catch all support for C++11 -#if (__cplusplus >= 201103L) +#if defined(__cplusplus) && __cplusplus >= 201103L # define CATCH_CPP11_OR_GREATER @@ -202,6 +211,9 @@ # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE # endif +# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) +# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR +# endif #endif // __cplusplus >= 201103L @@ -224,12 +236,15 @@ #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) # define CATCH_CONFIG_VARIADIC_MACROS #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) +#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) # define CATCH_CONFIG_CPP11_LONG_LONG #endif -#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) +#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) # define CATCH_CONFIG_CPP11_OVERRIDE #endif +#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) +# define CATCH_CONFIG_CPP11_UNIQUE_PTR +#endif // noexcept support: #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) @@ -254,6 +269,13 @@ # define CATCH_OVERRIDE #endif +// unique_ptr support +#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR +# define CATCH_AUTO_PTR( T ) std::unique_ptr +#else +# define CATCH_AUTO_PTR( T ) std::auto_ptr +#endif + namespace Catch { struct IConfig; @@ -828,6 +850,21 @@ namespace Matchers { }; namespace Generic { + template + struct Not : public MatcherImpl, ExpressionT> { + Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + Not( Not const& other ) : m_matcher( other.m_matcher ) {} + + virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { + return !m_matcher->match( expr ); + } + + virtual std::string toString() const CATCH_OVERRIDE { + return "not " + m_matcher->toString(); + } + + Ptr< Matcher > m_matcher; + }; template class AllOf : public MatcherImpl, ExpressionT> { @@ -896,7 +933,6 @@ namespace Matchers { private: std::vector > > m_matchers; }; - } namespace StdString { @@ -1000,6 +1036,11 @@ namespace Matchers { // The following functions create the actual matcher objects. // This allows the types to be inferred + template + inline Impl::Generic::Not Not( Impl::Matcher const& m ) { + return Impl::Generic::Not( m ); + } + template inline Impl::Generic::AllOf AllOf( Impl::Matcher const& m1, Impl::Matcher const& m2 ) { @@ -3908,12 +3949,7 @@ namespace Clara { } }; - // NOTE: std::auto_ptr is deprecated in c++11/c++0x -#if defined(__cplusplus) && __cplusplus > 199711L - typedef std::unique_ptr ArgAutoPtr; -#else - typedef std::auto_ptr ArgAutoPtr; -#endif + typedef CATCH_AUTO_PTR( Arg ) ArgAutoPtr; friend void addOptName( Arg& arg, std::string const& optName ) { @@ -6974,7 +7010,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 12 ); + Version libraryVersion( 1, 2, 1, "develop", 13 ); } From 166ca2e81901c2a12e10fcbf60908df286c2caed Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sat, 26 Sep 2015 18:12:21 -0700 Subject: [PATCH 45/87] Do uncaught_exception checking before calling sectionEnded - split the uncaught handling (adding to unfinishedSections) into separate method --- include/internal/catch_interfaces_capture.h | 4 ++- include/internal/catch_run_context.hpp | 39 ++++++++------------- include/internal/catch_section.hpp | 9 +++-- include/internal/catch_section_info.h | 13 ++++++- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index bdbcfb2f..b7b6e32d 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -18,6 +18,7 @@ namespace Catch { class AssertionResult; struct AssertionInfo; struct SectionInfo; + struct SectionEndInfo; struct MessageInfo; class ScopedMessageBuilder; struct Counts; @@ -29,7 +30,8 @@ namespace Catch { virtual void assertionEnded( AssertionResult const& result ) = 0; virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) = 0; - virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 39b9888b..3ec12af6 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -176,22 +176,21 @@ namespace Catch { assertions.failed++; return true; } - - virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { - if( std::uncaught_exception() ) { - m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); - return; - } - - Counts assertions = m_totals.assertions - prevAssertions; + + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); - + m_testCaseTracker->leaveSection(); - - m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); + + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); m_messages.clear(); } + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + m_unfinishedSections.push_back( endInfo ); + } + virtual void pushScopedMessage( MessageInfo const& message ) { m_messages.push_back( message ); } @@ -309,28 +308,18 @@ namespace Catch { m_lastAssertionInfo.capturedExpression.c_str(), m_lastAssertionInfo.resultDisposition ); } - + void handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. - for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), itEnd = m_unfinishedSections.rend(); it != itEnd; ++it ) - sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + sectionEnded( *it ); m_unfinishedSections.clear(); } - struct UnfinishedSections { - UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) - : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - - SectionInfo info; - Counts prevAssertions; - double durationInSeconds; - }; - TestRunInfo m_runInfo; IMutableContext& m_context; TestCase const* m_activeTestCase; @@ -345,7 +334,7 @@ namespace Catch { IResultCapture* m_prevResultCapture; Ptr m_prevConfig; AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; + std::vector m_unfinishedSections; }; IResultCapture& getResultCapture() { diff --git a/include/internal/catch_section.hpp b/include/internal/catch_section.hpp index ec4c1518..de65c4cd 100644 --- a/include/internal/catch_section.hpp +++ b/include/internal/catch_section.hpp @@ -32,8 +32,13 @@ namespace Catch { } Section::~Section() { - if( m_sectionIncluded ) - getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } } // This indicates whether the section should be executed or not diff --git a/include/internal/catch_section_info.h b/include/internal/catch_section_info.h index 93f3840e..e49ef638 100644 --- a/include/internal/catch_section_info.h +++ b/include/internal/catch_section_info.h @@ -9,6 +9,7 @@ #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED #include "catch_common.h" +#include "catch_totals.hpp" namespace Catch { @@ -22,7 +23,17 @@ namespace Catch { std::string description; SourceLineInfo lineInfo; }; - + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED From 0c1c9fa9229c7358ce16c9910004a39290b20f5f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sun, 27 Sep 2015 03:28:14 -0700 Subject: [PATCH 46/87] dev build 14 - workaround for uncaught_exception issue - avoid mutating vector while iterating it (due to re-entrancy) --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 90 ++++++++++++++++-------------- 3 files changed, 50 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index d84793ff..5b99b524 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.13* +*v1.2.1-develop.14* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index d292644c..e1878a28 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 13 ); + Version libraryVersion( 1, 2, 1, "develop", 14 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 94067d84..faaef35e 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.13 - * Generated: 2015-08-24 06:27:37.882342 + * Catch v1.2.1-develop.14 + * Generated: 2015-09-27 03:27:04.922060 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -1856,6 +1856,7 @@ namespace Catch { class AssertionResult; struct AssertionInfo; struct SectionInfo; + struct SectionEndInfo; struct MessageInfo; class ScopedMessageBuilder; struct Counts; @@ -1867,7 +1868,8 @@ namespace Catch { virtual void assertionEnded( AssertionResult const& result ) = 0; virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) = 0; - virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; @@ -2071,21 +2073,6 @@ namespace Catch { // #included from: catch_section_info.h #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED -namespace Catch { - - struct SectionInfo { - SectionInfo - ( SourceLineInfo const& _lineInfo, - std::string const& _name, - std::string const& _description = std::string() ); - - std::string name; - std::string description; - SourceLineInfo lineInfo; - }; - -} // end namespace Catch - // #included from: catch_totals.hpp #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED @@ -2156,6 +2143,31 @@ namespace Catch { }; } +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + // #included from: catch_timer.h #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED @@ -5487,21 +5499,20 @@ namespace Catch { return true; } - virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { - if( std::uncaught_exception() ) { - m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) ); - return; - } - - Counts assertions = m_totals.assertions - prevAssertions; + virtual void sectionEnded( SectionEndInfo const& endInfo ) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); m_testCaseTracker->leaveSection(); - m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) ); + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); m_messages.clear(); } + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + m_unfinishedSections.push_back( endInfo ); + } + virtual void pushScopedMessage( MessageInfo const& message ) { m_messages.push_back( message ); } @@ -5623,24 +5634,14 @@ namespace Catch { void handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. - for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), + for( std::vector::const_reverse_iterator it = m_unfinishedSections.rbegin(), itEnd = m_unfinishedSections.rend(); it != itEnd; ++it ) - sectionEnded( it->info, it->prevAssertions, it->durationInSeconds ); + sectionEnded( *it ); m_unfinishedSections.clear(); } - struct UnfinishedSections { - UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds ) - : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) - {} - - SectionInfo info; - Counts prevAssertions; - double durationInSeconds; - }; - TestRunInfo m_runInfo; IMutableContext& m_context; TestCase const* m_activeTestCase; @@ -5655,7 +5656,7 @@ namespace Catch { IResultCapture* m_prevResultCapture; Ptr m_prevConfig; AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; + std::vector m_unfinishedSections; }; IResultCapture& getResultCapture() { @@ -7010,7 +7011,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 13 ); + Version libraryVersion( 1, 2, 1, "develop", 14 ); } @@ -7349,8 +7350,13 @@ namespace Catch { } Section::~Section() { - if( m_sectionIncluded ) - getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( std::uncaught_exception() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } } // This indicates whether the section should be executed or not From a0de07d45bf84ed1c77652f097fd7c55c6cf1888 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 28 Sep 2015 01:09:06 -0700 Subject: [PATCH 47/87] Some small clean-ups and refactorings - removed previous instance saves in RunContext (they were a hang-over from embedded contexts) - started cleaning up config usage --- include/catch_session.hpp | 14 ++++++++------ include/internal/catch_interfaces_reporter.h | 10 +++++----- include/internal/catch_reporter_registry.hpp | 2 +- include/internal/catch_run_context.hpp | 12 +----------- include/reporters/catch_reporter_bases.hpp | 4 ++-- 5 files changed, 17 insertions(+), 25 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 50623ad4..1f37b5a5 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -43,7 +43,7 @@ namespace Catch { reporter = addReporter( reporter, createReporter( *it, config ) ); return reporter; } - Ptr addListeners( Ptr const& config, Ptr reporters ) { + Ptr addListeners( Ptr const& config, Ptr reporters ) { IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); it != itEnd; @@ -67,12 +67,14 @@ namespace Catch { Totals runTests( Ptr const& config ) { + Ptr iconfig = config.get(); + std::ofstream ofs; openStreamInto( config, ofs ); Ptr reporter = makeReporter( config ); - reporter = addListeners( config.get(), reporter ); + reporter = addListeners( iconfig, reporter ); - RunContext context( config.get(), reporter ); + RunContext context( iconfig, reporter ); Totals totals; @@ -82,17 +84,17 @@ namespace Catch { if( !testSpec.hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - std::vector const& allTestCases = getAllTestCasesSorted( *config ); + std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); it != itEnd; ++it ) { - if( !context.aborting() && matchTest( *it, testSpec, *config ) ) + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) totals += context.runTest( *it ); else reporter->skipTest( *it ); } - context.testGroupEnded( config->name(), totals, 1, 1 ); + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); return totals; } diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index 46720fbb..e40119df 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -26,18 +26,18 @@ namespace Catch { struct ReporterConfig { - explicit ReporterConfig( Ptr const& _fullConfig ) + explicit ReporterConfig( Ptr const& _fullConfig ) : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} std::ostream& stream() const { return *m_stream; } - Ptr fullConfig() const { return m_fullConfig; } + Ptr fullConfig() const { return m_fullConfig; } private: std::ostream* m_stream; - Ptr m_fullConfig; + Ptr m_fullConfig; }; struct ReporterPreferences { @@ -261,7 +261,7 @@ namespace Catch typedef std::vector > Listeners; virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; virtual Listeners const& getListeners() const = 0; }; diff --git a/include/internal/catch_reporter_registry.hpp b/include/internal/catch_reporter_registry.hpp index b67252f3..71f23ff7 100644 --- a/include/internal/catch_reporter_registry.hpp +++ b/include/internal/catch_reporter_registry.hpp @@ -20,7 +20,7 @@ namespace Catch { virtual ~ReporterRegistry() CATCH_OVERRIDE {} - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return CATCH_NULL; diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 3ec12af6..5e315f96 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -64,10 +64,7 @@ namespace Catch { m_context( getCurrentMutableContext() ), m_activeTestCase( CATCH_NULL ), m_config( _config ), - m_reporter( reporter ), - m_prevRunner( m_context.getRunner() ), - m_prevResultCapture( m_context.getResultCapture() ), - m_prevConfig( m_context.getConfig() ) + m_reporter( reporter ) { m_context.setRunner( this ); m_context.setConfig( m_config ); @@ -77,10 +74,6 @@ namespace Catch { virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - m_context.setRunner( m_prevRunner ); - m_context.setConfig( Ptr() ); - m_context.setResultCapture( m_prevResultCapture ); - m_context.setConfig( m_prevConfig ); } void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { @@ -330,9 +323,6 @@ namespace Catch { Totals m_totals; Ptr m_reporter; std::vector m_messages; - IRunner* m_prevRunner; - IResultCapture* m_prevResultCapture; - Ptr m_prevConfig; AssertionInfo m_lastAssertionInfo; std::vector m_unfinishedSections; }; diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 75a2bb44..e37cac00 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -65,7 +65,7 @@ namespace Catch { // It can optionally be overridden in the derived class. } - Ptr m_config; + Ptr m_config; std::ostream& stream; LazyStat currentTestRunInfo; @@ -204,7 +204,7 @@ namespace Catch { virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} - Ptr m_config; + Ptr m_config; std::ostream& stream; std::vector m_assertions; std::vector > > m_sections; From d43a47efca81129eb079b924e61d8cbcd12d8f3c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 29 Sep 2015 19:21:08 +0100 Subject: [PATCH 48/87] Refactored stream related stuff - simpler, polymorphic hierarchy-based, approach - less bitty conditionals spread across the code - all resolved up-front so now config class is immutable (it had evolved the way it was and in need of a clean-up sweep for a long time) --- include/catch_session.hpp | 14 ----- include/internal/catch_config.hpp | 38 ++++++------- include/internal/catch_context_impl.hpp | 8 --- include/internal/catch_impl.hpp | 1 + include/internal/catch_stream.h | 56 +++++++++++++------ include/internal/catch_stream.hpp | 49 ++++++++++------ .../SelfTest/SurrogateCpps/catch_stream.cpp | 1 + 7 files changed, 91 insertions(+), 76 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 1f37b5a5..c63f517b 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -52,25 +52,11 @@ namespace Catch { return reporters; } - void openStreamInto( Ptr const& config, std::ofstream& ofs ) { - // Open output file, if specified - if( !config->getFilename().empty() ) { - ofs.open( config->getFilename().c_str() ); - if( ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << config->getFilename() << "'"; - throw std::domain_error( oss.str() ); - } - config->setStreamBuf( ofs.rdbuf() ); - } - } Totals runTests( Ptr const& config ) { Ptr iconfig = config.get(); - std::ofstream ofs; - openStreamInto( config, ofs ); Ptr reporter = makeReporter( config ); reporter = addListeners( iconfig, reporter ); diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index 6b2b04a3..eca10363 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -85,12 +85,11 @@ namespace Catch { public: Config() - : m_os( Catch::cout().rdbuf() ) {} Config( ConfigData const& data ) : m_data( data ), - m_os( Catch::cout().rdbuf() ) + m_stream( openStream() ) { if( !data.testsOrTags.empty() ) { TestSpecParser parser( ITagAliasRegistry::get() ); @@ -101,12 +100,6 @@ namespace Catch { } virtual ~Config() { - m_os.rdbuf( Catch::cout().rdbuf() ); - m_stream.release(); - } - - void setFilename( std::string const& filename ) { - m_data.outputFilename = filename; } std::string const& getFilename() const { @@ -122,17 +115,6 @@ namespace Catch { bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } - void setStreamBuf( std::streambuf* buf ) { - m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() ); - } - - void useStream( std::string const& streamName ) { - Stream stream = createStream( streamName ); - setStreamBuf( stream.streamBuf ); - m_stream.release(); - m_stream = stream; - } - std::vector getReporterNames() const { return m_data.reporterNames; } int abortAfter() const { return m_data.abortAfter; } @@ -144,7 +126,7 @@ namespace Catch { // IConfig interface virtual bool allowThrows() const { return !m_data.noThrow; } - virtual std::ostream& stream() const { return m_os; } + virtual std::ostream& stream() const { return m_stream->stream(); } virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } @@ -154,10 +136,22 @@ namespace Catch { virtual bool forceColour() const { return m_data.forceColour; } private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } ConfigData m_data; - Stream m_stream; - mutable std::ostream m_os; + std::auto_ptr m_stream; TestSpec m_testSpec; }; diff --git a/include/internal/catch_context_impl.hpp b/include/internal/catch_context_impl.hpp index a3ac2ae5..030f29e2 100644 --- a/include/internal/catch_context_impl.hpp +++ b/include/internal/catch_context_impl.hpp @@ -95,14 +95,6 @@ namespace Catch { return getCurrentMutableContext(); } - Stream createStream( std::string const& streamName ) { - if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false ); - if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false ); - if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); - - throw std::domain_error( "Unknown stream: " + streamName ); - } - void cleanUpContext() { delete currentContext; currentContext = CATCH_NULL; diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 3ff5ac00..170b4807 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -45,6 +45,7 @@ namespace Catch { NonCopyable::~NonCopyable() {} IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} diff --git a/include/internal/catch_stream.h b/include/internal/catch_stream.h index 402a6617..a69c841e 100644 --- a/include/internal/catch_stream.h +++ b/include/internal/catch_stream.h @@ -9,28 +9,52 @@ #ifndef TWOBLUECUBES_CATCH_STREAM_H_INCLUDED #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED -#include +#include "catch_compiler_capabilities.h" +#include "catch_streambuf.h" -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" -#endif +#include +#include +#include namespace Catch { - class Stream { - public: - Stream(); - Stream( std::streambuf* _streamBuf, bool _isOwned ); - void release(); - - std::streambuf* streamBuf; - - private: - bool isOwned; - }; - std::ostream& cout(); std::ostream& cerr(); + + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + + class DebugOutStream : public IStream { + std::auto_ptr m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; } #endif // TWOBLUECUBES_CATCH_STREAM_H_INCLUDED diff --git a/include/internal/catch_stream.hpp b/include/internal/catch_stream.hpp index 42933487..e6bf7b0c 100644 --- a/include/internal/catch_stream.hpp +++ b/include/internal/catch_stream.hpp @@ -10,7 +10,6 @@ #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED #include "catch_stream.h" -#include "catch_streambuf.h" #include "catch_debugger.h" #include @@ -57,29 +56,47 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// - struct OutputDebugWriter { + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + + struct OutputDebugWriter { + void operator()( std::string const&str ) { writeToDebugConsole( str ); } }; - - Stream::Stream() - : streamBuf( CATCH_NULL ), isOwned( false ) + + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) {} - - Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) - : streamBuf( _streamBuf ), isOwned( _isOwned ) - {} - - void Stream::release() { - if( isOwned ) { - delete streamBuf; - streamBuf = CATCH_NULL; - isOwned = false; - } + + std::ostream& DebugOutStream::stream() const { + return m_os; } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) + {} + std::ostream& CoutStream::stream() const { + return m_os; + } + + #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions std::ostream& cout() { return std::cout; diff --git a/projects/SelfTest/SurrogateCpps/catch_stream.cpp b/projects/SelfTest/SurrogateCpps/catch_stream.cpp index 9911aec6..7aaffa1e 100644 --- a/projects/SelfTest/SurrogateCpps/catch_stream.cpp +++ b/projects/SelfTest/SurrogateCpps/catch_stream.cpp @@ -1,2 +1,3 @@ // This file is only here to verify (to the extent possible) the self sufficiency of the header +#include "catch_suppress_warnings.h" #include "catch_stream.h" From e904aa7f6e2e450f9515bce96a0c4b5669ed5d93 Mon Sep 17 00:00:00 2001 From: "Daniel J. Hofmann" Date: Tue, 6 Oct 2015 12:28:18 +0200 Subject: [PATCH 49/87] Improve the Travis CI integration. Adding several improvements, such as: - making use of the container based infrastructure - using ccache for faster building - builds for linux, osx - builds for verious gcc, clang versions - recent cmake installation --- .travis.yml | 164 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 154 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index cda2ad27..e63a76a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,163 @@ language: cpp +sudo: false -compiler: - - clang - - gcc +cache: + ccache: true + directories: + - $HOME/.ccache env: - - BUILD_TYPE=Debug - - BUILD_TYPE=Release + global: + - USE_CCACHE=1 + - CCACHE_COMPRESS=1 + - CCACHE_MAXSIZE=200M + - CCACHE_CPP2=1 + + +matrix: + include: + + # 1/ Linux Clang Builds + - os: linux + compiler: clang + addons: &clang35 + apt: + sources: ['llvm-toolchain-precise-3.5', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.5'] + env: COMPILER='ccache clang++-3.5' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang35 + env: COMPILER='ccache clang++-3.5' BUILD_TYPE='Debug' + + + - os: linux + compiler: clang + addons: &clang36 + apt: + sources: ['llvm-toolchain-precise-3.6', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.6'] + env: COMPILER='ccache clang++-3.6' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang36 + env: COMPILER='ccache clang++-3.6' BUILD_TYPE='Debug' + + + - os: linux + compiler: clang + addons: &clang37 + apt: + sources: ['llvm-toolchain-precise-3.7', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.7'] + env: COMPILER='ccache clang++-3.7' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang37 + env: COMPILER='ccache clang++-3.7' BUILD_TYPE='Debug' + + + - os: linux + compiler: clang + addons: &clang38 + apt: + sources: ['llvm-toolchain-precise', 'ubuntu-toolchain-r-test'] + packages: ['clang-3.8'] + env: COMPILER='ccache clang++-3.8' BUILD_TYPE='Release' + + - os: linux + compiler: clang + addons: *clang38 + env: COMPILER='ccache clang++-3.8' BUILD_TYPE='Debug' + + + # 2/ Linux GCC Builds + - os: linux + compiler: gcc + addons: &gcc48 + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-4.8'] + env: COMPILER='ccache g++-4.8' BUILD_TYPE='Release' + + - os: linux + compiler: gcc + addons: *gcc48 + env: COMPILER='ccache g++-4.8' BUILD_TYPE='Debug' + + + - os: linux + compiler: gcc + addons: &gcc49 + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-4.9'] + env: COMPILER='ccache g++-4.9' BUILD_TYPE='Release' + + - os: linux + compiler: gcc + addons: *gcc49 + env: COMPILER='ccache g++-4.9' BUILD_TYPE='Debug' + + + - os: linux + compiler: gcc + addons: &gcc5 + apt: + sources: ['ubuntu-toolchain-r-test'] + packages: ['g++-5'] + env: COMPILER='ccache g++-5' BUILD_TYPE='Release' + + - os: linux + compiler: gcc + addons: *gcc5 + env: COMPILER='ccache g++-5' BUILD_TYPE='Debug' + + + # 3/ OSX Clang Builds + - os: osx + osx_image: xcode6.4 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Debug' + + - os: osx + osx_image: xcode6.4 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Release' + + + - os: osx + osx_image: xcode7 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Debug' + + - os: osx + osx_image: xcode7 + compiler: clang + env: COMPILER='ccache clang++' BUILD_TYPE='Release' + install: - - cmake -Hprojects/CMake -BBuild -DCMAKE_BUILD_TYPE=$BUILD_TYPE + - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps" + - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR} + - | + if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then + CMAKE_URL="http://www.cmake.org/files/v3.3/cmake-3.3.2-Linux-x86_64.tar.gz" + mkdir cmake && travis_retry wget --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake + export PATH=${DEPS_DIR}/cmake/bin:${PATH} + elif [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then + brew install cmake ccache + fi + +before_script: + - export CXX=${COMPILER} + - cd ${TRAVIS_BUILD_DIR} + - cmake -Hprojects/CMake -BBuild -DCMAKE_BUILD_TYPE=${BUILD_TYPE} - cd Build - - make - - cd .. script: - - cd Build - - ctest -V + - make -j 2 + - ctest -V -j 2 From b3b23520454c96efb02a0dc274cc0c05ce130792 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 19 Oct 2015 09:16:16 +0100 Subject: [PATCH 50/87] Fixed some missing sentence structure Thanks to #517 --- docs/tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial.md b/docs/tutorial.md index ce81fb81..0fdaff9b 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -96,7 +96,7 @@ Although this was a simple test it's been enough to demonstrate a few things abo Most test frameworks have a class-based fixture mechanism. That is, test cases map to methods on a class and common setup and teardown can be performed in ```setup()``` and ```teardown()``` methods (or constructor/ destructor in languages, like C++, that support deterministic destruction). -While Catch fully supports this way of working there are a few problems with the approach. In particular, the way your code must be split up and the blunt granularity of cause problems. You can only have one setup/ teardown pair across a set of methods, but sometimes you want slightly different setup in each method, or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was problems like these that led James Newkirk, who led the team that built NUnit, to start again from scratch and build xUnit). +While Catch fully supports this way of working there are a few problems with the approach. In particular the way your code must be split up, and the blunt granularity of it, may cause problems. You can only have one setup/ teardown pair across a set of methods, but sometimes you want slightly different setup in each method, or you may even want several levels of setup (a concept which we will clarify later on in this tutorial). It was problems like these that led James Newkirk, who led the team that built NUnit, to start again from scratch and build xUnit). Catch takes a different approach (to both NUnit and xUnit) that is a more natural fit for C++ and the C family of languages. This is best explained through an example: From 1cb993970ad64a8dde8428fabc791e273d34520c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 23 Oct 2015 18:20:33 +0100 Subject: [PATCH 51/87] First cut of new section/ part tracking --- projects/SelfTest/PartTrackerTests.cpp | 422 ++++++++++++++++++ .../CatchSelfTest.xcodeproj/project.pbxproj | 4 + 2 files changed, 426 insertions(+) create mode 100644 projects/SelfTest/PartTrackerTests.cpp diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp new file mode 100644 index 00000000..6323f376 --- /dev/null +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -0,0 +1,422 @@ +/* + * Created by Phil on 1/10/2015. + * Copyright 2015 Two Blue Cubes Ltd + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#include "internal/catch_suppress_warnings.h" +#include "internal/catch_compiler_capabilities.h" +#include "internal/catch_ptr.hpp" + +#ifdef __clang__ +//# pragma clang diagnostic ignored "-Wpadded" +//# pragma clang diagnostic ignored "-Wc++98-compat" +#endif + +#include +#include +#include + +namespace Catch +{ + struct IContainerPart; + + struct ITrackedPart : SharedImpl<> { + virtual ~ITrackedPart() {} + virtual std::string name() const = 0; + virtual bool isUnstarted() const = 0; + virtual bool isCompleteOrFailed() const = 0; + virtual bool isComplete() const = 0; + virtual bool isOpen() const = 0; + + virtual IContainerPart& parent() = 0; + + virtual void close() = 0; + virtual void fail() = 0; + }; + + struct IContainerPart : ITrackedPart { + virtual void addChild( Ptr const& child ) = 0; + virtual ITrackedPart* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + virtual void childFailed() = 0; + }; + + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr m_rootPartTracker; + IContainerPart* m_currentPart; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentPart( CATCH_NULL ), + m_runState( NotStarted ) + {} + + int i() { + return 42; + } + + IContainerPart& startRun(); + + void endRun() { + m_rootPartTracker.reset(); + m_currentPart = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentPart = m_rootPartTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + + IContainerPart& currentPart() { + return *m_currentPart; + } + void setCurrentPart( IContainerPart* part ) { + m_currentPart = part; + } + + ITrackedPart* findPart( std::string const& name ) { + return m_currentPart->findChild( name ); + } + + + private: + }; + + + class PartTracker : public IContainerPart { + enum RunState { + NotStarted, + Executing, + ExecutingChildren, + CompletedSuccessfully, + Failed, + ChildFailed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector > Children; + std::string m_name; + TrackerContext& m_ctx; + IContainerPart* m_parent; + Children m_children; + RunState m_runState; + public: + PartTracker( std::string const& name, TrackerContext& ctx, IContainerPart* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) {} + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + + virtual bool isCompleteOrFailed() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isUnstarted() const CATCH_OVERRIDE { + return m_runState == NotStarted; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState == Executing || m_runState == ExecutingChildren; + } + + + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + size_t childCount = m_children.size(); + } + + virtual ITrackedPart* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual IContainerPart& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + virtual void childFailed() CATCH_OVERRIDE { + assert( m_runState == ExecutingChildren ); + m_runState = ChildFailed; + if( m_parent ) + m_parent->childFailed(); + } + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + switch( m_runState ) { + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( !hasUnstartedChildren() ) + m_runState = CompletedSuccessfully; + break; + case ChildFailed: + m_runState = ExecutingChildren; + break; + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->childFailed(); + moveToParent(); + m_ctx.completeCycle(); + } + private: + void moveToParent() { + m_ctx.setCurrentPart( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentPart( this ); + } + + bool hasUnstartedChildren() const { + return !m_children.empty() && m_children.back()->isUnstarted(); + } + }; + + IContainerPart& TrackerContext::startRun() { + m_rootPartTracker = new PartTracker( "{root}", *this, CATCH_NULL ); + m_currentPart = CATCH_NULL; + m_runState = Executing; + return *m_rootPartTracker; + } + + class LocalContext { + + public: + TrackerContext& operator()() const { + return TrackerContext::instance(); + } + }; + + class SectionPart : public PartTracker { + public: + SectionPart( std::string const& name, TrackerContext& ctx, IContainerPart* parent ) + : PartTracker( name, ctx, parent ) + {} + + static SectionPart& acquire( TrackerContext& ctx, std::string const& name ) { + SectionPart* section = CATCH_NULL; + + IContainerPart& currentPart = ctx.currentPart(); + if( ITrackedPart* part = currentPart.findChild( name ) ) { + section = dynamic_cast( part ); + assert( section ); + } + else { + section = new SectionPart( name, ctx, ¤tPart ); + currentPart.addChild( section ); + } + if( !ctx.completedCycle() && !section->isCompleteOrFailed() ) { + section->open(); + } + return *section; + } + }; + +} // namespace Catch + +inline Catch::TrackerContext& C_A_T_C_H_Context() { + return Catch::TrackerContext::instance(); +} + +// ------------------- + +#include "catch.hpp" + +using namespace Catch; + +inline void testCase( Catch::LocalContext const& C_A_T_C_H_Context ) { + + REQUIRE( C_A_T_C_H_Context().i() == 42 ); +} + +TEST_CASE( "PartTracker" ) { + + TrackerContext ctx; + ctx.startRun(); + ctx.startCycle(); + + SectionPart& testCase = SectionPart::acquire( ctx, "Testcase" ); + REQUIRE( testCase.isComplete() == false ); + + SectionPart& s1 = SectionPart::acquire( ctx, "S1" ); + REQUIRE( s1.isComplete() == false ); + + SECTION( "successfully close one section" ) { + s1.close(); + REQUIRE( s1.isComplete() == true ); + REQUIRE( testCase.isCompleteOrFailed() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() == true ); + + REQUIRE( ctx.completedCycle() == true ); + } + + SECTION( "fail one section" ) { + s1.fail(); + REQUIRE( s1.isComplete() == false ); + REQUIRE( s1.isCompleteOrFailed() == true ); + REQUIRE( testCase.isComplete() == false ); + REQUIRE( testCase.isCompleteOrFailed() == false ); + + testCase.close(); + REQUIRE( ctx.completedCycle() == true ); + REQUIRE( testCase.isComplete() == false ); + + SECTION( "re-enter after failed section" ) { + ctx.startCycle(); + SectionPart& testCase2 = SectionPart::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isComplete() == false ); + + SectionPart& s1b = SectionPart::acquire( ctx, "S1" ); + REQUIRE( s1b.isComplete() == false ); + + testCase2.close(); + REQUIRE( ctx.completedCycle() == true ); + REQUIRE( testCase.isComplete() == true ); + REQUIRE( testCase.isCompleteOrFailed() == true ); + } + SECTION( "re-enter after failed section and find next section" ) { + ctx.startCycle(); + SectionPart& testCase2 = SectionPart::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isComplete() == false ); + + SectionPart& s1b = SectionPart::acquire( ctx, "S1" ); + REQUIRE( s1b.isComplete() == false ); + + SectionPart& s2 = SectionPart::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + s2.close(); + REQUIRE( ctx.completedCycle() == true ); + + testCase2.close(); + REQUIRE( testCase.isComplete() == true ); + REQUIRE( testCase.isCompleteOrFailed() == true ); + } + } + + SECTION( "successfully close one section, then find another" ) { + s1.close(); + REQUIRE( ctx.completedCycle() == true ); + + SectionPart& s2 = SectionPart::acquire( ctx, "S2" ); + REQUIRE( s2.isComplete() == false ); + REQUIRE( s2.isOpen() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() == false ); + + SECTION( "Re-enter - skip S1 and enter S2" ) { + ctx.startCycle(); + SectionPart& testCase2 = SectionPart::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isComplete() == false ); + + SectionPart& s1b = SectionPart::acquire( ctx, "S1" ); + REQUIRE( s1b.isComplete() == true ); + + SectionPart& s2b = SectionPart::acquire( ctx, "S2" ); + REQUIRE( s2b.isComplete() == false ); + REQUIRE( s2b.isOpen() ); + + REQUIRE( ctx.completedCycle() == false ); + + SECTION ("Successfully close S2") { + s2b.close(); + REQUIRE( ctx.completedCycle() == true ); + + REQUIRE( s2b.isComplete() == true ); + REQUIRE( testCase2.isCompleteOrFailed() == false ); + + testCase2.close(); + REQUIRE( testCase2.isComplete() == true ); + } + SECTION ("fail S2") { + s2b.fail(); + REQUIRE( ctx.completedCycle() == true ); + + REQUIRE( s2b.isComplete() == false ); + REQUIRE( s2b.isCompleteOrFailed() == true ); + REQUIRE( testCase2.isCompleteOrFailed() == false ); + + testCase2.close(); + REQUIRE( testCase2.isComplete() == false ); + } + } + } + + SECTION( "open a nested section" ) { + SectionPart& s2 = SectionPart::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() == true ); + + s2.close(); + REQUIRE( s2.isComplete() == true ); + REQUIRE( s1.isComplete() == false ); + + s1.close(); + REQUIRE( s1.isComplete() == true ); + REQUIRE( testCase.isComplete() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() == true ); + + } + +} diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index 81f826b6..5ec14365 100644 --- a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 26059AF21BD4B94C003D575C /* PartTrackerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */; settings = {ASSET_TAGS = (); }; }; 263F7A4719B6FCBF009474C2 /* EnumToString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4619B6FCBF009474C2 /* EnumToString.cpp */; }; 263F7A4B19B6FE1E009474C2 /* ToStringPair.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */; }; 263F7A4C19B6FE1E009474C2 /* ToStringVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */; }; @@ -62,6 +63,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PartTrackerTests.cpp; path = ../../../SelfTest/PartTrackerTests.cpp; sourceTree = ""; }; 261488FA184C81130041FBEB /* catch_test_spec.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_spec.hpp; sourceTree = ""; }; 261488FC184D1DC10041FBEB /* catch_stream.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_stream.h; sourceTree = ""; }; 261488FD184D21290041FBEB /* catch_section_info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_section_info.h; sourceTree = ""; }; @@ -212,6 +214,7 @@ 266E9AD317290E710061DAB2 /* Introspective Tests */ = { isa = PBXGroup; children = ( + 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */, 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */, 26E1B7D119213BC900812682 /* CmdLineTests.cpp */, 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */, @@ -548,6 +551,7 @@ 4A6D0C3E149B3D9E00DB3EAA /* TestMain.cpp in Sources */, 4A6D0C3F149B3D9E00DB3EAA /* TrickyTests.cpp in Sources */, 263F7A4D19B6FE1E009474C2 /* ToStringWhich.cpp in Sources */, + 26059AF21BD4B94C003D575C /* PartTrackerTests.cpp in Sources */, 263F7A4B19B6FE1E009474C2 /* ToStringPair.cpp in Sources */, 4AEE032016142F910071E950 /* catch_common.cpp in Sources */, 263F7A4C19B6FE1E009474C2 /* ToStringVector.cpp in Sources */, From 2c6411e70a9325b8fdaf5051ad20cfe9b8c5a8be Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 23 Oct 2015 18:34:16 +0100 Subject: [PATCH 52/87] Tweaks --- projects/SelfTest/PartTrackerTests.cpp | 147 ++++++++++++------------- 1 file changed, 71 insertions(+), 76 deletions(-) diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index 6323f376..19a9c806 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -20,29 +20,29 @@ namespace Catch { - struct IContainerPart; - struct ITrackedPart : SharedImpl<> { virtual ~ITrackedPart() {} + + // queries virtual std::string name() const = 0; - virtual bool isUnstarted() const = 0; - virtual bool isCompleteOrFailed() const = 0; - virtual bool isComplete() const = 0; + virtual bool hasStarted() const = 0; // true even if ended + virtual bool hasEnded() const = 0; + virtual bool didCompleteSuccessfully() const = 0; virtual bool isOpen() const = 0; - virtual IContainerPart& parent() = 0; + virtual ITrackedPart& parent() = 0; + // actions virtual void close() = 0; virtual void fail() = 0; - }; - - struct IContainerPart : ITrackedPart { + virtual void addChild( Ptr const& child ) = 0; virtual ITrackedPart* findChild( std::string const& name ) = 0; virtual void openChild() = 0; virtual void childFailed() = 0; + }; - + class TrackerContext { @@ -52,8 +52,8 @@ namespace Catch CompletedCycle }; - Ptr m_rootPartTracker; - IContainerPart* m_currentPart; + Ptr m_rootPart; + ITrackedPart* m_currentPart; RunState m_runState; public: @@ -67,21 +67,18 @@ namespace Catch : m_currentPart( CATCH_NULL ), m_runState( NotStarted ) {} - - int i() { - return 42; - } - IContainerPart& startRun(); + + ITrackedPart& startRun(); void endRun() { - m_rootPartTracker.reset(); + m_rootPart.reset(); m_currentPart = CATCH_NULL; m_runState = NotStarted; } void startCycle() { - m_currentPart = m_rootPartTracker.get(); + m_currentPart = m_rootPart.get(); m_runState = Executing; } void completeCycle() { @@ -92,10 +89,10 @@ namespace Catch return m_runState == CompletedCycle; } - IContainerPart& currentPart() { + ITrackedPart& currentPart() { return *m_currentPart; } - void setCurrentPart( IContainerPart* part ) { + void setCurrentPart( ITrackedPart* part ) { m_currentPart = part; } @@ -103,12 +100,10 @@ namespace Catch return m_currentPart->findChild( name ); } - - private: }; - class PartTracker : public IContainerPart { + class SectionTracker : public ITrackedPart { enum RunState { NotStarted, Executing, @@ -128,11 +123,11 @@ namespace Catch typedef std::vector > Children; std::string m_name; TrackerContext& m_ctx; - IContainerPart* m_parent; + ITrackedPart* m_parent; Children m_children; RunState m_runState; public: - PartTracker( std::string const& name, TrackerContext& ctx, IContainerPart* parent ) + SectionTracker( std::string const& name, TrackerContext& ctx, ITrackedPart* parent ) : m_name( name ), m_ctx( ctx ), m_parent( parent ), @@ -142,14 +137,14 @@ namespace Catch return m_name; } - virtual bool isCompleteOrFailed() const CATCH_OVERRIDE { + virtual bool hasEnded() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully || m_runState == Failed; } - virtual bool isComplete() const CATCH_OVERRIDE { + virtual bool didCompleteSuccessfully() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully; } - virtual bool isUnstarted() const CATCH_OVERRIDE { - return m_runState == NotStarted; + virtual bool hasStarted() const CATCH_OVERRIDE { + return m_runState != NotStarted; } virtual bool isOpen() const CATCH_OVERRIDE { return m_runState == Executing || m_runState == ExecutingChildren; @@ -167,7 +162,7 @@ namespace Catch ? it->get() : CATCH_NULL; } - virtual IContainerPart& parent() CATCH_OVERRIDE { + virtual ITrackedPart& parent() CATCH_OVERRIDE { assert( m_parent ); // Should always be non-null except for root return *m_parent; } @@ -226,15 +221,15 @@ namespace Catch } bool hasUnstartedChildren() const { - return !m_children.empty() && m_children.back()->isUnstarted(); + return !m_children.empty() && !m_children.back()->hasStarted(); } }; - IContainerPart& TrackerContext::startRun() { - m_rootPartTracker = new PartTracker( "{root}", *this, CATCH_NULL ); + ITrackedPart& TrackerContext::startRun() { + m_rootPart = new SectionTracker( "{root}", *this, CATCH_NULL ); m_currentPart = CATCH_NULL; m_runState = Executing; - return *m_rootPartTracker; + return *m_rootPart; } class LocalContext { @@ -245,16 +240,16 @@ namespace Catch } }; - class SectionPart : public PartTracker { + class SectionPart : public SectionTracker { public: - SectionPart( std::string const& name, TrackerContext& ctx, IContainerPart* parent ) - : PartTracker( name, ctx, parent ) + SectionPart( std::string const& name, TrackerContext& ctx, ITrackedPart* parent ) + : SectionTracker( name, ctx, parent ) {} static SectionPart& acquire( TrackerContext& ctx, std::string const& name ) { SectionPart* section = CATCH_NULL; - IContainerPart& currentPart = ctx.currentPart(); + ITrackedPart& currentPart = ctx.currentPart(); if( ITrackedPart* part = currentPart.findChild( name ) ) { section = dynamic_cast( part ); assert( section ); @@ -263,7 +258,7 @@ namespace Catch section = new SectionPart( name, ctx, ¤tPart ); currentPart.addChild( section ); } - if( !ctx.completedCycle() && !section->isCompleteOrFailed() ) { + if( !ctx.completedCycle() && !section->hasEnded() ) { section->open(); } return *section; @@ -284,7 +279,7 @@ using namespace Catch; inline void testCase( Catch::LocalContext const& C_A_T_C_H_Context ) { - REQUIRE( C_A_T_C_H_Context().i() == 42 ); +// REQUIRE( C_A_T_C_H_Context().i() == 42 ); } TEST_CASE( "PartTracker" ) { @@ -294,53 +289,53 @@ TEST_CASE( "PartTracker" ) { ctx.startCycle(); SectionPart& testCase = SectionPart::acquire( ctx, "Testcase" ); - REQUIRE( testCase.isComplete() == false ); + REQUIRE( testCase.didCompleteSuccessfully() == false ); SectionPart& s1 = SectionPart::acquire( ctx, "S1" ); - REQUIRE( s1.isComplete() == false ); + REQUIRE( s1.didCompleteSuccessfully() == false ); SECTION( "successfully close one section" ) { s1.close(); - REQUIRE( s1.isComplete() == true ); - REQUIRE( testCase.isCompleteOrFailed() == false ); + REQUIRE( s1.didCompleteSuccessfully() == true ); + REQUIRE( testCase.hasEnded() == false ); testCase.close(); - REQUIRE( testCase.isComplete() == true ); + REQUIRE( testCase.didCompleteSuccessfully() == true ); REQUIRE( ctx.completedCycle() == true ); } SECTION( "fail one section" ) { s1.fail(); - REQUIRE( s1.isComplete() == false ); - REQUIRE( s1.isCompleteOrFailed() == true ); - REQUIRE( testCase.isComplete() == false ); - REQUIRE( testCase.isCompleteOrFailed() == false ); + REQUIRE( s1.didCompleteSuccessfully() == false ); + REQUIRE( s1.hasEnded() == true ); + REQUIRE( testCase.didCompleteSuccessfully() == false ); + REQUIRE( testCase.hasEnded() == false ); testCase.close(); REQUIRE( ctx.completedCycle() == true ); - REQUIRE( testCase.isComplete() == false ); + REQUIRE( testCase.didCompleteSuccessfully() == false ); SECTION( "re-enter after failed section" ) { ctx.startCycle(); SectionPart& testCase2 = SectionPart::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.isComplete() == false ); + REQUIRE( testCase2.didCompleteSuccessfully() == false ); SectionPart& s1b = SectionPart::acquire( ctx, "S1" ); - REQUIRE( s1b.isComplete() == false ); + REQUIRE( s1b.didCompleteSuccessfully() == false ); testCase2.close(); REQUIRE( ctx.completedCycle() == true ); - REQUIRE( testCase.isComplete() == true ); - REQUIRE( testCase.isCompleteOrFailed() == true ); + REQUIRE( testCase.didCompleteSuccessfully() == true ); + REQUIRE( testCase.hasEnded() == true ); } SECTION( "re-enter after failed section and find next section" ) { ctx.startCycle(); SectionPart& testCase2 = SectionPart::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.isComplete() == false ); + REQUIRE( testCase2.didCompleteSuccessfully() == false ); SectionPart& s1b = SectionPart::acquire( ctx, "S1" ); - REQUIRE( s1b.isComplete() == false ); + REQUIRE( s1b.didCompleteSuccessfully() == false ); SectionPart& s2 = SectionPart::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); @@ -348,8 +343,8 @@ TEST_CASE( "PartTracker" ) { REQUIRE( ctx.completedCycle() == true ); testCase2.close(); - REQUIRE( testCase.isComplete() == true ); - REQUIRE( testCase.isCompleteOrFailed() == true ); + REQUIRE( testCase.didCompleteSuccessfully() == true ); + REQUIRE( testCase.hasEnded() == true ); } } @@ -358,22 +353,22 @@ TEST_CASE( "PartTracker" ) { REQUIRE( ctx.completedCycle() == true ); SectionPart& s2 = SectionPart::acquire( ctx, "S2" ); - REQUIRE( s2.isComplete() == false ); + REQUIRE( s2.didCompleteSuccessfully() == false ); REQUIRE( s2.isOpen() == false ); testCase.close(); - REQUIRE( testCase.isComplete() == false ); + REQUIRE( testCase.didCompleteSuccessfully() == false ); SECTION( "Re-enter - skip S1 and enter S2" ) { ctx.startCycle(); SectionPart& testCase2 = SectionPart::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.isComplete() == false ); + REQUIRE( testCase2.didCompleteSuccessfully() == false ); SectionPart& s1b = SectionPart::acquire( ctx, "S1" ); - REQUIRE( s1b.isComplete() == true ); + REQUIRE( s1b.didCompleteSuccessfully() == true ); SectionPart& s2b = SectionPart::acquire( ctx, "S2" ); - REQUIRE( s2b.isComplete() == false ); + REQUIRE( s2b.didCompleteSuccessfully() == false ); REQUIRE( s2b.isOpen() ); REQUIRE( ctx.completedCycle() == false ); @@ -382,22 +377,22 @@ TEST_CASE( "PartTracker" ) { s2b.close(); REQUIRE( ctx.completedCycle() == true ); - REQUIRE( s2b.isComplete() == true ); - REQUIRE( testCase2.isCompleteOrFailed() == false ); + REQUIRE( s2b.didCompleteSuccessfully() == true ); + REQUIRE( testCase2.hasEnded() == false ); testCase2.close(); - REQUIRE( testCase2.isComplete() == true ); + REQUIRE( testCase2.didCompleteSuccessfully() == true ); } SECTION ("fail S2") { s2b.fail(); REQUIRE( ctx.completedCycle() == true ); - REQUIRE( s2b.isComplete() == false ); - REQUIRE( s2b.isCompleteOrFailed() == true ); - REQUIRE( testCase2.isCompleteOrFailed() == false ); + REQUIRE( s2b.didCompleteSuccessfully() == false ); + REQUIRE( s2b.hasEnded() == true ); + REQUIRE( testCase2.hasEnded() == false ); testCase2.close(); - REQUIRE( testCase2.isComplete() == false ); + REQUIRE( testCase2.didCompleteSuccessfully() == false ); } } } @@ -407,15 +402,15 @@ TEST_CASE( "PartTracker" ) { REQUIRE( s2.isOpen() == true ); s2.close(); - REQUIRE( s2.isComplete() == true ); - REQUIRE( s1.isComplete() == false ); + REQUIRE( s2.didCompleteSuccessfully() == true ); + REQUIRE( s1.didCompleteSuccessfully() == false ); s1.close(); - REQUIRE( s1.isComplete() == true ); - REQUIRE( testCase.isComplete() == false ); + REQUIRE( s1.didCompleteSuccessfully() == true ); + REQUIRE( testCase.didCompleteSuccessfully() == false ); testCase.close(); - REQUIRE( testCase.isComplete() == true ); + REQUIRE( testCase.didCompleteSuccessfully() == true ); } From 9a6a0865f2a0c60a831438c0516f3eb94043ca02 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 23 Oct 2015 18:44:48 +0100 Subject: [PATCH 53/87] More name changes --- projects/SelfTest/PartTrackerTests.cpp | 171 +++++++++++++------------ 1 file changed, 87 insertions(+), 84 deletions(-) diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index 19a9c806..f699e78f 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -20,24 +20,24 @@ namespace Catch { - struct ITrackedPart : SharedImpl<> { - virtual ~ITrackedPart() {} + struct IPartTracker : SharedImpl<> { + virtual ~IPartTracker() {} // queries virtual std::string name() const = 0; virtual bool hasStarted() const = 0; // true even if ended virtual bool hasEnded() const = 0; - virtual bool didCompleteSuccessfully() const = 0; + virtual bool isSuccessfullyCompleted() const = 0; virtual bool isOpen() const = 0; - virtual ITrackedPart& parent() = 0; + virtual IPartTracker& parent() = 0; // actions virtual void close() = 0; virtual void fail() = 0; - virtual void addChild( Ptr const& child ) = 0; - virtual ITrackedPart* findChild( std::string const& name ) = 0; + virtual void addChild( Ptr const& child ) = 0; + virtual IPartTracker* findChild( std::string const& name ) = 0; virtual void openChild() = 0; virtual void childFailed() = 0; @@ -52,8 +52,8 @@ namespace Catch CompletedCycle }; - Ptr m_rootPart; - ITrackedPart* m_currentPart; + Ptr m_rootPart; + IPartTracker* m_currentPart; RunState m_runState; public: @@ -69,7 +69,7 @@ namespace Catch {} - ITrackedPart& startRun(); + IPartTracker& startRun(); void endRun() { m_rootPart.reset(); @@ -89,21 +89,20 @@ namespace Catch return m_runState == CompletedCycle; } - ITrackedPart& currentPart() { + IPartTracker& currentPart() { return *m_currentPart; } - void setCurrentPart( ITrackedPart* part ) { + void setCurrentPart( IPartTracker* part ) { m_currentPart = part; } - ITrackedPart* findPart( std::string const& name ) { + IPartTracker* findPart( std::string const& name ) { return m_currentPart->findChild( name ); } }; - - class SectionTracker : public ITrackedPart { + class PartTrackerBase : public IPartTracker { enum RunState { NotStarted, Executing, @@ -116,18 +115,18 @@ namespace Catch std::string m_name; public: TrackerHasName( std::string const& name ) : m_name( name ) {} - bool operator ()( Ptr const& tracker ) { + bool operator ()( Ptr const& tracker ) { return tracker->name() == m_name; } }; - typedef std::vector > Children; + typedef std::vector > Children; std::string m_name; TrackerContext& m_ctx; - ITrackedPart* m_parent; + IPartTracker* m_parent; Children m_children; RunState m_runState; public: - SectionTracker( std::string const& name, TrackerContext& ctx, ITrackedPart* parent ) + PartTrackerBase( std::string const& name, TrackerContext& ctx, IPartTracker* parent ) : m_name( name ), m_ctx( ctx ), m_parent( parent ), @@ -140,7 +139,7 @@ namespace Catch virtual bool hasEnded() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully || m_runState == Failed; } - virtual bool didCompleteSuccessfully() const CATCH_OVERRIDE { + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully; } virtual bool hasStarted() const CATCH_OVERRIDE { @@ -151,18 +150,18 @@ namespace Catch } - virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { m_children.push_back( child ); size_t childCount = m_children.size(); } - virtual ITrackedPart* findChild( std::string const& name ) CATCH_OVERRIDE { + virtual IPartTracker* findChild( std::string const& name ) CATCH_OVERRIDE { Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); return( it != m_children.end() ) ? it->get() : CATCH_NULL; } - virtual ITrackedPart& parent() CATCH_OVERRIDE { + virtual IPartTracker& parent() CATCH_OVERRIDE { assert( m_parent ); // Should always be non-null except for root return *m_parent; } @@ -225,37 +224,24 @@ namespace Catch } }; - ITrackedPart& TrackerContext::startRun() { - m_rootPart = new SectionTracker( "{root}", *this, CATCH_NULL ); - m_currentPart = CATCH_NULL; - m_runState = Executing; - return *m_rootPart; - } - class LocalContext { - - public: - TrackerContext& operator()() const { - return TrackerContext::instance(); - } - }; - class SectionPart : public SectionTracker { + class SectionTracker : public PartTrackerBase { public: - SectionPart( std::string const& name, TrackerContext& ctx, ITrackedPart* parent ) - : SectionTracker( name, ctx, parent ) + SectionTracker( std::string const& name, TrackerContext& ctx, IPartTracker* parent ) + : PartTrackerBase( name, ctx, parent ) {} - static SectionPart& acquire( TrackerContext& ctx, std::string const& name ) { - SectionPart* section = CATCH_NULL; + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; - ITrackedPart& currentPart = ctx.currentPart(); - if( ITrackedPart* part = currentPart.findChild( name ) ) { - section = dynamic_cast( part ); + IPartTracker& currentPart = ctx.currentPart(); + if( IPartTracker* part = currentPart.findChild( name ) ) { + section = dynamic_cast( part ); assert( section ); } else { - section = new SectionPart( name, ctx, ¤tPart ); + section = new SectionTracker( name, ctx, ¤tPart ); currentPart.addChild( section ); } if( !ctx.completedCycle() && !section->hasEnded() ) { @@ -265,6 +251,21 @@ namespace Catch } }; + IPartTracker& TrackerContext::startRun() { + m_rootPart = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentPart = CATCH_NULL; + m_runState = Executing; + return *m_rootPart; + } + + class LocalContext { + + public: + TrackerContext& operator()() const { + return TrackerContext::instance(); + } + }; + } // namespace Catch inline Catch::TrackerContext& C_A_T_C_H_Context() { @@ -288,62 +289,63 @@ TEST_CASE( "PartTracker" ) { ctx.startRun(); ctx.startCycle(); - SectionPart& testCase = SectionPart::acquire( ctx, "Testcase" ); - REQUIRE( testCase.didCompleteSuccessfully() == false ); + IPartTracker& testCase = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); - SectionPart& s1 = SectionPart::acquire( ctx, "S1" ); - REQUIRE( s1.didCompleteSuccessfully() == false ); + IPartTracker& s1 = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1.isOpen() == true ); + REQUIRE( s1.isSuccessfullyCompleted() == false ); SECTION( "successfully close one section" ) { s1.close(); - REQUIRE( s1.didCompleteSuccessfully() == true ); + REQUIRE( s1.isSuccessfullyCompleted() == true ); REQUIRE( testCase.hasEnded() == false ); testCase.close(); - REQUIRE( testCase.didCompleteSuccessfully() == true ); + REQUIRE( testCase.isSuccessfullyCompleted() == true ); REQUIRE( ctx.completedCycle() == true ); } SECTION( "fail one section" ) { s1.fail(); - REQUIRE( s1.didCompleteSuccessfully() == false ); + REQUIRE( s1.isSuccessfullyCompleted() == false ); REQUIRE( s1.hasEnded() == true ); - REQUIRE( testCase.didCompleteSuccessfully() == false ); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); REQUIRE( testCase.hasEnded() == false ); testCase.close(); REQUIRE( ctx.completedCycle() == true ); - REQUIRE( testCase.didCompleteSuccessfully() == false ); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); SECTION( "re-enter after failed section" ) { ctx.startCycle(); - SectionPart& testCase2 = SectionPart::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.didCompleteSuccessfully() == false ); + IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isSuccessfullyCompleted() == false ); - SectionPart& s1b = SectionPart::acquire( ctx, "S1" ); - REQUIRE( s1b.didCompleteSuccessfully() == false ); + IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isSuccessfullyCompleted() == false ); testCase2.close(); REQUIRE( ctx.completedCycle() == true ); - REQUIRE( testCase.didCompleteSuccessfully() == true ); + REQUIRE( testCase.isSuccessfullyCompleted() == true ); REQUIRE( testCase.hasEnded() == true ); } SECTION( "re-enter after failed section and find next section" ) { ctx.startCycle(); - SectionPart& testCase2 = SectionPart::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.didCompleteSuccessfully() == false ); + IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isSuccessfullyCompleted() == false ); - SectionPart& s1b = SectionPart::acquire( ctx, "S1" ); - REQUIRE( s1b.didCompleteSuccessfully() == false ); + IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isSuccessfullyCompleted() == false ); - SectionPart& s2 = SectionPart::acquire( ctx, "S2" ); + IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); s2.close(); REQUIRE( ctx.completedCycle() == true ); testCase2.close(); - REQUIRE( testCase.didCompleteSuccessfully() == true ); + REQUIRE( testCase.isSuccessfullyCompleted() == true ); REQUIRE( testCase.hasEnded() == true ); } } @@ -352,24 +354,25 @@ TEST_CASE( "PartTracker" ) { s1.close(); REQUIRE( ctx.completedCycle() == true ); - SectionPart& s2 = SectionPart::acquire( ctx, "S2" ); - REQUIRE( s2.didCompleteSuccessfully() == false ); + IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() == false ); + REQUIRE( s2.isSuccessfullyCompleted() == false ); testCase.close(); - REQUIRE( testCase.didCompleteSuccessfully() == false ); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); - SECTION( "Re-enter - skip S1 and enter S2" ) { + SECTION( "Re-enter - skips S1 and enters S2" ) { ctx.startCycle(); - SectionPart& testCase2 = SectionPart::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.didCompleteSuccessfully() == false ); + IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isSuccessfullyCompleted() == false ); + REQUIRE( testCase2.isSuccessfullyCompleted() == false ); - SectionPart& s1b = SectionPart::acquire( ctx, "S1" ); - REQUIRE( s1b.didCompleteSuccessfully() == true ); + IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() == false ); - SectionPart& s2b = SectionPart::acquire( ctx, "S2" ); - REQUIRE( s2b.didCompleteSuccessfully() == false ); + IPartTracker& s2b = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2b.isOpen() ); + REQUIRE( s2b.isSuccessfullyCompleted() == false ); REQUIRE( ctx.completedCycle() == false ); @@ -377,40 +380,40 @@ TEST_CASE( "PartTracker" ) { s2b.close(); REQUIRE( ctx.completedCycle() == true ); - REQUIRE( s2b.didCompleteSuccessfully() == true ); + REQUIRE( s2b.isSuccessfullyCompleted() == true ); REQUIRE( testCase2.hasEnded() == false ); testCase2.close(); - REQUIRE( testCase2.didCompleteSuccessfully() == true ); + REQUIRE( testCase2.isSuccessfullyCompleted() == true ); } SECTION ("fail S2") { s2b.fail(); REQUIRE( ctx.completedCycle() == true ); - REQUIRE( s2b.didCompleteSuccessfully() == false ); + REQUIRE( s2b.isSuccessfullyCompleted() == false ); REQUIRE( s2b.hasEnded() == true ); REQUIRE( testCase2.hasEnded() == false ); testCase2.close(); - REQUIRE( testCase2.didCompleteSuccessfully() == false ); + REQUIRE( testCase2.isSuccessfullyCompleted() == false ); } } } SECTION( "open a nested section" ) { - SectionPart& s2 = SectionPart::acquire( ctx, "S2" ); + IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() == true ); s2.close(); - REQUIRE( s2.didCompleteSuccessfully() == true ); - REQUIRE( s1.didCompleteSuccessfully() == false ); + REQUIRE( s2.isSuccessfullyCompleted() == true ); + REQUIRE( s1.isSuccessfullyCompleted() == false ); s1.close(); - REQUIRE( s1.didCompleteSuccessfully() == true ); - REQUIRE( testCase.didCompleteSuccessfully() == false ); + REQUIRE( s1.isSuccessfullyCompleted() == true ); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); testCase.close(); - REQUIRE( testCase.didCompleteSuccessfully() == true ); + REQUIRE( testCase.isSuccessfullyCompleted() == true ); } From 293e54dcbee9189f32e97dd218e10f1025a0e5af Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Oct 2015 08:02:40 +0000 Subject: [PATCH 54/87] Added IndexTracker and got it working with a single generator - made some simplifications to state machine --- projects/SelfTest/PartTrackerTests.cpp | 187 +++++++++++++++++++++---- 1 file changed, 160 insertions(+), 27 deletions(-) diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index f699e78f..6f9abfca 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -23,8 +23,10 @@ namespace Catch struct IPartTracker : SharedImpl<> { virtual ~IPartTracker() {} - // queries + // static queries virtual std::string name() const = 0; + + // dynamic queries virtual bool hasStarted() const = 0; // true even if ended virtual bool hasEnded() const = 0; virtual bool isSuccessfullyCompleted() const = 0; @@ -35,12 +37,11 @@ namespace Catch // actions virtual void close() = 0; virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() =0; virtual void addChild( Ptr const& child ) = 0; virtual IPartTracker* findChild( std::string const& name ) = 0; virtual void openChild() = 0; - virtual void childFailed() = 0; - }; @@ -103,13 +104,14 @@ namespace Catch }; class PartTrackerBase : public IPartTracker { + protected: enum RunState { NotStarted, Executing, ExecutingChildren, + NeedsAnotherRun, CompletedSuccessfully, - Failed, - ChildFailed + Failed }; class TrackerHasName { std::string m_name; @@ -146,7 +148,7 @@ namespace Catch return m_runState != NotStarted; } virtual bool isOpen() const CATCH_OVERRIDE { - return m_runState == Executing || m_runState == ExecutingChildren; + return hasStarted() && !hasEnded(); } @@ -158,8 +160,8 @@ namespace Catch virtual IPartTracker* findChild( std::string const& name ) CATCH_OVERRIDE { Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); return( it != m_children.end() ) - ? it->get() - : CATCH_NULL; + ? it->get() + : CATCH_NULL; } virtual IPartTracker& parent() CATCH_OVERRIDE { assert( m_parent ); // Should always be non-null except for root @@ -173,12 +175,6 @@ namespace Catch m_parent->openChild(); } } - virtual void childFailed() CATCH_OVERRIDE { - assert( m_runState == ExecutingChildren ); - m_runState = ChildFailed; - if( m_parent ) - m_parent->childFailed(); - } void open() { m_runState = Executing; moveToThis(); @@ -187,16 +183,25 @@ namespace Catch } virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentPart() != this ) + m_ctx.currentPart().close(); + switch( m_runState ) { + case CompletedSuccessfully: + case Failed: + return; + case Executing: m_runState = CompletedSuccessfully; break; case ExecutingChildren: - if( !hasUnstartedChildren() ) + if( m_children.empty() || m_children.back()->hasEnded() ) m_runState = CompletedSuccessfully; break; - case ChildFailed: - m_runState = ExecutingChildren; + case NeedsAnotherRun: + m_runState = Executing; break; default: throw std::logic_error( "Unexpected state" ); @@ -207,21 +212,21 @@ namespace Catch virtual void fail() CATCH_OVERRIDE { m_runState = Failed; if( m_parent ) - m_parent->childFailed(); + m_parent->markAsNeedingAnotherRun(); moveToParent(); m_ctx.completeCycle(); } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } private: void moveToParent() { + assert( m_parent ); m_ctx.setCurrentPart( m_parent ); } void moveToThis() { m_ctx.setCurrentPart( this ); } - - bool hasUnstartedChildren() const { - return !m_children.empty() && !m_children.back()->hasStarted(); - } }; @@ -245,12 +250,60 @@ namespace Catch currentPart.addChild( section ); } if( !ctx.completedCycle() && !section->hasEnded() ) { + section->open(); } return *section; } }; + class IndexTracker : public PartTrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, IPartTracker* parent, int size ) + : PartTrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + IPartTracker& currentPart = ctx.currentPart(); + if( IPartTracker* part = currentPart.findChild( name ) ) { + tracker = dynamic_cast( part ); + assert( tracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tPart, size ); + currentPart.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->hasEnded() ) { + if( tracker->m_runState != ExecutingChildren ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + PartTrackerBase::close(); + if( m_runState == CompletedSuccessfully ) + if( m_index < m_size-1 ) + m_runState = Executing; + } + }; + IPartTracker& TrackerContext::startRun() { m_rootPart = new SectionTracker( "{root}", *this, CATCH_NULL ); m_currentPart = CATCH_NULL; @@ -302,9 +355,8 @@ TEST_CASE( "PartTracker" ) { REQUIRE( testCase.hasEnded() == false ); testCase.close(); - REQUIRE( testCase.isSuccessfullyCompleted() == true ); - REQUIRE( ctx.completedCycle() == true ); + REQUIRE( testCase.isSuccessfullyCompleted() == true ); } SECTION( "fail one section" ) { @@ -324,8 +376,8 @@ TEST_CASE( "PartTracker" ) { REQUIRE( testCase2.isSuccessfullyCompleted() == false ); IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); - REQUIRE( s1b.isSuccessfullyCompleted() == false ); - + REQUIRE( s1b.isOpen() == false ); + testCase2.close(); REQUIRE( ctx.completedCycle() == true ); REQUIRE( testCase.isSuccessfullyCompleted() == true ); @@ -414,7 +466,88 @@ TEST_CASE( "PartTracker" ) { testCase.close(); REQUIRE( testCase.isSuccessfullyCompleted() == true ); - } + SECTION( "start a generator" ) { + IndexTracker& g1 = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1.isOpen() == true ); + REQUIRE( g1.index() == 0 ); + + REQUIRE( g1.isSuccessfullyCompleted() == false ); + REQUIRE( s1.isSuccessfullyCompleted() == false ); + + SECTION( "close outer section" ) + { + s1.close(); + REQUIRE( s1.isSuccessfullyCompleted() == false ); + testCase.close(); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); + + SECTION( "Re-enter for second generation" ) { + ctx.startCycle(); + IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() == true ); + + IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() == true ); + + + IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1b.isOpen() == true ); + REQUIRE( g1b.index() == 1 ); + + REQUIRE( s1.isSuccessfullyCompleted() == false ); + + s1b.close(); + REQUIRE( s1b.isSuccessfullyCompleted() == true ); + REQUIRE( g1b.isSuccessfullyCompleted() == true ); + testCase2.close(); + REQUIRE( testCase2.isSuccessfullyCompleted() == true ); + } + } + SECTION( "Start a new inner section" ) { + IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() == true ); + + s2.close(); + REQUIRE( s2.isSuccessfullyCompleted() == true ); + + s1.close(); + REQUIRE( s1.isSuccessfullyCompleted() == false ); + + testCase.close(); + REQUIRE( testCase.isSuccessfullyCompleted() == false ); + + SECTION( "Re-enter for second generation" ) { + ctx.startCycle(); + IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isSuccessfullyCompleted() == false ); + + IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isSuccessfullyCompleted() == false ); + + // generator - next value + IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1b.isOpen() == true ); + REQUIRE( g1b.index() == 1 ); + + // inner section again + IPartTracker& s2b = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2b.isOpen() == true ); + + s2b.close(); + REQUIRE( s2b.isSuccessfullyCompleted() == true ); + + s1b.close(); + REQUIRE( s1b.isSuccessfullyCompleted() == true ); + REQUIRE( g1b.isSuccessfullyCompleted() == true ); + + testCase2.close(); + REQUIRE( testCase2.isSuccessfullyCompleted() == true ); + } + } + // !TBD" + // nested generator + // two sections within a generator + } } From 4b99be6a9a2c2933c8da84c5a5c59de18666cb57 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Oct 2015 08:17:55 +0000 Subject: [PATCH 55/87] Cleaned tests up a bit --- projects/SelfTest/PartTrackerTests.cpp | 110 +++++++++++++------------ 1 file changed, 59 insertions(+), 51 deletions(-) diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index 6f9abfca..9c5efa1e 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -343,134 +343,142 @@ TEST_CASE( "PartTracker" ) { ctx.startCycle(); IPartTracker& testCase = SectionTracker::acquire( ctx, "Testcase" ); - REQUIRE( testCase.isSuccessfullyCompleted() == false ); + REQUIRE( testCase.isOpen() ); IPartTracker& s1 = SectionTracker::acquire( ctx, "S1" ); - REQUIRE( s1.isOpen() == true ); - REQUIRE( s1.isSuccessfullyCompleted() == false ); + REQUIRE( s1.isOpen() ); SECTION( "successfully close one section" ) { s1.close(); - REQUIRE( s1.isSuccessfullyCompleted() == true ); + REQUIRE( s1.isSuccessfullyCompleted() ); REQUIRE( testCase.hasEnded() == false ); testCase.close(); - REQUIRE( ctx.completedCycle() == true ); - REQUIRE( testCase.isSuccessfullyCompleted() == true ); + REQUIRE( ctx.completedCycle() ); + REQUIRE( testCase.isSuccessfullyCompleted() ); } SECTION( "fail one section" ) { s1.fail(); + REQUIRE( s1.hasEnded() ); REQUIRE( s1.isSuccessfullyCompleted() == false ); - REQUIRE( s1.hasEnded() == true ); - REQUIRE( testCase.isSuccessfullyCompleted() == false ); REQUIRE( testCase.hasEnded() == false ); testCase.close(); - REQUIRE( ctx.completedCycle() == true ); + REQUIRE( ctx.completedCycle() ); REQUIRE( testCase.isSuccessfullyCompleted() == false ); SECTION( "re-enter after failed section" ) { ctx.startCycle(); IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.isSuccessfullyCompleted() == false ); + REQUIRE( testCase2.isOpen() ); IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() == false ); testCase2.close(); - REQUIRE( ctx.completedCycle() == true ); - REQUIRE( testCase.isSuccessfullyCompleted() == true ); - REQUIRE( testCase.hasEnded() == true ); + REQUIRE( ctx.completedCycle() ); + REQUIRE( testCase.hasEnded() ); + REQUIRE( testCase.isSuccessfullyCompleted() ); } SECTION( "re-enter after failed section and find next section" ) { ctx.startCycle(); IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.isSuccessfullyCompleted() == false ); + REQUIRE( testCase2.isOpen() ); IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); - REQUIRE( s1b.isSuccessfullyCompleted() == false ); + REQUIRE( s1b.isOpen() == false ); IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); + s2.close(); - REQUIRE( ctx.completedCycle() == true ); + REQUIRE( ctx.completedCycle() ); testCase2.close(); - REQUIRE( testCase.isSuccessfullyCompleted() == true ); - REQUIRE( testCase.hasEnded() == true ); + REQUIRE( testCase.hasEnded() ); + REQUIRE( testCase.isSuccessfullyCompleted() ); } } SECTION( "successfully close one section, then find another" ) { s1.close(); - REQUIRE( ctx.completedCycle() == true ); IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() == false ); - REQUIRE( s2.isSuccessfullyCompleted() == false ); testCase.close(); - REQUIRE( testCase.isSuccessfullyCompleted() == false ); + REQUIRE( testCase.hasEnded() == false ); SECTION( "Re-enter - skips S1 and enters S2" ) { ctx.startCycle(); IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.isSuccessfullyCompleted() == false ); - REQUIRE( testCase2.isSuccessfullyCompleted() == false ); + REQUIRE( testCase2.isOpen() ); IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() == false ); IPartTracker& s2b = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2b.isOpen() ); - REQUIRE( s2b.isSuccessfullyCompleted() == false ); REQUIRE( ctx.completedCycle() == false ); SECTION ("Successfully close S2") { s2b.close(); - REQUIRE( ctx.completedCycle() == true ); + REQUIRE( ctx.completedCycle() ); - REQUIRE( s2b.isSuccessfullyCompleted() == true ); + REQUIRE( s2b.isSuccessfullyCompleted() ); REQUIRE( testCase2.hasEnded() == false ); testCase2.close(); - REQUIRE( testCase2.isSuccessfullyCompleted() == true ); + REQUIRE( testCase2.isSuccessfullyCompleted() ); } SECTION ("fail S2") { s2b.fail(); - REQUIRE( ctx.completedCycle() == true ); + REQUIRE( ctx.completedCycle() ); + REQUIRE( s2b.hasEnded() ); REQUIRE( s2b.isSuccessfullyCompleted() == false ); - REQUIRE( s2b.hasEnded() == true ); - REQUIRE( testCase2.hasEnded() == false ); testCase2.close(); REQUIRE( testCase2.isSuccessfullyCompleted() == false ); + + // Need a final cycle + ctx.startCycle(); + IPartTracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase3.isOpen() ); + + IPartTracker& s1c = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1c.isOpen() == false ); + + IPartTracker& s2c = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2c.isOpen() == false ); + + testCase3.close(); + REQUIRE( testCase3.isSuccessfullyCompleted() ); } } } SECTION( "open a nested section" ) { IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); - REQUIRE( s2.isOpen() == true ); + REQUIRE( s2.isOpen() ); s2.close(); - REQUIRE( s2.isSuccessfullyCompleted() == true ); + REQUIRE( s2.isSuccessfullyCompleted() ); REQUIRE( s1.isSuccessfullyCompleted() == false ); s1.close(); - REQUIRE( s1.isSuccessfullyCompleted() == true ); + REQUIRE( s1.isSuccessfullyCompleted() ); REQUIRE( testCase.isSuccessfullyCompleted() == false ); testCase.close(); - REQUIRE( testCase.isSuccessfullyCompleted() == true ); + REQUIRE( testCase.isSuccessfullyCompleted() ); } SECTION( "start a generator" ) { IndexTracker& g1 = IndexTracker::acquire( ctx, "G1", 2 ); - REQUIRE( g1.isOpen() == true ); + REQUIRE( g1.isOpen() ); REQUIRE( g1.index() == 0 ); REQUIRE( g1.isSuccessfullyCompleted() == false ); @@ -486,31 +494,31 @@ TEST_CASE( "PartTracker" ) { SECTION( "Re-enter for second generation" ) { ctx.startCycle(); IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.isOpen() == true ); + REQUIRE( testCase2.isOpen() ); IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); - REQUIRE( s1b.isOpen() == true ); + REQUIRE( s1b.isOpen() ); IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); - REQUIRE( g1b.isOpen() == true ); + REQUIRE( g1b.isOpen() ); REQUIRE( g1b.index() == 1 ); REQUIRE( s1.isSuccessfullyCompleted() == false ); s1b.close(); - REQUIRE( s1b.isSuccessfullyCompleted() == true ); - REQUIRE( g1b.isSuccessfullyCompleted() == true ); + REQUIRE( s1b.isSuccessfullyCompleted() ); + REQUIRE( g1b.isSuccessfullyCompleted() ); testCase2.close(); - REQUIRE( testCase2.isSuccessfullyCompleted() == true ); + REQUIRE( testCase2.isSuccessfullyCompleted() ); } } SECTION( "Start a new inner section" ) { IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); - REQUIRE( s2.isOpen() == true ); + REQUIRE( s2.isOpen() ); s2.close(); - REQUIRE( s2.isSuccessfullyCompleted() == true ); + REQUIRE( s2.isSuccessfullyCompleted() ); s1.close(); REQUIRE( s1.isSuccessfullyCompleted() == false ); @@ -521,29 +529,29 @@ TEST_CASE( "PartTracker" ) { SECTION( "Re-enter for second generation" ) { ctx.startCycle(); IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); - REQUIRE( testCase2.isSuccessfullyCompleted() == false ); + REQUIRE( testCase2.isOpen() ); IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); - REQUIRE( s1b.isSuccessfullyCompleted() == false ); + REQUIRE( s1b.isOpen() ); // generator - next value IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); - REQUIRE( g1b.isOpen() == true ); + REQUIRE( g1b.isOpen() ); REQUIRE( g1b.index() == 1 ); // inner section again IPartTracker& s2b = SectionTracker::acquire( ctx, "S2" ); - REQUIRE( s2b.isOpen() == true ); + REQUIRE( s2b.isOpen() ); s2b.close(); - REQUIRE( s2b.isSuccessfullyCompleted() == true ); + REQUIRE( s2b.isSuccessfullyCompleted() ); s1b.close(); - REQUIRE( s1b.isSuccessfullyCompleted() == true ); - REQUIRE( g1b.isSuccessfullyCompleted() == true ); + REQUIRE( s1b.isSuccessfullyCompleted() ); + REQUIRE( g1b.isSuccessfullyCompleted() ); testCase2.close(); - REQUIRE( testCase2.isSuccessfullyCompleted() == true ); + REQUIRE( testCase2.isSuccessfullyCompleted() ); } } // !TBD" From f4389b4fdb1961cd09c0567c1f3de02aed067507 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Oct 2015 08:33:50 +0000 Subject: [PATCH 56/87] more minor clean-ups --- projects/SelfTest/PartTrackerTests.cpp | 45 ++++++++++++-------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index 9c5efa1e..74dd3ac4 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -27,17 +27,16 @@ namespace Catch virtual std::string name() const = 0; // dynamic queries - virtual bool hasStarted() const = 0; // true even if ended - virtual bool hasEnded() const = 0; + virtual bool isComplete() const = 0; // Successfully completed or failed virtual bool isSuccessfullyCompleted() const = 0; - virtual bool isOpen() const = 0; + virtual bool isOpen() const = 0; // Started but not complete virtual IPartTracker& parent() = 0; // actions - virtual void close() = 0; + virtual void close() = 0; // Successfully complete virtual void fail() = 0; - virtual void markAsNeedingAnotherRun() =0; + virtual void markAsNeedingAnotherRun() = 0; virtual void addChild( Ptr const& child ) = 0; virtual IPartTracker* findChild( std::string const& name ) = 0; @@ -138,17 +137,14 @@ namespace Catch return m_name; } - virtual bool hasEnded() const CATCH_OVERRIDE { + virtual bool isComplete() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully || m_runState == Failed; } virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully; } - virtual bool hasStarted() const CATCH_OVERRIDE { - return m_runState != NotStarted; - } virtual bool isOpen() const CATCH_OVERRIDE { - return hasStarted() && !hasEnded(); + return m_runState != NotStarted && !isComplete(); } @@ -191,18 +187,18 @@ namespace Catch switch( m_runState ) { case CompletedSuccessfully: case Failed: + assert(false); // Shouldn't really get here + case NeedsAnotherRun: return; case Executing: m_runState = CompletedSuccessfully; break; case ExecutingChildren: - if( m_children.empty() || m_children.back()->hasEnded() ) + if( m_children.empty() || m_children.back()->isComplete() ) m_runState = CompletedSuccessfully; break; - case NeedsAnotherRun: - m_runState = Executing; - break; + default: throw std::logic_error( "Unexpected state" ); } @@ -249,7 +245,7 @@ namespace Catch section = new SectionTracker( name, ctx, ¤tPart ); currentPart.addChild( section ); } - if( !ctx.completedCycle() && !section->hasEnded() ) { + if( !ctx.completedCycle() && !section->isComplete() ) { section->open(); } @@ -280,7 +276,7 @@ namespace Catch currentPart.addChild( tracker ); } - if( !ctx.completedCycle() && !tracker->hasEnded() ) { + if( !ctx.completedCycle() && !tracker->isComplete() ) { if( tracker->m_runState != ExecutingChildren ) tracker->moveNext(); tracker->open(); @@ -351,7 +347,7 @@ TEST_CASE( "PartTracker" ) { SECTION( "successfully close one section" ) { s1.close(); REQUIRE( s1.isSuccessfullyCompleted() ); - REQUIRE( testCase.hasEnded() == false ); + REQUIRE( testCase.isComplete() == false ); testCase.close(); REQUIRE( ctx.completedCycle() ); @@ -360,9 +356,9 @@ TEST_CASE( "PartTracker" ) { SECTION( "fail one section" ) { s1.fail(); - REQUIRE( s1.hasEnded() ); + REQUIRE( s1.isComplete() ); REQUIRE( s1.isSuccessfullyCompleted() == false ); - REQUIRE( testCase.hasEnded() == false ); + REQUIRE( testCase.isComplete() == false ); testCase.close(); REQUIRE( ctx.completedCycle() ); @@ -378,7 +374,7 @@ TEST_CASE( "PartTracker" ) { testCase2.close(); REQUIRE( ctx.completedCycle() ); - REQUIRE( testCase.hasEnded() ); + REQUIRE( testCase.isComplete() ); REQUIRE( testCase.isSuccessfullyCompleted() ); } SECTION( "re-enter after failed section and find next section" ) { @@ -396,7 +392,7 @@ TEST_CASE( "PartTracker" ) { REQUIRE( ctx.completedCycle() ); testCase2.close(); - REQUIRE( testCase.hasEnded() ); + REQUIRE( testCase.isComplete() ); REQUIRE( testCase.isSuccessfullyCompleted() ); } } @@ -408,7 +404,7 @@ TEST_CASE( "PartTracker" ) { REQUIRE( s2.isOpen() == false ); testCase.close(); - REQUIRE( testCase.hasEnded() == false ); + REQUIRE( testCase.isComplete() == false ); SECTION( "Re-enter - skips S1 and enters S2" ) { ctx.startCycle(); @@ -428,7 +424,7 @@ TEST_CASE( "PartTracker" ) { REQUIRE( ctx.completedCycle() ); REQUIRE( s2b.isSuccessfullyCompleted() ); - REQUIRE( testCase2.hasEnded() == false ); + REQUIRE( testCase2.isComplete() == false ); testCase2.close(); REQUIRE( testCase2.isSuccessfullyCompleted() ); @@ -437,10 +433,11 @@ TEST_CASE( "PartTracker" ) { s2b.fail(); REQUIRE( ctx.completedCycle() ); - REQUIRE( s2b.hasEnded() ); + REQUIRE( s2b.isComplete() ); REQUIRE( s2b.isSuccessfullyCompleted() == false ); testCase2.close(); +// REQUIRE( testCase2.isComplete() ); REQUIRE( testCase2.isSuccessfullyCompleted() == false ); // Need a final cycle From ef62b578e293e21b5f973d30130866c9a869fdeb Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Oct 2015 19:25:27 +0000 Subject: [PATCH 57/87] Added tests for failing a section within a generator - small fixes to implementation to make it work --- projects/SelfTest/PartTrackerTests.cpp | 112 ++++++++++++++++++++----- 1 file changed, 90 insertions(+), 22 deletions(-) diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index 74dd3ac4..b33084d9 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -187,9 +187,10 @@ namespace Catch switch( m_runState ) { case CompletedSuccessfully: case Failed: - assert(false); // Shouldn't really get here + throw std::logic_error( "Illogical state" ); + case NeedsAnotherRun: - return; + break;; case Executing: m_runState = CompletedSuccessfully; @@ -277,7 +278,7 @@ namespace Catch } if( !ctx.completedCycle() && !tracker->isComplete() ) { - if( tracker->m_runState != ExecutingChildren ) + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) tracker->moveNext(); tracker->open(); } @@ -462,15 +463,15 @@ TEST_CASE( "PartTracker" ) { REQUIRE( s2.isOpen() ); s2.close(); - REQUIRE( s2.isSuccessfullyCompleted() ); - REQUIRE( s1.isSuccessfullyCompleted() == false ); + REQUIRE( s2.isComplete() ); + REQUIRE( s1.isComplete() == false ); s1.close(); - REQUIRE( s1.isSuccessfullyCompleted() ); - REQUIRE( testCase.isSuccessfullyCompleted() == false ); + REQUIRE( s1.isComplete() ); + REQUIRE( testCase.isComplete() == false ); testCase.close(); - REQUIRE( testCase.isSuccessfullyCompleted() ); + REQUIRE( testCase.isComplete() ); } SECTION( "start a generator" ) { @@ -478,13 +479,13 @@ TEST_CASE( "PartTracker" ) { REQUIRE( g1.isOpen() ); REQUIRE( g1.index() == 0 ); - REQUIRE( g1.isSuccessfullyCompleted() == false ); - REQUIRE( s1.isSuccessfullyCompleted() == false ); + REQUIRE( g1.isComplete() == false ); + REQUIRE( s1.isComplete() == false ); SECTION( "close outer section" ) { s1.close(); - REQUIRE( s1.isSuccessfullyCompleted() == false ); + REQUIRE( s1.isComplete() == false ); testCase.close(); REQUIRE( testCase.isSuccessfullyCompleted() == false ); @@ -501,13 +502,13 @@ TEST_CASE( "PartTracker" ) { REQUIRE( g1b.isOpen() ); REQUIRE( g1b.index() == 1 ); - REQUIRE( s1.isSuccessfullyCompleted() == false ); + REQUIRE( s1.isComplete() == false ); s1b.close(); - REQUIRE( s1b.isSuccessfullyCompleted() ); - REQUIRE( g1b.isSuccessfullyCompleted() ); + REQUIRE( s1b.isComplete() ); + REQUIRE( g1b.isComplete() ); testCase2.close(); - REQUIRE( testCase2.isSuccessfullyCompleted() ); + REQUIRE( testCase2.isComplete() ); } } SECTION( "Start a new inner section" ) { @@ -515,13 +516,13 @@ TEST_CASE( "PartTracker" ) { REQUIRE( s2.isOpen() ); s2.close(); - REQUIRE( s2.isSuccessfullyCompleted() ); + REQUIRE( s2.isComplete() ); s1.close(); - REQUIRE( s1.isSuccessfullyCompleted() == false ); + REQUIRE( s1.isComplete() == false ); testCase.close(); - REQUIRE( testCase.isSuccessfullyCompleted() == false ); + REQUIRE( testCase.isComplete() == false ); SECTION( "Re-enter for second generation" ) { ctx.startCycle(); @@ -541,14 +542,81 @@ TEST_CASE( "PartTracker" ) { REQUIRE( s2b.isOpen() ); s2b.close(); - REQUIRE( s2b.isSuccessfullyCompleted() ); + REQUIRE( s2b.isComplete() ); s1b.close(); - REQUIRE( s1b.isSuccessfullyCompleted() ); - REQUIRE( g1b.isSuccessfullyCompleted() ); + REQUIRE( g1b.isComplete() ); + REQUIRE( s1b.isComplete() ); testCase2.close(); - REQUIRE( testCase2.isSuccessfullyCompleted() ); + REQUIRE( testCase2.isComplete() ); + } + } + + SECTION( "Fail an inner section" ) { + IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + s2.fail(); + REQUIRE( s2.isComplete() ); + REQUIRE( s2.isSuccessfullyCompleted() == false ); + + s1.close(); + REQUIRE( s1.isComplete() == false ); + + testCase.close(); + REQUIRE( testCase.isComplete() == false ); + + SECTION( "Re-enter for second generation" ) { + ctx.startCycle(); + IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() ); + + // generator - still same value + IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1b.isOpen() ); + REQUIRE( g1b.index() == 0 ); + + // inner section again - this time won't open + IPartTracker& s2b = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2b.isOpen() == false ); + + s1b.close(); + REQUIRE( g1b.isComplete() == false ); + REQUIRE( s1b.isComplete() == false ); + + testCase2.close(); + REQUIRE( testCase2.isComplete() == false ); + + // Another cycle - now should complete + ctx.startCycle(); + IPartTracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase3.isOpen() ); + + IPartTracker& s1c = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1c.isOpen() ); + + // generator - now next value + IndexTracker& g1c = IndexTracker::acquire( ctx, "G1", 2 ); + REQUIRE( g1c.isOpen() ); + REQUIRE( g1c.index() == 1 ); + + // inner section - now should open again + IPartTracker& s2c = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2c.isOpen() ); + + s2c.close(); + REQUIRE( s2c.isComplete() ); + + s1c.close(); + REQUIRE( g1c.isComplete() ); + REQUIRE( s1c.isComplete() ); + + testCase3.close(); + REQUIRE( testCase3.isComplete() ); } } // !TBD" From 73a140fb9e2aeed03011c70715ccd05be5eaf8d7 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Oct 2015 19:33:25 +0000 Subject: [PATCH 58/87] More minor tweaks --- projects/SelfTest/PartTrackerTests.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index b33084d9..88a8cb79 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -104,7 +104,7 @@ namespace Catch class PartTrackerBase : public IPartTracker { protected: - enum RunState { + enum CycleState { NotStarted, Executing, ExecutingChildren, @@ -125,18 +125,18 @@ namespace Catch TrackerContext& m_ctx; IPartTracker* m_parent; Children m_children; - RunState m_runState; + CycleState m_runState; public: PartTrackerBase( std::string const& name, TrackerContext& ctx, IPartTracker* parent ) : m_name( name ), m_ctx( ctx ), m_parent( parent ), - m_runState( NotStarted ) {} + m_runState( NotStarted ) + {} virtual std::string name() const CATCH_OVERRIDE { return m_name; } - virtual bool isComplete() const CATCH_OVERRIDE { return m_runState == CompletedSuccessfully || m_runState == Failed; } @@ -227,7 +227,6 @@ namespace Catch }; - class SectionTracker : public PartTrackerBase { public: SectionTracker( std::string const& name, TrackerContext& ctx, IPartTracker* parent ) @@ -438,7 +437,6 @@ TEST_CASE( "PartTracker" ) { REQUIRE( s2b.isSuccessfullyCompleted() == false ); testCase2.close(); -// REQUIRE( testCase2.isComplete() ); REQUIRE( testCase2.isSuccessfullyCompleted() == false ); // Need a final cycle From 3deb3e010f1fbe6eadb7ed0879b706853d574124 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 29 Oct 2015 19:41:50 +0000 Subject: [PATCH 59/87] Removed the "part" component of the tracker names --- projects/SelfTest/PartTrackerTests.cpp | 161 ++++++++++++------------- 1 file changed, 78 insertions(+), 83 deletions(-) diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index 88a8cb79..13dfe5e0 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -20,8 +20,8 @@ namespace Catch { - struct IPartTracker : SharedImpl<> { - virtual ~IPartTracker() {} + struct ITracker : SharedImpl<> { + virtual ~ITracker() {} // static queries virtual std::string name() const = 0; @@ -31,15 +31,15 @@ namespace Catch virtual bool isSuccessfullyCompleted() const = 0; virtual bool isOpen() const = 0; // Started but not complete - virtual IPartTracker& parent() = 0; + virtual ITracker& parent() = 0; // actions virtual void close() = 0; // Successfully complete virtual void fail() = 0; virtual void markAsNeedingAnotherRun() = 0; - virtual void addChild( Ptr const& child ) = 0; - virtual IPartTracker* findChild( std::string const& name ) = 0; + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; virtual void openChild() = 0; }; @@ -52,8 +52,8 @@ namespace Catch CompletedCycle }; - Ptr m_rootPart; - IPartTracker* m_currentPart; + Ptr m_rootTracker; + ITracker* m_currentTracker; RunState m_runState; public: @@ -64,21 +64,21 @@ namespace Catch } TrackerContext() - : m_currentPart( CATCH_NULL ), + : m_currentTracker( CATCH_NULL ), m_runState( NotStarted ) {} - IPartTracker& startRun(); + ITracker& startRun(); void endRun() { - m_rootPart.reset(); - m_currentPart = CATCH_NULL; + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; m_runState = NotStarted; } void startCycle() { - m_currentPart = m_rootPart.get(); + m_currentTracker = m_rootTracker.get(); m_runState = Executing; } void completeCycle() { @@ -89,20 +89,15 @@ namespace Catch return m_runState == CompletedCycle; } - IPartTracker& currentPart() { - return *m_currentPart; + ITracker& currentTracker() { + return *m_currentTracker; } - void setCurrentPart( IPartTracker* part ) { - m_currentPart = part; + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; } - - IPartTracker* findPart( std::string const& name ) { - return m_currentPart->findChild( name ); - } - }; - class PartTrackerBase : public IPartTracker { + class TrackerBase : public ITracker { protected: enum CycleState { NotStarted, @@ -116,18 +111,18 @@ namespace Catch std::string m_name; public: TrackerHasName( std::string const& name ) : m_name( name ) {} - bool operator ()( Ptr const& tracker ) { + bool operator ()( Ptr const& tracker ) { return tracker->name() == m_name; } }; - typedef std::vector > Children; + typedef std::vector > Children; std::string m_name; TrackerContext& m_ctx; - IPartTracker* m_parent; + ITracker* m_parent; Children m_children; CycleState m_runState; public: - PartTrackerBase( std::string const& name, TrackerContext& ctx, IPartTracker* parent ) + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) : m_name( name ), m_ctx( ctx ), m_parent( parent ), @@ -148,18 +143,18 @@ namespace Catch } - virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { m_children.push_back( child ); size_t childCount = m_children.size(); } - virtual IPartTracker* findChild( std::string const& name ) CATCH_OVERRIDE { + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); return( it != m_children.end() ) ? it->get() : CATCH_NULL; } - virtual IPartTracker& parent() CATCH_OVERRIDE { + virtual ITracker& parent() CATCH_OVERRIDE { assert( m_parent ); // Should always be non-null except for root return *m_parent; } @@ -181,8 +176,8 @@ namespace Catch virtual void close() CATCH_OVERRIDE { // Close any still open children (e.g. generators) - while( &m_ctx.currentPart() != this ) - m_ctx.currentPart().close(); + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); switch( m_runState ) { case CompletedSuccessfully: @@ -219,31 +214,31 @@ namespace Catch private: void moveToParent() { assert( m_parent ); - m_ctx.setCurrentPart( m_parent ); + m_ctx.setCurrentTracker( m_parent ); } void moveToThis() { - m_ctx.setCurrentPart( this ); + m_ctx.setCurrentTracker( this ); } }; - class SectionTracker : public PartTrackerBase { + class SectionTracker : public TrackerBase { public: - SectionTracker( std::string const& name, TrackerContext& ctx, IPartTracker* parent ) - : PartTrackerBase( name, ctx, parent ) + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) {} static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { SectionTracker* section = CATCH_NULL; - IPartTracker& currentPart = ctx.currentPart(); - if( IPartTracker* part = currentPart.findChild( name ) ) { - section = dynamic_cast( part ); + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + section = dynamic_cast( childTracker ); assert( section ); } else { - section = new SectionTracker( name, ctx, ¤tPart ); - currentPart.addChild( section ); + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); } if( !ctx.completedCycle() && !section->isComplete() ) { @@ -253,12 +248,12 @@ namespace Catch } }; - class IndexTracker : public PartTrackerBase { + class IndexTracker : public TrackerBase { int m_size; int m_index; public: - IndexTracker( std::string const& name, TrackerContext& ctx, IPartTracker* parent, int size ) - : PartTrackerBase( name, ctx, parent ), + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), m_size( size ), m_index( -1 ) {} @@ -266,14 +261,14 @@ namespace Catch static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { IndexTracker* tracker = CATCH_NULL; - IPartTracker& currentPart = ctx.currentPart(); - if( IPartTracker* part = currentPart.findChild( name ) ) { - tracker = dynamic_cast( part ); + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + tracker = dynamic_cast( childTracker ); assert( tracker ); } else { - tracker = new IndexTracker( name, ctx, ¤tPart, size ); - currentPart.addChild( tracker ); + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); } if( !ctx.completedCycle() && !tracker->isComplete() ) { @@ -293,18 +288,18 @@ namespace Catch } virtual void close() CATCH_OVERRIDE { - PartTrackerBase::close(); + TrackerBase::close(); if( m_runState == CompletedSuccessfully ) if( m_index < m_size-1 ) m_runState = Executing; } }; - IPartTracker& TrackerContext::startRun() { - m_rootPart = new SectionTracker( "{root}", *this, CATCH_NULL ); - m_currentPart = CATCH_NULL; + ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; m_runState = Executing; - return *m_rootPart; + return *m_rootTracker; } class LocalContext { @@ -332,16 +327,16 @@ inline void testCase( Catch::LocalContext const& C_A_T_C_H_Context ) { // REQUIRE( C_A_T_C_H_Context().i() == 42 ); } -TEST_CASE( "PartTracker" ) { +TEST_CASE( "Tracker" ) { TrackerContext ctx; ctx.startRun(); ctx.startCycle(); - IPartTracker& testCase = SectionTracker::acquire( ctx, "Testcase" ); + ITracker& testCase = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase.isOpen() ); - IPartTracker& s1 = SectionTracker::acquire( ctx, "S1" ); + ITracker& s1 = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1.isOpen() ); SECTION( "successfully close one section" ) { @@ -366,10 +361,10 @@ TEST_CASE( "PartTracker" ) { SECTION( "re-enter after failed section" ) { ctx.startCycle(); - IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() == false ); testCase2.close(); @@ -379,13 +374,13 @@ TEST_CASE( "PartTracker" ) { } SECTION( "re-enter after failed section and find next section" ) { ctx.startCycle(); - IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() == false ); - IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); s2.close(); @@ -400,7 +395,7 @@ TEST_CASE( "PartTracker" ) { SECTION( "successfully close one section, then find another" ) { s1.close(); - IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() == false ); testCase.close(); @@ -408,13 +403,13 @@ TEST_CASE( "PartTracker" ) { SECTION( "Re-enter - skips S1 and enters S2" ) { ctx.startCycle(); - IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() == false ); - IPartTracker& s2b = SectionTracker::acquire( ctx, "S2" ); + ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2b.isOpen() ); REQUIRE( ctx.completedCycle() == false ); @@ -441,13 +436,13 @@ TEST_CASE( "PartTracker" ) { // Need a final cycle ctx.startCycle(); - IPartTracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); + ITracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase3.isOpen() ); - IPartTracker& s1c = SectionTracker::acquire( ctx, "S1" ); + ITracker& s1c = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1c.isOpen() == false ); - IPartTracker& s2c = SectionTracker::acquire( ctx, "S2" ); + ITracker& s2c = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2c.isOpen() == false ); testCase3.close(); @@ -457,7 +452,7 @@ TEST_CASE( "PartTracker" ) { } SECTION( "open a nested section" ) { - IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); s2.close(); @@ -489,10 +484,10 @@ TEST_CASE( "PartTracker" ) { SECTION( "Re-enter for second generation" ) { ctx.startCycle(); - IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() ); @@ -510,7 +505,7 @@ TEST_CASE( "PartTracker" ) { } } SECTION( "Start a new inner section" ) { - IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); s2.close(); @@ -524,10 +519,10 @@ TEST_CASE( "PartTracker" ) { SECTION( "Re-enter for second generation" ) { ctx.startCycle(); - IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() ); // generator - next value @@ -536,7 +531,7 @@ TEST_CASE( "PartTracker" ) { REQUIRE( g1b.index() == 1 ); // inner section again - IPartTracker& s2b = SectionTracker::acquire( ctx, "S2" ); + ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2b.isOpen() ); s2b.close(); @@ -552,7 +547,7 @@ TEST_CASE( "PartTracker" ) { } SECTION( "Fail an inner section" ) { - IPartTracker& s2 = SectionTracker::acquire( ctx, "S2" ); + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); s2.fail(); @@ -567,10 +562,10 @@ TEST_CASE( "PartTracker" ) { SECTION( "Re-enter for second generation" ) { ctx.startCycle(); - IPartTracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - IPartTracker& s1b = SectionTracker::acquire( ctx, "S1" ); + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() ); // generator - still same value @@ -579,7 +574,7 @@ TEST_CASE( "PartTracker" ) { REQUIRE( g1b.index() == 0 ); // inner section again - this time won't open - IPartTracker& s2b = SectionTracker::acquire( ctx, "S2" ); + ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2b.isOpen() == false ); s1b.close(); @@ -591,10 +586,10 @@ TEST_CASE( "PartTracker" ) { // Another cycle - now should complete ctx.startCycle(); - IPartTracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); + ITracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase3.isOpen() ); - IPartTracker& s1c = SectionTracker::acquire( ctx, "S1" ); + ITracker& s1c = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1c.isOpen() ); // generator - now next value @@ -603,7 +598,7 @@ TEST_CASE( "PartTracker" ) { REQUIRE( g1c.index() == 1 ); // inner section - now should open again - IPartTracker& s2c = SectionTracker::acquire( ctx, "S2" ); + ITracker& s2c = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2c.isOpen() ); s2c.close(); From b8515929b87b471dff0675b450423c17b40c42a2 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 2 Nov 2015 06:14:52 +0000 Subject: [PATCH 60/87] Moved all new tracking impl into catch_test_case_tracker.pp --- include/internal/catch_config.hpp | 1 - include/internal/catch_impl.hpp | 10 + include/internal/catch_suppress_warnings.h | 1 + include/internal/catch_test_case_tracker.hpp | 294 ++++++++++++++++++ projects/SelfTest/PartTrackerTests.cpp | 299 +------------------ projects/SelfTest/SectionTrackerTests.cpp | 6 +- 6 files changed, 310 insertions(+), 301 deletions(-) diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index eca10363..c0d0948e 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -155,7 +155,6 @@ namespace Catch { TestSpec m_testSpec; }; - } // end namespace Catch #endif // TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 170b4807..baabd7ab 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -35,6 +35,7 @@ #include "catch_tostring.hpp" #include "catch_result_builder.hpp" #include "catch_tag_alias_registry.hpp" +#include "catch_test_case_tracker.hpp" #include "../reporters/catch_reporter_multi.hpp" #include "../reporters/catch_reporter_xml.hpp" @@ -43,6 +44,8 @@ #include "../reporters/catch_reporter_compact.hpp" namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods NonCopyable::~NonCopyable() {} IShared::~IShared() {} IStream::~IStream() CATCH_NOEXCEPT {} @@ -91,6 +94,13 @@ namespace Catch { Matchers::Impl::StdString::EndsWith::~EndsWith() {} void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } } #ifdef __clang__ diff --git a/include/internal/catch_suppress_warnings.h b/include/internal/catch_suppress_warnings.h index 094ed98b..8f57b285 100644 --- a/include/internal/catch_suppress_warnings.h +++ b/include/internal/catch_suppress_warnings.h @@ -19,6 +19,7 @@ # pragma clang diagnostic ignored "-Wc++98-compat" # pragma clang diagnostic ignored "-Wc++98-compat-pedantic" # pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" # endif #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wvariadic-macros" diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index eb2616e0..4f174fb6 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -9,14 +9,308 @@ #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED #include "catch_compiler_capabilities.h" +#include "catch_ptr.hpp" #include #include #include +#include namespace Catch { +namespace TestCaseTracking { + + struct ITracker : SharedImpl<> { + virtual ~ITracker(); + + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) + {} + + + ITracker& startRun(); + + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; + } + + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + + + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } + + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + virtual void close() CATCH_OVERRIDE { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); + } + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } + private: + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } + }; + + class SectionTracker : public TrackerBase { + public: + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) + {} + virtual ~SectionTracker(); + + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + section = dynamic_cast( childTracker ); + assert( section ); + } + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() && !section->isComplete() ) { + + section->open(); + } + return *section; + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + tracker = dynamic_cast( childTracker ); + assert( tracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +// !TBD: Deprecated namespace SectionTracking { + class TrackedSection { typedef std::map TrackedSections; diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index 13dfe5e0..11a501ad 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -6,302 +6,11 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #include "internal/catch_suppress_warnings.h" -#include "internal/catch_compiler_capabilities.h" -#include "internal/catch_ptr.hpp" +#include "internal/catch_test_case_tracker.hpp" -#ifdef __clang__ -//# pragma clang diagnostic ignored "-Wpadded" -//# pragma clang diagnostic ignored "-Wc++98-compat" -#endif - -#include -#include -#include namespace Catch { - struct ITracker : SharedImpl<> { - virtual ~ITracker() {} - - // static queries - virtual std::string name() const = 0; - - // dynamic queries - virtual bool isComplete() const = 0; // Successfully completed or failed - virtual bool isSuccessfullyCompleted() const = 0; - virtual bool isOpen() const = 0; // Started but not complete - - virtual ITracker& parent() = 0; - - // actions - virtual void close() = 0; // Successfully complete - virtual void fail() = 0; - virtual void markAsNeedingAnotherRun() = 0; - - virtual void addChild( Ptr const& child ) = 0; - virtual ITracker* findChild( std::string const& name ) = 0; - virtual void openChild() = 0; - }; - - - class TrackerContext { - - enum RunState { - NotStarted, - Executing, - CompletedCycle - }; - - Ptr m_rootTracker; - ITracker* m_currentTracker; - RunState m_runState; - - public: - - static TrackerContext& instance() { - static TrackerContext s_instance; - return s_instance; - } - - TrackerContext() - : m_currentTracker( CATCH_NULL ), - m_runState( NotStarted ) - {} - - - ITracker& startRun(); - - void endRun() { - m_rootTracker.reset(); - m_currentTracker = CATCH_NULL; - m_runState = NotStarted; - } - - void startCycle() { - m_currentTracker = m_rootTracker.get(); - m_runState = Executing; - } - void completeCycle() { - m_runState = CompletedCycle; - } - - bool completedCycle() const { - return m_runState == CompletedCycle; - } - - ITracker& currentTracker() { - return *m_currentTracker; - } - void setCurrentTracker( ITracker* tracker ) { - m_currentTracker = tracker; - } - }; - - class TrackerBase : public ITracker { - protected: - enum CycleState { - NotStarted, - Executing, - ExecutingChildren, - NeedsAnotherRun, - CompletedSuccessfully, - Failed - }; - class TrackerHasName { - std::string m_name; - public: - TrackerHasName( std::string const& name ) : m_name( name ) {} - bool operator ()( Ptr const& tracker ) { - return tracker->name() == m_name; - } - }; - typedef std::vector > Children; - std::string m_name; - TrackerContext& m_ctx; - ITracker* m_parent; - Children m_children; - CycleState m_runState; - public: - TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) - : m_name( name ), - m_ctx( ctx ), - m_parent( parent ), - m_runState( NotStarted ) - {} - - virtual std::string name() const CATCH_OVERRIDE { - return m_name; - } - virtual bool isComplete() const CATCH_OVERRIDE { - return m_runState == CompletedSuccessfully || m_runState == Failed; - } - virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { - return m_runState == CompletedSuccessfully; - } - virtual bool isOpen() const CATCH_OVERRIDE { - return m_runState != NotStarted && !isComplete(); - } - - - virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { - m_children.push_back( child ); - size_t childCount = m_children.size(); - } - - virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { - Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); - return( it != m_children.end() ) - ? it->get() - : CATCH_NULL; - } - virtual ITracker& parent() CATCH_OVERRIDE { - assert( m_parent ); // Should always be non-null except for root - return *m_parent; - } - - virtual void openChild() CATCH_OVERRIDE { - if( m_runState != ExecutingChildren ) { - m_runState = ExecutingChildren; - if( m_parent ) - m_parent->openChild(); - } - } - void open() { - m_runState = Executing; - moveToThis(); - if( m_parent ) - m_parent->openChild(); - } - - virtual void close() CATCH_OVERRIDE { - - // Close any still open children (e.g. generators) - while( &m_ctx.currentTracker() != this ) - m_ctx.currentTracker().close(); - - switch( m_runState ) { - case CompletedSuccessfully: - case Failed: - throw std::logic_error( "Illogical state" ); - - case NeedsAnotherRun: - break;; - - case Executing: - m_runState = CompletedSuccessfully; - break; - case ExecutingChildren: - if( m_children.empty() || m_children.back()->isComplete() ) - m_runState = CompletedSuccessfully; - break; - - default: - throw std::logic_error( "Unexpected state" ); - } - moveToParent(); - m_ctx.completeCycle(); - } - virtual void fail() CATCH_OVERRIDE { - m_runState = Failed; - if( m_parent ) - m_parent->markAsNeedingAnotherRun(); - moveToParent(); - m_ctx.completeCycle(); - } - virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { - m_runState = NeedsAnotherRun; - } - private: - void moveToParent() { - assert( m_parent ); - m_ctx.setCurrentTracker( m_parent ); - } - void moveToThis() { - m_ctx.setCurrentTracker( this ); - } - }; - - - class SectionTracker : public TrackerBase { - public: - SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) - : TrackerBase( name, ctx, parent ) - {} - - static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { - SectionTracker* section = CATCH_NULL; - - ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( name ) ) { - section = dynamic_cast( childTracker ); - assert( section ); - } - else { - section = new SectionTracker( name, ctx, ¤tTracker ); - currentTracker.addChild( section ); - } - if( !ctx.completedCycle() && !section->isComplete() ) { - - section->open(); - } - return *section; - } - }; - - class IndexTracker : public TrackerBase { - int m_size; - int m_index; - public: - IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) - : TrackerBase( name, ctx, parent ), - m_size( size ), - m_index( -1 ) - {} - - static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { - IndexTracker* tracker = CATCH_NULL; - - ITracker& currentTracker = ctx.currentTracker(); - if( ITracker* childTracker = currentTracker.findChild( name ) ) { - tracker = dynamic_cast( childTracker ); - assert( tracker ); - } - else { - tracker = new IndexTracker( name, ctx, ¤tTracker, size ); - currentTracker.addChild( tracker ); - } - - if( !ctx.completedCycle() && !tracker->isComplete() ) { - if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) - tracker->moveNext(); - tracker->open(); - } - - return *tracker; - } - - int index() const { return m_index; } - - void moveNext() { - m_index++; - m_children.clear(); - } - - virtual void close() CATCH_OVERRIDE { - TrackerBase::close(); - if( m_runState == CompletedSuccessfully ) - if( m_index < m_size-1 ) - m_runState = Executing; - } - }; - - ITracker& TrackerContext::startRun() { - m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); - m_currentTracker = CATCH_NULL; - m_runState = Executing; - return *m_rootTracker; - } - class LocalContext { public: @@ -322,10 +31,10 @@ inline Catch::TrackerContext& C_A_T_C_H_Context() { using namespace Catch; -inline void testCase( Catch::LocalContext const& C_A_T_C_H_Context ) { - +//inline void testCase( Catch::LocalContext const& C_A_T_C_H_Context ) { +// // REQUIRE( C_A_T_C_H_Context().i() == 42 ); -} +//} TEST_CASE( "Tracker" ) { diff --git a/projects/SelfTest/SectionTrackerTests.cpp b/projects/SelfTest/SectionTrackerTests.cpp index 96e96f5e..d3df994d 100644 --- a/projects/SelfTest/SectionTrackerTests.cpp +++ b/projects/SelfTest/SectionTrackerTests.cpp @@ -6,11 +6,7 @@ * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ -#ifdef __clang__ -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wc++98-compat" -#endif - +#include "internal/catch_suppress_warnings.h" #include "internal/catch_test_case_tracker.hpp" #include "catch.hpp" From 0b523db6b9276a1792d0723df440c393a843349c Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 2 Nov 2015 06:16:09 +0000 Subject: [PATCH 61/87] Converted all new part tracking tests/ sections to non variadic form --- projects/SelfTest/PartTrackerTests.cpp | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index 11a501ad..c576d53c 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -36,7 +36,7 @@ using namespace Catch; // REQUIRE( C_A_T_C_H_Context().i() == 42 ); //} -TEST_CASE( "Tracker" ) { +TEST_CASE( "Tracker", "" ) { TrackerContext ctx; ctx.startRun(); @@ -48,7 +48,7 @@ TEST_CASE( "Tracker" ) { ITracker& s1 = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1.isOpen() ); - SECTION( "successfully close one section" ) { + SECTION( "successfully close one section", "" ) { s1.close(); REQUIRE( s1.isSuccessfullyCompleted() ); REQUIRE( testCase.isComplete() == false ); @@ -58,7 +58,7 @@ TEST_CASE( "Tracker" ) { REQUIRE( testCase.isSuccessfullyCompleted() ); } - SECTION( "fail one section" ) { + SECTION( "fail one section", "" ) { s1.fail(); REQUIRE( s1.isComplete() ); REQUIRE( s1.isSuccessfullyCompleted() == false ); @@ -68,7 +68,7 @@ TEST_CASE( "Tracker" ) { REQUIRE( ctx.completedCycle() ); REQUIRE( testCase.isSuccessfullyCompleted() == false ); - SECTION( "re-enter after failed section" ) { + SECTION( "re-enter after failed section", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); @@ -81,7 +81,7 @@ TEST_CASE( "Tracker" ) { REQUIRE( testCase.isComplete() ); REQUIRE( testCase.isSuccessfullyCompleted() ); } - SECTION( "re-enter after failed section and find next section" ) { + SECTION( "re-enter after failed section and find next section", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); @@ -101,7 +101,7 @@ TEST_CASE( "Tracker" ) { } } - SECTION( "successfully close one section, then find another" ) { + SECTION( "successfully close one section, then find another", "" ) { s1.close(); ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); @@ -110,7 +110,7 @@ TEST_CASE( "Tracker" ) { testCase.close(); REQUIRE( testCase.isComplete() == false ); - SECTION( "Re-enter - skips S1 and enters S2" ) { + SECTION( "Re-enter - skips S1 and enters S2", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); @@ -160,7 +160,7 @@ TEST_CASE( "Tracker" ) { } } - SECTION( "open a nested section" ) { + SECTION( "open a nested section", "" ) { ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); @@ -176,7 +176,7 @@ TEST_CASE( "Tracker" ) { REQUIRE( testCase.isComplete() ); } - SECTION( "start a generator" ) { + SECTION( "start a generator", "" ) { IndexTracker& g1 = IndexTracker::acquire( ctx, "G1", 2 ); REQUIRE( g1.isOpen() ); REQUIRE( g1.index() == 0 ); @@ -191,7 +191,7 @@ TEST_CASE( "Tracker" ) { testCase.close(); REQUIRE( testCase.isSuccessfullyCompleted() == false ); - SECTION( "Re-enter for second generation" ) { + SECTION( "Re-enter for second generation", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); @@ -213,7 +213,7 @@ TEST_CASE( "Tracker" ) { REQUIRE( testCase2.isComplete() ); } } - SECTION( "Start a new inner section" ) { + SECTION( "Start a new inner section", "" ) { ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); @@ -226,7 +226,7 @@ TEST_CASE( "Tracker" ) { testCase.close(); REQUIRE( testCase.isComplete() == false ); - SECTION( "Re-enter for second generation" ) { + SECTION( "Re-enter for second generation", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); @@ -255,7 +255,7 @@ TEST_CASE( "Tracker" ) { } } - SECTION( "Fail an inner section" ) { + SECTION( "Fail an inner section", "" ) { ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); @@ -269,7 +269,7 @@ TEST_CASE( "Tracker" ) { testCase.close(); REQUIRE( testCase.isComplete() == false ); - SECTION( "Re-enter for second generation" ) { + SECTION( "Re-enter for second generation", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); From 52a417df7b3f5a52169004ad9138bc7fb5a1ddd2 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Mon, 2 Nov 2015 19:21:46 +0000 Subject: [PATCH 62/87] Fitted new section tracking --- include/internal/catch_run_context.hpp | 45 +++++++++++++++----- include/internal/catch_test_case_tracker.hpp | 4 ++ 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 5e315f96..c607b432 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -70,6 +70,7 @@ namespace Catch { m_context.setConfig( m_config ); m_context.setResultCapture( this ); m_reporter->testRunStarting( m_runInfo ); + m_trackerContext.startRun(); } virtual ~RunContext() { @@ -94,14 +95,17 @@ namespace Catch { m_reporter->testCaseStarting( testInfo ); m_activeTestCase = &testCase; - m_testCaseTracker = TestCaseTracker( testInfo.name ); + do { do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); runCurrentTest( redirectedCout, redirectedCerr ); } - while( !m_testCaseTracker->isCompleted() && !aborting() ); + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); } + // !TBD: deprecated while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); Totals deltaTotals = m_totals.delta( prevTotals ); @@ -113,7 +117,7 @@ namespace Catch { aborting() ) ); m_activeTestCase = CATCH_NULL; - m_testCaseTracker.reset(); + m_testCaseTracker = CATCH_NULL; return deltaTotals; } @@ -149,9 +153,11 @@ namespace Catch { std::ostringstream oss; oss << sectionInfo.name << "@" << sectionInfo.lineInfo; - if( !m_testCaseTracker->enterSection( oss.str() ) ) + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) return false; - + m_activeSections.push_back( §ionTracker ); + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; m_reporter->sectionStarting( sectionInfo ); @@ -161,9 +167,11 @@ namespace Catch { return true; } bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 || - !m_config->warnAboutMissingAssertions() || - m_testCaseTracker->currentSectionHasChildren() ) + if( assertions.total() != 0 ) + return false; + if( m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) return false; m_totals.assertions.failed++; assertions.failed++; @@ -174,13 +182,22 @@ namespace Catch { Counts assertions = m_totals.assertions - endInfo.prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); - m_testCaseTracker->leaveSection(); + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); m_messages.clear(); } virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + m_unfinishedSections.push_back( endInfo ); } @@ -249,7 +266,7 @@ namespace Catch { double duration = 0; try { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); - TestCaseTracker::Guard guard( *m_testCaseTracker ); +// TestCaseTracker::Guard guard( *m_testCaseTracker ); seedRng( *m_config ); @@ -267,10 +284,13 @@ namespace Catch { } catch( TestFailureException& ) { // This just means the test was aborted due to failure +// m_testCaseTracker->fail(); } catch(...) { makeUnexpectedResultBuilder().useActiveException(); +// m_testCaseTracker->fail(); } + m_testCaseTracker->close(); handleUnfinishedSections(); m_messages.clear(); @@ -316,7 +336,8 @@ namespace Catch { TestRunInfo m_runInfo; IMutableContext& m_context; TestCase const* m_activeTestCase; - Option m_testCaseTracker; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; AssertionResult m_lastResult; Ptr m_config; @@ -325,6 +346,8 @@ namespace Catch { std::vector m_messages; AssertionInfo m_lastAssertionInfo; std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; }; IResultCapture& getResultCapture() { diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index 4f174fb6..0bb82dbf 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -29,6 +29,7 @@ namespace TestCaseTracking { virtual bool isComplete() const = 0; // Successfully completed or failed virtual bool isSuccessfullyCompleted() const = 0; virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; virtual ITracker& parent() = 0; @@ -139,6 +140,9 @@ namespace TestCaseTracking { virtual bool isOpen() const CATCH_OVERRIDE { return m_runState != NotStarted && !isComplete(); } + virtual bool hasChildren() const CATCH_OVERRIDE { + return !m_children.empty(); + } virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { From aa49823bc07cf2422866454fd04de20a47ce620f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 3 Nov 2015 07:29:23 +0000 Subject: [PATCH 63/87] perform startRun() at the start of each test case --- include/internal/catch_run_context.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index c607b432..7a93af0d 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -70,7 +70,6 @@ namespace Catch { m_context.setConfig( m_config ); m_context.setResultCapture( this ); m_reporter->testRunStarting( m_runInfo ); - m_trackerContext.startRun(); } virtual ~RunContext() { @@ -98,6 +97,7 @@ namespace Catch { do { + m_trackerContext.startRun(); do { m_trackerContext.startCycle(); m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); From 471bd2556a597f54a120b8382215296e3473f95d Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 3 Nov 2015 07:33:43 +0000 Subject: [PATCH 64/87] Approved changes due to "No assertions" warnings now firing correctly on inner sections --- .../Baselines/console.std.approved.txt | 76 +- .../Baselines/console.sw.approved.txt | 1159 ++++++++++++++-- .../SelfTest/Baselines/junit.sw.approved.txt | 21 +- .../SelfTest/Baselines/xml.sw.approved.txt | 1188 ++++++++++++++++- 4 files changed, 2271 insertions(+), 173 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index dbaca8ba..6f0b0a2c 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -494,7 +494,27 @@ explicitly with message: Message from section two Message from section one +------------------------------------------------------------------------------- +Standard output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + + +No assertions in section 'one' + Message from section two +------------------------------------------------------------------------------- +Standard output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + + +No assertions in section 'two' + ------------------------------------------------------------------------------- SCOPED_INFO is reset for each loop ------------------------------------------------------------------------------- @@ -558,6 +578,38 @@ MiscTests.cpp:: FAILED: with expansion: 1 == 2 +------------------------------------------------------------------------------- +even more nested SECTION tests + c + d (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + + +No assertions in section 'd (leaf)' + +------------------------------------------------------------------------------- +even more nested SECTION tests + c + e (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + + +No assertions in section 'e (leaf)' + +------------------------------------------------------------------------------- +even more nested SECTION tests + f (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + + +No assertions in section 'f (leaf)' + ------------------------------------------------------------------------------- looped SECTION tests s1 @@ -652,6 +704,26 @@ MiscTests.cpp:: FAILED: with expansion: false +------------------------------------------------------------------------------- +xmlentitycheck + embedded xml +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + + +No assertions in section 'embedded xml' + +------------------------------------------------------------------------------- +xmlentitycheck + encoded chars +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + + +No assertions in section 'encoded chars' + ------------------------------------------------------------------------------- send a single char to INFO ------------------------------------------------------------------------------- @@ -797,6 +869,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 159 | 119 passed | 39 failed | 1 failed as expected -assertions: 788 | 695 passed | 80 failed | 13 failed as expected +test cases: 160 | 117 passed | 42 failed | 1 failed as expected +assertions: 927 | 827 passed | 87 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 82702ecf..2d07e380 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1216,15 +1216,6 @@ ExceptionTests.cpp:: FAILED: due to unexpected exception with message: expected exception -------------------------------------------------------------------------------- -When unchecked exceptions are thrown, but caught, they do not affect the test -------------------------------------------------------------------------------- -ExceptionTests.cpp: -............................................................................... - - -No assertions in test case 'When unchecked exceptions are thrown, but caught, they do not affect the test' - ------------------------------------------------------------------------------- Unexpected custom exceptions can be translated ------------------------------------------------------------------------------- @@ -2668,9 +2659,6 @@ warning: this is a message this is a warning - -No assertions in test case 'INFO and WARN do not abort tests' - ------------------------------------------------------------------------------- SUCCEED counts as a test pass ------------------------------------------------------------------------------- @@ -2782,27 +2770,7 @@ explicitly with message: Message from section two Message from section one -------------------------------------------------------------------------------- -Standard output from all sections is reported - one -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - - -No assertions in section 'one' - Message from section two -------------------------------------------------------------------------------- -Standard output from all sections is reported - two -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - - -No assertions in section 'two' - ------------------------------------------------------------------------------- SCOPED_INFO is reset for each loop ------------------------------------------------------------------------------- @@ -2917,18 +2885,6 @@ MessageTests.cpp:: FAILED - but was ok: CHECK_NOFAIL( 1 == 2 ) - -No assertions in test case 'The NO_FAIL macro reports a failure but does not fail the test' - -------------------------------------------------------------------------------- -just info -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - - -No assertions in test case 'just info' - ------------------------------------------------------------------------------- just failure ------------------------------------------------------------------------------- @@ -2965,9 +2921,6 @@ MessageTests.cpp:: warning: toString(p): 0x - -No assertions in test case 'Pointers can be converted to strings' - ------------------------------------------------------------------------------- random SECTION tests s1 @@ -3047,36 +3000,32 @@ with expansion: 1 == 2 ------------------------------------------------------------------------------- -even more nested SECTION tests - c - d (leaf) +more nested SECTION tests + s1 + s3 ------------------------------------------------------------------------------- MiscTests.cpp: ............................................................................... - -No assertions in section 'd (leaf)' +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 ------------------------------------------------------------------------------- -even more nested SECTION tests - c - e (leaf) +more nested SECTION tests + s1 + s4 ------------------------------------------------------------------------------- MiscTests.cpp: ............................................................................... - -No assertions in section 'e (leaf)' - -------------------------------------------------------------------------------- -even more nested SECTION tests - f (leaf) -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in section 'f (leaf)' +MiscTests.cpp:: +PASSED: + REQUIRE( a < b ) +with expansion: + 1 < 2 ------------------------------------------------------------------------------- looped SECTION tests @@ -3156,15 +3105,6 @@ with message: A string sent directly to stdout A string sent directly to stderr -------------------------------------------------------------------------------- -Sends stuff to stdout and stderr -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in test case 'Sends stuff to stdout and stderr' - ------------------------------------------------------------------------------- null strings ------------------------------------------------------------------------------- @@ -3251,26 +3191,6 @@ MiscTests.cpp:: FAILED: with expansion: false -------------------------------------------------------------------------------- -xmlentitycheck - embedded xml -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in section 'embedded xml' - -------------------------------------------------------------------------------- -xmlentitycheck - encoded chars -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in section 'encoded chars' - ------------------------------------------------------------------------------- send a single char to INFO ------------------------------------------------------------------------------- @@ -3462,15 +3382,6 @@ PASSED: with expansion: 3628800 (0x) == 3628800 (0x) -------------------------------------------------------------------------------- -An empty test with no assertions -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in test case 'An empty test with no assertions' - ------------------------------------------------------------------------------- Nice descriptive name ------------------------------------------------------------------------------- @@ -3481,27 +3392,6 @@ MiscTests.cpp:: warning: This one ran - -No assertions in test case 'Nice descriptive name' - -------------------------------------------------------------------------------- -first tag -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in test case 'first tag' - -------------------------------------------------------------------------------- -second tag -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in test case 'second tag' - ------------------------------------------------------------------------------- vectors can be sized and resized ------------------------------------------------------------------------------- @@ -4917,15 +4807,6 @@ with expansion: hello hello -------------------------------------------------------------------------------- -Strings can be rendered with colour -------------------------------------------------------------------------------- -TestMain.cpp: -............................................................................... - - -No assertions in test case 'Strings can be rendered with colour' - ------------------------------------------------------------------------------- Text can be formatted using the Text class ------------------------------------------------------------------------------- @@ -5983,9 +5864,6 @@ warning: Uncomment the code in this test to check that it gives a sensible compiler error - -No assertions in test case 'Where there is more to the expression after the RHS' - ------------------------------------------------------------------------------- Where the LHS is not a simple value ------------------------------------------------------------------------------- @@ -5997,9 +5875,6 @@ warning: Uncomment the code in this test to check that it gives a sensible compiler error - -No assertions in test case 'Where the LHS is not a simple value' - ------------------------------------------------------------------------------- A failing expression with a non streamable type is still captured ------------------------------------------------------------------------------- @@ -6464,6 +6339,1004 @@ with expansion: == "{ StringMaker }" +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + fail one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + fail one section + re-enter after failed section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + fail one section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + fail one section + re-enter after failed section and find next section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 + Successfully close S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isSuccessfullyCompleted() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + successfully close one section, then find another + Re-enter - skips S1 and enters S2 + fail S2 +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( ctx.completedCycle() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1c.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2c.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isSuccessfullyCompleted() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + open a nested section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + close outer section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + close outer section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Start a new inner section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Start a new inner section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isOpen() ) +with expansion: + true + +------------------------------------------------------------------------------- +Tracker + start a generator +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Fail an inner section +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2.isSuccessfullyCompleted() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase.isComplete() == false ) +with expansion: + false == false + +------------------------------------------------------------------------------- +Tracker + start a generator + Fail an inner section + Re-enter for second generation +------------------------------------------------------------------------------- +PartTrackerTests.cpp: +............................................................................... + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.index() == 0 ) +with expansion: + 0 == 0 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2b.isOpen() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1b.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1b.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase2.isComplete() == false ) +with expansion: + false == false + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1c.index() == 1 ) +with expansion: + 1 == 1 + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2c.isOpen() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s2c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( g1c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( s1c.isComplete() ) +with expansion: + true + +PartTrackerTests.cpp:: +PASSED: + REQUIRE( testCase3.isComplete() ) +with expansion: + true + ------------------------------------------------------------------------------- std::pair -> toString ------------------------------------------------------------------------------- @@ -8170,6 +9043,6 @@ with expansion: true =============================================================================== -test cases: 159 | 103 passed | 55 failed | 1 failed as expected -assertions: 808 | 695 passed | 100 failed | 13 failed as expected +test cases: 160 | 120 passed | 39 failed | 1 failed as expected +assertions: 920 | 827 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 6c6e5208..94f59b8e 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -341,6 +341,8 @@ MessageTests.cpp: MiscTests.cpp: + + MiscTests.cpp: @@ -566,6 +568,23 @@ TrickyTests.cpp: + + + + + + + + + + + + + + + + + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 3d20d996..56695fe1 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1543,7 +1543,7 @@ - + @@ -2856,7 +2856,7 @@ this is a warning - + @@ -2949,12 +2949,12 @@
- +
- +
- +
@@ -3062,10 +3062,10 @@ 1 == 2 - + - + @@ -3097,7 +3097,7 @@ toString(p): 0x - +
@@ -3180,25 +3180,53 @@
+
+
+ + + a != b + + + 1 != 2 + + + +
+ +
+
+
+ + + a < b + + + 1 < 2 + + + +
+ +
- +
- +
- +
- +
- +
- +
@@ -3300,7 +3328,7 @@ - + @@ -3399,12 +3427,12 @@
- +
- +
- +
@@ -3606,19 +3634,19 @@ - + This one ran - + - + - + @@ -5140,7 +5168,7 @@ four" - + @@ -6191,13 +6219,13 @@ there" Uncomment the code in this test to check that it gives a sensible compiler error - + Uncomment the code in this test to check that it gives a sensible compiler error - + @@ -6617,6 +6645,1112 @@ there" + + + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isSuccessfullyCompleted() + + + true + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isComplete() + + + true + + + + + s1.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isComplete() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s1.isComplete() + + + true + + + + + s1.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + + + + ctx.completedCycle() + + + true + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2.isOpen() + + + true + + + + + ctx.completedCycle() + + + true + + + + + testCase.isComplete() + + + true + + + + + testCase.isSuccessfullyCompleted() + + + true + + + +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2b.isOpen() + + + true + + + + + ctx.completedCycle() == false + + + false == false + + +
+ + + ctx.completedCycle() + + + true + + + + + s2b.isSuccessfullyCompleted() + + + true + + + + + testCase2.isComplete() == false + + + false == false + + + + + testCase2.isSuccessfullyCompleted() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() == false + + + false == false + + + + + s2b.isOpen() + + + true + + + + + ctx.completedCycle() == false + + + false == false + + +
+ + + ctx.completedCycle() + + + true + + + + + s2b.isComplete() + + + true + + + + + s2b.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase2.isSuccessfullyCompleted() == false + + + false == false + + + + + testCase3.isOpen() + + + true + + + + + s1c.isOpen() == false + + + false == false + + + + + s2c.isOpen() == false + + + false == false + + + + + testCase3.isSuccessfullyCompleted() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s1.isComplete() == false + + + false == false + + + + + s1.isComplete() + + + true + + + + + testCase.isComplete() == false + + + false == false + + + + + testCase.isComplete() + + + true + + + +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s1.isComplete() == false + + + false == false + + + + + testCase.isSuccessfullyCompleted() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 1 + + + 1 == 1 + + + + + s1.isComplete() == false + + + false == false + + + + + s1b.isComplete() + + + true + + + + + g1b.isComplete() + + + true + + + + + testCase2.isComplete() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s1.isComplete() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 1 + + + 1 == 1 + + + + + s2b.isOpen() + + + true + + + + + s2b.isComplete() + + + true + + + + + g1b.isComplete() + + + true + + + + + s1b.isComplete() + + + true + + + + + testCase2.isComplete() + + + true + + + +
+ +
+ +
+ + + testCase.isOpen() + + + true + + + + + s1.isOpen() + + + true + + +
+ + + g1.isOpen() + + + true + + + + + g1.index() == 0 + + + 0 == 0 + + + + + g1.isComplete() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + +
+ + + s2.isOpen() + + + true + + + + + s2.isComplete() + + + true + + + + + s2.isSuccessfullyCompleted() == false + + + false == false + + + + + s1.isComplete() == false + + + false == false + + + + + testCase.isComplete() == false + + + false == false + + +
+ + + testCase2.isOpen() + + + true + + + + + s1b.isOpen() + + + true + + + + + g1b.isOpen() + + + true + + + + + g1b.index() == 0 + + + 0 == 0 + + + + + s2b.isOpen() == false + + + false == false + + + + + g1b.isComplete() == false + + + false == false + + + + + s1b.isComplete() == false + + + false == false + + + + + testCase2.isComplete() == false + + + false == false + + + + + testCase3.isOpen() + + + true + + + + + s1c.isOpen() + + + true + + + + + g1c.isOpen() + + + true + + + + + g1c.index() == 1 + + + 1 == 1 + + + + + s2c.isOpen() + + + true + + + + + s2c.isComplete() + + + true + + + + + g1c.isComplete() + + + true + + + + + s1c.isComplete() + + + true + + + + + testCase3.isComplete() + + + true + + + +
+ +
+ +
+ +
@@ -8463,7 +9597,7 @@ there"
- + - + From bc8840cbb86fe57155620695714eb3936b85244b Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 3 Nov 2015 07:38:14 +0000 Subject: [PATCH 65/87] Removed deprecated section tracking implementation and tests --- include/internal/catch_run_context.hpp | 5 +- include/internal/catch_test_case_tracker.hpp | 132 ------------- .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 176 +---------------- .../SelfTest/Baselines/junit.sw.approved.txt | 7 +- .../SelfTest/Baselines/xml.sw.approved.txt | 179 +----------------- projects/SelfTest/SectionTrackerTests.cpp | 114 ----------- .../CatchSelfTest.xcodeproj/project.pbxproj | 6 +- 8 files changed, 9 insertions(+), 614 deletions(-) delete mode 100644 projects/SelfTest/SectionTrackerTests.cpp diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 7a93af0d..a3098b5f 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -105,7 +105,7 @@ namespace Catch { } while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); } - // !TBD: deprecated + // !TBD: deprecated - this will be replaced by indexed trackers while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); Totals deltaTotals = m_totals.delta( prevTotals ); @@ -266,7 +266,6 @@ namespace Catch { double duration = 0; try { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); -// TestCaseTracker::Guard guard( *m_testCaseTracker ); seedRng( *m_config ); @@ -284,11 +283,9 @@ namespace Catch { } catch( TestFailureException& ) { // This just means the test was aborted due to failure -// m_testCaseTracker->fail(); } catch(...) { makeUnexpectedResultBuilder().useActiveException(); -// m_testCaseTracker->fail(); } m_testCaseTracker->close(); handleUnfinishedSections(); diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index 0bb82dbf..713ec96c 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -310,138 +310,6 @@ using TestCaseTracking::ITracker; using TestCaseTracking::TrackerContext; using TestCaseTracking::SectionTracker; using TestCaseTracking::IndexTracker; - -// !TBD: Deprecated -namespace SectionTracking { - - - class TrackedSection { - - typedef std::map TrackedSections; - - public: - enum RunState { - NotStarted, - Executing, - ExecutingChildren, - Completed - }; - - TrackedSection( std::string const& name, TrackedSection* parent ) - : m_name( name ), m_runState( NotStarted ), m_parent( parent ) - {} - - RunState runState() const { return m_runState; } - - TrackedSection* findChild( std::string const& childName ); - TrackedSection* acquireChild( std::string const& childName ); - - void enter() { - if( m_runState == NotStarted ) - m_runState = Executing; - } - void leave(); - - TrackedSection* getParent() { - return m_parent; - } - bool hasChildren() const { - return !m_children.empty(); - } - - private: - std::string m_name; - RunState m_runState; - TrackedSections m_children; - TrackedSection* m_parent; - }; - - inline TrackedSection* TrackedSection::findChild( std::string const& childName ) { - TrackedSections::iterator it = m_children.find( childName ); - return it != m_children.end() - ? &it->second - : CATCH_NULL; - } - inline TrackedSection* TrackedSection::acquireChild( std::string const& childName ) { - if( TrackedSection* child = findChild( childName ) ) - return child; - m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); - return findChild( childName ); - } - inline void TrackedSection::leave() { - for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); - it != itEnd; - ++it ) - if( it->second.runState() != Completed ) { - m_runState = ExecutingChildren; - return; - } - m_runState = Completed; - } - - class TestCaseTracker { - public: - TestCaseTracker( std::string const& testCaseName ) - : m_testCase( testCaseName, CATCH_NULL ), - m_currentSection( &m_testCase ), - m_completedASectionThisRun( false ) - {} - - bool enterSection( std::string const& name ) { - TrackedSection* child = m_currentSection->acquireChild( name ); - if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) - return false; - - m_currentSection = child; - m_currentSection->enter(); - return true; - } - void leaveSection() { - m_currentSection->leave(); - m_currentSection = m_currentSection->getParent(); - assert( m_currentSection != CATCH_NULL ); - m_completedASectionThisRun = true; - } - - bool currentSectionHasChildren() const { - return m_currentSection->hasChildren(); - } - bool isCompleted() const { - return m_testCase.runState() == TrackedSection::Completed; - } - - class Guard { - public: - Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { - m_tracker.enterTestCase(); - } - ~Guard() { - m_tracker.leaveTestCase(); - } - private: - Guard( Guard const& ); - void operator = ( Guard const& ); - TestCaseTracker& m_tracker; - }; - - private: - void enterTestCase() { - m_currentSection = &m_testCase; - m_completedASectionThisRun = false; - m_testCase.enter(); - } - void leaveTestCase() { - m_testCase.leave(); - } - - TrackedSection m_testCase; - TrackedSection* m_currentSection; - bool m_completedASectionThisRun; - }; - -} // namespace SectionTracking - -using SectionTracking::TestCaseTracker; } // namespace Catch diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 6f0b0a2c..92c2624b 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -869,6 +869,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 160 | 117 passed | 42 failed | 1 failed as expected -assertions: 927 | 827 passed | 87 failed | 13 failed as expected +test cases: 159 | 116 passed | 42 failed | 1 failed as expected +assertions: 907 | 807 passed | 87 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 2d07e380..8e2ba564 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -8870,179 +8870,7 @@ PASSED: with expansion: 1 > 0 -------------------------------------------------------------------------------- -section tracking -------------------------------------------------------------------------------- -SectionTrackerTests.cpp: -............................................................................... - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.isCompleted() ) -with expansion: - !false - -------------------------------------------------------------------------------- -section tracking - test case with no sections -------------------------------------------------------------------------------- -SectionTrackerTests.cpp: -............................................................................... - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.isCompleted() ) -with expansion: - !false - -SectionTrackerTests.cpp:: -PASSED: - CHECK( testCaseTracker.isCompleted() ) -with expansion: - true - -------------------------------------------------------------------------------- -section tracking -------------------------------------------------------------------------------- -SectionTrackerTests.cpp: -............................................................................... - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.isCompleted() ) -with expansion: - !false - -------------------------------------------------------------------------------- -section tracking - test case with one section -------------------------------------------------------------------------------- -SectionTrackerTests.cpp: -............................................................................... - -SectionTrackerTests.cpp:: -PASSED: - CHECK( testCaseTracker.enterSection( section1Name ) ) -with expansion: - true - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.isCompleted() ) -with expansion: - !false - -SectionTrackerTests.cpp:: -PASSED: - CHECK( testCaseTracker.isCompleted() ) -with expansion: - true - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ) -with expansion: - !false - -------------------------------------------------------------------------------- -section tracking -------------------------------------------------------------------------------- -SectionTrackerTests.cpp: -............................................................................... - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.isCompleted() ) -with expansion: - !false - -------------------------------------------------------------------------------- -section tracking - test case with two consecutive sections -------------------------------------------------------------------------------- -SectionTrackerTests.cpp: -............................................................................... - -SectionTrackerTests.cpp:: -PASSED: - CHECK( testCaseTracker.enterSection( section1Name ) ) -with expansion: - true - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.enterSection( section2Name ) ) -with expansion: - !false - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.isCompleted() ) -with expansion: - !false - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ) -with expansion: - !false - -SectionTrackerTests.cpp:: -PASSED: - CHECK( testCaseTracker.enterSection( section2Name ) ) -with expansion: - true - -SectionTrackerTests.cpp:: -PASSED: - CHECK( testCaseTracker.isCompleted() ) -with expansion: - true - -------------------------------------------------------------------------------- -section tracking -------------------------------------------------------------------------------- -SectionTrackerTests.cpp: -............................................................................... - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.isCompleted() ) -with expansion: - !false - -------------------------------------------------------------------------------- -section tracking - test case with one section within another -------------------------------------------------------------------------------- -SectionTrackerTests.cpp: -............................................................................... - -SectionTrackerTests.cpp:: -PASSED: - CHECK( testCaseTracker.enterSection( section1Name ) ) -with expansion: - true - -SectionTrackerTests.cpp:: -PASSED: - CHECK( testCaseTracker.enterSection( section2Name ) ) -with expansion: - true - -SectionTrackerTests.cpp:: -PASSED: - CHECK_FALSE( testCaseTracker.isCompleted() ) -with expansion: - !false - -SectionTrackerTests.cpp:: -PASSED: - CHECK( testCaseTracker.isCompleted() ) -with expansion: - true - =============================================================================== -test cases: 160 | 120 passed | 39 failed | 1 failed as expected -assertions: 920 | 827 passed | 80 failed | 13 failed as expected +test cases: 159 | 119 passed | 39 failed | 1 failed as expected +assertions: 900 | 807 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 94f59b8e..a7ad8583 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -644,11 +644,6 @@ TrickyTests.cpp: - - - - - Message from section one Message from section two diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 56695fe1..a11f61b4 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -9422,182 +9422,7 @@ there"
- - - - !testCaseTracker.isCompleted() - - - !false - - -
- - - !testCaseTracker.isCompleted() - - - !false - - - - - testCaseTracker.isCompleted() - - - true - - - -
- - - !testCaseTracker.isCompleted() - - - !false - - -
- - - testCaseTracker.enterSection( section1Name ) - - - true - - - - - !testCaseTracker.isCompleted() - - - !false - - - - - testCaseTracker.isCompleted() - - - true - - - - - !testCaseTracker.enterSection( section1Name ) - - - !false - - - -
- - - !testCaseTracker.isCompleted() - - - !false - - -
- - - testCaseTracker.enterSection( section1Name ) - - - true - - - - - !testCaseTracker.enterSection( section2Name ) - - - !false - - - - - !testCaseTracker.isCompleted() - - - !false - - - - - !testCaseTracker.enterSection( section1Name ) - - - !false - - - - - testCaseTracker.enterSection( section2Name ) - - - true - - - - - testCaseTracker.isCompleted() - - - true - - - -
- - - !testCaseTracker.isCompleted() - - - !false - - -
- - - testCaseTracker.enterSection( section1Name ) - - - true - - - - - testCaseTracker.enterSection( section2Name ) - - - true - - - - - !testCaseTracker.isCompleted() - - - !false - - - - - testCaseTracker.isCompleted() - - - true - - - -
- -
- + - + diff --git a/projects/SelfTest/SectionTrackerTests.cpp b/projects/SelfTest/SectionTrackerTests.cpp deleted file mode 100644 index d3df994d..00000000 --- a/projects/SelfTest/SectionTrackerTests.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Created by Phil on 20/07/2013. - * Copyright 2013 Two Blue Cubes Ltd - * - * Distributed under the Boost Software License, Version 1.0. (See accompanying - * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - */ - -#include "internal/catch_suppress_warnings.h" -#include "internal/catch_test_case_tracker.hpp" - -#include "catch.hpp" - -TEST_CASE( "section tracking", "" ) { - - using namespace Catch; - TestCaseTracker testCaseTracker( "test case" ); - - const std::string section1Name = "section 1"; - const std::string section2Name = "section 2"; - - CHECK_FALSE( testCaseTracker.isCompleted() ); - - SECTION( "test case with no sections", "" ) { - - { - TestCaseTracker::Guard guard( testCaseTracker ); - CHECK_FALSE( testCaseTracker.isCompleted() ); - } - CHECK( testCaseTracker.isCompleted() ); - } - - SECTION( "test case with one section", "" ) { - - { - TestCaseTracker::Guard guard( testCaseTracker ); - - // Enter section? - yes - CHECK( testCaseTracker.enterSection( section1Name ) ); - CHECK_FALSE( testCaseTracker.isCompleted() ); - testCaseTracker.leaveSection(); - - // Leave test case - now complete - } - CHECK( testCaseTracker.isCompleted() ); - - // ... - - // Enter test case again - { - TestCaseTracker::Guard guard( testCaseTracker ); - - // Enter section? - no - now complete - CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ); - } - } - - SECTION( "test case with two consecutive sections", "" ) { - - // Enter test case - { - TestCaseTracker::Guard guard( testCaseTracker ); - - // Enter section 1? - yes - CHECK( testCaseTracker.enterSection( section1Name ) ); - testCaseTracker.leaveSection(); - - // Enter section 2? - no - we just exected section 1 - CHECK_FALSE( testCaseTracker.enterSection( section2Name ) ); - - // Leave test case - incomplete (still need to visit section 2) - } - CHECK_FALSE( testCaseTracker.isCompleted() ); - - // ... - - // Enter test case again - { - TestCaseTracker::Guard guard( testCaseTracker ); - - // Enter section 1? - no, already done now - CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ); - - // Enter section 2? - yes - CHECK( testCaseTracker.enterSection( section2Name ) ); - testCaseTracker.leaveSection(); - - // Leave test case - now complete - } - CHECK( testCaseTracker.isCompleted() ); - } - - SECTION( "test case with one section within another", "" ) { - - // Enter test case again - { - TestCaseTracker::Guard guard( testCaseTracker ); - - // Enter section 1? - yes - CHECK( testCaseTracker.enterSection( section1Name ) ); - - // Enter section 2? - yes - CHECK( testCaseTracker.enterSection( section2Name ) ); - - CHECK_FALSE( testCaseTracker.isCompleted() ); - - testCaseTracker.leaveSection(); // section 2 - testCaseTracker.leaveSection(); // section 1 - - // Leave test case - now complete - } - CHECK( testCaseTracker.isCompleted() ); - } -} diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index 5ec14365..8947e38e 100644 --- a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj +++ b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj @@ -7,7 +7,7 @@ objects = { /* Begin PBXBuildFile section */ - 26059AF21BD4B94C003D575C /* PartTrackerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */; settings = {ASSET_TAGS = (); }; }; + 26059AF21BD4B94C003D575C /* PartTrackerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */; }; 263F7A4719B6FCBF009474C2 /* EnumToString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4619B6FCBF009474C2 /* EnumToString.cpp */; }; 263F7A4B19B6FE1E009474C2 /* ToStringPair.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4819B6FE1E009474C2 /* ToStringPair.cpp */; }; 263F7A4C19B6FE1E009474C2 /* ToStringVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 263F7A4919B6FE1E009474C2 /* ToStringVector.cpp */; }; @@ -18,7 +18,6 @@ 26711C8F195D465C0033EDA2 /* TagAliasTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */; }; 26847E5F16BBADB40043B9C1 /* catch_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26847E5D16BBADB40043B9C1 /* catch_message.cpp */; }; 2691574C1A532A280054F1ED /* ToStringTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2691574B1A532A280054F1ED /* ToStringTuple.cpp */; }; - 26948286179A9AB900ED166E /* SectionTrackerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */; }; 2694A1FD16A0000E004816E3 /* catch_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2694A1FB16A0000E004816E3 /* catch_text.cpp */; }; 26E1B7D319213BC900812682 /* CmdLineTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E1B7D119213BC900812682 /* CmdLineTests.cpp */; }; 4A45DA2416161EF9004F8D6B /* catch_console_colour.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */; }; @@ -102,7 +101,6 @@ 2691574B1A532A280054F1ED /* ToStringTuple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ToStringTuple.cpp; path = ../../../SelfTest/ToStringTuple.cpp; sourceTree = ""; }; 26926E8318D7777D004E10F2 /* clara.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = clara.h; path = ../../../../include/external/clara.h; sourceTree = ""; }; 26926E8418D77809004E10F2 /* tbc_text_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tbc_text_format.h; path = ../../../../include/external/tbc_text_format.h; sourceTree = ""; }; - 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionTrackerTests.cpp; path = ../../../SelfTest/SectionTrackerTests.cpp; sourceTree = ""; }; 26948287179EF7F900ED166E /* catch_test_case_tracker.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_tracker.hpp; sourceTree = ""; }; 2694A1FB16A0000E004816E3 /* catch_text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catch_text.cpp; sourceTree = ""; }; 269831E519078C1600BB0CE0 /* catch_tostring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catch_tostring.h; sourceTree = ""; }; @@ -215,7 +213,6 @@ isa = PBXGroup; children = ( 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */, - 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */, 26E1B7D119213BC900812682 /* CmdLineTests.cpp */, 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */, ); @@ -578,7 +575,6 @@ 26847E5F16BBADB40043B9C1 /* catch_message.cpp in Sources */, 266B06B816F3A60A004ED264 /* VariadicMacrosTests.cpp in Sources */, 266ECD74170F3C620030D735 /* BDDTests.cpp in Sources */, - 26948286179A9AB900ED166E /* SectionTrackerTests.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From 015e07100eebdf0557fbd08154e6adc1cf128ae2 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 3 Nov 2015 07:46:37 +0000 Subject: [PATCH 66/87] Added SUCCEEDs to empty leaf sections to avoid failing due to no assertions --- .../Baselines/console.std.approved.txt | 56 +------------------ .../Baselines/console.sw.approved.txt | 54 +++++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 7 ++- .../SelfTest/Baselines/xml.sw.approved.txt | 18 +++--- projects/SelfTest/MiscTests.cpp | 7 ++- 5 files changed, 75 insertions(+), 67 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 92c2624b..ad144d77 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -578,38 +578,6 @@ MiscTests.cpp:: FAILED: with expansion: 1 == 2 -------------------------------------------------------------------------------- -even more nested SECTION tests - c - d (leaf) -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in section 'd (leaf)' - -------------------------------------------------------------------------------- -even more nested SECTION tests - c - e (leaf) -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in section 'e (leaf)' - -------------------------------------------------------------------------------- -even more nested SECTION tests - f (leaf) -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in section 'f (leaf)' - ------------------------------------------------------------------------------- looped SECTION tests s1 @@ -704,26 +672,6 @@ MiscTests.cpp:: FAILED: with expansion: false -------------------------------------------------------------------------------- -xmlentitycheck - embedded xml -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in section 'embedded xml' - -------------------------------------------------------------------------------- -xmlentitycheck - encoded chars -------------------------------------------------------------------------------- -MiscTests.cpp: -............................................................................... - - -No assertions in section 'encoded chars' - ------------------------------------------------------------------------------- send a single char to INFO ------------------------------------------------------------------------------- @@ -869,6 +817,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 159 | 116 passed | 42 failed | 1 failed as expected -assertions: 907 | 807 passed | 87 failed | 13 failed as expected +test cases: 159 | 118 passed | 40 failed | 1 failed as expected +assertions: 907 | 812 passed | 82 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 8e2ba564..5fb53373 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -3027,6 +3027,38 @@ PASSED: with expansion: 1 < 2 +------------------------------------------------------------------------------- +even more nested SECTION tests + c + d (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +even more nested SECTION tests + c + e (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +even more nested SECTION tests + f (leaf) +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + ------------------------------------------------------------------------------- looped SECTION tests s1 @@ -3191,6 +3223,26 @@ MiscTests.cpp:: FAILED: with expansion: false +------------------------------------------------------------------------------- +xmlentitycheck + embedded xml +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + +------------------------------------------------------------------------------- +xmlentitycheck + encoded chars +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + ------------------------------------------------------------------------------- send a single char to INFO ------------------------------------------------------------------------------- @@ -8872,5 +8924,5 @@ with expansion: =============================================================================== test cases: 159 | 119 passed | 39 failed | 1 failed as expected -assertions: 900 | 807 passed | 80 failed | 13 failed as expected +assertions: 905 | 812 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index a7ad8583..40447d11 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -343,6 +343,9 @@ MiscTests.cpp: + + + MiscTests.cpp: @@ -401,6 +404,8 @@ MiscTests.cpp: MiscTests.cpp: + + 3 diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index a11f61b4..ebe5c69b 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -3213,18 +3213,18 @@
- +
- +
- +
- +
- +
@@ -3427,10 +3427,10 @@
- +
- +
@@ -9422,7 +9422,7 @@ there"
- + - + diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 36b8a608..e791cb10 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -80,15 +80,18 @@ TEST_CASE( "even more nested SECTION tests", "[sections]" ) { SECTION( "d (leaf)", "" ) { + SUCCEED(""); // avoid failing due to no tests } SECTION( "e (leaf)", "" ) { + SUCCEED(""); // avoid failing due to no tests } } SECTION( "f (leaf)", "" ) { + SUCCEED(""); // avoid failing due to no tests } } @@ -177,11 +180,11 @@ TEST_CASE( "xmlentitycheck", "" ) { SECTION( "embedded xml", "it should be possible to embed xml characters, such as <, \" or &, or even whole documents within an attribute" ) { - // No test + SUCCEED(""); // We need this here to stop it failing due to no tests } SECTION( "encoded chars", "these should all be encoded: &&&\"\"\"<<<&\"<<&\"" ) { - // No test + SUCCEED(""); // We need this here to stop it failing due to no tests } } From 7e34619f03a85eb24994166bbdf1e2039ab2fd57 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 3 Nov 2015 08:00:43 +0000 Subject: [PATCH 67/87] v1.2.1-develop.15 - includes all new section tracker --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 626 +++++++++++++++++++---------- 3 files changed, 410 insertions(+), 220 deletions(-) diff --git a/README.md b/README.md index 5b99b524..395bc3f3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.14* +*v1.2.1-develop.15* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index e1878a28..08b1c989 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 14 ); + Version libraryVersion( 1, 2, 1, "develop", 15 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index faaef35e..4ba0d193 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.14 - * Generated: 2015-09-27 03:27:04.922060 + * Catch v1.2.1-develop.15 + * Generated: 2015-11-03 08:00:19.120246 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -35,6 +35,7 @@ # pragma clang diagnostic ignored "-Wc++98-compat" # pragma clang diagnostic ignored "-Wc++98-compat-pedantic" # pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" # endif #elif defined __GNUC__ # pragma GCC diagnostic ignored "-Wvariadic-macros" @@ -3287,28 +3288,59 @@ namespace Catch { // #included from: catch_stream.h #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED -#include +// #included from: catch_streambuf.h +#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wpadded" -#endif +#include namespace Catch { - class Stream { + class StreamBufBase : public std::streambuf { public: - Stream(); - Stream( std::streambuf* _streamBuf, bool _isOwned ); - void release(); - - std::streambuf* streamBuf; - - private: - bool isOwned; + virtual ~StreamBufBase() CATCH_NOEXCEPT; }; +} + +#include +#include +#include + +namespace Catch { std::ostream& cout(); std::ostream& cerr(); + + struct IStream { + virtual ~IStream() CATCH_NOEXCEPT; + virtual std::ostream& stream() const = 0; + }; + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( std::string const& filename ); + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + CoutStream(); + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; + + class DebugOutStream : public IStream { + std::auto_ptr m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream(); + + public: // IStream + virtual std::ostream& stream() const CATCH_OVERRIDE; + }; } #include @@ -3382,12 +3414,11 @@ namespace Catch { public: Config() - : m_os( Catch::cout().rdbuf() ) {} Config( ConfigData const& data ) : m_data( data ), - m_os( Catch::cout().rdbuf() ) + m_stream( openStream() ) { if( !data.testsOrTags.empty() ) { TestSpecParser parser( ITagAliasRegistry::get() ); @@ -3398,12 +3429,6 @@ namespace Catch { } virtual ~Config() { - m_os.rdbuf( Catch::cout().rdbuf() ); - m_stream.release(); - } - - void setFilename( std::string const& filename ) { - m_data.outputFilename = filename; } std::string const& getFilename() const { @@ -3419,17 +3444,6 @@ namespace Catch { bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } - void setStreamBuf( std::streambuf* buf ) { - m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() ); - } - - void useStream( std::string const& streamName ) { - Stream stream = createStream( streamName ); - setStreamBuf( stream.streamBuf ); - m_stream.release(); - m_stream = stream; - } - std::vector getReporterNames() const { return m_data.reporterNames; } int abortAfter() const { return m_data.abortAfter; } @@ -3441,7 +3455,7 @@ namespace Catch { // IConfig interface virtual bool allowThrows() const { return !m_data.noThrow; } - virtual std::ostream& stream() const { return m_os; } + virtual std::ostream& stream() const { return m_stream->stream(); } virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } @@ -3451,10 +3465,22 @@ namespace Catch { virtual bool forceColour() const { return m_data.forceColour; } private: + + IStream const* openStream() { + if( m_data.outputFilename.empty() ) + return new CoutStream(); + else if( m_data.outputFilename[0] == '%' ) { + if( m_data.outputFilename == "%debug" ) + return new DebugOutStream(); + else + throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); + } + else + return new FileStream( m_data.outputFilename ); + } ConfigData m_data; - Stream m_stream; - mutable std::ostream m_os; + std::auto_ptr m_stream; TestSpec m_testSpec; }; @@ -4726,18 +4752,18 @@ namespace Catch { namespace Catch { struct ReporterConfig { - explicit ReporterConfig( Ptr const& _fullConfig ) + explicit ReporterConfig( Ptr const& _fullConfig ) : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} - ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) + ReporterConfig( Ptr const& _fullConfig, std::ostream& _stream ) : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} std::ostream& stream() const { return *m_stream; } - Ptr fullConfig() const { return m_fullConfig; } + Ptr fullConfig() const { return m_fullConfig; } private: std::ostream* m_stream; - Ptr m_fullConfig; + Ptr m_fullConfig; }; struct ReporterPreferences { @@ -4959,7 +4985,7 @@ namespace Catch typedef std::vector > Listeners; virtual ~IReporterRegistry(); - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const = 0; virtual FactoryMap const& getFactories() const = 0; virtual Listeners const& getListeners() const = 0; }; @@ -5136,137 +5162,300 @@ namespace Catch { #include #include #include +#include namespace Catch { -namespace SectionTracking { +namespace TestCaseTracking { - class TrackedSection { + struct ITracker : SharedImpl<> { + virtual ~ITracker(); - typedef std::map TrackedSections; + // static queries + virtual std::string name() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( Ptr const& child ) = 0; + virtual ITracker* findChild( std::string const& name ) = 0; + virtual void openChild() = 0; + }; + + class TrackerContext { - public: enum RunState { NotStarted, Executing, - ExecutingChildren, - Completed + CompletedCycle }; - TrackedSection( std::string const& name, TrackedSection* parent ) - : m_name( name ), m_runState( NotStarted ), m_parent( parent ) + Ptr m_rootTracker; + ITracker* m_currentTracker; + RunState m_runState; + + public: + + static TrackerContext& instance() { + static TrackerContext s_instance; + return s_instance; + } + + TrackerContext() + : m_currentTracker( CATCH_NULL ), + m_runState( NotStarted ) {} - RunState runState() const { return m_runState; } + ITracker& startRun(); - TrackedSection* findChild( std::string const& childName ); - TrackedSection* acquireChild( std::string const& childName ); - - void enter() { - if( m_runState == NotStarted ) - m_runState = Executing; + void endRun() { + m_rootTracker.reset(); + m_currentTracker = CATCH_NULL; + m_runState = NotStarted; } - void leave(); - TrackedSection* getParent() { - return m_parent; + void startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; } - bool hasChildren() const { + void completeCycle() { + m_runState = CompletedCycle; + } + + bool completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& currentTracker() { + return *m_currentTracker; + } + void setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + class TrackerHasName { + std::string m_name; + public: + TrackerHasName( std::string const& name ) : m_name( name ) {} + bool operator ()( Ptr const& tracker ) { + return tracker->name() == m_name; + } + }; + typedef std::vector > Children; + std::string m_name; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState; + public: + TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : m_name( name ), + m_ctx( ctx ), + m_parent( parent ), + m_runState( NotStarted ) + {} + virtual ~TrackerBase(); + + virtual std::string name() const CATCH_OVERRIDE { + return m_name; + } + virtual bool isComplete() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { + return m_runState == CompletedSuccessfully; + } + virtual bool isOpen() const CATCH_OVERRIDE { + return m_runState != NotStarted && !isComplete(); + } + virtual bool hasChildren() const CATCH_OVERRIDE { return !m_children.empty(); } - private: - std::string m_name; - RunState m_runState; - TrackedSections m_children; - TrackedSection* m_parent; - }; + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { + m_children.push_back( child ); + } - inline TrackedSection* TrackedSection::findChild( std::string const& childName ) { - TrackedSections::iterator it = m_children.find( childName ); - return it != m_children.end() - ? &it->second - : CATCH_NULL; - } - inline TrackedSection* TrackedSection::acquireChild( std::string const& childName ) { - if( TrackedSection* child = findChild( childName ) ) - return child; - m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) ); - return findChild( childName ); - } - inline void TrackedSection::leave() { - for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end(); - it != itEnd; - ++it ) - if( it->second.runState() != Completed ) { + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { + Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); + return( it != m_children.end() ) + ? it->get() + : CATCH_NULL; + } + virtual ITracker& parent() CATCH_OVERRIDE { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + virtual void openChild() CATCH_OVERRIDE { + if( m_runState != ExecutingChildren ) { m_runState = ExecutingChildren; - return; + if( m_parent ) + m_parent->openChild(); } - m_runState = Completed; - } - - class TestCaseTracker { - public: - TestCaseTracker( std::string const& testCaseName ) - : m_testCase( testCaseName, CATCH_NULL ), - m_currentSection( &m_testCase ), - m_completedASectionThisRun( false ) - {} - - bool enterSection( std::string const& name ) { - TrackedSection* child = m_currentSection->acquireChild( name ); - if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed ) - return false; - - m_currentSection = child; - m_currentSection->enter(); - return true; } - void leaveSection() { - m_currentSection->leave(); - m_currentSection = m_currentSection->getParent(); - assert( m_currentSection != CATCH_NULL ); - m_completedASectionThisRun = true; + void open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); } - bool currentSectionHasChildren() const { - return m_currentSection->hasChildren(); - } - bool isCompleted() const { - return m_testCase.runState() == TrackedSection::Completed; - } + virtual void close() CATCH_OVERRIDE { - class Guard { - public: - Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) { - m_tracker.enterTestCase(); + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NotStarted: + case CompletedSuccessfully: + case Failed: + throw std::logic_error( "Illogical state" ); + + case NeedsAnotherRun: + break;; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + default: + throw std::logic_error( "Unexpected state" ); } - ~Guard() { - m_tracker.leaveTestCase(); - } - private: - Guard( Guard const& ); - void operator = ( Guard const& ); - TestCaseTracker& m_tracker; - }; - + moveToParent(); + m_ctx.completeCycle(); + } + virtual void fail() CATCH_OVERRIDE { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { + m_runState = NeedsAnotherRun; + } private: - void enterTestCase() { - m_currentSection = &m_testCase; - m_completedASectionThisRun = false; - m_testCase.enter(); + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); } - void leaveTestCase() { - m_testCase.leave(); + void moveToThis() { + m_ctx.setCurrentTracker( this ); } - - TrackedSection m_testCase; - TrackedSection* m_currentSection; - bool m_completedASectionThisRun; }; -} // namespace SectionTracking + class SectionTracker : public TrackerBase { + public: + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) + {} + virtual ~SectionTracker(); -using SectionTracking::TestCaseTracker; + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { + SectionTracker* section = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + section = dynamic_cast( childTracker ); + assert( section ); + } + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() && !section->isComplete() ) { + + section->open(); + } + return *section; + } + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index; + public: + IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( name, ctx, parent ), + m_size( size ), + m_index( -1 ) + {} + virtual ~IndexTracker(); + + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { + IndexTracker* tracker = CATCH_NULL; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITracker* childTracker = currentTracker.findChild( name ) ) { + tracker = dynamic_cast( childTracker ); + assert( tracker ); + } + else { + tracker = new IndexTracker( name, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int index() const { return m_index; } + + void moveNext() { + m_index++; + m_children.clear(); + } + + virtual void close() CATCH_OVERRIDE { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + }; + + inline ITracker& TrackerContext::startRun() { + m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); + m_currentTracker = CATCH_NULL; + m_runState = Executing; + return *m_rootTracker; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; } // namespace Catch @@ -5387,10 +5576,7 @@ namespace Catch { m_context( getCurrentMutableContext() ), m_activeTestCase( CATCH_NULL ), m_config( _config ), - m_reporter( reporter ), - m_prevRunner( m_context.getRunner() ), - m_prevResultCapture( m_context.getResultCapture() ), - m_prevConfig( m_context.getConfig() ) + m_reporter( reporter ) { m_context.setRunner( this ); m_context.setConfig( m_config ); @@ -5400,10 +5586,6 @@ namespace Catch { virtual ~RunContext() { m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); - m_context.setRunner( m_prevRunner ); - m_context.setConfig( Ptr() ); - m_context.setResultCapture( m_prevResultCapture ); - m_context.setConfig( m_prevConfig ); } void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { @@ -5424,14 +5606,17 @@ namespace Catch { m_reporter->testCaseStarting( testInfo ); m_activeTestCase = &testCase; - m_testCaseTracker = TestCaseTracker( testInfo.name ); do { + m_trackerContext.startRun(); do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name ); runCurrentTest( redirectedCout, redirectedCerr ); } - while( !m_testCaseTracker->isCompleted() && !aborting() ); + while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); } + // !TBD: deprecated - this will be replaced by indexed trackers while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); Totals deltaTotals = m_totals.delta( prevTotals ); @@ -5443,7 +5628,7 @@ namespace Catch { aborting() ) ); m_activeTestCase = CATCH_NULL; - m_testCaseTracker.reset(); + m_testCaseTracker = CATCH_NULL; return deltaTotals; } @@ -5478,8 +5663,10 @@ namespace Catch { std::ostringstream oss; oss << sectionInfo.name << "@" << sectionInfo.lineInfo; - if( !m_testCaseTracker->enterSection( oss.str() ) ) + ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() ); + if( !sectionTracker.isOpen() ) return false; + m_activeSections.push_back( §ionTracker ); m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; @@ -5490,9 +5677,11 @@ namespace Catch { return true; } bool testForMissingAssertions( Counts& assertions ) { - if( assertions.total() != 0 || - !m_config->warnAboutMissingAssertions() || - m_testCaseTracker->currentSectionHasChildren() ) + if( assertions.total() != 0 ) + return false; + if( m_config->warnAboutMissingAssertions() ) + return false; + if( m_trackerContext.currentTracker().hasChildren() ) return false; m_totals.assertions.failed++; assertions.failed++; @@ -5503,13 +5692,22 @@ namespace Catch { Counts assertions = m_totals.assertions - endInfo.prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); - m_testCaseTracker->leaveSection(); + if( !m_activeSections.empty() ) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); m_messages.clear(); } virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { + if( m_unfinishedSections.empty() ) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + m_unfinishedSections.push_back( endInfo ); } @@ -5578,7 +5776,6 @@ namespace Catch { double duration = 0; try { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); - TestCaseTracker::Guard guard( *m_testCaseTracker ); seedRng( *m_config ); @@ -5600,6 +5797,7 @@ namespace Catch { catch(...) { makeUnexpectedResultBuilder().useActiveException(); } + m_testCaseTracker->close(); handleUnfinishedSections(); m_messages.clear(); @@ -5645,18 +5843,18 @@ namespace Catch { TestRunInfo m_runInfo; IMutableContext& m_context; TestCase const* m_activeTestCase; - Option m_testCaseTracker; + ITracker* m_testCaseTracker; + ITracker* m_currentSectionTracker; AssertionResult m_lastResult; Ptr m_config; Totals m_totals; Ptr m_reporter; std::vector m_messages; - IRunner* m_prevRunner; - IResultCapture* m_prevResultCapture; - Ptr m_prevConfig; AssertionInfo m_lastAssertionInfo; std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; }; IResultCapture& getResultCapture() { @@ -5726,7 +5924,7 @@ namespace Catch { reporter = addReporter( reporter, createReporter( *it, config ) ); return reporter; } - Ptr addListeners( Ptr const& config, Ptr reporters ) { + Ptr addListeners( Ptr const& config, Ptr reporters ) { IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); it != itEnd; @@ -5735,27 +5933,14 @@ namespace Catch { return reporters; } - void openStreamInto( Ptr const& config, std::ofstream& ofs ) { - // Open output file, if specified - if( !config->getFilename().empty() ) { - ofs.open( config->getFilename().c_str() ); - if( ofs.fail() ) { - std::ostringstream oss; - oss << "Unable to open file: '" << config->getFilename() << "'"; - throw std::domain_error( oss.str() ); - } - config->setStreamBuf( ofs.rdbuf() ); - } - } - Totals runTests( Ptr const& config ) { - std::ofstream ofs; - openStreamInto( config, ofs ); - Ptr reporter = makeReporter( config ); - reporter = addListeners( config.get(), reporter ); + Ptr iconfig = config.get(); - RunContext context( config.get(), reporter ); + Ptr reporter = makeReporter( config ); + reporter = addListeners( iconfig, reporter ); + + RunContext context( iconfig, reporter ); Totals totals; @@ -5765,17 +5950,17 @@ namespace Catch { if( !testSpec.hasFilters() ) testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests - std::vector const& allTestCases = getAllTestCasesSorted( *config ); + std::vector const& allTestCases = getAllTestCasesSorted( *iconfig ); for( std::vector::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); it != itEnd; ++it ) { - if( !context.aborting() && matchTest( *it, testSpec, *config ) ) + if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) totals += context.runTest( *it ); else reporter->skipTest( *it ); } - context.testGroupEnded( config->name(), totals, 1, 1 ); + context.testGroupEnded( iconfig->name(), totals, 1, 1 ); return totals; } @@ -6094,7 +6279,7 @@ namespace Catch { virtual ~ReporterRegistry() CATCH_OVERRIDE {} - virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { + virtual IStreamingReporter* create( std::string const& name, Ptr const& config ) const CATCH_OVERRIDE { FactoryMap::const_iterator it = m_factories.find( name ); if( it == m_factories.end() ) return CATCH_NULL; @@ -6283,19 +6468,6 @@ namespace Catch { // #included from: catch_stream.hpp #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED -// #included from: catch_streambuf.h -#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED - -#include - -namespace Catch { - - class StreamBufBase : public std::streambuf { - public: - virtual ~StreamBufBase() CATCH_NOEXCEPT; - }; -} - #include #include #include @@ -6340,6 +6512,19 @@ namespace Catch { /////////////////////////////////////////////////////////////////////////// + FileStream::FileStream( std::string const& filename ) { + m_ofs.open( filename.c_str() ); + if( m_ofs.fail() ) { + std::ostringstream oss; + oss << "Unable to open file: '" << filename << "'"; + throw std::domain_error( oss.str() ); + } + } + + std::ostream& FileStream::stream() const { + return m_ofs; + } + struct OutputDebugWriter { void operator()( std::string const&str ) { @@ -6347,20 +6532,23 @@ namespace Catch { } }; - Stream::Stream() - : streamBuf( CATCH_NULL ), isOwned( false ) + DebugOutStream::DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) {} - Stream::Stream( std::streambuf* _streamBuf, bool _isOwned ) - : streamBuf( _streamBuf ), isOwned( _isOwned ) + std::ostream& DebugOutStream::stream() const { + return m_os; + } + + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream::CoutStream() + : m_os( Catch::cout().rdbuf() ) {} - void Stream::release() { - if( isOwned ) { - delete streamBuf; - streamBuf = CATCH_NULL; - isOwned = false; - } + std::ostream& CoutStream::stream() const { + return m_os; } #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions @@ -6455,14 +6643,6 @@ namespace Catch { return getCurrentMutableContext(); } - Stream createStream( std::string const& streamName ) { - if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false ); - if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false ); - if( streamName == "debug" ) return Stream( new StreamBufImpl, true ); - - throw std::domain_error( "Unknown stream: " + streamName ); - } - void cleanUpContext() { delete currentContext; currentContext = CATCH_NULL; @@ -7011,7 +7191,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 14 ); + Version libraryVersion( 1, 2, 1, "develop", 15 ); } @@ -8076,7 +8256,7 @@ namespace Catch { // It can optionally be overridden in the derived class. } - Ptr m_config; + Ptr m_config; std::ostream& stream; LazyStat currentTestRunInfo; @@ -8214,7 +8394,7 @@ namespace Catch { virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} - Ptr m_config; + Ptr m_config; std::ostream& stream; std::vector m_assertions; std::vector > > m_sections; @@ -9689,8 +9869,11 @@ namespace Catch { } // end namespace Catch namespace Catch { + // These are all here to avoid warnings about not having any out of line + // virtual methods NonCopyable::~NonCopyable() {} IShared::~IShared() {} + IStream::~IStream() CATCH_NOEXCEPT {} StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} @@ -9736,6 +9919,13 @@ namespace Catch { Matchers::Impl::StdString::EndsWith::~EndsWith() {} void Config::dummy() {} + + namespace TestCaseTracking { + ITracker::~ITracker() {} + TrackerBase::~TrackerBase() {} + SectionTracker::~SectionTracker() {} + IndexTracker::~IndexTracker() {} + } } #ifdef __clang__ From f5642be7b4362f29eb1cc7ea4932008eb2565b04 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 3 Nov 2015 17:05:08 +0000 Subject: [PATCH 68/87] Fixed reversed logic of NoAssertions warning check (that explains the previous regressions) --- include/internal/catch_run_context.hpp | 2 +- .../Baselines/console.std.approved.txt | 24 ++----------------- .../Baselines/console.sw.approved.txt | 24 +++++++++++++++++-- .../SelfTest/Baselines/junit.sw.approved.txt | 2 +- .../SelfTest/Baselines/xml.sw.approved.txt | 10 ++++---- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index a3098b5f..6ae67568 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -169,7 +169,7 @@ namespace Catch { bool testForMissingAssertions( Counts& assertions ) { if( assertions.total() != 0 ) return false; - if( m_config->warnAboutMissingAssertions() ) + if( !m_config->warnAboutMissingAssertions() ) return false; if( m_trackerContext.currentTracker().hasChildren() ) return false; diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index ad144d77..c222e306 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -494,27 +494,7 @@ explicitly with message: Message from section two Message from section one -------------------------------------------------------------------------------- -Standard output from all sections is reported - one -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - - -No assertions in section 'one' - Message from section two -------------------------------------------------------------------------------- -Standard output from all sections is reported - two -------------------------------------------------------------------------------- -MessageTests.cpp: -............................................................................... - - -No assertions in section 'two' - ------------------------------------------------------------------------------- SCOPED_INFO is reset for each loop ------------------------------------------------------------------------------- @@ -817,6 +797,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 159 | 118 passed | 40 failed | 1 failed as expected -assertions: 907 | 812 passed | 82 failed | 13 failed as expected +test cases: 159 | 119 passed | 39 failed | 1 failed as expected +assertions: 905 | 812 passed | 80 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 5fb53373..981fce15 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -2770,7 +2770,27 @@ explicitly with message: Message from section two Message from section one +------------------------------------------------------------------------------- +Standard output from all sections is reported + one +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + + +No assertions in section 'one' + Message from section two +------------------------------------------------------------------------------- +Standard output from all sections is reported + two +------------------------------------------------------------------------------- +MessageTests.cpp: +............................................................................... + + +No assertions in section 'two' + ------------------------------------------------------------------------------- SCOPED_INFO is reset for each loop ------------------------------------------------------------------------------- @@ -8923,6 +8943,6 @@ with expansion: 1 > 0 =============================================================================== -test cases: 159 | 119 passed | 39 failed | 1 failed as expected -assertions: 905 | 812 passed | 80 failed | 13 failed as expected +test cases: 159 | 118 passed | 40 failed | 1 failed as expected +assertions: 907 | 812 passed | 82 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 40447d11..0766b19e 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index ebe5c69b..1bb662f2 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -2949,12 +2949,12 @@
- +
- +
- +
@@ -9422,7 +9422,7 @@ there"
- + - + From c81778ecd0803dd96587bb6419ae0723c6c0d896 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 3 Nov 2015 17:06:24 +0000 Subject: [PATCH 69/87] Fixed CMake file (changed SectionTrackerTests.cpp - now deleted - to the new PartTrackerTests.cpp) --- projects/CMake/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/CMake/CMakeLists.txt b/projects/CMake/CMakeLists.txt index 240e1ebe..960d9fb1 100644 --- a/projects/CMake/CMakeLists.txt +++ b/projects/CMake/CMakeLists.txt @@ -22,7 +22,7 @@ set(SOURCES ${SELF_TEST_DIR}/GeneratorTests.cpp ${SELF_TEST_DIR}/MessageTests.cpp ${SELF_TEST_DIR}/MiscTests.cpp - ${SELF_TEST_DIR}/SectionTrackerTests.cpp + ${SELF_TEST_DIR}/PartTrackerTests.cpp ${SELF_TEST_DIR}/TestMain.cpp ${SELF_TEST_DIR}/TrickyTests.cpp ${SELF_TEST_DIR}/VariadicMacrosTests.cpp From 9e42153fe5eab3ae46c2a7c9e110383bbec5d0ea Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 3 Nov 2015 17:06:54 +0000 Subject: [PATCH 70/87] dev build 16 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 395bc3f3..e2c2a39f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.15* +*v1.2.1-develop.16* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 08b1c989..3df960da 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 15 ); + Version libraryVersion( 1, 2, 1, "develop", 16 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 4ba0d193..5f17ee1c 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.15 - * Generated: 2015-11-03 08:00:19.120246 + * Catch v1.2.1-develop.16 + * Generated: 2015-11-03 17:06:36.466681 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -5679,7 +5679,7 @@ namespace Catch { bool testForMissingAssertions( Counts& assertions ) { if( assertions.total() != 0 ) return false; - if( m_config->warnAboutMissingAssertions() ) + if( !m_config->warnAboutMissingAssertions() ) return false; if( m_trackerContext.currentTracker().hasChildren() ) return false; @@ -7191,7 +7191,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 15 ); + Version libraryVersion( 1, 2, 1, "develop", 16 ); } From ece529ae7cd5fe15d698986aabdd5faf23e333f8 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Tue, 3 Nov 2015 17:37:43 +0000 Subject: [PATCH 71/87] Fixed noexcept destructors issue --- include/internal/catch_impl.hpp | 3 +++ include/internal/catch_stream.h | 3 +++ single_include/catch.hpp | 8 +++++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index baabd7ab..74ac775e 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -49,6 +49,9 @@ namespace Catch { NonCopyable::~NonCopyable() {} IShared::~IShared() {} IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} diff --git a/include/internal/catch_stream.h b/include/internal/catch_stream.h index a69c841e..20acaff6 100644 --- a/include/internal/catch_stream.h +++ b/include/internal/catch_stream.h @@ -31,6 +31,7 @@ namespace Catch { mutable std::ofstream m_ofs; public: FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; }; @@ -40,6 +41,7 @@ namespace Catch { mutable std::ostream m_os; public: CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; @@ -51,6 +53,7 @@ namespace Catch { mutable std::ostream m_os; public: DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 5f17ee1c..c0c9db16 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* * Catch v1.2.1-develop.16 - * Generated: 2015-11-03 17:06:36.466681 + * Generated: 2015-11-03 17:37:18.144715 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -3319,6 +3319,7 @@ namespace Catch { mutable std::ofstream m_ofs; public: FileStream( std::string const& filename ); + virtual ~FileStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; }; @@ -3327,6 +3328,7 @@ namespace Catch { mutable std::ostream m_os; public: CoutStream(); + virtual ~CoutStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; @@ -3337,6 +3339,7 @@ namespace Catch { mutable std::ostream m_os; public: DebugOutStream(); + virtual ~DebugOutStream() CATCH_NOEXCEPT; public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; @@ -9874,6 +9877,9 @@ namespace Catch { NonCopyable::~NonCopyable() {} IShared::~IShared() {} IStream::~IStream() CATCH_NOEXCEPT {} + FileStream::~FileStream() CATCH_NOEXCEPT {} + CoutStream::~CoutStream() CATCH_NOEXCEPT {} + DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} From 8c32b49d5fd2329b20c684f21fe7098cd6da95b8 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 4 Nov 2015 07:33:39 +0000 Subject: [PATCH 72/87] Added script to strip trailing whitespace from source files --- scripts/fixTrailingWhitespace.py | 46 ++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 scripts/fixTrailingWhitespace.py diff --git a/scripts/fixTrailingWhitespace.py b/scripts/fixTrailingWhitespace.py new file mode 100644 index 00000000..0ffe8e91 --- /dev/null +++ b/scripts/fixTrailingWhitespace.py @@ -0,0 +1,46 @@ +from __future__ import print_function +import os +from scriptCommon import catchPath + +changedFiles = 0 + +def isSourceFile( path ): + return path.endswith( ".cpp" ) or path.endswith( ".h" ) or path.endswith( ".hpp" ) + +def fixAllFilesInDir( dir ): + for f in os.listdir( dir ): + path = os.path.join( dir,f ) + if os.path.isfile( path ): + if( isSourceFile( path ) ): + fixFile( path ) + else: + fixAllFilesInDir( path ) + +def fixFile( path ): + f = open( path, 'r' ) + lines = [] + changed = 0 + for line in f: + trimmed = line.rstrip() + "\n" + if trimmed != line: + changed = changed +1 + lines.append( trimmed ) + f.close() + if changed > 0: + global changedFiles + changedFiles = changedFiles + 1 + print( path + ":" ) + print( " - fixed " + str(changed) + " line(s)" ) + altPath = path + ".backup" + os.rename( path, altPath ) + f2 = open( path, 'w' ) + for line in lines: + f2.write( line ) + f2.close() + os.remove( altPath ) + +fixAllFilesInDir(catchPath) +if changedFiles > 0: + print( "Fixed " + str(changedFiles) + " file(s)" ) +else: + print( "No trailing whitespace found" ) From e91738103ce8dc6c0ca6c096c66b79d25f3c18d6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 4 Nov 2015 18:01:28 +0000 Subject: [PATCH 73/87] Stripped trailing whitespace from all source code lines (replaces need for PRs #310 and #504) --- include/catch_session.hpp | 22 ++-- include/internal/catch_commandline.hpp | 4 +- include/internal/catch_common.h | 6 +- include/internal/catch_common.hpp | 4 +- include/internal/catch_config.hpp | 2 +- include/internal/catch_evaluate.hpp | 6 +- include/internal/catch_impl.hpp | 2 +- include/internal/catch_interfaces_reporter.h | 6 +- include/internal/catch_interfaces_testcase.h | 2 +- include/internal/catch_matchers.hpp | 6 +- .../internal/catch_reporter_registrars.hpp | 10 +- include/internal/catch_result_builder.h | 2 +- include/internal/catch_result_builder.hpp | 6 +- include/internal/catch_result_type.h | 2 +- include/internal/catch_run_context.hpp | 18 +-- include/internal/catch_section_info.h | 6 +- include/internal/catch_stream.h | 6 +- include/internal/catch_stream.hpp | 16 +-- include/internal/catch_test_case_info.h | 4 +- include/internal/catch_test_case_info.hpp | 6 +- .../catch_test_case_registry_impl.hpp | 10 +- include/internal/catch_test_case_tracker.hpp | 86 +++++++------- include/internal/catch_test_spec.hpp | 6 +- include/internal/catch_tostring.h | 4 +- include/internal/catch_tostring.hpp | 4 +- include/internal/catch_version.h | 2 +- include/internal/catch_wildcard_pattern.hpp | 6 +- include/internal/catch_xmlwriter.hpp | 16 +-- include/reporters/catch_reporter_bases.hpp | 6 +- include/reporters/catch_reporter_junit.hpp | 8 +- include/reporters/catch_reporter_multi.hpp | 26 ++--- include/reporters/catch_reporter_teamcity.hpp | 40 +++---- include/reporters/catch_reporter_xml.hpp | 10 +- projects/SelfTest/ApproxTests.cpp | 12 +- projects/SelfTest/BDDTests.cpp | 14 +-- projects/SelfTest/ClassTests.cpp | 18 +-- projects/SelfTest/ConditionTests.cpp | 52 ++++----- projects/SelfTest/ExceptionTests.cpp | 4 +- projects/SelfTest/GeneratorTests.cpp | 12 +- projects/SelfTest/MessageTests.cpp | 4 +- projects/SelfTest/MiscTests.cpp | 44 ++++---- projects/SelfTest/PartTrackerTests.cpp | 106 +++++++++--------- projects/SelfTest/TestMain.cpp | 62 +++++----- projects/SelfTest/TrickyTests.cpp | 50 ++++----- .../internal/iTchRunnerAppDelegate.h | 26 ++--- .../iTchRunner/internal/iTchRunnerMainView.h | 10 +- .../iTchRunner/internal/iTchRunnerReporter.h | 22 ++-- 47 files changed, 398 insertions(+), 398 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index c63f517b..1b1cba54 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -30,7 +30,7 @@ namespace Catch { } return reporter; } - + Ptr makeReporter( Ptr const& config ) { std::vector reporters = config->getReporterNames(); if( reporters.empty() ) @@ -40,7 +40,7 @@ namespace Catch { for( std::vector::const_iterator it = reporters.begin(), itEnd = reporters.end(); it != itEnd; ++it ) - reporter = addReporter( reporter, createReporter( *it, config ) ); + reporter = addReporter( reporter, createReporter( *it, config ) ); return reporter; } Ptr addListeners( Ptr const& config, Ptr reporters ) { @@ -51,15 +51,15 @@ namespace Catch { reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); return reporters; } - - + + Totals runTests( Ptr const& config ) { Ptr iconfig = config.get(); - + Ptr reporter = makeReporter( config ); reporter = addListeners( iconfig, reporter ); - + RunContext context( iconfig, reporter ); Totals totals; @@ -83,13 +83,13 @@ namespace Catch { context.testGroupEnded( iconfig->name(), totals, 1, 1 ); return totals; } - + void applyFilenamesAsTags( IConfig const& config ) { std::vector const& tests = getAllTestCasesSorted( config ); for(std::size_t i = 0; i < tests.size(); ++i ) { TestCase& test = const_cast( tests[i] ); std::set tags = test.tags; - + std::string filename = test.lineInfo.file; std::string::size_type lastSlash = filename.find_last_of( "\\/" ); if( lastSlash != std::string::npos ) @@ -98,7 +98,7 @@ namespace Catch { std::string::size_type lastDot = filename.find_last_of( "." ); if( lastDot != std::string::npos ) filename = filename.substr( 0, lastDot ); - + tags.insert( "#" + filename ); setTags( test, tags ); } @@ -173,12 +173,12 @@ namespace Catch { try { config(); // Force config to be constructed - + seedRng( *m_config ); if( m_configData.filenamesAsTags ) applyFilenamesAsTags( *m_config ); - + // Handle list request if( Option listed = list( config() ) ) return static_cast( *listed ); diff --git a/include/internal/catch_commandline.hpp b/include/internal/catch_commandline.hpp index f2fce31b..640b304d 100644 --- a/include/internal/catch_commandline.hpp +++ b/include/internal/catch_commandline.hpp @@ -163,7 +163,7 @@ namespace Catch { .describe( "list all/matching test cases names only" ) .bind( &ConfigData::listTestNamesOnly ); - cli["--list-reporters"] + cli["--list-reporters"] .describe( "list all reporters" ) .bind( &ConfigData::listReporters ); @@ -178,7 +178,7 @@ namespace Catch { cli["--force-colour"] .describe( "force colourised output" ) .bind( &ConfigData::forceColour ); - + return cli; } diff --git a/include/internal/catch_common.h b/include/internal/catch_common.h index 2ae79b18..7f9cfc44 100644 --- a/include/internal/catch_common.h +++ b/include/internal/catch_common.h @@ -22,14 +22,14 @@ #include "catch_compiler_capabilities.h" namespace Catch { - + struct IConfig; struct CaseSensitive { enum Choice { Yes, No }; }; - + class NonCopyable { #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS NonCopyable( NonCopyable const& ) = delete; @@ -118,7 +118,7 @@ namespace Catch { void seedRng( IConfig const& config ); unsigned int rngSeed(); - + // Use this in variadic streaming macros to allow // >> +StreamEndStop // as well as diff --git a/include/internal/catch_common.hpp b/include/internal/catch_common.hpp index 69a64ad1..2342ae61 100644 --- a/include/internal/catch_common.hpp +++ b/include/internal/catch_common.hpp @@ -36,7 +36,7 @@ namespace Catch { return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; } - + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { bool replaced = false; std::size_t i = str.find( replaceThis ); @@ -50,7 +50,7 @@ namespace Catch { } return replaced; } - + pluralise::pluralise( std::size_t count, std::string const& label ) : m_count( count ), m_label( label ) diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp index c0d0948e..a09210cb 100644 --- a/include/internal/catch_config.hpp +++ b/include/internal/catch_config.hpp @@ -136,7 +136,7 @@ namespace Catch { virtual bool forceColour() const { return m_data.forceColour; } private: - + IStream const* openStream() { if( m_data.outputFilename.empty() ) return new CoutStream(); diff --git a/include/internal/catch_evaluate.hpp b/include/internal/catch_evaluate.hpp index 76f19e2a..1d8ca93e 100644 --- a/include/internal/catch_evaluate.hpp +++ b/include/internal/catch_evaluate.hpp @@ -174,7 +174,7 @@ namespace Internal { template bool compare( long long lhs, unsigned char rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } - + // unsigned long long to X template bool compare( unsigned long long lhs, int rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); @@ -188,7 +188,7 @@ namespace Internal { template bool compare( unsigned long long lhs, char rhs ) { return applyEvaluator( static_cast( lhs ), rhs ); } - + // pointer to long long (when comparing against NULL) template bool compare( long long lhs, T* rhs ) { return Evaluator::evaluate( reinterpret_cast( lhs ), rhs ); @@ -197,7 +197,7 @@ namespace Internal { return Evaluator::evaluate( lhs, reinterpret_cast( rhs ) ); } #endif // CATCH_CONFIG_CPP11_LONG_LONG - + #ifdef CATCH_CONFIG_CPP11_NULLPTR // pointer to nullptr_t (when comparing against nullptr) template bool compare( std::nullptr_t, T* rhs ) { diff --git a/include/internal/catch_impl.hpp b/include/internal/catch_impl.hpp index 74ac775e..53c89574 100644 --- a/include/internal/catch_impl.hpp +++ b/include/internal/catch_impl.hpp @@ -97,7 +97,7 @@ namespace Catch { Matchers::Impl::StdString::EndsWith::~EndsWith() {} void Config::dummy() {} - + namespace TestCaseTracking { ITracker::~ITracker() {} TrackerBase::~TrackerBase() {} diff --git a/include/internal/catch_interfaces_reporter.h b/include/internal/catch_interfaces_reporter.h index e40119df..d1c6e704 100644 --- a/include/internal/catch_interfaces_reporter.h +++ b/include/internal/catch_interfaces_reporter.h @@ -240,12 +240,12 @@ namespace Catch // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; - + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; - + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; }; @@ -267,7 +267,7 @@ namespace Catch }; Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ); - + } #endif // TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED diff --git a/include/internal/catch_interfaces_testcase.h b/include/internal/catch_interfaces_testcase.h index 3ae412c5..a1052b71 100644 --- a/include/internal/catch_interfaces_testcase.h +++ b/include/internal/catch_interfaces_testcase.h @@ -34,7 +34,7 @@ namespace Catch { bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector const& getAllTestCasesSorted( IConfig const& config ); - + } #endif // TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 8b0783cc..fd9dfd2b 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -132,7 +132,7 @@ namespace Matchers { return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; - + } std::string toStringSuffix() const { @@ -143,7 +143,7 @@ namespace Matchers { CaseSensitive::Choice m_caseSensitivity; std::string m_str; }; - + struct Equals : MatcherImpl { Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) : m_data( str, caseSensitivity ) @@ -182,7 +182,7 @@ namespace Matchers { struct StartsWith : MatcherImpl { StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) : m_data( substr, caseSensitivity ){} - + StartsWith( StartsWith const& other ) : m_data( other.m_data ){} virtual ~StartsWith(); diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp index 0aed0823..7bd7b610 100644 --- a/include/internal/catch_reporter_registrars.hpp +++ b/include/internal/catch_reporter_registrars.hpp @@ -64,12 +64,12 @@ namespace Catch { getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); } }; - + template class ListenerRegistrar { - + class ListenerFactory : public SharedImpl { - + virtual IStreamingReporter* create( ReporterConfig const& config ) const { return new T( config ); } @@ -77,9 +77,9 @@ namespace Catch { return ""; } }; - + public: - + ListenerRegistrar() { getMutableRegistryHub().registerListener( new ListenerFactory() ); } diff --git a/include/internal/catch_result_builder.h b/include/internal/catch_result_builder.h index c27fe5c2..89002660 100644 --- a/include/internal/catch_result_builder.h +++ b/include/internal/catch_result_builder.h @@ -85,7 +85,7 @@ namespace Catch { std::string lhs, rhs, op; } m_exprComponents; CopyableStream m_stream; - + bool m_shouldDebugBreak; bool m_shouldThrow; }; diff --git a/include/internal/catch_result_builder.hpp b/include/internal/catch_result_builder.hpp index 5e2ba32b..d453fecf 100644 --- a/include/internal/catch_result_builder.hpp +++ b/include/internal/catch_result_builder.hpp @@ -77,12 +77,12 @@ namespace Catch { } void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher const& matcher ) { - + assert( m_exprComponents.testFalse == false ); AssertionResultData data = m_data; data.resultType = ResultWas::Ok; data.reconstructedExpression = m_assertionInfo.capturedExpression; - + std::string actualMessage = Catch::translateActiveException(); if( !matcher.match( actualMessage ) ) { data.resultType = ResultWas::ExpressionFailed; @@ -99,7 +99,7 @@ namespace Catch { void ResultBuilder::handleResult( AssertionResult const& result ) { getResultCapture().assertionEnded( result ); - + if( !result.isOk() ) { if( getCurrentContext().getConfig()->shouldDebugBreak() ) m_shouldDebugBreak = true; diff --git a/include/internal/catch_result_type.h b/include/internal/catch_result_type.h index beaff369..4c3d77dc 100644 --- a/include/internal/catch_result_type.h +++ b/include/internal/catch_result_type.h @@ -55,7 +55,7 @@ namespace Catch { inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } - + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED diff --git a/include/internal/catch_run_context.hpp b/include/internal/catch_run_context.hpp index 6ae67568..da5990ad 100644 --- a/include/internal/catch_run_context.hpp +++ b/include/internal/catch_run_context.hpp @@ -94,7 +94,7 @@ namespace Catch { m_reporter->testCaseStarting( testInfo ); m_activeTestCase = &testCase; - + do { m_trackerContext.startRun(); @@ -157,7 +157,7 @@ namespace Catch { if( !sectionTracker.isOpen() ) return false; m_activeSections.push_back( §ionTracker ); - + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; m_reporter->sectionStarting( sectionInfo ); @@ -177,16 +177,16 @@ namespace Catch { assertions.failed++; return true; } - + virtual void sectionEnded( SectionEndInfo const& endInfo ) { Counts assertions = m_totals.assertions - endInfo.prevAssertions; bool missingAssertions = testForMissingAssertions( assertions ); - + if( !m_activeSections.empty() ) { m_activeSections.back()->close(); m_activeSections.pop_back(); } - + m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); m_messages.clear(); } @@ -197,10 +197,10 @@ namespace Catch { else m_activeSections.back()->close(); m_activeSections.pop_back(); - + m_unfinishedSections.push_back( endInfo ); } - + virtual void pushScopedMessage( MessageInfo const& message ) { m_messages.push_back( message ); } @@ -268,7 +268,7 @@ namespace Catch { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); seedRng( *m_config ); - + Timer timer; timer.start(); if( m_reporter->getPreferences().shouldRedirectStdOut ) { @@ -318,7 +318,7 @@ namespace Catch { m_lastAssertionInfo.capturedExpression.c_str(), m_lastAssertionInfo.resultDisposition ); } - + void handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. diff --git a/include/internal/catch_section_info.h b/include/internal/catch_section_info.h index e49ef638..00b65600 100644 --- a/include/internal/catch_section_info.h +++ b/include/internal/catch_section_info.h @@ -23,17 +23,17 @@ namespace Catch { std::string description; SourceLineInfo lineInfo; }; - + struct SectionEndInfo { SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) {} - + SectionInfo sectionInfo; Counts prevAssertions; double durationInSeconds; }; - + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED diff --git a/include/internal/catch_stream.h b/include/internal/catch_stream.h index 20acaff6..5f22ad67 100644 --- a/include/internal/catch_stream.h +++ b/include/internal/catch_stream.h @@ -21,7 +21,7 @@ namespace Catch { std::ostream& cout(); std::ostream& cerr(); - + struct IStream { virtual ~IStream() CATCH_NOEXCEPT; virtual std::ostream& stream() const = 0; @@ -35,7 +35,7 @@ namespace Catch { public: // IStream virtual std::ostream& stream() const CATCH_OVERRIDE; }; - + class CoutStream : public IStream { mutable std::ostream m_os; @@ -47,7 +47,7 @@ namespace Catch { virtual std::ostream& stream() const CATCH_OVERRIDE; }; - + class DebugOutStream : public IStream { std::auto_ptr m_streamBuf; mutable std::ostream m_os; diff --git a/include/internal/catch_stream.hpp b/include/internal/catch_stream.hpp index e6bf7b0c..afd52f39 100644 --- a/include/internal/catch_stream.hpp +++ b/include/internal/catch_stream.hpp @@ -65,27 +65,27 @@ namespace Catch { throw std::domain_error( oss.str() ); } } - + std::ostream& FileStream::stream() const { return m_ofs; } - + struct OutputDebugWriter { - + void operator()( std::string const&str ) { writeToDebugConsole( str ); } }; - + DebugOutStream::DebugOutStream() : m_streamBuf( new StreamBufImpl() ), m_os( m_streamBuf.get() ) {} - + std::ostream& DebugOutStream::stream() const { return m_os; } - + // Store the streambuf from cout up-front because // cout may get redirected when running tests CoutStream::CoutStream() @@ -95,8 +95,8 @@ namespace Catch { std::ostream& CoutStream::stream() const { return m_os; } - - + + #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions std::ostream& cout() { return std::cout; diff --git a/include/internal/catch_test_case_info.h b/include/internal/catch_test_case_info.h index 685825e1..6ab1f375 100644 --- a/include/internal/catch_test_case_info.h +++ b/include/internal/catch_test_case_info.h @@ -31,7 +31,7 @@ namespace Catch { MayFail = 1 << 3, Throws = 1 << 4 }; - + TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, @@ -41,7 +41,7 @@ namespace Catch { TestCaseInfo( TestCaseInfo const& other ); friend void setTags( TestCaseInfo& testCaseInfo, std::set const& tags ); - + bool isHidden() const; bool throws() const; bool okToFail() const; diff --git a/include/internal/catch_test_case_info.hpp b/include/internal/catch_test_case_info.hpp index 2101c985..90f53411 100644 --- a/include/internal/catch_test_case_info.hpp +++ b/include/internal/catch_test_case_info.hpp @@ -88,7 +88,7 @@ namespace Catch { tags.insert( "hide" ); tags.insert( "." ); } - + TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); return TestCase( _testCase, info ); } @@ -97,7 +97,7 @@ namespace Catch { { testCaseInfo.tags = tags; testCaseInfo.lcaseTags.clear(); - + std::ostringstream oss; for( std::set::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { oss << "[" << *it << "]"; @@ -107,7 +107,7 @@ namespace Catch { } testCaseInfo.tagsAsString = oss.str(); } - + TestCaseInfo::TestCaseInfo( std::string const& _name, std::string const& _className, std::string const& _description, diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index fda70aae..7f63dc54 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -27,11 +27,11 @@ namespace Catch { struct RandomNumberGenerator { int operator()( int n ) const { return std::rand() % n; } }; - + inline std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { - + std::vector sorted = unsortedTestCases; - + switch( config.runOrder() ) { case RunTests::InLexicographicalOrder: std::sort( sorted.begin(), sorted.end(), LexSort() ); @@ -39,7 +39,7 @@ namespace Catch { case RunTests::InRandomOrder: { seedRng( config ); - + RandomNumberGenerator rng; std::random_shuffle( sorted.begin(), sorted.end(), rng ); } @@ -70,7 +70,7 @@ namespace Catch { } } } - + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { std::vector filtered; filtered.reserve( testCases.size() ); diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index 713ec96c..505c3ab8 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -21,61 +21,61 @@ namespace TestCaseTracking { struct ITracker : SharedImpl<> { virtual ~ITracker(); - + // static queries virtual std::string name() const = 0; - + // dynamic queries virtual bool isComplete() const = 0; // Successfully completed or failed virtual bool isSuccessfullyCompleted() const = 0; virtual bool isOpen() const = 0; // Started but not complete virtual bool hasChildren() const = 0; - + virtual ITracker& parent() = 0; - + // actions virtual void close() = 0; // Successfully complete virtual void fail() = 0; virtual void markAsNeedingAnotherRun() = 0; - + virtual void addChild( Ptr const& child ) = 0; virtual ITracker* findChild( std::string const& name ) = 0; virtual void openChild() = 0; }; - + class TrackerContext { - + enum RunState { NotStarted, Executing, CompletedCycle }; - + Ptr m_rootTracker; ITracker* m_currentTracker; RunState m_runState; - + public: - + static TrackerContext& instance() { static TrackerContext s_instance; return s_instance; } - + TrackerContext() : m_currentTracker( CATCH_NULL ), m_runState( NotStarted ) {} - - + + ITracker& startRun(); - + void endRun() { m_rootTracker.reset(); m_currentTracker = CATCH_NULL; m_runState = NotStarted; } - + void startCycle() { m_currentTracker = m_rootTracker.get(); m_runState = Executing; @@ -83,7 +83,7 @@ namespace TestCaseTracking { void completeCycle() { m_runState = CompletedCycle; } - + bool completedCycle() const { return m_runState == CompletedCycle; } @@ -94,7 +94,7 @@ namespace TestCaseTracking { m_currentTracker = tracker; } }; - + class TrackerBase : public ITracker { protected: enum CycleState { @@ -127,7 +127,7 @@ namespace TestCaseTracking { m_runState( NotStarted ) {} virtual ~TrackerBase(); - + virtual std::string name() const CATCH_OVERRIDE { return m_name; } @@ -143,12 +143,12 @@ namespace TestCaseTracking { virtual bool hasChildren() const CATCH_OVERRIDE { return !m_children.empty(); } - - + + virtual void addChild( Ptr const& child ) CATCH_OVERRIDE { m_children.push_back( child ); } - + virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE { Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) ); return( it != m_children.end() ) @@ -159,7 +159,7 @@ namespace TestCaseTracking { assert( m_parent ); // Should always be non-null except for root return *m_parent; } - + virtual void openChild() CATCH_OVERRIDE { if( m_runState != ExecutingChildren ) { m_runState = ExecutingChildren; @@ -173,22 +173,22 @@ namespace TestCaseTracking { if( m_parent ) m_parent->openChild(); } - + virtual void close() CATCH_OVERRIDE { - + // Close any still open children (e.g. generators) while( &m_ctx.currentTracker() != this ) m_ctx.currentTracker().close(); - + switch( m_runState ) { case NotStarted: case CompletedSuccessfully: case Failed: throw std::logic_error( "Illogical state" ); - + case NeedsAnotherRun: break;; - + case Executing: m_runState = CompletedSuccessfully; break; @@ -196,7 +196,7 @@ namespace TestCaseTracking { if( m_children.empty() || m_children.back()->isComplete() ) m_runState = CompletedSuccessfully; break; - + default: throw std::logic_error( "Unexpected state" ); } @@ -222,17 +222,17 @@ namespace TestCaseTracking { m_ctx.setCurrentTracker( this ); } }; - + class SectionTracker : public TrackerBase { public: SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) : TrackerBase( name, ctx, parent ) {} virtual ~SectionTracker(); - + static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) { SectionTracker* section = CATCH_NULL; - + ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( name ) ) { section = dynamic_cast( childTracker ); @@ -243,13 +243,13 @@ namespace TestCaseTracking { currentTracker.addChild( section ); } if( !ctx.completedCycle() && !section->isComplete() ) { - + section->open(); } return *section; } }; - + class IndexTracker : public TrackerBase { int m_size; int m_index; @@ -260,10 +260,10 @@ namespace TestCaseTracking { m_index( -1 ) {} virtual ~IndexTracker(); - + static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) { IndexTracker* tracker = CATCH_NULL; - + ITracker& currentTracker = ctx.currentTracker(); if( ITracker* childTracker = currentTracker.findChild( name ) ) { tracker = dynamic_cast( childTracker ); @@ -273,39 +273,39 @@ namespace TestCaseTracking { tracker = new IndexTracker( name, ctx, ¤tTracker, size ); currentTracker.addChild( tracker ); } - + if( !ctx.completedCycle() && !tracker->isComplete() ) { if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) tracker->moveNext(); tracker->open(); } - + return *tracker; } - + int index() const { return m_index; } - + void moveNext() { m_index++; m_children.clear(); } - + virtual void close() CATCH_OVERRIDE { TrackerBase::close(); if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) m_runState = Executing; } }; - + inline ITracker& TrackerContext::startRun() { m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL ); m_currentTracker = CATCH_NULL; m_runState = Executing; return *m_rootTracker; } - + } // namespace TestCaseTracking - + using TestCaseTracking::ITracker; using TestCaseTracking::TrackerContext; using TestCaseTracking::SectionTracker; diff --git a/include/internal/catch_test_spec.hpp b/include/internal/catch_test_spec.hpp index 8428b09d..7e4ea9d1 100644 --- a/include/internal/catch_test_spec.hpp +++ b/include/internal/catch_test_spec.hpp @@ -20,7 +20,7 @@ #include namespace Catch { - + class TestSpec { struct Pattern : SharedImpl<> { virtual ~Pattern(); @@ -38,7 +38,7 @@ namespace Catch { private: WildcardPattern m_wildcardPattern; }; - + class TagPattern : public Pattern { public: TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} @@ -49,7 +49,7 @@ namespace Catch { private: std::string m_tag; }; - + class ExcludedPattern : public Pattern { public: ExcludedPattern( Ptr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} diff --git a/include/internal/catch_tostring.h b/include/internal/catch_tostring.h index 91bc106a..e6f7ec9d 100644 --- a/include/internal/catch_tostring.h +++ b/include/internal/catch_tostring.h @@ -67,7 +67,7 @@ std::string toString( std::nullptr_t ); std::string toString( NSObject* const& nsObject ); #endif - + namespace Detail { extern const std::string unprintableString; @@ -78,7 +78,7 @@ namespace Detail { struct TrueType { char sizer[1]; }; struct FalseType { char sizer[2]; }; - + TrueType& testStreamable( std::ostream& ); FalseType testStreamable( FalseType ); diff --git a/include/internal/catch_tostring.hpp b/include/internal/catch_tostring.hpp index 50b587d1..0a20ee2d 100644 --- a/include/internal/catch_tostring.hpp +++ b/include/internal/catch_tostring.hpp @@ -16,7 +16,7 @@ namespace Catch { namespace Detail { const std::string unprintableString = "{?}"; - + namespace { const int hexThreshold = 255; @@ -175,7 +175,7 @@ std::string toString( unsigned long long value ) { return oss.str(); } #endif - + #ifdef CATCH_CONFIG_CPP11_NULLPTR std::string toString( std::nullptr_t ) { return "nullptr"; diff --git a/include/internal/catch_version.h b/include/internal/catch_version.h index b6a97077..1a79c5c5 100644 --- a/include/internal/catch_version.h +++ b/include/internal/catch_version.h @@ -27,7 +27,7 @@ namespace Catch { unsigned int const buildNumber; friend std::ostream& operator << ( std::ostream& os, Version const& version ); - + private: void operator=( Version const& ); }; diff --git a/include/internal/catch_wildcard_pattern.hpp b/include/internal/catch_wildcard_pattern.hpp index a5e89b6e..cd8b07e1 100644 --- a/include/internal/catch_wildcard_pattern.hpp +++ b/include/internal/catch_wildcard_pattern.hpp @@ -19,9 +19,9 @@ namespace Catch WildcardAtEnd = 2, WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd }; - + public: - + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) : m_caseSensitivity( caseSensitivity ), m_wildcard( NoWildcard ), @@ -48,7 +48,7 @@ namespace Catch case WildcardAtBothEnds: return contains( adjustCase( str ), m_pattern ); } - + #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunreachable-code" diff --git a/include/internal/catch_xmlwriter.hpp b/include/internal/catch_xmlwriter.hpp index 738415c3..c59725b0 100644 --- a/include/internal/catch_xmlwriter.hpp +++ b/include/internal/catch_xmlwriter.hpp @@ -22,23 +22,23 @@ namespace Catch { class XmlEncode { public: enum ForWhat { ForTextNodes, ForAttributes }; - + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) : m_str( str ), m_forWhat( forWhat ) {} - + void encodeTo( std::ostream& os ) const { // Apostrophe escaping not necessary if we always use " to write attributes // (see: http://www.w3.org/TR/xml/#syntax) - + for( std::size_t i = 0; i < m_str.size(); ++ i ) { char c = m_str[i]; switch( c ) { case '<': os << "<"; break; case '&': os << "&"; break; - + case '>': // See: http://www.w3.org/TR/xml/#syntax if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) @@ -46,14 +46,14 @@ namespace Catch { else os << c; break; - + case '\"': if( m_forWhat == ForAttributes ) os << """; else os << c; break; - + default: // Escape control chars - based on contribution by @espenalb in PR #465 if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) @@ -68,12 +68,12 @@ namespace Catch { xmlEncode.encodeTo( os ); return os; } - + private: std::string m_str; ForWhat m_forWhat; }; - + class XmlWriter { public: diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index e37cac00..936bc6d7 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -230,18 +230,18 @@ namespace Catch { return line; } - + struct TestEventListenerBase : StreamingReporterBase { TestEventListenerBase( ReporterConfig const& _config ) : StreamingReporterBase( _config ) {} - + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { return false; } }; - + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED diff --git a/include/reporters/catch_reporter_junit.hpp b/include/reporters/catch_reporter_junit.hpp index ae27f698..e656882f 100644 --- a/include/reporters/catch_reporter_junit.hpp +++ b/include/reporters/catch_reporter_junit.hpp @@ -104,7 +104,7 @@ namespace Catch { SectionNode const& rootSection = *testCaseNode.children.front(); std::string className = stats.testInfo.className; - + if( className.empty() ) { if( rootSection.childSections.empty() ) className = "global"; @@ -118,7 +118,7 @@ namespace Catch { std::string name = trim( sectionNode.stats.sectionInfo.name ); if( !rootName.empty() ) name = rootName + "/" + name; - + if( !sectionNode.assertions.empty() || !sectionNode.stdOut.empty() || !sectionNode.stdErr.empty() ) { @@ -187,7 +187,7 @@ namespace Catch { elementName = "internalError"; break; } - + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); xml.writeAttribute( "message", result.getExpandedExpression() ); @@ -216,7 +216,7 @@ namespace Catch { unsigned int unexpectedExceptions; }; - INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) } // end namespace Catch diff --git a/include/reporters/catch_reporter_multi.hpp b/include/reporters/catch_reporter_multi.hpp index 63d86c38..d3282666 100644 --- a/include/reporters/catch_reporter_multi.hpp +++ b/include/reporters/catch_reporter_multi.hpp @@ -15,18 +15,18 @@ namespace Catch { class MultipleReporters : public SharedImpl { typedef std::vector > Reporters; Reporters m_reporters; - + public: void add( Ptr const& reporter ) { m_reporters.push_back( reporter ); } - + public: // IStreamingReporter - + virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { return m_reporters[0]->getPreferences(); } - + virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; @@ -34,7 +34,7 @@ public: // IStreamingReporter (*it)->noMatchingTestCases( spec ); } - + virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; @@ -49,7 +49,7 @@ public: // IStreamingReporter (*it)->testGroupStarting( groupInfo ); } - + virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; @@ -64,7 +64,7 @@ public: // IStreamingReporter (*it)->sectionStarting( sectionInfo ); } - + virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; @@ -72,7 +72,7 @@ public: // IStreamingReporter (*it)->assertionStarting( assertionInfo ); } - + // The return value indicates if the messages buffer should be cleared: virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { bool clearBuffer = false; @@ -111,7 +111,7 @@ public: // IStreamingReporter (*it)->testRunEnded( testRunStats ); } - + virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); it != itEnd; @@ -122,7 +122,7 @@ public: // IStreamingReporter Ptr addReporter( Ptr const& existingReporter, Ptr const& additionalReporter ) { Ptr resultingReporter; - + if( existingReporter ) { MultipleReporters* multi = dynamic_cast( existingReporter.get() ); if( !multi ) { @@ -137,11 +137,11 @@ Ptr addReporter( Ptr const& existingRepo } else resultingReporter = additionalReporter; - + return resultingReporter; } - - + + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED diff --git a/include/reporters/catch_reporter_teamcity.hpp b/include/reporters/catch_reporter_teamcity.hpp index 2e1b008b..1e633f1d 100644 --- a/include/reporters/catch_reporter_teamcity.hpp +++ b/include/reporters/catch_reporter_teamcity.hpp @@ -24,7 +24,7 @@ #endif namespace Catch { - + struct TeamCityReporter : StreamingReporterBase { TeamCityReporter( ReporterConfig const& _config ) : StreamingReporterBase( _config ), @@ -32,7 +32,7 @@ namespace Catch { { m_reporterPrefs.shouldRedirectStdOut = true; } - + static std::string escape( std::string const& str ) { std::string escaped = str; replaceInPlace( escaped, "|", "||" ); @@ -58,9 +58,9 @@ namespace Catch { stream << " message='test skipped because it didn|'t match the test spec'"; stream << "]\n"; } - + virtual void noMatchingTestCases( std::string const& /* spec */ ) CATCH_OVERRIDE {} - + virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { StreamingReporterBase::testGroupStarting( groupInfo ); stream << "##teamcity[testSuiteStarted name='" @@ -72,21 +72,21 @@ namespace Catch { << escape( testGroupStats.groupInfo.name ) << "']\n"; } - + virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } - + virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { AssertionResult const& result = assertionStats.assertionResult; if( !result.isOk() ) { - + std::ostringstream msg; if( !m_headerPrintedForThisSection ) printSectionHeader( msg ); m_headerPrintedForThisSection = true; - + msg << result.getSourceInfo() << "\n"; - + switch( result.getResultType() ) { case ResultWas::ExpressionFailed: msg << "expression failed"; @@ -125,15 +125,15 @@ namespace Catch { it != itEnd; ++it ) msg << "\n \"" << it->message << "\""; - - + + if( result.hasExpression() ) { msg << "\n " << result.getExpressionInMacro() << "\n" "with expansion:\n" << " " << result.getExpandedExpression() << "\n"; } - + stream << "##teamcity[testFailed" << " name='" << escape( currentTestCaseInfo->name )<< "'" << " message='" << escape( msg.str() ) << "'" @@ -141,7 +141,7 @@ namespace Catch { } return true; } - + virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { m_headerPrintedForThisSection = false; StreamingReporterBase::sectionStarting( sectionInfo ); @@ -152,7 +152,7 @@ namespace Catch { stream << "##teamcity[testStarted name='" << escape( testInfo.name ) << "']\n"; } - + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { StreamingReporterBase::testCaseEnded( testCaseStats ); if( !testCaseStats.stdOut.empty() ) @@ -181,9 +181,9 @@ namespace Catch { printHeaderString( os, it->name ); os << getLineOfChars<'-'>() << "\n"; } - + SourceLineInfo lineInfo = m_sectionStack.front().lineInfo; - + if( !lineInfo.empty() ) os << lineInfo << "\n"; os << getLineOfChars<'.'>() << "\n\n"; @@ -203,15 +203,15 @@ namespace Catch { } private: bool m_headerPrintedForThisSection; - + }; - + #ifdef CATCH_IMPL TeamCityReporter::~TeamCityReporter() {} #endif - + INTERNAL_CATCH_REGISTER_REPORTER( "teamcity", TeamCityReporter ) - + } // end namespace Catch #ifdef __clang__ diff --git a/include/reporters/catch_reporter_xml.hpp b/include/reporters/catch_reporter_xml.hpp index 4268473b..bbe8780b 100644 --- a/include/reporters/catch_reporter_xml.hpp +++ b/include/reporters/catch_reporter_xml.hpp @@ -26,7 +26,7 @@ namespace Catch { } virtual ~XmlReporter() CATCH_OVERRIDE; - + static std::string getDescription() { return "Reports test results as an XML document"; } @@ -72,7 +72,7 @@ namespace Catch { virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { const AssertionResult& assertionResult = assertionStats.assertionResult; - + // Print any info messages in tags. if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { for( std::vector::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); @@ -134,10 +134,10 @@ namespace Catch { default: break; } - + if( assertionResult.hasExpression() ) m_xml.endElement(); - + return true; } @@ -176,7 +176,7 @@ namespace Catch { .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); m_xml.endElement(); } - + virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { StreamingReporterBase::testRunEnded( testRunStats ); m_xml.scopedElement( "OverallResults" ) diff --git a/projects/SelfTest/ApproxTests.cpp b/projects/SelfTest/ApproxTests.cpp index 1df76155..53656596 100644 --- a/projects/SelfTest/ApproxTests.cpp +++ b/projects/SelfTest/ApproxTests.cpp @@ -16,7 +16,7 @@ TEST_CASE ) { double d = 1.23; - + REQUIRE( d == Approx( 1.23 ) ); REQUIRE( d != Approx( 1.22 ) ); REQUIRE( d != Approx( 1.24 ) ); @@ -34,7 +34,7 @@ TEST_CASE ) { double d = 1.23; - + REQUIRE( d != Approx( 1.231 ) ); REQUIRE( d == Approx( 1.231 ).epsilon( 0.1 ) ); } @@ -71,7 +71,7 @@ TEST_CASE const double dZero = 0; const double dSmall = 0.00001; const double dMedium = 1.234; - + REQUIRE( 1.0f == Approx( 1 ) ); REQUIRE( 0 == Approx( dZero) ); REQUIRE( 0 == Approx( dSmall ).epsilon( 0.001 ) ); @@ -87,14 +87,14 @@ TEST_CASE ) { double d = 1.23; - + Approx approx = Approx::custom().epsilon( 0.005 ); - + REQUIRE( d == approx( 1.23 ) ); REQUIRE( d == approx( 1.22 ) ); REQUIRE( d == approx( 1.24 ) ); REQUIRE( d != approx( 1.25 ) ); - + REQUIRE( approx( d ) == 1.23 ); REQUIRE( approx( d ) == 1.22 ); REQUIRE( approx( d ) == 1.24 ); diff --git a/projects/SelfTest/BDDTests.cpp b/projects/SelfTest/BDDTests.cpp index 3b5c959d..2c8bc249 100644 --- a/projects/SelfTest/BDDTests.cpp +++ b/projects/SelfTest/BDDTests.cpp @@ -30,13 +30,13 @@ SCENARIO( "Vector resizing affects size and capacity", "[vector][bdd][size][capa GIVEN( "an empty vector" ) { std::vector v; REQUIRE( v.size() == 0 ); - + WHEN( "it is made larger" ) { v.resize( 10 ); THEN( "the size and capacity go up" ) { REQUIRE( v.size() == 10 ); REQUIRE( v.capacity() >= 10 ); - + AND_WHEN( "it is made smaller again" ) { v.resize( 5 ); THEN( "the size goes down but the capacity stays the same" ) { @@ -46,7 +46,7 @@ SCENARIO( "Vector resizing affects size and capacity", "[vector][bdd][size][capa } } } - + WHEN( "we reserve more space" ) { v.reserve( 10 ); THEN( "The capacity is increased but the size remains the same" ) { @@ -76,19 +76,19 @@ struct Fixture : d_counter(0) { } - + int counter() { return d_counter++; } - + int d_counter; }; - + } SCENARIO_METHOD(Fixture, - "BDD tests requiring Fixtures to provide commonly-accessed data or methods", + "BDD tests requiring Fixtures to provide commonly-accessed data or methods", "[bdd][fixtures]") { const int before(counter()); GIVEN("No operations precede me") { diff --git a/projects/SelfTest/ClassTests.cpp b/projects/SelfTest/ClassTests.cpp index e22f3d24..a4707849 100644 --- a/projects/SelfTest/ClassTests.cpp +++ b/projects/SelfTest/ClassTests.cpp @@ -13,18 +13,18 @@ namespace class TestClass { std::string s; - + public: TestClass() : s( "hello" ) {} - + void succeedingCase() - { + { REQUIRE( s == "hello" ); } void failingCase() - { + { REQUIRE( s == "world" ); } }; @@ -38,20 +38,20 @@ METHOD_AS_TEST_CASE( TestClass::failingCase, "A METHOD_AS_TEST_CASE based test r struct Fixture { Fixture() : m_a( 1 ) {} - + int m_a; }; TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that succeeds", "[class]" ) -{ - REQUIRE( m_a == 1 ); +{ + REQUIRE( m_a == 1 ); } // We should be able to write our tests within a different namespace namespace Inner { TEST_CASE_METHOD( Fixture, "A TEST_CASE_METHOD based test run that fails", "[.][class][failing]" ) - { - REQUIRE( m_a == 2 ); + { + REQUIRE( m_a == 2 ); } } diff --git a/projects/SelfTest/ConditionTests.cpp b/projects/SelfTest/ConditionTests.cpp index 195188ac..d1b7ed24 100644 --- a/projects/SelfTest/ConditionTests.cpp +++ b/projects/SelfTest/ConditionTests.cpp @@ -22,7 +22,7 @@ struct TestData { float_nine_point_one( 9.1f ), double_pi( 3.1415926535 ) {} - + int int_seven; std::string str_hello; float float_nine_point_one; @@ -37,7 +37,7 @@ struct TestDef { TestDef& operator[]( const std::string& ) { return *this; } - + }; // The "failing" tests all use the CHECK macro, which continues if the specific test fails. @@ -49,14 +49,14 @@ TEST_CASE( "Equality checks that should succeed", "" ) TestDef td; td + "hello" + "hello"; - + TestData data; - + REQUIRE( data.int_seven == 7 ); REQUIRE( data.float_nine_point_one == Approx( 9.1f ) ); REQUIRE( data.double_pi == Approx( 3.1415926535 ) ); REQUIRE( data.str_hello == "hello" ); - REQUIRE( "hello" == data.str_hello ); + REQUIRE( "hello" == data.str_hello ); REQUIRE( data.str_hello.size() == 5 ); double x = 1.1 + 0.1 + 0.1; @@ -66,7 +66,7 @@ TEST_CASE( "Equality checks that should succeed", "" ) TEST_CASE( "Equality checks that should fail", "[.][failing][!mayfail]" ) { TestData data; - + CHECK( data.int_seven == 6 ); CHECK( data.int_seven == 8 ); CHECK( data.int_seven == 0 ); @@ -87,7 +87,7 @@ TEST_CASE( "Equality checks that should fail", "[.][failing][!mayfail]" ) TEST_CASE( "Inequality checks that should succeed", "" ) { TestData data; - + REQUIRE( data.int_seven != 6 ); REQUIRE( data.int_seven != 8 ); REQUIRE( data.float_nine_point_one != Approx( 9.11f ) ); @@ -104,7 +104,7 @@ TEST_CASE( "Inequality checks that should succeed", "" ) TEST_CASE( "Inequality checks that should fail", "[.][failing]" ) { TestData data; - + CHECK( data.int_seven != 7 ); CHECK( data.float_nine_point_one != Approx( 9.1f ) ); CHECK( data.double_pi != Approx( 3.1415926535 ) ); @@ -116,7 +116,7 @@ TEST_CASE( "Inequality checks that should fail", "[.][failing]" ) TEST_CASE( "Ordering comparison checks that should succeed", "" ) { TestData data; - + REQUIRE( data.int_seven < 8 ); REQUIRE( data.int_seven > 6 ); REQUIRE( data.int_seven > 0 ); @@ -126,14 +126,14 @@ TEST_CASE( "Ordering comparison checks that should succeed", "" ) REQUIRE( data.int_seven >= 6 ); REQUIRE( data.int_seven <= 7 ); REQUIRE( data.int_seven <= 8 ); - + REQUIRE( data.float_nine_point_one > 9 ); REQUIRE( data.float_nine_point_one < 10 ); REQUIRE( data.float_nine_point_one < 9.2 ); - + REQUIRE( data.str_hello <= "hello" ); REQUIRE( data.str_hello >= "hello" ); - + REQUIRE( data.str_hello < "hellp" ); REQUIRE( data.str_hello < "zebra" ); REQUIRE( data.str_hello > "hellm" ); @@ -143,7 +143,7 @@ TEST_CASE( "Ordering comparison checks that should succeed", "" ) TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" ) { TestData data; - + CHECK( data.int_seven > 7 ); CHECK( data.int_seven < 7 ); CHECK( data.int_seven > 8 ); @@ -153,11 +153,11 @@ TEST_CASE( "Ordering comparison checks that should fail", "[.][failing]" ) CHECK( data.int_seven >= 8 ); CHECK( data.int_seven <= 6 ); - + CHECK( data.float_nine_point_one < 9 ); CHECK( data.float_nine_point_one > 10 ); CHECK( data.float_nine_point_one > 9.2 ); - + CHECK( data.str_hello > "hello" ); CHECK( data.str_hello < "hello" ); CHECK( data.str_hello > "hellp" ); @@ -178,7 +178,7 @@ TEST_CASE( "Comparisons with int literals don't warn when mixing signed/ unsigne unsigned long ul = 4; char c = 5; unsigned char uc = 6; - + REQUIRE( i == 1 ); REQUIRE( ui == 2 ); REQUIRE( l == 3 ); @@ -215,7 +215,7 @@ TEST_CASE( "comparisons between int variables", "" ) unsigned short unsigned_short_var = 1; unsigned int unsigned_int_var = 1; unsigned long unsigned_long_var = 1L; - + REQUIRE( long_var == unsigned_char_var ); REQUIRE( long_var == unsigned_short_var ); REQUIRE( long_var == unsigned_int_var ); @@ -252,7 +252,7 @@ template struct Ex { Ex( T ){} - + bool operator == ( const T& ) const { return true; } T operator * ( const T& ) const { return T(); } }; @@ -273,13 +273,13 @@ TEST_CASE( "Pointers can be compared to null", "" ) { TestData* p = CATCH_NULL; TestData* pNULL = CATCH_NULL; - + REQUIRE( p == CATCH_NULL ); REQUIRE( p == pNULL ); - + TestData data; p = &data; - + REQUIRE( p != CATCH_NULL ); const TestData* cp = p; @@ -290,7 +290,7 @@ TEST_CASE( "Pointers can be compared to null", "" ) REQUIRE( returnsNull() == CATCH_NULL ); REQUIRE( returnsConstNull() == CATCH_NULL ); - + REQUIRE( CATCH_NULL != p ); } @@ -304,7 +304,7 @@ TEST_CASE( "Pointers can be compared to null", "" ) TEST_CASE( "'Not' checks that should succeed", "" ) { bool falseValue = false; - + REQUIRE( false == false ); REQUIRE( true == true ); REQUIRE( !false ); @@ -320,15 +320,15 @@ TEST_CASE( "'Not' checks that should succeed", "" ) TEST_CASE( "'Not' checks that should fail", "[.][failing]" ) { bool trueValue = true; - + CHECK( false != false ); CHECK( true != true ); CHECK( !true ); CHECK_FALSE( true ); - + CHECK( !trueValue ); CHECK_FALSE( trueValue ); - + CHECK( !(1 == 1) ); CHECK_FALSE( 1 == 1 ); } diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index 3826c58b..eb8b7d8f 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -96,12 +96,12 @@ public: CustomException( const std::string& msg ) : m_msg( msg ) {} - + std::string getMessage() const { return m_msg; } - + private: std::string m_msg; }; diff --git a/projects/SelfTest/GeneratorTests.cpp b/projects/SelfTest/GeneratorTests.cpp index a961b698..af08b1d3 100644 --- a/projects/SelfTest/GeneratorTests.cpp +++ b/projects/SelfTest/GeneratorTests.cpp @@ -19,10 +19,10 @@ inline int multiply( int a, int b ) CATCH_TEST_CASE( "Generators over two ranges", "[generators]" ) { using namespace Catch::Generators; - + int i = CATCH_GENERATE( between( 1, 5 ).then( values( 15, 20, 21 ).then( 36 ) ) ); int j = CATCH_GENERATE( between( 100, 107 ) ); - + CATCH_REQUIRE( multiply( i, 2 ) == i*2 ); CATCH_REQUIRE( multiply( j, 2 ) == j*2 ); } @@ -32,11 +32,11 @@ struct IntPair { int first, second; }; CATCH_TEST_CASE( "Generator over a range of pairs", "[generators]" ) { using namespace Catch::Generators; - + IntPair p[] = { { 0, 1 }, { 2, 3 } }; - + IntPair* i = CATCH_GENERATE( between( p, &p[1] ) ); - + CATCH_REQUIRE( i->first == i->second-1 ); - + } diff --git a/projects/SelfTest/MessageTests.cpp b/projects/SelfTest/MessageTests.cpp index 69ef03dd..87a85a82 100644 --- a/projects/SelfTest/MessageTests.cpp +++ b/projects/SelfTest/MessageTests.cpp @@ -38,7 +38,7 @@ TEST_CASE( "INFO gets logged on failure, even if captured before successful asse CHECK( a == 2 ); INFO( "this message should be logged" ); - + CHECK( a == 1 ); INFO( "and this, but later" ); @@ -85,7 +85,7 @@ TEST_CASE( "Standard output from all sections is reported", "[messages][.]" ) { std::cout << "Message from section one" << std::endl; } - + SECTION( "two", "" ) { std::cout << "Message from section two" << std::endl; diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index e791cb10..70a6cee1 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -21,7 +21,7 @@ TEST_CASE( "random SECTION tests", "[.][sections][failing]" ) { int a = 1; int b = 2; - + SECTION( "s1", "doesn't equal" ) { REQUIRE( a != b ); @@ -38,7 +38,7 @@ TEST_CASE( "nested SECTION tests", "[.][sections][failing]" ) { int a = 1; int b = 2; - + SECTION( "s1", "doesn't equal" ) { REQUIRE( a != b ); @@ -55,7 +55,7 @@ TEST_CASE( "more nested SECTION tests", "[sections][failing][.]" ) { int a = 1; int b = 2; - + SECTION( "s1", "doesn't equal" ) { SECTION( "s2", "equal" ) @@ -82,7 +82,7 @@ TEST_CASE( "even more nested SECTION tests", "[sections]" ) { SUCCEED(""); // avoid failing due to no tests } - + SECTION( "e (leaf)", "" ) { SUCCEED(""); // avoid failing due to no tests @@ -98,14 +98,14 @@ TEST_CASE( "even more nested SECTION tests", "[sections]" ) TEST_CASE( "looped SECTION tests", "[.][failing][sections]" ) { int a = 1; - + for( int b = 0; b < 10; ++b ) { std::ostringstream oss; oss << "b is currently: " << b; SECTION( "s1", oss.str() ) { - CHECK( b > a ); + CHECK( b > a ); } } } @@ -113,18 +113,18 @@ TEST_CASE( "looped SECTION tests", "[.][failing][sections]" ) TEST_CASE( "looped tests", "[.][failing]" ) { static const int fib[] = { 1, 1, 2, 3, 5, 8, 13, 21 }; - + for( size_t i=0; i < sizeof(fib)/sizeof(int); ++i ) { INFO( "Testing if fib[" << i << "] (" << fib[i] << ") is even" ); - CHECK( ( fib[i] % 2 ) == 0 ); + CHECK( ( fib[i] % 2 ) == 0 ); } } TEST_CASE( "Sends stuff to stdout and stderr", "[.]" ) { std::cout << "A string sent directly to stdout" << std::endl; - + std::cerr << "A string sent directly to stderr" << std::endl; } @@ -162,7 +162,7 @@ inline bool testCheckedElse( bool flag ) { CHECKED_ELSE( flag ) return false; - + return true; } @@ -191,13 +191,13 @@ TEST_CASE( "xmlentitycheck", "" ) TEST_CASE( "send a single char to INFO", "[failing][.]" ) { INFO(3); - REQUIRE(false); + REQUIRE(false); } TEST_CASE( "atomic if", "[failing][0]") { size_t x = 0; - + if( x ) REQUIRE(x > 0); else @@ -211,7 +211,7 @@ inline const char* testStringForMatching() TEST_CASE("String matchers", "[matchers]" ) { - REQUIRE_THAT( testStringForMatching(), Contains( "string" ) ); + REQUIRE_THAT( testStringForMatching(), Contains( "string" ) ); CHECK_THAT( testStringForMatching(), Contains( "abc" ) ); CHECK_THAT( testStringForMatching(), StartsWith( "this" ) ); @@ -297,38 +297,38 @@ TEST_CASE( "second tag", "[tag2]" ) TEST_CASE( "vectors can be sized and resized", "[vector]" ) { std::vector v( 5 ); - + REQUIRE( v.size() == 5 ); REQUIRE( v.capacity() >= 5 ); - + SECTION( "resizing bigger changes size and capacity", "" ) { v.resize( 10 ); - + REQUIRE( v.size() == 10 ); REQUIRE( v.capacity() >= 10 ); } SECTION( "resizing smaller changes size but not capacity", "" ) { v.resize( 0 ); - + REQUIRE( v.size() == 0 ); REQUIRE( v.capacity() >= 5 ); - + SECTION( "We can use the 'swap trick' to reset the capacity", "" ) { std::vector empty; empty.swap( v ); - + REQUIRE( v.capacity() == 0 ); } } SECTION( "reserving bigger changes capacity but not size", "" ) { v.reserve( 10 ); - + REQUIRE( v.size() == 5 ); REQUIRE( v.capacity() >= 10 ); } SECTION( "reserving smaller does not change size or capacity", "" ) { v.reserve( 0 ); - + REQUIRE( v.size() == 5 ); REQUIRE( v.capacity() >= 5 ); } @@ -426,7 +426,7 @@ TEST_CASE( "XmlEncode" ) { #ifdef CATCH_CONFIG_CPP11_LONG_LONG TEST_CASE( "long long" ) { long long l = std::numeric_limits::max(); - + REQUIRE( l == std::numeric_limits::max() ); } #endif diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp index c576d53c..29256351 100644 --- a/projects/SelfTest/PartTrackerTests.cpp +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -12,13 +12,13 @@ namespace Catch { class LocalContext { - + public: TrackerContext& operator()() const { return TrackerContext::instance(); } }; - + } // namespace Catch inline Catch::TrackerContext& C_A_T_C_H_Context() { @@ -37,11 +37,11 @@ using namespace Catch; //} TEST_CASE( "Tracker", "" ) { - + TrackerContext ctx; ctx.startRun(); ctx.startCycle(); - + ITracker& testCase = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase.isOpen() ); @@ -57,13 +57,13 @@ TEST_CASE( "Tracker", "" ) { REQUIRE( ctx.completedCycle() ); REQUIRE( testCase.isSuccessfullyCompleted() ); } - + SECTION( "fail one section", "" ) { s1.fail(); REQUIRE( s1.isComplete() ); REQUIRE( s1.isSuccessfullyCompleted() == false ); REQUIRE( testCase.isComplete() == false ); - + testCase.close(); REQUIRE( ctx.completedCycle() ); REQUIRE( testCase.isSuccessfullyCompleted() == false ); @@ -72,10 +72,10 @@ TEST_CASE( "Tracker", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() == false ); - + testCase2.close(); REQUIRE( ctx.completedCycle() ); REQUIRE( testCase.isComplete() ); @@ -85,7 +85,7 @@ TEST_CASE( "Tracker", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() == false ); @@ -94,19 +94,19 @@ TEST_CASE( "Tracker", "" ) { s2.close(); REQUIRE( ctx.completedCycle() ); - + testCase2.close(); REQUIRE( testCase.isComplete() ); REQUIRE( testCase.isSuccessfullyCompleted() ); } } - + SECTION( "successfully close one section, then find another", "" ) { s1.close(); - + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() == false ); - + testCase.close(); REQUIRE( testCase.isComplete() == false ); @@ -114,7 +114,7 @@ TEST_CASE( "Tracker", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() == false ); @@ -122,14 +122,14 @@ TEST_CASE( "Tracker", "" ) { REQUIRE( s2b.isOpen() ); REQUIRE( ctx.completedCycle() == false ); - + SECTION ("Successfully close S2") { s2b.close(); REQUIRE( ctx.completedCycle() ); REQUIRE( s2b.isSuccessfullyCompleted() ); REQUIRE( testCase2.isComplete() == false ); - + testCase2.close(); REQUIRE( testCase2.isSuccessfullyCompleted() ); } @@ -139,7 +139,7 @@ TEST_CASE( "Tracker", "" ) { REQUIRE( s2b.isComplete() ); REQUIRE( s2b.isSuccessfullyCompleted() == false ); - + testCase2.close(); REQUIRE( testCase2.isSuccessfullyCompleted() == false ); @@ -147,19 +147,19 @@ TEST_CASE( "Tracker", "" ) { ctx.startCycle(); ITracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase3.isOpen() ); - + ITracker& s1c = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1c.isOpen() == false ); - + ITracker& s2c = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2c.isOpen() == false ); - + testCase3.close(); REQUIRE( testCase3.isSuccessfullyCompleted() ); } } } - + SECTION( "open a nested section", "" ) { ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); @@ -167,15 +167,15 @@ TEST_CASE( "Tracker", "" ) { s2.close(); REQUIRE( s2.isComplete() ); REQUIRE( s1.isComplete() == false ); - + s1.close(); REQUIRE( s1.isComplete() ); REQUIRE( testCase.isComplete() == false ); - + testCase.close(); REQUIRE( testCase.isComplete() ); } - + SECTION( "start a generator", "" ) { IndexTracker& g1 = IndexTracker::acquire( ctx, "G1", 2 ); REQUIRE( g1.isOpen() ); @@ -195,17 +195,17 @@ TEST_CASE( "Tracker", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() ); - - + + IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); REQUIRE( g1b.isOpen() ); REQUIRE( g1b.index() == 1 ); - + REQUIRE( s1.isComplete() == false ); - + s1b.close(); REQUIRE( s1b.isComplete() ); REQUIRE( g1b.isComplete() ); @@ -225,98 +225,98 @@ TEST_CASE( "Tracker", "" ) { testCase.close(); REQUIRE( testCase.isComplete() == false ); - + SECTION( "Re-enter for second generation", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() ); - + // generator - next value IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); REQUIRE( g1b.isOpen() ); REQUIRE( g1b.index() == 1 ); - + // inner section again ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2b.isOpen() ); - + s2b.close(); REQUIRE( s2b.isComplete() ); - + s1b.close(); REQUIRE( g1b.isComplete() ); REQUIRE( s1b.isComplete() ); - + testCase2.close(); REQUIRE( testCase2.isComplete() ); } } - + SECTION( "Fail an inner section", "" ) { ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2.isOpen() ); - + s2.fail(); REQUIRE( s2.isComplete() ); REQUIRE( s2.isSuccessfullyCompleted() == false ); - + s1.close(); REQUIRE( s1.isComplete() == false ); - + testCase.close(); REQUIRE( testCase.isComplete() == false ); - + SECTION( "Re-enter for second generation", "" ) { ctx.startCycle(); ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase2.isOpen() ); - + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1b.isOpen() ); - + // generator - still same value IndexTracker& g1b = IndexTracker::acquire( ctx, "G1", 2 ); REQUIRE( g1b.isOpen() ); REQUIRE( g1b.index() == 0 ); - + // inner section again - this time won't open ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2b.isOpen() == false ); - + s1b.close(); REQUIRE( g1b.isComplete() == false ); REQUIRE( s1b.isComplete() == false ); - + testCase2.close(); REQUIRE( testCase2.isComplete() == false ); - + // Another cycle - now should complete ctx.startCycle(); ITracker& testCase3 = SectionTracker::acquire( ctx, "Testcase" ); REQUIRE( testCase3.isOpen() ); - + ITracker& s1c = SectionTracker::acquire( ctx, "S1" ); REQUIRE( s1c.isOpen() ); - + // generator - now next value IndexTracker& g1c = IndexTracker::acquire( ctx, "G1", 2 ); REQUIRE( g1c.isOpen() ); REQUIRE( g1c.index() == 1 ); - + // inner section - now should open again ITracker& s2c = SectionTracker::acquire( ctx, "S2" ); REQUIRE( s2c.isOpen() ); - + s2c.close(); REQUIRE( s2c.isComplete() ); - + s1c.close(); REQUIRE( g1c.isComplete() ); REQUIRE( s1c.isComplete() ); - + testCase3.close(); REQUIRE( testCase3.isComplete() ); } diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index f4c660d6..f8d17fdd 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -49,13 +49,13 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" SECTION( "default - no arguments", "" ) { const char* argv[] = { "test" }; CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - + CHECK( config.shouldDebugBreak == false ); CHECK( config.abortAfter == -1 ); CHECK( config.noThrow == false ); CHECK( config.reporterNames.empty() ); } - + SECTION( "test lists", "" ) { SECTION( "1 test", "Specify one test case using" ) { const char* argv[] = { "test", "test1" }; @@ -84,24 +84,24 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" } } - + SECTION( "reporter", "" ) { SECTION( "-r/console", "" ) { const char* argv[] = { "test", "-r", "console" }; CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - + REQUIRE( config.reporterNames[0] == "console" ); } SECTION( "-r/xml", "" ) { const char* argv[] = { "test", "-r", "xml" }; CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - + REQUIRE( config.reporterNames[0] == "xml" ); } SECTION( "-r xml and junit", "" ) { const char* argv[] = { "test", "-r", "xml", "-r", "junit" }; CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - + REQUIRE( config.reporterNames.size() == 2 ); REQUIRE( config.reporterNames[0] == "xml" ); REQUIRE( config.reporterNames[1] == "junit" ); @@ -109,26 +109,26 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" SECTION( "--reporter/junit", "" ) { const char* argv[] = { "test", "--reporter", "junit" }; CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - + REQUIRE( config.reporterNames[0] == "junit" ); } } - + SECTION( "debugger", "" ) { SECTION( "-b", "" ) { const char* argv[] = { "test", "-b" }; CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - + REQUIRE( config.shouldDebugBreak == true ); } SECTION( "--break", "" ) { const char* argv[] = { "test", "--break" }; CHECK_NOTHROW( parseIntoConfig( argv, config ) ); - + REQUIRE( config.shouldDebugBreak ); } } - + SECTION( "abort", "" ) { SECTION( "-a aborts after first failure", "" ) { const char* argv[] = { "test", "-a" }; @@ -151,7 +151,7 @@ TEST_CASE( "Process can be configured on command line", "[config][command-line]" REQUIRE_THAT( parseIntoConfigAndReturnError( argv, config ), Contains( "-x" ) ); } } - + SECTION( "nothrow", "" ) { SECTION( "-e", "" ) { const char* argv[] = { "test", "-e" }; @@ -217,7 +217,7 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) { SECTION( "plain string", "" ) { // guide: 123456789012345678 std::string testString = "one two three four"; - + SECTION( "No wrapping", "" ) { CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); @@ -261,14 +261,14 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) { .setInitialIndent( 1 ) ); CHECK( text.toString() == " one two\n three\n four" ); } - + } - + SECTION( "With newlines", "" ) { - + // guide: 1234567890123456789 std::string testString = "one two\nthree four"; - + SECTION( "No wrapping" , "" ) { CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); @@ -288,17 +288,17 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) { CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ); } } - + SECTION( "With tabs", "" ) { // guide: 1234567890123456789 std::string testString = "one two \tthree four five six"; - + CHECK( Text( testString, TextAttributes().setWidth( 15 ) ).toString() == "one two three\n four\n five\n six" ); } - - + + } using namespace Catch; @@ -324,7 +324,7 @@ public: ColourString( std::string const& _string, std::vector const& _colours ) : string( _string ), colours( _colours ) {} - + ColourString& addColour( Colour::Code colour, int _index ) { colours.push_back( ColourIndex( colour, resolveRelativeIndex( _index ), @@ -337,7 +337,7 @@ public: resolveLastRelativeIndex( _toIndex ) ) ); return *this; } - + void writeToStream( std::ostream& _stream ) const { std::size_t last = 0; for( std::size_t i = 0; i < colours.size(); ++i ) { @@ -351,7 +351,7 @@ public: last = index.toIndex; } if( last < string.size() ) - _stream << string.substr( last ); + _stream << string.substr( last ); } friend std::ostream& operator << ( std::ostream& _stream, ColourString const& _colourString ) { _colourString.writeToStream( _stream ); @@ -408,7 +408,7 @@ TEST_CASE( "replaceInPlace", "" ) { // !TBD: This will be folded into Text class TEST_CASE( "Strings can be rendered with colour", "[.colour]" ) { - + { ColourString cs( "hello" ); cs .addColour( Colour::Red, 0 ) @@ -420,19 +420,19 @@ TEST_CASE( "Strings can be rendered with colour", "[.colour]" ) { { ColourString cs( "hello" ); cs .addColour( Colour::Blue, 1, -2 ); - + Catch::cout() << cs << std::endl; } - + } TEST_CASE( "Text can be formatted using the Text class", "" ) { - + CHECK( Text( "hi there" ).toString() == "hi there" ); - + TextAttributes narrow; narrow.setWidth( 6 ); - + CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" ); } @@ -445,5 +445,5 @@ TEST_CASE( "Long text is truncted", "[Text][Truncated]" ) { oss << longLine << longLine << "\n"; Text t( oss.str() ); CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ); - + } diff --git a/projects/SelfTest/TrickyTests.cpp b/projects/SelfTest/TrickyTests.cpp index 95612022..eb53e420 100644 --- a/projects/SelfTest/TrickyTests.cpp +++ b/projects/SelfTest/TrickyTests.cpp @@ -25,7 +25,7 @@ namespace Catch std::ostringstream oss; oss << "std::pair( " << value.first << ", " << value.second << " )"; return oss.str(); - + } } @@ -38,7 +38,7 @@ TEST_CASE { std::pair aNicePair( 1, 2 ); - REQUIRE( (std::pair( 1, 2 )) == aNicePair ); + REQUIRE( (std::pair( 1, 2 )) == aNicePair ); } /////////////////////////////////////////////////////////////////////////////// @@ -62,7 +62,7 @@ TEST_CASE /* int a = 1; int b = 2; - + // This only captures part of the expression, but issues a warning about the rest REQUIRE( a+1 == b-1 ); */ @@ -85,38 +85,38 @@ TEST_CASE "[Tricky][failing][.]" ) { - + Opaque o1, o2; o1.val = 7; o2.val = 8; - + CHECK( &o1 == &o2 ); CHECK( o1 == o2 ); } /////////////////////////////////////////////////////////////////////////////// TEST_CASE -( +( "string literals of different sizes can be compared", "[Tricky][failing][.]" ) { REQUIRE( std::string( "first" ) == "second" ); - + } /////////////////////////////////////////////////////////////////////////////// TEST_CASE -( +( "An expression with side-effects should only be evaluated once", "[Tricky]" ) { int i = 7; - + REQUIRE( i++ == 7 ); REQUIRE( i++ == 8 ); - + } namespace A { @@ -167,8 +167,8 @@ TEST_CASE */ namespace ObjectWithConversions -{ - struct Object +{ + struct Object { operator unsigned int() {return 0xc0000000;} }; @@ -179,31 +179,31 @@ namespace ObjectWithConversions "Operators at different namespace levels not hijacked by Koenig lookup", "[Tricky]" ) - { + { Object o; REQUIRE(0xc0000000 == o ); } } -namespace ObjectWithNonConstEqualityOperator +namespace ObjectWithNonConstEqualityOperator { struct Test { Test( unsigned int v ) - : m_value(v) + : m_value(v) {} - + bool operator==( const Test&rhs ) - { + { return (m_value == rhs.m_value); } bool operator==( const Test&rhs ) const - { + { return (m_value != rhs.m_value); } unsigned int m_value; }; - + TEST_CASE("Demonstrate that a non-const == is not used", "[Tricky]" ) { Test t( 1 ); @@ -226,7 +226,7 @@ namespace EnumBitFieldTests struct Obj { Obj():prop(&p){} - + int p; int* prop; }; @@ -284,11 +284,11 @@ TEST_CASE( "(unimplemented) static bools can be evaluated", "[Tricky]" ) /* TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) { - + } TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) { - + } */ @@ -317,13 +317,13 @@ TEST_CASE( "Assertions then sections", "[Tricky]" ) { // This was causing a failure due to the way the console reporter was handling // the current section - + REQUIRE( Catch::alwaysTrue() ); - + SECTION( "A section", "" ) { REQUIRE( Catch::alwaysTrue() ); - + SECTION( "Another section", "" ) { REQUIRE( Catch::alwaysTrue() ); diff --git a/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h b/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h index a98b45d5..522291a9 100644 --- a/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h +++ b/projects/runners/iTchRunner/internal/iTchRunnerAppDelegate.h @@ -13,7 +13,7 @@ -@interface iTchRunnerAppDelegate : NSObject +@interface iTchRunnerAppDelegate : NSObject { UIWindow *window; } @@ -25,15 +25,15 @@ /////////////////////////////////////////////////////////////////////////////// -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions -{ +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; [window setUserInteractionEnabled:YES]; [window setMultipleTouchEnabled:YES]; - + CGRect screenRect = [[UIScreen mainScreen] applicationFrame]; iTchRunnerMainView* view = [[iTchRunnerMainView alloc] initWithFrame:screenRect]; - + [window addSubview:view]; [window makeKeyAndVisible]; arcSafeRelease( view ); @@ -42,7 +42,7 @@ } /////////////////////////////////////////////////////////////////////////////// -- (void)dealloc +- (void)dealloc { #if !CATCH_ARC_ENABLED [window release]; @@ -52,7 +52,7 @@ /////////////////////////////////////////////////////////////////////////////// -- (void)applicationWillResignActive:(UIApplication *)application +- (void)applicationWillResignActive:(UIApplication *)application { /* Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. @@ -62,17 +62,17 @@ /////////////////////////////////////////////////////////////////////////////// -- (void)applicationDidEnterBackground:(UIApplication *)application +- (void)applicationDidEnterBackground:(UIApplication *)application { /* - Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. If your application supports background execution, called instead of applicationWillTerminate: when the user quits. */ } /////////////////////////////////////////////////////////////////////////////// -- (void)applicationWillEnterForeground:(UIApplication *)application +- (void)applicationWillEnterForeground:(UIApplication *)application { /* Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. @@ -81,7 +81,7 @@ /////////////////////////////////////////////////////////////////////////////// -- (void)applicationDidBecomeActive:(UIApplication *)application +- (void)applicationDidBecomeActive:(UIApplication *)application { /* Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. @@ -90,7 +90,7 @@ /////////////////////////////////////////////////////////////////////////////// -- (void)applicationWillTerminate:(UIApplication *)application +- (void)applicationWillTerminate:(UIApplication *)application { /* Called when the application is about to terminate. @@ -100,7 +100,7 @@ /////////////////////////////////////////////////////////////////////////////// -- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application +- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { /* Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. diff --git a/projects/runners/iTchRunner/internal/iTchRunnerMainView.h b/projects/runners/iTchRunner/internal/iTchRunnerMainView.h index ee78004c..c6a6394e 100644 --- a/projects/runners/iTchRunner/internal/iTchRunnerMainView.h +++ b/projects/runners/iTchRunner/internal/iTchRunnerMainView.h @@ -33,7 +33,7 @@ /////////////////////////////////////////////////////////////////////////////// -(id) initWithFrame:(CGRect)frame { - if ((self = [super initWithFrame:frame])) + if ((self = [super initWithFrame:frame])) { // Initialization code self.backgroundColor = [UIColor blackColor]; @@ -64,7 +64,7 @@ /////////////////////////////////////////////////////////////////////////////// -(void) showAlert -{ +{ UIActionSheet* menu = [[UIActionSheet alloc] initWithTitle:@"Options" delegate:self cancelButtonTitle:nil @@ -72,7 +72,7 @@ otherButtonTitles:@"Run all tests", nil]; [menu showInView: self]; arcSafeRelease( menu ); - + } // This is a copy & paste from Catch::Runner2 to get us bootstrapped (this is due to all be @@ -144,7 +144,7 @@ inline Catch::Totals runTestsForGroup( Catch::RunContext& context, const Catch:: { const Catch::AssertionResult& resultInfo = *pResultInfo; std::ostringstream oss; - + if( resultInfo.hasExpression() ) { oss << resultInfo.getExpression(); @@ -174,7 +174,7 @@ inline Catch::Totals runTestsForGroup( Catch::RunContext& context, const Catch:: default: break; } - + if( resultInfo.hasExpression() ) { oss << " for: " << resultInfo.getExpandedExpression(); diff --git a/projects/runners/iTchRunner/internal/iTchRunnerReporter.h b/projects/runners/iTchRunner/internal/iTchRunnerReporter.h index a7adf866..d2628861 100644 --- a/projects/runners/iTchRunner/internal/iTchRunnerReporter.h +++ b/projects/runners/iTchRunner/internal/iTchRunnerReporter.h @@ -13,7 +13,7 @@ @protocol iTchRunnerDelegate --(void) testWasRun: (const Catch::AssertionResult*) result; +-(void) testWasRun: (const Catch::AssertionResult*) result; @end @@ -38,14 +38,14 @@ namespace Catch { return true; } - + /////////////////////////////////////////////////////////////////////////// static std::string getDescription () { return "Captures results for iOS runner"; } - + /////////////////////////////////////////////////////////////////////////// size_t getSucceeded () @@ -53,7 +53,7 @@ namespace Catch { return m_totals.assertions.passed; } - + /////////////////////////////////////////////////////////////////////////// size_t getFailed () @@ -61,20 +61,20 @@ namespace Catch { return m_totals.assertions.failed; } - + /////////////////////////////////////////////////////////////////////////// void reset() { m_totals = Totals(); } - + private: // IReporter - + /////////////////////////////////////////////////////////////////////////// virtual void StartTesting () {} - + /////////////////////////////////////////////////////////////////////////// virtual void EndTesting ( @@ -83,7 +83,7 @@ namespace Catch { m_totals = totals; } - + /////////////////////////////////////////////////////////////////////////// virtual void Result ( @@ -92,7 +92,7 @@ namespace Catch { [m_delegate testWasRun: &result]; } - + /////////////////////////////////////////////////////////////////////////// // Deliberately unimplemented: virtual void StartGroup( const std::string& ){} @@ -107,7 +107,7 @@ namespace Catch private: Totals m_totals; - + id m_delegate; }; } From 9576ad910856d513dc155e71e950fdd2b9a7b194 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 4 Nov 2015 18:11:54 +0000 Subject: [PATCH 74/87] Removed unused parameter - as per PR #530 --- include/reporters/catch_reporter_bases.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp index 936bc6d7..4fdeb195 100644 --- a/include/reporters/catch_reporter_bases.hpp +++ b/include/reporters/catch_reporter_bases.hpp @@ -237,7 +237,7 @@ namespace Catch { {} virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { return false; } }; From 315c83ad87d3ef8fce2a4bd3e5d77866ba2b7c78 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 4 Nov 2015 18:49:19 +0000 Subject: [PATCH 75/87] Removed unnecessary parentheses --- scripts/fixTrailingWhitespace.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/fixTrailingWhitespace.py b/scripts/fixTrailingWhitespace.py index 0ffe8e91..a1b6bbe8 100644 --- a/scripts/fixTrailingWhitespace.py +++ b/scripts/fixTrailingWhitespace.py @@ -11,7 +11,7 @@ def fixAllFilesInDir( dir ): for f in os.listdir( dir ): path = os.path.join( dir,f ) if os.path.isfile( path ): - if( isSourceFile( path ) ): + if isSourceFile( path ): fixFile( path ) else: fixAllFilesInDir( path ) From f3e7722cc604793f6d07eee1afa912f3e095a6f7 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 5 Nov 2015 18:10:33 +0000 Subject: [PATCH 76/87] Don't introduce Catch::Matchers namespace in macro - this could be a breaking change - fixed up self-test code to compensate --- include/internal/catch_capture.hpp | 4 ++-- projects/SelfTest/MiscTests.cpp | 1 + projects/SelfTest/TagAliasTests.cpp | 2 ++ projects/SelfTest/TestMain.cpp | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index 544fc120..22cf6959 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -131,12 +131,12 @@ do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ try { \ - std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \ + std::string matcherAsString = (matcher).toString(); \ __catchResult \ .setLhs( Catch::toString( arg ) ) \ .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ .setOp( "matches" ) \ - .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ + .setResultType( (matcher).match( arg ) ); \ __catchResult.captureExpression(); \ } catch( ... ) { \ __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 70a6cee1..8bd271c4 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -208,6 +208,7 @@ inline const char* testStringForMatching() { return "this string contains 'abc' as a substring"; } +using namespace Catch::Matchers; TEST_CASE("String matchers", "[matchers]" ) { diff --git a/projects/SelfTest/TagAliasTests.cpp b/projects/SelfTest/TagAliasTests.cpp index b95ad009..002a93c0 100644 --- a/projects/SelfTest/TagAliasTests.cpp +++ b/projects/SelfTest/TagAliasTests.cpp @@ -11,6 +11,8 @@ TEST_CASE( "Tag alias can be registered against tag patterns", "" ) { + using namespace Catch::Matchers; + Catch::TagAliasRegistry registry; registry.add( "[@zzz]", "[one][two]", Catch::SourceLineInfo( "file", 2 ) ); diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index f8d17fdd..bffc7e77 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -44,6 +44,8 @@ inline Catch::TestCase fakeTestCase( const char* name, const char* desc = "" ){ TEST_CASE( "Process can be configured on command line", "[config][command-line]" ) { + using namespace Catch::Matchers; + Catch::ConfigData config; SECTION( "default - no arguments", "" ) { From 054e3c5b4319ee21b7160736d0bdde2df438ad5f Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 5 Nov 2015 18:46:00 +0000 Subject: [PATCH 77/87] Added &&, || and ! operator overloads for matchers (syntactic sugar for AllOf, AnyOf and Not compositional matchers, respectively) --- include/internal/catch_matchers.hpp | 47 +++++++++- .../Baselines/console.std.approved.txt | 27 +++++- .../Baselines/console.sw.approved.txt | 85 ++++++++++++++++++- .../SelfTest/Baselines/junit.sw.approved.txt | 16 +++- .../SelfTest/Baselines/xml.sw.approved.txt | 78 ++++++++++++++++- projects/SelfTest/MiscTests.cpp | 41 +++++++++ 6 files changed, 286 insertions(+), 8 deletions(-) diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index fd9dfd2b..14249ebf 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -12,6 +12,12 @@ namespace Catch { namespace Matchers { namespace Impl { + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + template struct Matcher : SharedImpl { @@ -21,6 +27,10 @@ namespace Matchers { virtual Ptr clone() const = 0; virtual bool match( ExpressionT const& expr ) const = 0; virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; }; template @@ -34,7 +44,7 @@ namespace Matchers { namespace Generic { template struct Not : public MatcherImpl, ExpressionT> { - Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} Not( Not const& other ) : m_matcher( other.m_matcher ) {} virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { @@ -78,6 +88,12 @@ namespace Matchers { return oss.str(); } + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + private: std::vector > > m_matchers; }; @@ -112,11 +128,40 @@ namespace Matchers { return oss.str(); } + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + private: std::vector > > m_matchers; }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; } + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); + } + + namespace StdString { inline std::string makeString( std::string const& str ) { return str; } diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index c222e306..73cef33c 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -707,6 +707,29 @@ MiscTests.cpp:: FAILED: with expansion: "this string contains 'abc' as a substring" equals: "something else" +------------------------------------------------------------------------------- +Matchers can be composed with both + and | - failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching() ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator - failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching() !Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "substring" + ------------------------------------------------------------------------------- Nice descriptive name ------------------------------------------------------------------------------- @@ -797,6 +820,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 159 | 119 passed | 39 failed | 1 failed as expected -assertions: 905 | 812 passed | 80 failed | 13 failed as expected +test cases: 165 | 123 passed | 41 failed | 1 failed as expected +assertions: 912 | 817 passed | 82 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 981fce15..082fa32d 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -3418,6 +3418,87 @@ with expansion: "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" +------------------------------------------------------------------------------- +Matchers can be (AllOf) composed with the + operator +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching() Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" and + contains: "abc" and contains: "substring" and contains: "contains" ) + +------------------------------------------------------------------------------- +Matchers can be (AnyOf) composed with the | operator +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching() Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( contains: "string" or contains: + "different" or contains: "random" ) + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching2() Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ) +with expansion: + "some completely different text that contains one common word" ( contains: + "string" or contains: "different" or contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be composed with both + and | +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching() ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "substring" ) + +------------------------------------------------------------------------------- +Matchers can be composed with both + and | - failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching() ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ) +with expansion: + "this string contains 'abc' as a substring" ( ( contains: "string" or + contains: "different" ) and contains: "random" ) + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + CHECK_THAT( testStringForMatching() !Contains( "different" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "different" + +------------------------------------------------------------------------------- +Matchers can be negated (Not) with the ! operator - failing +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: FAILED: + CHECK_THAT( testStringForMatching() !Contains( "substring" ) ) +with expansion: + "this string contains 'abc' as a substring" not contains: "substring" + ------------------------------------------------------------------------------- Factorials are computed ------------------------------------------------------------------------------- @@ -8943,6 +9024,6 @@ with expansion: 1 > 0 =============================================================================== -test cases: 159 | 118 passed | 40 failed | 1 failed as expected -assertions: 907 | 812 passed | 82 failed | 13 failed as expected +test cases: 165 | 122 passed | 42 failed | 1 failed as expected +assertions: 914 | 817 passed | 84 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 0766b19e..039aeaae 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -438,6 +438,20 @@ MiscTests.cpp: + + + + + +MiscTests.cpp: + + + + + +MiscTests.cpp: + + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 1bb662f2..ed4ce494 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -3590,6 +3590,80 @@ + + + + testStringForMatching() Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) + + + "this string contains 'abc' as a substring" ( contains: "string" and contains: "abc" and contains: "substring" and contains: "contains" ) + + + + + + + + testStringForMatching() Contains( "string" ) || Contains( "different" ) || Contains( "random" ) + + + "this string contains 'abc' as a substring" ( contains: "string" or contains: "different" or contains: "random" ) + + + + + testStringForMatching2() Contains( "string" ) || Contains( "different" ) || Contains( "random" ) + + + "some completely different text that contains one common word" ( contains: "string" or contains: "different" or contains: "random" ) + + + + + + + + testStringForMatching() ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) + + + "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "substring" ) + + + + + + + + testStringForMatching() ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) + + + "this string contains 'abc' as a substring" ( ( contains: "string" or contains: "different" ) and contains: "random" ) + + + + + + + + testStringForMatching() !Contains( "different" ) + + + "this string contains 'abc' as a substring" not contains: "different" + + + + + + + + testStringForMatching() !Contains( "substring" ) + + + "this string contains 'abc' as a substring" not contains: "substring" + + + + @@ -9422,7 +9496,7 @@ there"
- + - + diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index 8bd271c4..c2a7784c 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -208,6 +208,11 @@ inline const char* testStringForMatching() { return "this string contains 'abc' as a substring"; } +inline const char* testStringForMatching2() +{ + return "some completely different text that contains one common word"; +} + using namespace Catch::Matchers; TEST_CASE("String matchers", "[matchers]" ) @@ -257,6 +262,42 @@ TEST_CASE("Equals", "[matchers]") CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) ); } +TEST_CASE("Matchers can be (AllOf) composed with the + operator", "[matchers][operators][operator+]") +{ + CHECK_THAT( testStringForMatching(), + Contains( "string" ) && + Contains( "abc" ) && + Contains( "substring" ) && + Contains( "contains" ) ); +} + +TEST_CASE("Matchers can be (AnyOf) composed with the | operator", "[matchers][operators][operator|]") +{ + CHECK_THAT( testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ); + CHECK_THAT( testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ); +} + +TEST_CASE("Matchers can be composed with both + and |", "[matchers][operators][operator|][operator+]") +{ + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) ); +} + +TEST_CASE("Matchers can be composed with both + and | - failing", "[matchers][operators][operator|][operator+][.failing]") +{ + CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ); +} + +TEST_CASE("Matchers can be negated (Not) with the ! operator", "[matchers][operators][not]") +{ + CHECK_THAT( testStringForMatching(), !Contains( "different" ) ); +} + +TEST_CASE("Matchers can be negated (Not) with the ! operator - failing", "[matchers][operators][not][.failing]") +{ + CHECK_THAT( testStringForMatching(), !Contains( "substring" ) ); +} + + inline unsigned int Factorial( unsigned int number ) { // return number <= 1 ? number : Factorial(number-1)*number; From 08844e7e57fe9c604579962ab3848a4b9a820b2d Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Thu, 5 Nov 2015 18:52:18 +0000 Subject: [PATCH 78/87] build 1.3.0-develop.1 I've incremented the minor release number. This is a slight abuse of semantic versioning so let me explain: I've slightly changed how matchers are used. The matcher macro (REQUIRE_THAT/ CHECK_THAT) used to introduce the Catch::Matchers namespace before the macro token for the matcher, to save you having import the namespace yourself. The trouble is if the matcher token is not a simple matcher (can now be an expression) this breaks! So I've removed that qualification. Now if you use Matchers you'll have to do somethings like using namespace Catch::Matchers to bring them in. This is a breaking change - but, OTTOH, Matchers are an undocumented "beta' feature that I've stated in the past is not guaranteed to have a stable API - so I don't think this warrants a major version change - but I did want to make it significant enough that people do notice that something is going on - and perhaps lead them to this commit message. --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 58 ++++++++++++++++++++++++++---- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index e2c2a39f..8aa1cf2d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.2.1-develop.16* +*v1.3.0-develop.1* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 3df960da..30540c82 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 16 ); + Version libraryVersion( 1, 3, 0, "develop", 1 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index c0c9db16..f50973a1 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.2.1-develop.16 - * Generated: 2015-11-03 17:37:18.144715 + * Catch v1.3.0-develop.1 + * Generated: 2015-11-05 18:47:08.462966 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -831,6 +831,12 @@ namespace Catch { namespace Matchers { namespace Impl { + namespace Generic { + template class AllOf; + template class AnyOf; + template class Not; + } + template struct Matcher : SharedImpl { @@ -840,6 +846,10 @@ namespace Matchers { virtual Ptr clone() const = 0; virtual bool match( ExpressionT const& expr ) const = 0; virtual std::string toString() const = 0; + + Generic::AllOf operator && ( Matcher const& other ) const; + Generic::AnyOf operator || ( Matcher const& other ) const; + Generic::Not operator ! () const; }; template @@ -853,7 +863,7 @@ namespace Matchers { namespace Generic { template struct Not : public MatcherImpl, ExpressionT> { - Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} + explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} Not( Not const& other ) : m_matcher( other.m_matcher ) {} virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE { @@ -897,6 +907,12 @@ namespace Matchers { return oss.str(); } + AllOf operator && ( Matcher const& other ) const { + AllOf allOfExpr( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + private: std::vector > > m_matchers; }; @@ -931,9 +947,37 @@ namespace Matchers { return oss.str(); } + AnyOf operator || ( Matcher const& other ) const { + AnyOf anyOfExpr( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + private: std::vector > > m_matchers; }; + + } // namespace Generic + + template + Generic::AllOf Matcher::operator && ( Matcher const& other ) const { + Generic::AllOf allOfExpr; + allOfExpr.add( *this ); + allOfExpr.add( other ); + return allOfExpr; + } + + template + Generic::AnyOf Matcher::operator || ( Matcher const& other ) const { + Generic::AnyOf anyOfExpr; + anyOfExpr.add( *this ); + anyOfExpr.add( other ); + return anyOfExpr; + } + + template + Generic::Not Matcher::operator ! () const { + return Generic::Not( *this ); } namespace StdString { @@ -2055,12 +2099,12 @@ namespace Catch { do { \ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \ try { \ - std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \ + std::string matcherAsString = (matcher).toString(); \ __catchResult \ .setLhs( Catch::toString( arg ) ) \ .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \ .setOp( "matches" ) \ - .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ + .setResultType( (matcher).match( arg ) ); \ __catchResult.captureExpression(); \ } catch( ... ) { \ __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ @@ -7194,7 +7238,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 2, 1, "develop", 16 ); + Version libraryVersion( 1, 3, 0, "develop", 1 ); } @@ -8429,7 +8473,7 @@ namespace Catch { {} virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} - virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { + virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { return false; } }; From 71fd2c2fdf3297b785fee4f3dead7b7412a2eac2 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 6 Nov 2015 06:54:15 +0000 Subject: [PATCH 79/87] Fixed test names mentioning the new Matcher combinator operators --- projects/SelfTest/Baselines/console.std.approved.txt | 2 +- projects/SelfTest/Baselines/console.sw.approved.txt | 8 ++++---- projects/SelfTest/Baselines/junit.sw.approved.txt | 8 ++++---- projects/SelfTest/Baselines/xml.sw.approved.txt | 8 ++++---- projects/SelfTest/MiscTests.cpp | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 73cef33c..2b312e67 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -708,7 +708,7 @@ with expansion: "this string contains 'abc' as a substring" equals: "something else" ------------------------------------------------------------------------------- -Matchers can be composed with both + and | - failing +Matchers can be composed with both && and || - failing ------------------------------------------------------------------------------- MiscTests.cpp: ............................................................................... diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 082fa32d..edfedded 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -3419,7 +3419,7 @@ with expansion: 'abc' as a substring" ------------------------------------------------------------------------------- -Matchers can be (AllOf) composed with the + operator +Matchers can be (AllOf) composed with the && operator ------------------------------------------------------------------------------- MiscTests.cpp: ............................................................................... @@ -3432,7 +3432,7 @@ with expansion: contains: "abc" and contains: "substring" and contains: "contains" ) ------------------------------------------------------------------------------- -Matchers can be (AnyOf) composed with the | operator +Matchers can be (AnyOf) composed with the || operator ------------------------------------------------------------------------------- MiscTests.cpp: ............................................................................... @@ -3452,7 +3452,7 @@ with expansion: "string" or contains: "different" or contains: "random" ) ------------------------------------------------------------------------------- -Matchers can be composed with both + and | +Matchers can be composed with both && and || ------------------------------------------------------------------------------- MiscTests.cpp: ............................................................................... @@ -3465,7 +3465,7 @@ with expansion: contains: "different" ) and contains: "substring" ) ------------------------------------------------------------------------------- -Matchers can be composed with both + and | - failing +Matchers can be composed with both && and || - failing ------------------------------------------------------------------------------- MiscTests.cpp: ............................................................................... diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 039aeaae..0243909e 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -438,10 +438,10 @@ MiscTests.cpp: - - - - + + + + MiscTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index ed4ce494..f185891a 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -3590,7 +3590,7 @@ - + testStringForMatching() Contains( "string" ) && Contains( "abc" ) && Contains( "substring" ) && Contains( "contains" ) @@ -3601,7 +3601,7 @@ - + testStringForMatching() Contains( "string" ) || Contains( "different" ) || Contains( "random" ) @@ -3620,7 +3620,7 @@ - + testStringForMatching() ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) @@ -3631,7 +3631,7 @@ - + testStringForMatching() ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) diff --git a/projects/SelfTest/MiscTests.cpp b/projects/SelfTest/MiscTests.cpp index c2a7784c..cf7f48cf 100644 --- a/projects/SelfTest/MiscTests.cpp +++ b/projects/SelfTest/MiscTests.cpp @@ -262,7 +262,7 @@ TEST_CASE("Equals", "[matchers]") CHECK_THAT( testStringForMatching(), Equals( "this string contains 'abc' as a substring" ) ); } -TEST_CASE("Matchers can be (AllOf) composed with the + operator", "[matchers][operators][operator+]") +TEST_CASE("Matchers can be (AllOf) composed with the && operator", "[matchers][operators][operator&&]") { CHECK_THAT( testStringForMatching(), Contains( "string" ) && @@ -271,18 +271,18 @@ TEST_CASE("Matchers can be (AllOf) composed with the + operator", "[matchers][op Contains( "contains" ) ); } -TEST_CASE("Matchers can be (AnyOf) composed with the | operator", "[matchers][operators][operator|]") +TEST_CASE("Matchers can be (AnyOf) composed with the || operator", "[matchers][operators][operator||]") { CHECK_THAT( testStringForMatching(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ); CHECK_THAT( testStringForMatching2(), Contains( "string" ) || Contains( "different" ) || Contains( "random" ) ); } -TEST_CASE("Matchers can be composed with both + and |", "[matchers][operators][operator|][operator+]") +TEST_CASE("Matchers can be composed with both && and ||", "[matchers][operators][operator||][operator&&]") { CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "substring" ) ); } -TEST_CASE("Matchers can be composed with both + and | - failing", "[matchers][operators][operator|][operator+][.failing]") +TEST_CASE("Matchers can be composed with both && and || - failing", "[matchers][operators][operator||][operator&&][.failing]") { CHECK_THAT( testStringForMatching(), ( Contains( "string" ) || Contains( "different" ) ) && Contains( "random" ) ); } From d10b73f9f178ea99e447d6e854fa110948eaa0a0 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 6 Nov 2015 18:05:35 +0000 Subject: [PATCH 80/87] changed Not struct to a class. - it was forward declared as a class, which caused warnings on some compilers. It should really have been a class anyway. - this addresses the same issue as PR #534, albeit from the other angle. --- include/internal/catch_matchers.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/internal/catch_matchers.hpp b/include/internal/catch_matchers.hpp index 14249ebf..27878612 100644 --- a/include/internal/catch_matchers.hpp +++ b/include/internal/catch_matchers.hpp @@ -43,7 +43,8 @@ namespace Matchers { namespace Generic { template - struct Not : public MatcherImpl, ExpressionT> { + class Not : public MatcherImpl, ExpressionT> { + public: explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} Not( Not const& other ) : m_matcher( other.m_matcher ) {} @@ -54,7 +55,7 @@ namespace Matchers { virtual std::string toString() const CATCH_OVERRIDE { return "not " + m_matcher->toString(); } - + private: Ptr< Matcher > m_matcher; }; From 92356769f15fbdf97737809e6381bb4aa11adcc5 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 6 Nov 2015 18:06:56 +0000 Subject: [PATCH 81/87] dev build 2 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8aa1cf2d..9c3db9d9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.3.0-develop.1* +*v1.3.0-develop.2* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 30540c82..e61dcb17 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 3, 0, "develop", 1 ); + Version libraryVersion( 1, 3, 0, "develop", 2 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index f50973a1..e9ed2436 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.3.0-develop.1 - * Generated: 2015-11-05 18:47:08.462966 + * Catch v1.3.0-develop.2 + * Generated: 2015-11-06 18:05:44.676531 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -862,7 +862,8 @@ namespace Matchers { namespace Generic { template - struct Not : public MatcherImpl, ExpressionT> { + class Not : public MatcherImpl, ExpressionT> { + public: explicit Not( Matcher const& matcher ) : m_matcher(matcher.clone()) {} Not( Not const& other ) : m_matcher( other.m_matcher ) {} @@ -873,7 +874,7 @@ namespace Matchers { virtual std::string toString() const CATCH_OVERRIDE { return "not " + m_matcher->toString(); } - + private: Ptr< Matcher > m_matcher; }; @@ -7238,7 +7239,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 3, 0, "develop", 1 ); + Version libraryVersion( 1, 3, 0, "develop", 2 ); } From ed6e9128a4f1d8c5e24be01d8ad9341f83a39562 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 29 May 2015 06:16:24 +0100 Subject: [PATCH 82/87] Session's argv now taken by char const* const* - see #427 --- include/catch_session.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 1b1cba54..9cfc28fd 100644 --- a/include/catch_session.hpp +++ b/include/catch_session.hpp @@ -131,7 +131,7 @@ namespace Catch { Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; } - int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + int applyCommandLine( int argc, char const* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { try { m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); @@ -158,7 +158,7 @@ namespace Catch { m_config.reset(); } - int run( int argc, char* const argv[] ) { + int run( int argc, char const* const argv[] ) { int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) From a49f088032be4d9d2e1c87f888254974c79fc5b8 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 18 Nov 2015 08:39:21 +0000 Subject: [PATCH 83/87] exception translators considered even for types deriving from std::exception, now - also added docs for exception translators - updated approvals --- docs/tostring.md | 10 +++++++ .../catch_exception_translator_registry.hpp | 21 +++++-------- include/internal/catch_interfaces_exception.h | 14 +++++++-- .../Baselines/console.std.approved.txt | 16 ++++++++-- .../Baselines/console.sw.approved.txt | 16 ++++++++-- .../SelfTest/Baselines/junit.sw.approved.txt | 10 +++++-- .../SelfTest/Baselines/xml.sw.approved.txt | 12 ++++++-- projects/SelfTest/ExceptionTests.cpp | 30 ++++++++++++++++++- 8 files changed, 101 insertions(+), 28 deletions(-) diff --git a/docs/tostring.md b/docs/tostring.md index 1f801b3a..dbb6cb8d 100644 --- a/docs/tostring.md +++ b/docs/tostring.md @@ -55,6 +55,16 @@ namespace Catch { } ``` +## Exceptions + +By default all exceptions deriving from `std::exception` will be translated to strings by calling the `what()` method. For exception types that do not derive from `std::exception` - or if `what()` does not return a suitable string - use `CATCH_TRANSLATE_EXCEPTION`. This defines a function that takes your exception type, by reference, and returns a string. It can appear anywhere in the code - it doesn't have to be in the same translation unit. For example: + +``` +CATCH_TRANSLATE_EXCEPTION( MyType& ex ) { + return ex.message(); +} +``` + --- [Home](Readme.md) diff --git a/include/internal/catch_exception_translator_registry.hpp b/include/internal/catch_exception_translator_registry.hpp index 29ddf8e7..c4bdb400 100644 --- a/include/internal/catch_exception_translator_registry.hpp +++ b/include/internal/catch_exception_translator_registry.hpp @@ -32,13 +32,13 @@ namespace Catch { #ifdef __OBJC__ // In Objective-C try objective-c exceptions first @try { - throw; + return tryTranslators(); } @catch (NSException *exception) { return Catch::toString( [exception description] ); } #else - throw; + return tryTranslators(); #endif } catch( TestFailureException& ) { @@ -54,20 +54,15 @@ namespace Catch { return msg; } catch(...) { - return tryTranslators( m_translators.begin() ); + return "Unknown exception"; } } - std::string tryTranslators( std::vector::const_iterator it ) const { - if( it == m_translators.end() ) - return "Unknown exception"; - - try { - return (*it)->translate(); - } - catch(...) { - return tryTranslators( it+1 ); - } + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); } private: diff --git a/include/internal/catch_interfaces_exception.h b/include/internal/catch_interfaces_exception.h index c2fc5bf5..67247e1e 100644 --- a/include/internal/catch_interfaces_exception.h +++ b/include/internal/catch_interfaces_exception.h @@ -9,15 +9,20 @@ #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED #include +#include + #include "catch_interfaces_registry_hub.h" namespace Catch { typedef std::string(*exceptionTranslateFunction)(); + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + struct IExceptionTranslator { virtual ~IExceptionTranslator(); - virtual std::string translate() const = 0; + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; }; struct IExceptionTranslatorRegistry { @@ -35,9 +40,12 @@ namespace Catch { : m_translateFunction( translateFunction ) {} - virtual std::string translate() const { + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { try { - throw; + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); } catch( T& ex ) { return m_translateFunction( ex ); diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 2b312e67..87106c25 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -356,7 +356,7 @@ due to unexpected exception with message: expected exception ------------------------------------------------------------------------------- -Unexpected custom exceptions can be translated +Non-std exceptions can be translated ------------------------------------------------------------------------------- ExceptionTests.cpp: ............................................................................... @@ -365,6 +365,16 @@ ExceptionTests.cpp:: FAILED: due to unexpected exception with message: custom exception +------------------------------------------------------------------------------- +Custom std-exceptions can be custom translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom std exception + ------------------------------------------------------------------------------- Custom exceptions can be translated when testing for nothrow ------------------------------------------------------------------------------- @@ -820,6 +830,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 165 | 123 passed | 41 failed | 1 failed as expected -assertions: 912 | 817 passed | 82 failed | 13 failed as expected +test cases: 166 | 123 passed | 42 failed | 1 failed as expected +assertions: 913 | 817 passed | 83 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index edfedded..4cbe98bb 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -1217,7 +1217,7 @@ due to unexpected exception with message: expected exception ------------------------------------------------------------------------------- -Unexpected custom exceptions can be translated +Non-std exceptions can be translated ------------------------------------------------------------------------------- ExceptionTests.cpp: ............................................................................... @@ -1226,6 +1226,16 @@ ExceptionTests.cpp:: FAILED: due to unexpected exception with message: custom exception +------------------------------------------------------------------------------- +Custom std-exceptions can be custom translated +------------------------------------------------------------------------------- +ExceptionTests.cpp: +............................................................................... + +ExceptionTests.cpp:: FAILED: +due to unexpected exception with message: + custom std exception + ------------------------------------------------------------------------------- Custom exceptions can be translated when testing for nothrow ------------------------------------------------------------------------------- @@ -9024,6 +9034,6 @@ with expansion: 1 > 0 =============================================================================== -test cases: 165 | 122 passed | 42 failed | 1 failed as expected -assertions: 914 | 817 passed | 84 failed | 13 failed as expected +test cases: 166 | 122 passed | 43 failed | 1 failed as expected +assertions: 915 | 817 passed | 85 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 0243909e..4daba14a 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -226,9 +226,15 @@ expected exception ExceptionTests.cpp: - + custom exception +ExceptionTests.cpp: + + + + +custom std exception ExceptionTests.cpp: diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index f185891a..2ab95bbe 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -1545,12 +1545,18 @@ - + custom exception + + + custom std exception + + + @@ -9496,7 +9502,7 @@ there"
- + - + diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index eb8b7d8f..949962ec 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -106,22 +106,50 @@ private: std::string m_msg; }; +class CustomStdException : public std::exception +{ +public: + CustomStdException( const std::string& msg ) + : m_msg( msg ) + {} + + std::string getMessage() const + { + return m_msg; + } + +private: + std::string m_msg; +}; + + CATCH_TRANSLATE_EXCEPTION( CustomException& ex ) { return ex.getMessage(); } +CATCH_TRANSLATE_EXCEPTION( CustomStdException& ex ) +{ + return ex.getMessage(); +} + CATCH_TRANSLATE_EXCEPTION( double& ex ) { return Catch::toString( ex ); } -TEST_CASE("Unexpected custom exceptions can be translated", "[.][failing]" ) +TEST_CASE("Non-std exceptions can be translated", "[.][failing]" ) { if( Catch::alwaysTrue() ) throw CustomException( "custom exception" ); } +TEST_CASE("Custom std-exceptions can be custom translated", "[.][failing]" ) +{ + if( Catch::alwaysTrue() ) + throw CustomException( "custom std exception" ); +} + inline void throwCustom() { if( Catch::alwaysTrue() ) throw CustomException( "custom exception - not std" ); From e4fa62a14e26241b8eb2b585be8ad459b73bddc6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 18 Nov 2015 08:39:54 +0000 Subject: [PATCH 84/87] dev build 3 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 46 ++++++++++++++++-------------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 9c3db9d9..caa68089 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.3.0-develop.2* +*v1.3.0-develop.3* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index e61dcb17..4d048822 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 3, 0, "develop", 2 ); + Version libraryVersion( 1, 3, 0, "develop", 3 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index e9ed2436..782d8be7 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.3.0-develop.2 - * Generated: 2015-11-06 18:05:44.676531 + * Catch v1.3.0-develop.3 + * Generated: 2015-11-18 08:39:33.879583 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -2454,6 +2454,8 @@ using namespace Generators; #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED #include +#include + // #included from: catch_interfaces_registry_hub.h #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED @@ -2491,14 +2493,16 @@ namespace Catch { } - namespace Catch { typedef std::string(*exceptionTranslateFunction)(); + struct IExceptionTranslator; + typedef std::vector ExceptionTranslators; + struct IExceptionTranslator { virtual ~IExceptionTranslator(); - virtual std::string translate() const = 0; + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; }; struct IExceptionTranslatorRegistry { @@ -2516,9 +2520,12 @@ namespace Catch { : m_translateFunction( translateFunction ) {} - virtual std::string translate() const { + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { try { - throw; + if( it == itEnd ) + throw; + else + return (*it)->translate( it+1, itEnd ); } catch( T& ex ) { return m_translateFunction( ex ); @@ -6059,7 +6066,7 @@ namespace Catch { Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; } - int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { + int applyCommandLine( int argc, char const* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { try { m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); m_unusedTokens = m_cli.parseInto( argc, argv, m_configData ); @@ -6086,7 +6093,7 @@ namespace Catch { m_config.reset(); } - int run( int argc, char* const argv[] ) { + int run( int argc, char const* const argv[] ) { int returnCode = applyCommandLine( argc, argv ); if( returnCode == 0 ) @@ -6378,13 +6385,13 @@ namespace Catch { #ifdef __OBJC__ // In Objective-C try objective-c exceptions first @try { - throw; + return tryTranslators(); } @catch (NSException *exception) { return Catch::toString( [exception description] ); } #else - throw; + return tryTranslators(); #endif } catch( TestFailureException& ) { @@ -6400,20 +6407,15 @@ namespace Catch { return msg; } catch(...) { - return tryTranslators( m_translators.begin() ); + return "Unknown exception"; } } - std::string tryTranslators( std::vector::const_iterator it ) const { - if( it == m_translators.end() ) - return "Unknown exception"; - - try { - return (*it)->translate(); - } - catch(...) { - return tryTranslators( it+1 ); - } + std::string tryTranslators() const { + if( m_translators.empty() ) + throw; + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); } private: @@ -7239,7 +7241,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 3, 0, "develop", 2 ); + Version libraryVersion( 1, 3, 0, "develop", 3 ); } From 0e64973f55d69e01b057b3d3450433eca73797e6 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 20 Nov 2015 16:54:07 +0000 Subject: [PATCH 85/87] Added support for manually registering test functions. As discussed in #421 --- include/catch.hpp | 4 ++ .../catch_test_case_registry_impl.hpp | 43 +++++++++------- include/internal/catch_test_registry.hpp | 49 +++++++++++++------ .../Baselines/console.std.approved.txt | 4 +- .../Baselines/console.sw.approved.txt | 15 +++++- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +- .../SelfTest/Baselines/xml.sw.approved.txt | 7 ++- projects/SelfTest/TestMain.cpp | 10 ++++ 8 files changed, 95 insertions(+), 40 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index 897b2959..06ed7eee 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -99,6 +99,7 @@ #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( ... ) INTERNAL_CATCH_REGISTER_TESTCASE( __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) @@ -106,6 +107,7 @@ #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) @@ -166,6 +168,7 @@ #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( ... ) INTERNAL_CATCH_REGISTER_TESTCASE( __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) @@ -173,6 +176,7 @@ #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( ... ) INTERNAL_CATCH_REGISTER_TESTCASE( __VA_ARGS__ ) #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) diff --git a/include/internal/catch_test_case_registry_impl.hpp b/include/internal/catch_test_case_registry_impl.hpp index 7f63dc54..728adcb0 100644 --- a/include/internal/catch_test_case_registry_impl.hpp +++ b/include/internal/catch_test_case_registry_impl.hpp @@ -152,29 +152,38 @@ namespace Catch { return className; } + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { + + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + } + /////////////////////////////////////////////////////////////////////////// - AutoReg::AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { - registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); } AutoReg::~AutoReg() {} - void AutoReg::registerTestCase( ITestCase* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - getMutableRegistryHub().registerTest - ( makeTestCase( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); - } - } // end namespace Catch diff --git a/include/internal/catch_test_registry.hpp b/include/internal/catch_test_registry.hpp index d12411d4..bd27ba0e 100644 --- a/include/internal/catch_test_registry.hpp +++ b/include/internal/catch_test_registry.hpp @@ -42,27 +42,32 @@ struct NameAndDesc { const char* description; }; +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + struct AutoReg { - AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); template - AutoReg( void (C::*method)(), - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - registerTestCase( new MethodTestCase( method ), - className, - nameAndDesc, - lineInfo ); - } + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { - void registerTestCase( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); + registerTestCase + ( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } ~AutoReg(); @@ -71,6 +76,11 @@ private: void operator= ( AutoReg const& ); }; +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + } // end namespace Catch #ifdef CATCH_CONFIG_VARIADIC_MACROS @@ -94,6 +104,10 @@ private: } \ void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + #else /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ @@ -115,6 +129,9 @@ private: } \ void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); #endif #endif // TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index 87106c25..976a7105 100644 --- a/projects/SelfTest/Baselines/console.std.approved.txt +++ b/projects/SelfTest/Baselines/console.std.approved.txt @@ -830,6 +830,6 @@ with expansion: "first" == "second" =============================================================================== -test cases: 166 | 123 passed | 42 failed | 1 failed as expected -assertions: 913 | 817 passed | 83 failed | 13 failed as expected +test cases: 167 | 124 passed | 42 failed | 1 failed as expected +assertions: 914 | 818 passed | 83 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt index 4cbe98bb..4f3800b9 100644 --- a/projects/SelfTest/Baselines/console.sw.approved.txt +++ b/projects/SelfTest/Baselines/console.sw.approved.txt @@ -6004,6 +6004,17 @@ with expansion: ************************ ... message truncated due to excessive size +------------------------------------------------------------------------------- +ManuallyRegistered +------------------------------------------------------------------------------- +TestMain.cpp: +............................................................................... + +TestMain.cpp:: +PASSED: +with message: + was called + ------------------------------------------------------------------------------- Parsing a std::pair ------------------------------------------------------------------------------- @@ -9034,6 +9045,6 @@ with expansion: 1 > 0 =============================================================================== -test cases: 166 | 122 passed | 43 failed | 1 failed as expected -assertions: 915 | 817 passed | 85 failed | 13 failed as expected +test cases: 167 | 123 passed | 43 failed | 1 failed as expected +assertions: 916 | 818 passed | 85 failed | 13 failed as expected diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 4daba14a..18792059 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -547,6 +547,7 @@ hello + diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt index 2ab95bbe..407c8928 100644 --- a/projects/SelfTest/Baselines/xml.sw.approved.txt +++ b/projects/SelfTest/Baselines/xml.sw.approved.txt @@ -6284,6 +6284,9 @@ there" + + + @@ -9502,7 +9505,7 @@ there"
- + - + diff --git a/projects/SelfTest/TestMain.cpp b/projects/SelfTest/TestMain.cpp index bffc7e77..1713b51a 100644 --- a/projects/SelfTest/TestMain.cpp +++ b/projects/SelfTest/TestMain.cpp @@ -449,3 +449,13 @@ TEST_CASE( "Long text is truncted", "[Text][Truncated]" ) { CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ); } + +inline void manuallyRegisteredTestFunction() { + SUCCEED( "was called" ); +} +struct AutoTestReg { + AutoTestReg() { + REGISTER_TEST_CASE( manuallyRegisteredTestFunction, "ManuallyRegistered", "" ); + } +}; +AutoTestReg autoTestReg; From 7e15d9b20bc9751e7fa985252fc43a6e8082dad7 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 20 Nov 2015 16:59:14 +0000 Subject: [PATCH 86/87] dev build 4 --- README.md | 2 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 100 +++++++++++++++++++---------- 3 files changed, 67 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index caa68089..6cf7dad5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![catch logo](catch-logo-small.png) -*v1.3.0-develop.3* +*v1.3.0-develop.4* Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch) diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 4d048822..d0c7c198 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -37,7 +37,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 3, 0, "develop", 3 ); + Version libraryVersion( 1, 3, 0, "develop", 4 ); } diff --git a/single_include/catch.hpp b/single_include/catch.hpp index 782d8be7..11e5d364 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * Catch v1.3.0-develop.3 - * Generated: 2015-11-18 08:39:33.879583 + * Catch v1.3.0-develop.4 + * Generated: 2015-11-20 16:58:58.532767 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -629,27 +629,32 @@ struct NameAndDesc { const char* description; }; +void registerTestCase + ( ITestCase* testCase, + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ); + struct AutoReg { - AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ); + AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); template - AutoReg( void (C::*method)(), - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - registerTestCase( new MethodTestCase( method ), - className, - nameAndDesc, - lineInfo ); - } + AutoReg + ( void (C::*method)(), + char const* className, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { - void registerTestCase( ITestCase* testCase, - char const* className, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ); + registerTestCase + ( new MethodTestCase( method ), + className, + nameAndDesc, + lineInfo ); + } ~AutoReg(); @@ -658,6 +663,11 @@ private: void operator= ( AutoReg const& ); }; +void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ); + } // end namespace Catch #ifdef CATCH_CONFIG_VARIADIC_MACROS @@ -681,6 +691,10 @@ private: } \ void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); + #else /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ @@ -702,6 +716,9 @@ private: } \ void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test() + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ + Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); #endif // #included from: internal/catch_capture.hpp @@ -6296,29 +6313,38 @@ namespace Catch { return className; } - /////////////////////////////////////////////////////////////////////////// + void registerTestCase + ( ITestCase* testCase, + char const* classOrQualifiedMethodName, + NameAndDesc const& nameAndDesc, + SourceLineInfo const& lineInfo ) { - AutoReg::AutoReg( TestFunction function, - SourceLineInfo const& lineInfo, - NameAndDesc const& nameAndDesc ) { + getMutableRegistryHub().registerTest + ( makeTestCase + ( testCase, + extractClassName( classOrQualifiedMethodName ), + nameAndDesc.name, + nameAndDesc.description, + lineInfo ) ); + } + void registerTestCaseFunction + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); } - AutoReg::~AutoReg() {} + /////////////////////////////////////////////////////////////////////////// - void AutoReg::registerTestCase( ITestCase* testCase, - char const* classOrQualifiedMethodName, - NameAndDesc const& nameAndDesc, - SourceLineInfo const& lineInfo ) { - - getMutableRegistryHub().registerTest - ( makeTestCase( testCase, - extractClassName( classOrQualifiedMethodName ), - nameAndDesc.name, - nameAndDesc.description, - lineInfo ) ); + AutoReg::AutoReg + ( TestFunction function, + SourceLineInfo const& lineInfo, + NameAndDesc const& nameAndDesc ) { + registerTestCaseFunction( function, lineInfo, nameAndDesc ); } + AutoReg::~AutoReg() {} + } // end namespace Catch // #included from: catch_reporter_registry.hpp @@ -7241,7 +7267,7 @@ namespace Catch { return os; } - Version libraryVersion( 1, 3, 0, "develop", 3 ); + Version libraryVersion( 1, 3, 0, "develop", 4 ); } @@ -10061,6 +10087,7 @@ int main (int argc, char * const argv[]) { #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define CATCH_REGISTER_TEST_CASE( ... ) INTERNAL_CATCH_REGISTER_TESTCASE( __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) @@ -10068,6 +10095,7 @@ int main (int argc, char * const argv[]) { #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) @@ -10128,6 +10156,7 @@ int main (int argc, char * const argv[]) { #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) + #define REGISTER_TEST_CASE( ... ) INTERNAL_CATCH_REGISTER_TESTCASE( __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) @@ -10135,6 +10164,7 @@ int main (int argc, char * const argv[]) { #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) + #define REGISTER_TEST_CASE( ... ) INTERNAL_CATCH_REGISTER_TESTCASE( __VA_ARGS__ ) #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) From d274fc571c3980b5ac04cbe1416cf2205e6c99f7 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Fri, 20 Nov 2015 17:09:48 +0000 Subject: [PATCH 87/87] Added noexcept to CustomStdException destructor --- projects/SelfTest/ExceptionTests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/SelfTest/ExceptionTests.cpp b/projects/SelfTest/ExceptionTests.cpp index 949962ec..dfcaa4b8 100644 --- a/projects/SelfTest/ExceptionTests.cpp +++ b/projects/SelfTest/ExceptionTests.cpp @@ -112,6 +112,7 @@ public: CustomStdException( const std::string& msg ) : m_msg( msg ) {} + ~CustomStdException() CATCH_NOEXCEPT {} std::string getMessage() const {