First cut of generators

This commit is contained in:
Phil Nash 2011-01-26 23:23:33 +00:00
parent 455c2998a0
commit c2b96d7ddb
8 changed files with 256 additions and 21 deletions

View File

@ -79,3 +79,16 @@ TEST_CASE( "./succeeding/Misc/stdout,stderr", "Sends stuff to stdout and stderr"
std::cerr << "An error"; 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 );
}

View File

@ -33,6 +33,27 @@ namespace Catch
// create a T for use in sizeof expressions // create a T for use in sizeof expressions
template<typename T> T Synth(); template<typename T> T Synth();
template<typename ContainerT>
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<typename AssociativeContainerT>
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 #endif // TWOBLUECUBES_CATCH_COMMON_H_INCLUDED

View File

@ -23,6 +23,7 @@ namespace Catch
struct IResultCapture; struct IResultCapture;
struct ITestCaseRegistry; struct ITestCaseRegistry;
struct IRunner; struct IRunner;
class GeneratorsForTest;
class StreamBufBase : public std::streambuf class StreamBufBase : public std::streambuf
{ {
@ -60,11 +61,24 @@ namespace Catch
static IRunner& getRunner static IRunner& getRunner
(); ();
static size_t getGeneratorIndex
( const std::string& fileInfo,
size_t totalSize
);
static bool advanceGeneratorsForCurrentTest
();
private: private:
GeneratorsForTest* findGeneratorsForCurrentTest
();
GeneratorsForTest& getGeneratorsForCurrentTest
();
std::auto_ptr<IReporterRegistry> m_reporterRegistry; std::auto_ptr<IReporterRegistry> m_reporterRegistry;
std::auto_ptr<ITestCaseRegistry> m_testCaseRegistry; std::auto_ptr<ITestCaseRegistry> m_testCaseRegistry;
IRunner* m_runner; IRunner* m_runner;
IResultCapture* m_resultCapture; IResultCapture* m_resultCapture;
std::map<std::string, GeneratorsForTest*> m_generatorsByTestName;
}; };
} }

View File

@ -85,4 +85,152 @@ namespace Catch
throw std::domain_error( "Unknown stream: " + streamName ); 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<std::string, GeneratorInfo*>::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<GeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
std::vector<GeneratorInfo*>::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<std::string, GeneratorInfo*> m_generatorsByName;
std::vector<GeneratorInfo*> m_generatorsInOrder;
std::size_t m_currentGenerator;
};
///////////////////////////////////////////////////////////////////////////
GeneratorsForTest* Hub::findGeneratorsForCurrentTest
()
{
std::string testName = getResultCapture().getCurrentTestName();
std::map<std::string, GeneratorsForTest*>::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();
}
} }

View File

@ -23,18 +23,49 @@ namespace Catch
struct IResultCapture struct IResultCapture
{ {
virtual ~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 testEnded
virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0; ( const ResultInfo& result
virtual bool shouldDebugBreak() const = 0; ) = 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;
}; };
} }

View File

@ -26,12 +26,7 @@ namespace Catch
~ReporterRegistry ~ReporterRegistry
() ()
{ {
FactoryMap::const_iterator it = m_factories.begin(); deleteAllValues( m_factories );
FactoryMap::const_iterator itEnd = m_factories.end();
for(; it != itEnd; ++it )
{
delete it->second;
}
} }
/////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////

View File

@ -199,10 +199,14 @@ namespace Catch
do do
{ {
m_runningTest.resetSectionSeen(); do
runCurrentTest( redirectedCout, redirectedCerr ); {
m_runningTest.resetSectionSeen();
runCurrentTest( redirectedCout, redirectedCerr );
}
while( m_runningTest.wasSectionSeen() );
} }
while( m_runningTest.wasSectionSeen() ); while( Hub::advanceGeneratorsForCurrentTest() );
m_runningTest = RunningTest(); m_runningTest = RunningTest();
@ -358,6 +362,15 @@ namespace Catch
{ {
return m_config.shouldDebugBreak(); return m_config.shouldDebugBreak();
} }
///////////////////////////////////////////////////////////////////////////
virtual std::string getCurrentTestName
()
const
{
return m_runningTest.getTestCaseInfo().getName();
}
private: private:
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////