From c2b96d7ddb6ad69f2360bd1c657685da9985fb07 Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Wed, 26 Jan 2011 23:23:33 +0000 Subject: [PATCH] First cut of generators --- Test/MiscTests.cpp | 13 +++ internal/catch_common.h | 21 ++++ internal/catch_hub.h | 14 +++ internal/catch_hub_impl.hpp | 148 +++++++++++++++++++++++++++ internal/catch_interfaces_capture.h | 53 ++++++++-- internal/catch_reporter_registry.hpp | 7 +- internal/catch_runner_impl.hpp | 19 +++- internal/catch_section.hpp | 2 +- 8 files changed, 256 insertions(+), 21 deletions(-) diff --git a/Test/MiscTests.cpp b/Test/MiscTests.cpp index 7f0da4f8..59084f85 100644 --- a/Test/MiscTests.cpp +++ b/Test/MiscTests.cpp @@ -79,3 +79,16 @@ TEST_CASE( "./succeeding/Misc/stdout,stderr", "Sends stuff to stdout and stderr" std::cerr << "An error"; } + +// An unnamed test case. A name, of the form, "unnamed/#" is generated, where +// # is an incrementing integer +ANON_TEST_CASE() +{ + int i = 7; + REQUIRE( i == 7 ); +} +ANON_TEST_CASE() +{ + int i = 7; + REQUIRE( i == 8 ); +} diff --git a/internal/catch_common.h b/internal/catch_common.h index 1491f7e5..ac60aaa4 100644 --- a/internal/catch_common.h +++ b/internal/catch_common.h @@ -33,6 +33,27 @@ namespace Catch // create a T for use in sizeof expressions template T Synth(); + template + inline void deleteAll( ContainerT& container ) + { + typename ContainerT::const_iterator it = container.begin(); + typename ContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + { + delete *it; + } + } + template + inline void deleteAllValues( AssociativeContainerT& container ) + { + typename AssociativeContainerT::const_iterator it = container.begin(); + typename AssociativeContainerT::const_iterator itEnd = container.end(); + for(; it != itEnd; ++it ) + { + delete it->second; + } + } + } #endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED \ No newline at end of file diff --git a/internal/catch_hub.h b/internal/catch_hub.h index 9f8537bb..bb091691 100644 --- a/internal/catch_hub.h +++ b/internal/catch_hub.h @@ -23,6 +23,7 @@ namespace Catch struct IResultCapture; struct ITestCaseRegistry; struct IRunner; + class GeneratorsForTest; class StreamBufBase : public std::streambuf { @@ -60,11 +61,24 @@ namespace Catch static IRunner& getRunner (); + static size_t getGeneratorIndex + ( const std::string& fileInfo, + size_t totalSize + ); + static bool advanceGeneratorsForCurrentTest + (); + private: + GeneratorsForTest* findGeneratorsForCurrentTest + (); + GeneratorsForTest& getGeneratorsForCurrentTest + (); + std::auto_ptr m_reporterRegistry; std::auto_ptr m_testCaseRegistry; IRunner* m_runner; IResultCapture* m_resultCapture; + std::map m_generatorsByTestName; }; } diff --git a/internal/catch_hub_impl.hpp b/internal/catch_hub_impl.hpp index ad642a86..71608675 100644 --- a/internal/catch_hub_impl.hpp +++ b/internal/catch_hub_impl.hpp @@ -84,5 +84,153 @@ namespace Catch throw std::domain_error( "Unknown stream: " + streamName ); } + + struct GeneratorInfo + { + GeneratorInfo + ( + std::size_t size + ) + : m_size( size ), + m_currentIndex( 0 ) + { + } + + void reset + () + { + m_currentIndex = 0; + } + + bool moveNext + () + { + if( ++m_currentIndex == m_size ) + { + reset(); + return false; + } + return true; + } + + std::size_t getCurrentIndex + () + const + { + return m_currentIndex; + } + + std::size_t m_size; + std::size_t m_currentIndex; + }; + + class GeneratorsForTest + { + + public: + GeneratorsForTest + () + : m_currentGenerator( 0 ) + { + } + + ~GeneratorsForTest + () + { + deleteAll( m_generatorsInOrder ); + } + + GeneratorInfo& getGeneratorInfo + ( + const std::string& fileInfo, + std::size_t size + ) + { + std::map::const_iterator it = m_generatorsByName.find( fileInfo ); + if( it == m_generatorsByName.end() ) + { + GeneratorInfo* info = new GeneratorInfo( size ); + m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); + m_generatorsInOrder.push_back( info ); + return *info; + } + return *it->second; + } + + void reset + () + { + std::vector::const_iterator it = m_generatorsInOrder.begin(); + std::vector::const_iterator itEnd = m_generatorsInOrder.begin(); + for(; it != itEnd; ++it ) + { + (*it)->reset(); + } + } + + bool moveNext + () + { + if( !m_generatorsInOrder[m_currentGenerator]->moveNext() ) + { + if( ++m_currentGenerator == m_generatorsInOrder.size() ) + { + m_currentGenerator = 0; + return false; + } + } + return true; + } + + private: + std::map m_generatorsByName; + std::vector m_generatorsInOrder; + std::size_t m_currentGenerator; + }; + /////////////////////////////////////////////////////////////////////////// + GeneratorsForTest* Hub::findGeneratorsForCurrentTest + () + { + std::string testName = getResultCapture().getCurrentTestName(); + + std::map::const_iterator it = + m_generatorsByTestName.find( testName ); + return it != m_generatorsByTestName.end() + ? it->second + : NULL; + } + /////////////////////////////////////////////////////////////////////////// + GeneratorsForTest& Hub::getGeneratorsForCurrentTest + () + { + GeneratorsForTest* generators = findGeneratorsForCurrentTest(); + if( !generators ) + { + std::string testName = getResultCapture().getCurrentTestName(); + generators = new GeneratorsForTest(); + m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); + } + return *generators; + } + + /////////////////////////////////////////////////////////////////////////// + size_t Hub::getGeneratorIndex + ( + const std::string& fileInfo, + size_t totalSize + ) + { + return me().getGeneratorsForCurrentTest() + .getGeneratorInfo( fileInfo, totalSize ) + .getCurrentIndex(); + } + + /////////////////////////////////////////////////////////////////////////// + bool Hub::advanceGeneratorsForCurrentTest + () + { + GeneratorsForTest* generators = me().findGeneratorsForCurrentTest(); + return generators && generators->moveNext(); + } } diff --git a/internal/catch_interfaces_capture.h b/internal/catch_interfaces_capture.h index 31f92ba8..a030f65a 100644 --- a/internal/catch_interfaces_capture.h +++ b/internal/catch_interfaces_capture.h @@ -23,18 +23,49 @@ namespace Catch struct IResultCapture { - virtual ~IResultCapture(){} - virtual void testEnded( const ResultInfo& result ) = 0; - virtual bool sectionStarted( const std::string& name, const std::string& description, std::size_t& successes, std::size_t& failures ) = 0; - virtual void sectionEnded( const std::string& name, std::size_t successes, std::size_t failures ) = 0; - virtual void pushScopedInfo( ScopedInfo* scopedInfo ) = 0; - virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0; - virtual bool shouldDebugBreak() const = 0; + virtual ~IResultCapture + () + {} + + virtual void testEnded + ( const ResultInfo& result + ) = 0; + virtual bool sectionStarted + ( const std::string& name, + const std::string& description, + std::size_t& successes, + std::size_t& failures + ) = 0; + virtual void sectionEnded + ( const std::string& name, + std::size_t successes, + std::size_t failures + ) = 0; + virtual void pushScopedInfo + ( ScopedInfo* scopedInfo + ) = 0; + virtual void popScopedInfo + ( ScopedInfo* scopedInfo + ) = 0; + virtual bool shouldDebugBreak + () const = 0; + + virtual ResultAction::Value acceptResult + ( bool result + ) = 0; + virtual ResultAction::Value acceptResult + ( ResultWas::OfType result + ) = 0; + virtual void acceptExpression + ( const MutableResultInfo& resultInfo + ) = 0; + virtual void acceptMessage + ( const std::string& msg + ) = 0; + + virtual std::string getCurrentTestName + () const = 0; - virtual ResultAction::Value acceptResult( bool result ) = 0; - virtual ResultAction::Value acceptResult( ResultWas::OfType result ) = 0; - virtual void acceptExpression( const MutableResultInfo& resultInfo ) = 0; - virtual void acceptMessage( const std::string& msg ) = 0; }; } diff --git a/internal/catch_reporter_registry.hpp b/internal/catch_reporter_registry.hpp index b9283ee5..57643e3c 100644 --- a/internal/catch_reporter_registry.hpp +++ b/internal/catch_reporter_registry.hpp @@ -26,12 +26,7 @@ namespace Catch ~ReporterRegistry () { - FactoryMap::const_iterator it = m_factories.begin(); - FactoryMap::const_iterator itEnd = m_factories.end(); - for(; it != itEnd; ++it ) - { - delete it->second; - } + deleteAllValues( m_factories ); } /////////////////////////////////////////////////////////////////////// diff --git a/internal/catch_runner_impl.hpp b/internal/catch_runner_impl.hpp index 7ba1bb9c..8d454e52 100644 --- a/internal/catch_runner_impl.hpp +++ b/internal/catch_runner_impl.hpp @@ -199,10 +199,14 @@ namespace Catch do { - m_runningTest.resetSectionSeen(); - runCurrentTest( redirectedCout, redirectedCerr ); + do + { + m_runningTest.resetSectionSeen(); + runCurrentTest( redirectedCout, redirectedCerr ); + } + while( m_runningTest.wasSectionSeen() ); } - while( m_runningTest.wasSectionSeen() ); + while( Hub::advanceGeneratorsForCurrentTest() ); m_runningTest = RunningTest(); @@ -358,6 +362,15 @@ namespace Catch { return m_config.shouldDebugBreak(); } + + /////////////////////////////////////////////////////////////////////////// + virtual std::string getCurrentTestName + () + const + { + return m_runningTest.getTestCaseInfo().getName(); + } + private: /////////////////////////////////////////////////////////////////////////// diff --git a/internal/catch_section.hpp b/internal/catch_section.hpp index fb8d5731..9d9f3cfc 100644 --- a/internal/catch_section.hpp +++ b/internal/catch_section.hpp @@ -27,7 +27,7 @@ namespace Catch m_sectionIncluded( Hub::getResultCapture().sectionStarted( name, description, m_successes, m_failures ) ) { } - + ~Section() { if( m_sectionIncluded )