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>
namespace Catch {
void prepareExpandedExpression(AssertionResult& result) {
result.getExpandedExpression();
}
namespace {
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
// Alternatively we could use stringstream, but its performance is... not good.
@ -82,6 +101,80 @@ namespace Catch {
StreamingReporterBase::~StreamingReporterBase() = 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) {
for (size_t idx = 0; idx < CATCH_CONFIG_CONSOLE_WIDTH - 1; ++idx) {

View File

@ -19,8 +19,6 @@
#include <iosfwd>
namespace Catch {
void prepareExpandedExpression(AssertionResult& result);
// Returns double formatted as %.3f (format expected on output)
std::string getFormattedDuration( double duration );
@ -120,19 +118,6 @@ namespace Catch {
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 TestGroupNode = Node<TestGroupStats, TestCaseNode>;
@ -155,73 +140,15 @@ namespace Catch {
void testCaseStarting( TestCaseInfo const& ) 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 sectionStarting( SectionInfo const& sectionInfo ) override;
void assertionStarting(AssertionInfo const&) override {}
void assertionStarting( AssertionInfo const& ) override {}
bool assertionEnded(AssertionStats const& assertionStats) override {
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 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();
}
bool assertionEnded( AssertionStats const& assertionStats ) override;
void sectionEnded( SectionStats const& sectionStats ) override;
void testCaseEnded( TestCaseStats const& testCaseStats ) override;
void testGroupEnded( TestGroupStats const& testGroupStats ) override;
void testRunEnded( TestRunStats const& testRunStats ) override;
virtual void testRunEndedCumulative() = 0;
void skipTest(TestCaseInfo const&) override {}