diff --git a/include/catch_session.hpp b/include/catch_session.hpp index 50623ad4..c63f517b 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; @@ -52,27 +52,15 @@ 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; @@ -82,17 +70,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_config.hpp b/include/internal/catch_config.hpp index 6b2b04a3..c0d0948e 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,14 +136,25 @@ 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; }; - } // end namespace Catch #endif // TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED 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..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,8 +44,11 @@ #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 {} StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} IContext::~IContext() {} IResultCapture::~IResultCapture() {} @@ -90,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_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..a3098b5f 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 ) { @@ -101,14 +94,18 @@ 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 ); @@ -120,7 +117,7 @@ namespace Catch { aborting() ) ); m_activeTestCase = CATCH_NULL; - m_testCaseTracker.reset(); + m_testCaseTracker = CATCH_NULL; return deltaTotals; } @@ -156,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 ); @@ -168,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++; @@ -181,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 ); } @@ -256,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 ); @@ -278,6 +287,7 @@ namespace Catch { catch(...) { makeUnexpectedResultBuilder().useActiveException(); } + m_testCaseTracker->close(); handleUnfinishedSections(); m_messages.clear(); @@ -323,18 +333,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() { 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/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..713ec96c 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -9,141 +9,307 @@ #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED #include "catch_compiler_capabilities.h" +#include "catch_ptr.hpp" #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; } - TrackedSection* findChild( std::string const& childName ); - TrackedSection* acquireChild( std::string const& childName ); - - void enter() { - if( m_runState == NotStarted ) - m_runState = Executing; + ITracker& startRun(); + + 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(); } + + 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: - std::string m_name; - RunState m_runState; - TrackedSections m_children; - TrackedSection* m_parent; + void moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void moveToThis() { + m_ctx.setCurrentTracker( this ); + } }; - 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 { + class SectionTracker : public TrackerBase { public: - TestCaseTracker( std::string const& testCaseName ) - : m_testCase( testCaseName, CATCH_NULL ), - m_currentSection( &m_testCase ), - m_completedASectionThisRun( false ) + SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( name, ctx, parent ) {} - - 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(); + 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 ); } - ~Guard() { - m_tracker.leaveTestCase(); + else { + section = new SectionTracker( name, ctx, ¤tTracker ); + currentTracker.addChild( section ); } - private: - Guard( Guard const& ); - void operator = ( Guard const& ); - TestCaseTracker& m_tracker; - }; - - private: - void enterTestCase() { - m_currentSection = &m_testCase; - m_completedASectionThisRun = false; - m_testCase.enter(); + if( !ctx.completedCycle() && !section->isComplete() ) { + + section->open(); + } + return *section; } - void leaveTestCase() { - m_testCase.leave(); - } - - TrackedSection m_testCase; - TrackedSection* m_currentSection; - bool m_completedASectionThisRun; }; - -} // namespace SectionTracking - -using SectionTracking::TestCaseTracker; + + 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 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; diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt index dbaca8ba..ad144d77 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 ------------------------------------------------------------------------------- @@ -797,6 +817,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: 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 82702ecf..5fb53373 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 @@ -3046,6 +2999,34 @@ MiscTests.cpp:: FAILED: with expansion: 1 == 2 +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s3 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a != b ) +with expansion: + 1 != 2 + +------------------------------------------------------------------------------- +more nested SECTION tests + s1 + s4 +------------------------------------------------------------------------------- +MiscTests.cpp: +............................................................................... + +MiscTests.cpp:: +PASSED: + REQUIRE( a < b ) +with expansion: + 1 < 2 + ------------------------------------------------------------------------------- even more nested SECTION tests c @@ -3054,8 +3035,8 @@ even more nested SECTION tests MiscTests.cpp: ............................................................................... - -No assertions in section 'd (leaf)' +MiscTests.cpp:: +PASSED: ------------------------------------------------------------------------------- even more nested SECTION tests @@ -3065,8 +3046,8 @@ even more nested SECTION tests MiscTests.cpp: ............................................................................... - -No assertions in section 'e (leaf)' +MiscTests.cpp:: +PASSED: ------------------------------------------------------------------------------- even more nested SECTION tests @@ -3075,8 +3056,8 @@ even more nested SECTION tests MiscTests.cpp: ............................................................................... - -No assertions in section 'f (leaf)' +MiscTests.cpp:: +PASSED: ------------------------------------------------------------------------------- looped SECTION tests @@ -3156,15 +3137,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 ------------------------------------------------------------------------------- @@ -3258,8 +3230,8 @@ xmlentitycheck MiscTests.cpp: ............................................................................... - -No assertions in section 'embedded xml' +MiscTests.cpp:: +PASSED: ------------------------------------------------------------------------------- xmlentitycheck @@ -3268,8 +3240,8 @@ xmlentitycheck MiscTests.cpp: ............................................................................... - -No assertions in section 'encoded chars' +MiscTests.cpp:: +PASSED: ------------------------------------------------------------------------------- send a single char to INFO @@ -3462,15 +3434,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 +3444,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 +4859,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 +5916,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 +5927,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 +6391,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 ------------------------------------------------------------------------------- @@ -7997,179 +8922,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: 159 | 103 passed | 55 failed | 1 failed as expected -assertions: 808 | 695 passed | 100 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/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt index 6c6e5208..40447d11 100644 --- a/projects/SelfTest/Baselines/junit.sw.approved.txt +++ b/projects/SelfTest/Baselines/junit.sw.approved.txt @@ -1,5 +1,5 @@ - + @@ -341,6 +341,11 @@ MessageTests.cpp: MiscTests.cpp: + + + + + MiscTests.cpp: @@ -399,6 +404,8 @@ MiscTests.cpp: MiscTests.cpp: + + 3 @@ -566,6 +573,23 @@ TrickyTests.cpp: + + + + + + + + + + + + + + + + + @@ -625,11 +649,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 3d20d996..ebe5c69b 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 + + + +
+ +
+ +
+ +
@@ -8288,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/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 } } diff --git a/projects/SelfTest/PartTrackerTests.cpp b/projects/SelfTest/PartTrackerTests.cpp new file mode 100644 index 00000000..c576d53c --- /dev/null +++ b/projects/SelfTest/PartTrackerTests.cpp @@ -0,0 +1,328 @@ +/* + * 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_test_case_tracker.hpp" + + +namespace Catch +{ + class LocalContext { + + public: + TrackerContext& operator()() const { + return TrackerContext::instance(); + } + }; + +} // 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( "Tracker", "" ) { + + TrackerContext ctx; + ctx.startRun(); + ctx.startCycle(); + + ITracker& testCase = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase.isOpen() ); + + ITracker& s1 = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1.isOpen() ); + + SECTION( "successfully close one section", "" ) { + s1.close(); + REQUIRE( s1.isSuccessfullyCompleted() ); + REQUIRE( testCase.isComplete() == false ); + + testCase.close(); + 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 ); + + SECTION( "re-enter after failed section", "" ) { + 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() ); + REQUIRE( testCase.isSuccessfullyCompleted() ); + } + SECTION( "re-enter after failed section and find next section", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() == false ); + + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + 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 ); + + SECTION( "Re-enter - skips S1 and enters S2", "" ) { + ctx.startCycle(); + ITracker& testCase2 = SectionTracker::acquire( ctx, "Testcase" ); + REQUIRE( testCase2.isOpen() ); + + ITracker& s1b = SectionTracker::acquire( ctx, "S1" ); + REQUIRE( s1b.isOpen() == false ); + + ITracker& s2b = SectionTracker::acquire( ctx, "S2" ); + 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() ); + } + SECTION ("fail S2") { + s2b.fail(); + REQUIRE( ctx.completedCycle() ); + + REQUIRE( s2b.isComplete() ); + REQUIRE( s2b.isSuccessfullyCompleted() == false ); + + testCase2.close(); + REQUIRE( testCase2.isSuccessfullyCompleted() == false ); + + // Need a final cycle + 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() ); + + 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() ); + REQUIRE( g1.index() == 0 ); + + REQUIRE( g1.isComplete() == false ); + REQUIRE( s1.isComplete() == false ); + + SECTION( "close outer section" ) + { + s1.close(); + REQUIRE( s1.isComplete() == false ); + testCase.close(); + REQUIRE( testCase.isSuccessfullyCompleted() == 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() ); + + + 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() ); + testCase2.close(); + REQUIRE( testCase2.isComplete() ); + } + } + SECTION( "Start a new inner section", "" ) { + ITracker& s2 = SectionTracker::acquire( ctx, "S2" ); + REQUIRE( s2.isOpen() ); + + s2.close(); + REQUIRE( s2.isComplete() ); + + 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 - 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() ); + } + } + // !TBD" + // nested generator + // two sections within a generator + } +} diff --git a/projects/SelfTest/SectionTrackerTests.cpp b/projects/SelfTest/SectionTrackerTests.cpp deleted file mode 100644 index 96e96f5e..00000000 --- a/projects/SelfTest/SectionTrackerTests.cpp +++ /dev/null @@ -1,118 +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) - */ - -#ifdef __clang__ -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wc++98-compat" -#endif - -#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/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" diff --git a/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj b/projects/XCode/CatchSelfTest/CatchSelfTest.xcodeproj/project.pbxproj index 81f826b6..8947e38e 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 */; }; 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 */; }; @@ -17,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 */; }; @@ -62,6 +62,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 = ""; }; @@ -100,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 = ""; }; @@ -212,7 +212,7 @@ 266E9AD317290E710061DAB2 /* Introspective Tests */ = { isa = PBXGroup; children = ( - 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */, + 26059AF11BD4B94C003D575C /* PartTrackerTests.cpp */, 26E1B7D119213BC900812682 /* CmdLineTests.cpp */, 26711C8D195D465C0033EDA2 /* TagAliasTests.cpp */, ); @@ -548,6 +548,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 */, @@ -574,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; };