mirror of
https://github.com/catchorg/Catch2.git
synced 2024-12-25 04:23:30 +01:00
Eliminate dynamic cast by implementing MultipleReporters as a linked list
This eliminates one use of RTTI in Catch. I also tend to think that this is a more sensible design.
This commit is contained in:
parent
c984fc3ecd
commit
2ebd7dc10e
@ -13,132 +13,121 @@
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
class MultipleReporters : public SharedImpl<IStreamingReporter> {
|
class MultipleReporters : public SharedImpl<IStreamingReporter> {
|
||||||
typedef std::vector<Ptr<IStreamingReporter> > Reporters;
|
Ptr<IStreamingReporter> m_reporter;
|
||||||
Reporters m_reporters;
|
Ptr<MultipleReporters> m_next;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
MultipleReporters( Ptr<IStreamingReporter> const& reporter )
|
||||||
|
: m_reporter( reporter )
|
||||||
|
, m_next( CATCH_NULL )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MultipleReporters( Ptr<IStreamingReporter> const& first, Ptr<IStreamingReporter> const& second )
|
||||||
|
: m_reporter( first )
|
||||||
|
, m_next( new MultipleReporters( second ) )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void add( Ptr<IStreamingReporter> const& reporter ) {
|
void add( Ptr<IStreamingReporter> const& reporter ) {
|
||||||
m_reporters.push_back( reporter );
|
if( m_next )
|
||||||
|
m_next->add( reporter );
|
||||||
|
else
|
||||||
|
m_next = new MultipleReporters( reporter );
|
||||||
}
|
}
|
||||||
|
|
||||||
public: // IStreamingReporter
|
public: // IStreamingReporter
|
||||||
|
|
||||||
virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
|
virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
|
||||||
return m_reporters[0]->getPreferences();
|
return m_reporter->getPreferences();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
|
virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->noMatchingTestCases( spec );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->noMatchingTestCases( spec );
|
||||||
(*it)->noMatchingTestCases( spec );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
|
virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->testRunStarting( testRunInfo );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->testRunStarting( testRunInfo );
|
||||||
(*it)->testRunStarting( testRunInfo );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
|
virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->testGroupStarting( groupInfo );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->testGroupStarting( groupInfo );
|
||||||
(*it)->testGroupStarting( groupInfo );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->testCaseStarting( testInfo );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->testCaseStarting( testInfo );
|
||||||
(*it)->testCaseStarting( testInfo );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
|
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->sectionStarting( sectionInfo );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->sectionStarting( sectionInfo );
|
||||||
(*it)->sectionStarting( sectionInfo );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
|
virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->assertionStarting( assertionInfo );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->assertionStarting( assertionInfo );
|
||||||
(*it)->assertionStarting( assertionInfo );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// The return value indicates if the messages buffer should be cleared:
|
// The return value indicates if the messages buffer should be cleared:
|
||||||
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
|
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
|
||||||
bool clearBuffer = false;
|
bool clearBuffer = m_reporter->assertionEnded( assertionStats );
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
// Be careful with how the two calls' return values are anded.
|
||||||
it != itEnd;
|
// We don't want short-circuiting to eliminate one of the calls.
|
||||||
++it )
|
if( m_next && m_next->assertionEnded( assertionStats ) )
|
||||||
clearBuffer |= (*it)->assertionEnded( assertionStats );
|
return true;
|
||||||
return clearBuffer;
|
return clearBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
|
virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->sectionEnded( sectionStats );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->sectionEnded( sectionStats );
|
||||||
(*it)->sectionEnded( sectionStats );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
|
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->testCaseEnded( testCaseStats );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->testCaseEnded( testCaseStats );
|
||||||
(*it)->testCaseEnded( testCaseStats );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
|
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->testGroupEnded( testGroupStats );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->testGroupEnded( testGroupStats );
|
||||||
(*it)->testGroupEnded( testGroupStats );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
|
virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->testRunEnded( testRunStats );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->testRunEnded( testRunStats );
|
||||||
(*it)->testRunEnded( testRunStats );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
|
||||||
for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
|
m_reporter->skipTest( testInfo );
|
||||||
it != itEnd;
|
if( m_next )
|
||||||
++it )
|
m_next->skipTest( testInfo );
|
||||||
(*it)->skipTest( testInfo );
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
|
Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
|
||||||
Ptr<IStreamingReporter> resultingReporter;
|
if( !existingReporter )
|
||||||
|
return additionalReporter;
|
||||||
if( existingReporter ) {
|
return Ptr<IStreamingReporter>( new MultipleReporters(existingReporter, additionalReporter) );
|
||||||
MultipleReporters* multi = dynamic_cast<MultipleReporters*>( existingReporter.get() );
|
|
||||||
if( !multi ) {
|
|
||||||
multi = new MultipleReporters;
|
|
||||||
resultingReporter = Ptr<IStreamingReporter>( multi );
|
|
||||||
if( existingReporter )
|
|
||||||
multi->add( existingReporter );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
resultingReporter = existingReporter;
|
|
||||||
multi->add( additionalReporter );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
resultingReporter = additionalReporter;
|
|
||||||
|
|
||||||
return resultingReporter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user