1
0
mirror of https://github.com/catchorg/Catch2.git synced 2025-01-16 15:18:00 +00:00

Compare commits

...

3 Commits

Author SHA1 Message Date
Martin Hořeňovský
125d4b4164
Devirtualize test case registration 2020-07-27 08:49:49 +02:00
Martin Hořeňovský
c9b4867441
Move some impls of StreamingReporterBase members to .cpp file 2020-07-27 08:46:35 +02:00
Martin Hořeňovský
258cac63f8
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.
2020-07-27 07:32:21 +02:00
3 changed files with 118 additions and 92 deletions

View File

@ -35,7 +35,7 @@ namespace Catch {
public:
~TestRegistry() override = default;
virtual void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker );
void registerTest( Detail::unique_ptr<TestCaseInfo> testInfo, Detail::unique_ptr<ITestInvoker> testInvoker );
std::vector<TestCaseInfo*> const& getAllInfos() const override;
std::vector<TestCaseHandle> const& getAllTests() const override;

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.
@ -80,8 +99,94 @@ namespace Catch {
StreamingReporterBase::~StreamingReporterBase() = default;
void StreamingReporterBase::testGroupEnded( TestGroupStats const& ) {
currentGroupInfo.reset();
}
void StreamingReporterBase::testRunEnded( TestRunStats const& ) {
currentTestCaseInfo = nullptr;
currentGroupInfo.reset();
currentTestRunInfo.reset();
}
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 );
@ -69,14 +67,8 @@ namespace Catch {
void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {
currentTestCaseInfo = nullptr;
}
void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override {
currentGroupInfo.reset();
}
void testRunEnded(TestRunStats const& /* _testRunStats */) override {
currentTestCaseInfo = nullptr;
currentGroupInfo.reset();
currentTestRunInfo.reset();
}
void testGroupEnded( TestGroupStats const& ) override;
void testRunEnded( TestRunStats const& /* _testRunStats */ ) override;
void skipTest(TestCaseInfo const&) override {
// Don't do anything with this by default.
@ -120,19 +112,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 +134,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 {}