Move impls of CumulativeReporterBase member functions to .cpp file

`catch_reporter_bases.hpp` turned out fairly expensive for parsing
when building the main library, and the significant amount of code
in headers likely doesn't help. Since the reason it is in the header
is legacy from CRTP reporter bases, moving as much of the
implementations to the .cpp file is free compilation perf.
This commit is contained in:
Martin Hořeňovský 2020-07-27 07:32:21 +02:00
parent 5f6990d746
commit 258cac63f8
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
2 changed files with 103 additions and 83 deletions

View File

@ -19,9 +19,28 @@
#include <cassert> #include <cassert>
namespace Catch { namespace Catch {
void prepareExpandedExpression(AssertionResult& result) { namespace {
result.getExpandedExpression(); struct BySectionInfo {
} BySectionInfo( SectionInfo const& other ): m_other( other ) {}
BySectionInfo( BySectionInfo const& other ):
m_other( other.m_other ) {}
bool operator()(
std::shared_ptr<CumulativeReporterBase::SectionNode> const&
node ) const {
return (
( node->stats.sectionInfo.name == m_other.name ) &&
( node->stats.sectionInfo.lineInfo == m_other.lineInfo ) );
}
void operator=( BySectionInfo const& ) = delete;
private:
SectionInfo const& m_other;
};
void prepareExpandedExpression( AssertionResult& result ) {
result.getExpandedExpression();
}
} // namespace
// Because formatting using c++ streams is stateful, drop down to C is required // Because formatting using c++ streams is stateful, drop down to C is required
// Alternatively we could use stringstream, but its performance is... not good. // Alternatively we could use stringstream, but its performance is... not good.
@ -82,6 +101,80 @@ namespace Catch {
StreamingReporterBase::~StreamingReporterBase() = default; StreamingReporterBase::~StreamingReporterBase() = default;
CumulativeReporterBase::~CumulativeReporterBase() = default; CumulativeReporterBase::~CumulativeReporterBase() = default;
void
CumulativeReporterBase::sectionStarting( SectionInfo const& sectionInfo ) {
SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
std::shared_ptr<SectionNode> node;
if ( m_sectionStack.empty() ) {
if ( !m_rootSection )
m_rootSection =
std::make_shared<SectionNode>( incompleteStats );
node = m_rootSection;
} else {
SectionNode& parentNode = *m_sectionStack.back();
auto it = std::find_if( parentNode.childSections.begin(),
parentNode.childSections.end(),
BySectionInfo( sectionInfo ) );
if ( it == parentNode.childSections.end() ) {
node = std::make_shared<SectionNode>( incompleteStats );
parentNode.childSections.push_back( node );
} else {
node = *it;
}
}
m_sectionStack.push_back( node );
m_deepestSection = std::move( node );
}
bool CumulativeReporterBase::assertionEnded(
AssertionStats const& assertionStats ) {
assert( !m_sectionStack.empty() );
// AssertionResult holds a pointer to a temporary DecomposedExpression,
// which getExpandedExpression() calls to build the expression string.
// Our section stack copy of the assertionResult will likely outlive the
// temporary, so it must be expanded or discarded now to avoid calling
// a destroyed object later.
prepareExpandedExpression(
const_cast<AssertionResult&>( assertionStats.assertionResult ) );
SectionNode& sectionNode = *m_sectionStack.back();
sectionNode.assertions.push_back( assertionStats );
return true;
}
void CumulativeReporterBase::sectionEnded( SectionStats const& sectionStats ) {
assert( !m_sectionStack.empty() );
SectionNode& node = *m_sectionStack.back();
node.stats = sectionStats;
m_sectionStack.pop_back();
}
void CumulativeReporterBase::testCaseEnded(
TestCaseStats const& testCaseStats ) {
auto node = std::make_shared<TestCaseNode>( testCaseStats );
assert( m_sectionStack.size() == 0 );
node->children.push_back( m_rootSection );
m_testCases.push_back( node );
m_rootSection.reset();
assert( m_deepestSection );
m_deepestSection->stdOut = testCaseStats.stdOut;
m_deepestSection->stdErr = testCaseStats.stdErr;
}
void CumulativeReporterBase::testGroupEnded(
TestGroupStats const& testGroupStats ) {
auto node = std::make_shared<TestGroupNode>( testGroupStats );
node->children.swap( m_testCases );
m_testGroups.push_back( node );
}
void CumulativeReporterBase::testRunEnded( TestRunStats const& testRunStats ) {
auto node = std::make_shared<TestRunNode>( testRunStats );
node->children.swap( m_testGroups );
m_testRuns.push_back( node );
testRunEndedCumulative();
}
std::ostream& operator<<(std::ostream& out, lineOfChars value) { std::ostream& operator<<(std::ostream& out, lineOfChars value) {
for (size_t idx = 0; idx < CATCH_CONFIG_CONSOLE_WIDTH - 1; ++idx) { for (size_t idx = 0; idx < CATCH_CONFIG_CONSOLE_WIDTH - 1; ++idx) {

View File

@ -19,8 +19,6 @@
#include <iosfwd> #include <iosfwd>
namespace Catch { namespace Catch {
void prepareExpandedExpression(AssertionResult& result);
// Returns double formatted as %.3f (format expected on output) // Returns double formatted as %.3f (format expected on output)
std::string getFormattedDuration( double duration ); std::string getFormattedDuration( double duration );
@ -120,19 +118,6 @@ namespace Catch {
std::string stdErr; std::string stdErr;
}; };
struct BySectionInfo {
BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
bool operator() (std::shared_ptr<SectionNode> const& node) const {
return ((node->stats.sectionInfo.name == m_other.name) &&
(node->stats.sectionInfo.lineInfo == m_other.lineInfo));
}
void operator=(BySectionInfo const&) = delete;
private:
SectionInfo const& m_other;
};
using TestCaseNode = Node<TestCaseStats, SectionNode>; using TestCaseNode = Node<TestCaseStats, SectionNode>;
using TestGroupNode = Node<TestGroupStats, TestCaseNode>; using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
@ -155,73 +140,15 @@ namespace Catch {
void testCaseStarting( TestCaseInfo const& ) override {} void testCaseStarting( TestCaseInfo const& ) override {}
void sectionStarting( SectionInfo const& sectionInfo ) override { void sectionStarting( SectionInfo const& sectionInfo ) override;
SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
std::shared_ptr<SectionNode> node;
if( m_sectionStack.empty() ) {
if( !m_rootSection )
m_rootSection = std::make_shared<SectionNode>( incompleteStats );
node = m_rootSection;
}
else {
SectionNode& parentNode = *m_sectionStack.back();
auto it =
std::find_if( parentNode.childSections.begin(),
parentNode.childSections.end(),
BySectionInfo( sectionInfo ) );
if( it == parentNode.childSections.end() ) {
node = std::make_shared<SectionNode>( incompleteStats );
parentNode.childSections.push_back( node );
}
else
node = *it;
}
m_sectionStack.push_back( node );
m_deepestSection = std::move(node);
}
void assertionStarting(AssertionInfo const&) override {} void assertionStarting( AssertionInfo const& ) override {}
bool assertionEnded(AssertionStats const& assertionStats) override { bool assertionEnded( AssertionStats const& assertionStats ) override;
assert(!m_sectionStack.empty()); void sectionEnded( SectionStats const& sectionStats ) override;
// AssertionResult holds a pointer to a temporary DecomposedExpression, void testCaseEnded( TestCaseStats const& testCaseStats ) override;
// which getExpandedExpression() calls to build the expression string. void testGroupEnded( TestGroupStats const& testGroupStats ) override;
// Our section stack copy of the assertionResult will likely outlive the void testRunEnded( TestRunStats const& testRunStats ) override;
// temporary, so it must be expanded or discarded now to avoid calling
// a destroyed object later.
prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );
SectionNode& sectionNode = *m_sectionStack.back();
sectionNode.assertions.push_back(assertionStats);
return true;
}
void sectionEnded(SectionStats const& sectionStats) override {
assert(!m_sectionStack.empty());
SectionNode& node = *m_sectionStack.back();
node.stats = sectionStats;
m_sectionStack.pop_back();
}
void testCaseEnded(TestCaseStats const& testCaseStats) override {
auto node = std::make_shared<TestCaseNode>(testCaseStats);
assert(m_sectionStack.size() == 0);
node->children.push_back(m_rootSection);
m_testCases.push_back(node);
m_rootSection.reset();
assert(m_deepestSection);
m_deepestSection->stdOut = testCaseStats.stdOut;
m_deepestSection->stdErr = testCaseStats.stdErr;
}
void testGroupEnded(TestGroupStats const& testGroupStats) override {
auto node = std::make_shared<TestGroupNode>(testGroupStats);
node->children.swap(m_testCases);
m_testGroups.push_back(node);
}
void testRunEnded(TestRunStats const& testRunStats) override {
auto node = std::make_shared<TestRunNode>(testRunStats);
node->children.swap(m_testGroups);
m_testRuns.push_back(node);
testRunEndedCumulative();
}
virtual void testRunEndedCumulative() = 0; virtual void testRunEndedCumulative() = 0;
void skipTest(TestCaseInfo const&) override {} void skipTest(TestCaseInfo const&) override {}