diff --git a/src/catch2/reporters/catch_reporter_bases.cpp b/src/catch2/reporters/catch_reporter_bases.cpp index 09cec4f0..afcfcafc 100644 --- a/src/catch2/reporters/catch_reporter_bases.cpp +++ b/src/catch2/reporters/catch_reporter_bases.cpp @@ -19,9 +19,28 @@ #include 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 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 node; + if ( m_sectionStack.empty() ) { + if ( !m_rootSection ) + m_rootSection = + std::make_shared( 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( 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( 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( 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( testGroupStats ); + node->children.swap( m_testCases ); + m_testGroups.push_back( node ); + } + + void CumulativeReporterBase::testRunEnded( TestRunStats const& testRunStats ) { + auto node = std::make_shared( 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) { diff --git a/src/catch2/reporters/catch_reporter_bases.hpp b/src/catch2/reporters/catch_reporter_bases.hpp index d5f22181..55cbd2d0 100644 --- a/src/catch2/reporters/catch_reporter_bases.hpp +++ b/src/catch2/reporters/catch_reporter_bases.hpp @@ -19,8 +19,6 @@ #include 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 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; using TestGroupNode = Node; @@ -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 node; - if( m_sectionStack.empty() ) { - if( !m_rootSection ) - m_rootSection = std::make_shared( 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( 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( 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(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(testGroupStats); - node->children.swap(m_testCases); - m_testGroups.push_back(node); - } - void testRunEnded(TestRunStats const& testRunStats) override { - auto node = std::make_shared(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 {}