From 5db31e587edd139529785b3341a8afe97f5e631e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 16 Mar 2023 23:49:24 +0100 Subject: [PATCH] WIP: devirtualize RunContext --- src/CMakeLists.txt | 4 +- src/catch2/benchmark/catch_benchmark.hpp | 3 +- .../detail/catch_complete_invoke.hpp | 1 - src/catch2/catch_all.hpp | 2 + src/catch2/catch_message.cpp | 2 +- src/catch2/catch_message.hpp | 4 +- src/catch2/catch_session.cpp | 3 +- src/catch2/catch_test_run_info.hpp | 23 +++ src/catch2/generators/catch_generators.cpp | 2 +- .../interfaces/catch_interfaces_all.hpp | 1 - .../interfaces/catch_interfaces_capture.cpp | 13 -- .../interfaces/catch_interfaces_capture.hpp | 110 ------------ .../interfaces/catch_interfaces_reporter.hpp | 11 +- .../internal/catch_assertion_handler.hpp | 6 +- .../internal/catch_benchmark_stats_fwd.hpp | 23 +++ src/catch2/internal/catch_context.cpp | 2 +- src/catch2/internal/catch_context.hpp | 8 +- .../catch_fatal_condition_handler.cpp | 2 +- src/catch2/internal/catch_message_info.hpp | 2 +- src/catch2/internal/catch_run_context.cpp | 163 +++++++++++------- src/catch2/internal/catch_run_context.hpp | 109 +++++++----- src/catch2/internal/catch_test_macro_impl.hpp | 1 - src/catch2/meson.build | 4 +- 23 files changed, 236 insertions(+), 263 deletions(-) create mode 100644 src/catch2/catch_test_run_info.hpp delete mode 100644 src/catch2/interfaces/catch_interfaces_capture.cpp delete mode 100644 src/catch2/interfaces/catch_interfaces_capture.hpp create mode 100644 src/catch2/internal/catch_benchmark_stats_fwd.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d115b3dd..68ff60a5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,6 +55,7 @@ set(IMPL_HEADERS ${SOURCES_DIR}/catch_template_test_macros.hpp ${SOURCES_DIR}/catch_test_case_info.hpp ${SOURCES_DIR}/catch_test_macros.hpp + ${SOURCES_DIR}/catch_test_run_info.hpp ${SOURCES_DIR}/catch_test_spec.hpp ${SOURCES_DIR}/catch_timer.hpp ${SOURCES_DIR}/catch_tostring.hpp @@ -63,6 +64,7 @@ set(IMPL_HEADERS ${SOURCES_DIR}/catch_version.hpp ${SOURCES_DIR}/catch_version_macros.hpp ${SOURCES_DIR}/internal/catch_assertion_handler.hpp + ${SOURCES_DIR}/internal/catch_benchmark_stats_fwd.hpp ${SOURCES_DIR}/internal/catch_case_insensitive_comparisons.hpp ${SOURCES_DIR}/internal/catch_case_sensitive.hpp ${SOURCES_DIR}/internal/catch_clara.hpp @@ -210,7 +212,6 @@ set(INTERNAL_FILES ${IMPL_SOURCES} ${IMPL_HEADERS}) set(INTERFACE_HEADERS ${SOURCES_DIR}/interfaces/catch_interfaces_all.hpp - ${SOURCES_DIR}/interfaces/catch_interfaces_capture.hpp ${SOURCES_DIR}/interfaces/catch_interfaces_config.hpp ${SOURCES_DIR}/interfaces/catch_interfaces_exception.hpp ${SOURCES_DIR}/interfaces/catch_interfaces_generatortracker.hpp @@ -219,7 +220,6 @@ set(INTERFACE_HEADERS ${SOURCES_DIR}/interfaces/catch_interfaces_testcase.hpp ) set(INTERFACE_SOURCES - ${SOURCES_DIR}/interfaces/catch_interfaces_capture.cpp ${SOURCES_DIR}/interfaces/catch_interfaces_config.cpp ${SOURCES_DIR}/interfaces/catch_interfaces_exception.cpp ${SOURCES_DIR}/interfaces/catch_interfaces_generatortracker.cpp diff --git a/src/catch2/benchmark/catch_benchmark.hpp b/src/catch2/benchmark/catch_benchmark.hpp index 6683dc05..f7307466 100644 --- a/src/catch2/benchmark/catch_benchmark.hpp +++ b/src/catch2/benchmark/catch_benchmark.hpp @@ -11,9 +11,10 @@ #define CATCH_BENCHMARK_HPP_INCLUDED #include +#include #include #include -#include +#include #include #include #include diff --git a/src/catch2/benchmark/detail/catch_complete_invoke.hpp b/src/catch2/benchmark/detail/catch_complete_invoke.hpp index d24da37d..6b6b13bf 100644 --- a/src/catch2/benchmark/detail/catch_complete_invoke.hpp +++ b/src/catch2/benchmark/detail/catch_complete_invoke.hpp @@ -12,7 +12,6 @@ #include #include -#include #include #include diff --git a/src/catch2/catch_all.hpp b/src/catch2/catch_all.hpp index d0fd8c6d..3dfd2eb6 100644 --- a/src/catch2/catch_all.hpp +++ b/src/catch2/catch_all.hpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ #include #include #include +#include #include #include #include diff --git a/src/catch2/catch_message.cpp b/src/catch2/catch_message.cpp index d4723e94..8414b53f 100644 --- a/src/catch2/catch_message.cpp +++ b/src/catch2/catch_message.cpp @@ -6,10 +6,10 @@ // SPDX-License-Identifier: BSL-1.0 #include -#include #include #include #include +#include #include #include diff --git a/src/catch2/catch_message.hpp b/src/catch2/catch_message.hpp index e6bc1b5d..b421c724 100644 --- a/src/catch2/catch_message.hpp +++ b/src/catch2/catch_message.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include @@ -61,7 +61,7 @@ namespace Catch { class Capturer { std::vector m_messages; - IResultCapture& m_resultCapture = getResultCapture(); + RunContext& m_resultCapture = getResultCapture(); size_t m_captured = 0; public: Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); diff --git a/src/catch2/catch_session.cpp b/src/catch2/catch_session.cpp index 681a82d9..84eeb33c 100644 --- a/src/catch2/catch_session.cpp +++ b/src/catch2/catch_session.cpp @@ -25,7 +25,8 @@ #include #include #include - +#include +#include #include #include diff --git a/src/catch2/catch_test_run_info.hpp b/src/catch2/catch_test_run_info.hpp new file mode 100644 index 00000000..5fca6879 --- /dev/null +++ b/src/catch2/catch_test_run_info.hpp @@ -0,0 +1,23 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +#ifndef CATCH_TEST_RUN_INFO_HPP_INCLUDED +#define CATCH_TEST_RUN_INFO_HPP_INCLUDED + +#include + +namespace Catch { + + struct TestRunInfo { + constexpr TestRunInfo(StringRef _name) : name(_name) {} + StringRef name; + }; + + +} // end namespace Catch + +#endif // CATCH_TEST_RUN_INFO_HPP_INCLUDED diff --git a/src/catch2/generators/catch_generators.cpp b/src/catch2/generators/catch_generators.cpp index 3514e9f6..265ef37e 100644 --- a/src/catch2/generators/catch_generators.cpp +++ b/src/catch2/generators/catch_generators.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include namespace Catch { diff --git a/src/catch2/interfaces/catch_interfaces_all.hpp b/src/catch2/interfaces/catch_interfaces_all.hpp index 8ee9dcea..00c2fb2c 100644 --- a/src/catch2/interfaces/catch_interfaces_all.hpp +++ b/src/catch2/interfaces/catch_interfaces_all.hpp @@ -22,7 +22,6 @@ #ifndef CATCH_INTERFACES_ALL_HPP_INCLUDED #define CATCH_INTERFACES_ALL_HPP_INCLUDED -#include #include #include #include diff --git a/src/catch2/interfaces/catch_interfaces_capture.cpp b/src/catch2/interfaces/catch_interfaces_capture.cpp deleted file mode 100644 index 9b40ee5d..00000000 --- a/src/catch2/interfaces/catch_interfaces_capture.cpp +++ /dev/null @@ -1,13 +0,0 @@ - -// Copyright Catch2 Authors -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.txt or copy at -// https://www.boost.org/LICENSE_1_0.txt) - -// SPDX-License-Identifier: BSL-1.0 - -#include - -namespace Catch { - IResultCapture::~IResultCapture() = default; -} diff --git a/src/catch2/interfaces/catch_interfaces_capture.hpp b/src/catch2/interfaces/catch_interfaces_capture.hpp deleted file mode 100644 index c3c80d75..00000000 --- a/src/catch2/interfaces/catch_interfaces_capture.hpp +++ /dev/null @@ -1,110 +0,0 @@ - -// Copyright Catch2 Authors -// Distributed under the Boost Software License, Version 1.0. -// (See accompanying file LICENSE.txt or copy at -// https://www.boost.org/LICENSE_1_0.txt) - -// SPDX-License-Identifier: BSL-1.0 -#ifndef CATCH_INTERFACES_CAPTURE_HPP_INCLUDED -#define CATCH_INTERFACES_CAPTURE_HPP_INCLUDED - -#include -#include - -#include -#include -#include - -namespace Catch { - - class AssertionResult; - struct AssertionInfo; - struct SectionInfo; - struct SectionEndInfo; - struct MessageInfo; - struct MessageBuilder; - struct Counts; - struct AssertionReaction; - struct SourceLineInfo; - - class ITransientExpression; - class IGeneratorTracker; - - struct BenchmarkInfo; - template > - struct BenchmarkStats; - - namespace Generators { - class GeneratorUntypedBase; - using GeneratorBasePtr = Catch::Detail::unique_ptr; - } - - - class IResultCapture { - public: - virtual ~IResultCapture(); - - virtual bool sectionStarted( StringRef sectionName, - SourceLineInfo const& sectionLineInfo, - Counts& assertions ) = 0; - virtual void sectionEnded( SectionEndInfo&& endInfo ) = 0; - virtual void sectionEndedEarly( SectionEndInfo&& endInfo ) = 0; - - virtual IGeneratorTracker* - acquireGeneratorTracker( StringRef generatorName, - SourceLineInfo const& lineInfo ) = 0; - virtual IGeneratorTracker* - createGeneratorTracker( StringRef generatorName, - SourceLineInfo lineInfo, - Generators::GeneratorBasePtr&& generator ) = 0; - - virtual void benchmarkPreparing( StringRef name ) = 0; - virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; - virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0; - virtual void benchmarkFailed( StringRef error ) = 0; - - virtual void pushScopedMessage( MessageInfo const& message ) = 0; - virtual void popScopedMessage( MessageInfo const& message ) = 0; - - virtual void emplaceUnscopedMessage( MessageBuilder&& builder ) = 0; - - virtual void handleFatalErrorCondition( StringRef message ) = 0; - - virtual void handleExpr - ( AssertionInfo const& info, - ITransientExpression const& expr, - AssertionReaction& reaction ) = 0; - virtual void handleMessage - ( AssertionInfo const& info, - ResultWas::OfType resultType, - StringRef message, - AssertionReaction& reaction ) = 0; - virtual void handleUnexpectedExceptionNotThrown - ( AssertionInfo const& info, - AssertionReaction& reaction ) = 0; - virtual void handleUnexpectedInflightException - ( AssertionInfo const& info, - std::string&& message, - AssertionReaction& reaction ) = 0; - virtual void handleIncomplete - ( AssertionInfo const& info ) = 0; - virtual void handleNonExpr - ( AssertionInfo const &info, - ResultWas::OfType resultType, - AssertionReaction &reaction ) = 0; - - - - virtual bool lastAssertionPassed() = 0; - virtual void assertionPassed() = 0; - - // Deprecated, do not use: - virtual std::string getCurrentTestName() const = 0; - virtual const AssertionResult* getLastResult() const = 0; - virtual void exceptionEarlyReported() = 0; - }; - - IResultCapture& getResultCapture(); -} - -#endif // CATCH_INTERFACES_CAPTURE_HPP_INCLUDED diff --git a/src/catch2/interfaces/catch_interfaces_reporter.hpp b/src/catch2/interfaces/catch_interfaces_reporter.hpp index cf414f10..ad9c90fa 100644 --- a/src/catch2/interfaces/catch_interfaces_reporter.hpp +++ b/src/catch2/interfaces/catch_interfaces_reporter.hpp @@ -9,6 +9,7 @@ #define CATCH_INTERFACES_REPORTER_HPP_INCLUDED #include +#include #include #include #include @@ -17,15 +18,18 @@ #include #include #include - +#include #include #include #include #include +#include namespace Catch { + struct BenchmarkInfo; + struct ReporterDescription; struct ListenerDescription; struct TagInfo; @@ -57,11 +61,6 @@ namespace Catch { std::map m_customOptions; }; - struct TestRunInfo { - constexpr TestRunInfo(StringRef _name) : name(_name) {} - StringRef name; - }; - struct AssertionStats { AssertionStats( AssertionResult const& _assertionResult, std::vector const& _infoMessages, diff --git a/src/catch2/internal/catch_assertion_handler.hpp b/src/catch2/internal/catch_assertion_handler.hpp index ee7188ba..c8f8e469 100644 --- a/src/catch2/internal/catch_assertion_handler.hpp +++ b/src/catch2/internal/catch_assertion_handler.hpp @@ -10,14 +10,14 @@ #include #include -#include +#include #include #include namespace Catch { - class IResultCapture; + class RunContext; struct AssertionReaction { bool shouldDebugBreak = false; @@ -29,7 +29,7 @@ namespace Catch { AssertionInfo m_assertionInfo; AssertionReaction m_reaction; bool m_completed = false; - IResultCapture& m_resultCapture; + RunContext& m_resultCapture; public: AssertionHandler diff --git a/src/catch2/internal/catch_benchmark_stats_fwd.hpp b/src/catch2/internal/catch_benchmark_stats_fwd.hpp new file mode 100644 index 00000000..60772561 --- /dev/null +++ b/src/catch2/internal/catch_benchmark_stats_fwd.hpp @@ -0,0 +1,23 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +#ifndef CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED +#define CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED + +#include + +namespace Catch { + + // We cannot forward declare the type with default template argument + // multiple times, so it is split out into a separate header so that + // we can prevent multiple declarations in dependees + template > + struct BenchmarkStats; + +} // end namespace Catch + +#endif // CATCH_BENCHMARK_STATS_FWD_HPP_INCLUDED diff --git a/src/catch2/internal/catch_context.cpp b/src/catch2/internal/catch_context.cpp index 3b1cc277..9151c385 100644 --- a/src/catch2/internal/catch_context.cpp +++ b/src/catch2/internal/catch_context.cpp @@ -27,7 +27,7 @@ namespace Catch { return *Context::currentContext; } - void Context::setResultCapture( IResultCapture* resultCapture ) { + void Context::setResultCapture( RunContext* resultCapture ) { m_resultCapture = resultCapture; } diff --git a/src/catch2/internal/catch_context.hpp b/src/catch2/internal/catch_context.hpp index 6ccb3b31..90838da2 100644 --- a/src/catch2/internal/catch_context.hpp +++ b/src/catch2/internal/catch_context.hpp @@ -12,12 +12,12 @@ namespace Catch { - class IResultCapture; + class RunContext; class IConfig; class Context { IConfig const* m_config = nullptr; - IResultCapture* m_resultCapture = nullptr; + RunContext* m_resultCapture = nullptr; CATCH_EXPORT static Context* currentContext; friend Context& getCurrentMutableContext(); @@ -26,9 +26,9 @@ namespace Catch { friend void cleanUpContext(); public: - IResultCapture* getResultCapture() const { return m_resultCapture; } + RunContext* getResultCapture() const { return m_resultCapture; } IConfig const* getConfig() const { return m_config; } - void setResultCapture( IResultCapture* resultCapture ); + void setResultCapture( RunContext* resultCapture ); void setConfig( IConfig const* config ); }; diff --git a/src/catch2/internal/catch_fatal_condition_handler.cpp b/src/catch2/internal/catch_fatal_condition_handler.cpp index f9702b18..84321123 100644 --- a/src/catch2/internal/catch_fatal_condition_handler.cpp +++ b/src/catch2/internal/catch_fatal_condition_handler.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include diff --git a/src/catch2/internal/catch_message_info.hpp b/src/catch2/internal/catch_message_info.hpp index d2658429..1ef43fda 100644 --- a/src/catch2/internal/catch_message_info.hpp +++ b/src/catch2/internal/catch_message_info.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include #include diff --git a/src/catch2/internal/catch_run_context.cpp b/src/catch2/internal/catch_run_context.cpp index 11fcda45..bdac876b 100644 --- a/src/catch2/internal/catch_run_context.cpp +++ b/src/catch2/internal/catch_run_context.cpp @@ -7,7 +7,11 @@ // SPDX-License-Identifier: BSL-1.0 #include +#include +#include +#include #include +#include #include #include #include @@ -15,10 +19,14 @@ #include #include #include -#include #include #include #include +#include +#include +#include +#include +#include #include #include @@ -164,30 +172,44 @@ namespace Catch { } // namespace } - RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter) - : m_runInfo(_config->name()), + + struct RunContext::RunContextImpl { + Optional lastResult; + FatalConditionHandler fatalConditionhandler; + TrackerContext trackerContext; + std::vector messages; + // Fake owners for unscoped messages + std::vector messageScopes; + IEventListenerPtr reporter; + std::vector unfinishedSections; + std::vector activeSections; + }; + + RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter): + m_impl( Detail::make_unique() ), + m_runInfo(_config->name()), m_config(_config), - m_reporter(CATCH_MOVE(reporter)), m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal }, - m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions ) + m_includeSuccessfulResults( m_config->includeSuccessfulResults() || reporter->getPreferences().shouldReportAllAssertions ) { - getCurrentMutableContext().setResultCapture( this ); - m_reporter->testRunStarting(m_runInfo); + getCurrentMutableContext().setResultCapture(this); + m_impl->reporter = CATCH_MOVE( reporter ); + m_impl->reporter->testRunStarting(m_runInfo); } RunContext::~RunContext() { - m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); + m_impl->reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); } Totals RunContext::runTest(TestCaseHandle const& testCase) { const Totals prevTotals = m_totals; auto const& testInfo = testCase.getTestCaseInfo(); - m_reporter->testCaseStarting(testInfo); + m_impl->reporter->testCaseStarting( testInfo ); m_activeTestCase = &testCase; - ITracker& rootTracker = m_trackerContext.startRun(); + ITracker& rootTracker = m_impl->trackerContext.startRun(); assert(rootTracker.isSectionTracker()); static_cast(rootTracker).addInitialFilters(m_config->getSectionsToRun()); @@ -228,10 +250,10 @@ namespace Catch { std::string redirectedCout; std::string redirectedCerr; do { - m_trackerContext.startCycle(); - m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocationRef(testInfo.name, testInfo.lineInfo)); + m_impl->trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire(m_impl->trackerContext, TestCaseTracking::NameAndLocationRef(testInfo.name, testInfo.lineInfo)); - m_reporter->testCasePartialStarting(testInfo, testRuns); + m_impl->reporter->testCasePartialStarting( testInfo, testRuns ); const auto beforeRunTotals = m_totals; std::string oneRunCout, oneRunCerr; @@ -242,7 +264,7 @@ namespace Catch { const auto singleRunTotals = m_totals.delta(beforeRunTotals); auto statsForOneRun = TestCaseStats(testInfo, singleRunTotals, CATCH_MOVE(oneRunCout), CATCH_MOVE(oneRunCerr), aborting()); - m_reporter->testCasePartialEnded(statsForOneRun, testRuns); + m_impl->reporter->testCasePartialEnded( statsForOneRun, testRuns ); ++testRuns; } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); @@ -253,11 +275,12 @@ namespace Catch { deltaTotals.testCases.failed++; } m_totals.testCases += deltaTotals.testCases; - m_reporter->testCaseEnded(TestCaseStats(testInfo, - deltaTotals, - CATCH_MOVE(redirectedCout), - CATCH_MOVE(redirectedCerr), - aborting())); + m_impl->reporter->testCaseEnded( + TestCaseStats( testInfo, + deltaTotals, + CATCH_MOVE( redirectedCout ), + CATCH_MOVE( redirectedCerr ), + aborting() ) ); m_activeTestCase = nullptr; m_testCaseTracker = nullptr; @@ -286,14 +309,15 @@ namespace Catch { m_lastAssertionPassed = true; } - m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)); + m_impl->reporter->assertionEnded(AssertionStats(result, m_impl->messages, m_totals)); - if (result.getResultType() != ResultWas::Warning) - m_messageScopes.clear(); + if ( result.getResultType() != ResultWas::Warning ) { + m_impl->messageScopes.clear(); + } // Reset working state resetAssertionInfo(); - m_lastResult = result; + m_impl->lastResult = result; } void RunContext::resetAssertionInfo() { m_lastAssertionInfo.macroName = StringRef(); @@ -302,18 +326,18 @@ namespace Catch { bool RunContext::sectionStarted(StringRef sectionName, SourceLineInfo const& sectionLineInfo, Counts & assertions) { ITracker& sectionTracker = - SectionTracker::acquire( m_trackerContext, + SectionTracker::acquire( m_impl->trackerContext, TestCaseTracking::NameAndLocationRef( sectionName, sectionLineInfo ) ); if (!sectionTracker.isOpen()) return false; - m_activeSections.push_back(§ionTracker); + m_impl->activeSections.push_back(§ionTracker); SectionInfo sectionInfo( sectionLineInfo, static_cast(sectionName) ); m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; - m_reporter->sectionStarting(sectionInfo); + m_impl->reporter->sectionStarting( sectionInfo ); assertions = m_totals.assertions; @@ -324,7 +348,7 @@ namespace Catch { SourceLineInfo const& lineInfo ) { using namespace Generators; GeneratorTracker* tracker = GeneratorTracker::acquire( - m_trackerContext, + m_impl->trackerContext, TestCaseTracking::NameAndLocationRef( generatorName, lineInfo ) ); m_lastAssertionInfo.lineInfo = lineInfo; @@ -337,13 +361,13 @@ namespace Catch { Generators::GeneratorBasePtr&& generator ) { auto nameAndLoc = TestCaseTracking::NameAndLocation( static_cast( generatorName ), lineInfo ); - auto& currentTracker = m_trackerContext.currentTracker(); + auto& currentTracker = m_impl->trackerContext.currentTracker(); assert( currentTracker.nameAndLocation() != nameAndLoc && "Trying to create tracker for a genreator that already has one" ); auto newTracker = Catch::Detail::make_unique( - CATCH_MOVE(nameAndLoc), m_trackerContext, ¤tTracker ); + CATCH_MOVE(nameAndLoc), m_impl->trackerContext, ¤tTracker ); auto ret = newTracker.get(); currentTracker.addChild( CATCH_MOVE( newTracker ) ); @@ -357,7 +381,7 @@ namespace Catch { return false; if (!m_config->warnAboutMissingAssertions()) return false; - if (m_trackerContext.currentTracker().hasChildren()) + if (m_impl->trackerContext.currentTracker().hasChildren()) return false; m_totals.assertions.failed++; assertions.failed++; @@ -368,50 +392,57 @@ namespace Catch { Counts assertions = m_totals.assertions - endInfo.prevAssertions; bool missingAssertions = testForMissingAssertions(assertions); - if (!m_activeSections.empty()) { - m_activeSections.back()->close(); - m_activeSections.pop_back(); + if (!m_impl->activeSections.empty()) { + m_impl->activeSections.back()->close(); + m_impl->activeSections.pop_back(); } - m_reporter->sectionEnded(SectionStats(CATCH_MOVE(endInfo.sectionInfo), assertions, endInfo.durationInSeconds, missingAssertions)); - m_messages.clear(); - m_messageScopes.clear(); + m_impl->reporter->sectionEnded( + SectionStats( CATCH_MOVE( endInfo.sectionInfo ), + assertions, + endInfo.durationInSeconds, + missingAssertions ) ); + m_impl->messages.clear(); + m_impl->messageScopes.clear(); } void RunContext::sectionEndedEarly(SectionEndInfo&& endInfo) { - if ( m_unfinishedSections.empty() ) { - m_activeSections.back()->fail(); + if ( m_impl->unfinishedSections.empty() ) { + m_impl->activeSections.back()->fail(); } else { - m_activeSections.back()->close(); + m_impl->activeSections.back()->close(); } - m_activeSections.pop_back(); + m_impl->activeSections.pop_back(); - m_unfinishedSections.push_back(CATCH_MOVE(endInfo)); + m_impl->unfinishedSections.push_back(CATCH_MOVE(endInfo)); } void RunContext::benchmarkPreparing( StringRef name ) { - m_reporter->benchmarkPreparing(name); + m_impl->reporter->benchmarkPreparing( name ); } void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { - m_reporter->benchmarkStarting( info ); + m_impl->reporter->benchmarkStarting( info ); } void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) { - m_reporter->benchmarkEnded( stats ); + m_impl->reporter->benchmarkEnded( stats ); } void RunContext::benchmarkFailed( StringRef error ) { - m_reporter->benchmarkFailed( error ); + m_impl->reporter->benchmarkFailed( error ); } void RunContext::pushScopedMessage(MessageInfo const & message) { - m_messages.push_back(message); + m_impl->messages.push_back(message); } void RunContext::popScopedMessage(MessageInfo const & message) { - m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); + m_impl->messages.erase( std::remove( m_impl->messages.begin(), + m_impl->messages.end(), + message ), + m_impl->messages.end() ); } void RunContext::emplaceUnscopedMessage( MessageBuilder&& builder ) { - m_messageScopes.emplace_back( CATCH_MOVE(builder) ); + m_impl->messageScopes.emplace_back( CATCH_MOVE(builder) ); } std::string RunContext::getCurrentTestName() const { @@ -421,7 +452,7 @@ namespace Catch { } const AssertionResult * RunContext::getLastResult() const { - return &(*m_lastResult); + return &(*m_impl->lastResult); } void RunContext::exceptionEarlyReported() { @@ -430,7 +461,7 @@ namespace Catch { void RunContext::handleFatalErrorCondition( StringRef message ) { // First notify reporter that bad things happened - m_reporter->fatalErrorEncountered(message); + m_impl->reporter->fatalErrorEncountered(message); // Don't rebuild the result -- the stringification itself can cause more fatal errors // Instead, fake a result data. @@ -449,20 +480,20 @@ namespace Catch { Counts assertions; assertions.failed = 1; SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, 0, false); - m_reporter->sectionEnded(testCaseSectionStats); + m_impl->reporter->sectionEnded(testCaseSectionStats); auto const& testInfo = m_activeTestCase->getTestCaseInfo(); Totals deltaTotals; deltaTotals.testCases.failed = 1; deltaTotals.assertions.failed = 1; - m_reporter->testCaseEnded(TestCaseStats(testInfo, + m_impl->reporter->testCaseEnded(TestCaseStats(testInfo, deltaTotals, std::string(), std::string(), false)); m_totals.testCases.failed++; - m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); + m_impl->reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); } bool RunContext::lastAssertionPassed() { @@ -473,7 +504,7 @@ namespace Catch { m_lastAssertionPassed = true; ++m_totals.assertions.passed; resetAssertionInfo(); - m_messageScopes.clear(); + m_impl->messageScopes.clear(); } bool RunContext::aborting() const { @@ -483,7 +514,7 @@ namespace Catch { void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name); - m_reporter->sectionStarting(testCaseSection); + m_impl->reporter->sectionStarting(testCaseSection); Counts prevAssertions = m_totals.assertions; double duration = 0; m_shouldReportUnexpected = true; @@ -491,7 +522,7 @@ namespace Catch { Timer timer; CATCH_TRY { - if (m_reporter->getPreferences().shouldRedirectStdOut) { + if (m_impl->reporter->getPreferences().shouldRedirectStdOut) { #if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr); @@ -524,18 +555,18 @@ namespace Catch { m_testCaseTracker->close(); handleUnfinishedSections(); - m_messages.clear(); - m_messageScopes.clear(); + m_impl->messages.clear(); + m_impl->messageScopes.clear(); SectionStats testCaseSectionStats(CATCH_MOVE(testCaseSection), assertions, duration, missingAssertions); - m_reporter->sectionEnded(testCaseSectionStats); + m_impl->reporter->sectionEnded(testCaseSectionStats); } void RunContext::invokeActiveTestCase() { // We need to engage a handler for signals/structured exceptions // before running the tests themselves, or the binary can crash // without failed test being reported. - FatalConditionHandlerGuard _(&m_fatalConditionhandler); + FatalConditionHandlerGuard _(&m_impl->fatalConditionhandler); // We keep having issue where some compilers warn about an unused // variable, even though the type has non-trivial constructor and // destructor. This is annoying and ugly, but it makes them stfu. @@ -547,12 +578,12 @@ namespace Catch { void RunContext::handleUnfinishedSections() { // If sections ended prematurely due to an exception we stored their // infos here so we can tear them down outside the unwind process. - for (auto it = m_unfinishedSections.rbegin(), - itEnd = m_unfinishedSections.rend(); + for (auto it = m_impl->unfinishedSections.rbegin(), + itEnd = m_impl->unfinishedSections.rend(); it != itEnd; ++it) sectionEnded(CATCH_MOVE(*it)); - m_unfinishedSections.clear(); + m_impl->unfinishedSections.clear(); } void RunContext::handleExpr( @@ -560,7 +591,7 @@ namespace Catch { ITransientExpression const& expr, AssertionReaction& reaction ) { - m_reporter->assertionStarting( info ); + m_impl->reporter->assertionStarting( info ); bool negated = isFalseTest( info.resultDisposition ); bool result = expr.getResult() != negated; @@ -599,7 +630,7 @@ namespace Catch { StringRef message, AssertionReaction& reaction ) { - m_reporter->assertionStarting( info ); + m_impl->reporter->assertionStarting( info ); m_lastAssertionInfo = info; @@ -669,7 +700,7 @@ namespace Catch { } - IResultCapture& getResultCapture() { + RunContext& getResultCapture() { if (auto* capture = getCurrentContext().getResultCapture()) return *capture; else diff --git a/src/catch2/internal/catch_run_context.hpp b/src/catch2/internal/catch_run_context.hpp index de6999e5..ad45db54 100644 --- a/src/catch2/internal/catch_run_context.hpp +++ b/src/catch2/internal/catch_run_context.hpp @@ -8,36 +8,60 @@ #ifndef CATCH_RUN_CONTEXT_HPP_INCLUDED #define CATCH_RUN_CONTEXT_HPP_INCLUDED -#include -#include -#include -#include -#include +#include #include -#include #include -#include -#include -#include +#include +#include #include +#include namespace Catch { + class TestCaseHandle; + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + struct MessageBuilder; + struct Counts; + struct AssertionReaction; + struct SourceLineInfo; + + class ITransientExpression; + class IGeneratorTracker; + + struct BenchmarkInfo; + + namespace Generators { + class GeneratorUntypedBase; + using GeneratorBasePtr = Catch::Detail::unique_ptr; + } + + class IGeneratorTracker; class IConfig; + // Fixme: Take out the namespace? + namespace TestCaseTracking { + class ITracker; + } + using TestCaseTracking::ITracker; - /////////////////////////////////////////////////////////////////////////// - - class RunContext final : public IResultCapture { + class IEventListener; + using IEventListenerPtr = Detail::unique_ptr; + class RunContext { + struct RunContextImpl; + Detail::unique_ptr m_impl; public: RunContext( RunContext const& ) = delete; RunContext& operator =( RunContext const& ) = delete; explicit RunContext( IConfig const* _config, IEventListenerPtr&& reporter ); - ~RunContext() override; + ~RunContext(); Totals runTest(TestCaseHandle const& testCase); @@ -47,63 +71,63 @@ namespace Catch { void handleExpr ( AssertionInfo const& info, ITransientExpression const& expr, - AssertionReaction& reaction ) override; + AssertionReaction& reaction ); void handleMessage ( AssertionInfo const& info, ResultWas::OfType resultType, StringRef message, - AssertionReaction& reaction ) override; + AssertionReaction& reaction ); void handleUnexpectedExceptionNotThrown ( AssertionInfo const& info, - AssertionReaction& reaction ) override; + AssertionReaction& reaction ); void handleUnexpectedInflightException ( AssertionInfo const& info, std::string&& message, - AssertionReaction& reaction ) override; + AssertionReaction& reaction ); void handleIncomplete - ( AssertionInfo const& info ) override; + ( AssertionInfo const& info ); void handleNonExpr ( AssertionInfo const &info, ResultWas::OfType resultType, - AssertionReaction &reaction ) override; + AssertionReaction &reaction ); bool sectionStarted( StringRef sectionName, SourceLineInfo const& sectionLineInfo, - Counts& assertions ) override; + Counts& assertions ); - void sectionEnded( SectionEndInfo&& endInfo ) override; - void sectionEndedEarly( SectionEndInfo&& endInfo ) override; + void sectionEnded( SectionEndInfo&& endInfo ); + void sectionEndedEarly( SectionEndInfo&& endInfo ); IGeneratorTracker* acquireGeneratorTracker( StringRef generatorName, - SourceLineInfo const& lineInfo ) override; + SourceLineInfo const& lineInfo ); IGeneratorTracker* createGeneratorTracker( StringRef generatorName, SourceLineInfo lineInfo, - Generators::GeneratorBasePtr&& generator ) override; + Generators::GeneratorBasePtr&& generator ); - void benchmarkPreparing( StringRef name ) override; - void benchmarkStarting( BenchmarkInfo const& info ) override; - void benchmarkEnded( BenchmarkStats<> const& stats ) override; - void benchmarkFailed( StringRef error ) override; + void benchmarkPreparing( StringRef name ); + void benchmarkStarting( BenchmarkInfo const& info ); + void benchmarkEnded( BenchmarkStats<> const& stats ); + void benchmarkFailed( StringRef error ); - void pushScopedMessage( MessageInfo const& message ) override; - void popScopedMessage( MessageInfo const& message ) override; + void pushScopedMessage( MessageInfo const& message ); + void popScopedMessage( MessageInfo const& message ); - void emplaceUnscopedMessage( MessageBuilder&& builder ) override; + void emplaceUnscopedMessage( MessageBuilder&& builder ); - std::string getCurrentTestName() const override; + std::string getCurrentTestName() const; - const AssertionResult* getLastResult() const override; + const AssertionResult* getLastResult() const; - void exceptionEarlyReported() override; + void exceptionEarlyReported(); - void handleFatalErrorCondition( StringRef message ) override; + void handleFatalErrorCondition( StringRef message ); - bool lastAssertionPassed() override; + bool lastAssertionPassed(); - void assertionPassed() override; + void assertionPassed(); public: // !TBD We need to do this another way! @@ -133,18 +157,10 @@ namespace Catch { TestRunInfo m_runInfo; TestCaseHandle const* m_activeTestCase = nullptr; ITracker* m_testCaseTracker = nullptr; - Optional m_lastResult; IConfig const* m_config; Totals m_totals; - IEventListenerPtr m_reporter; - std::vector m_messages; - std::vector m_messageScopes; /* Keeps owners of so-called unscoped messages. */ AssertionInfo m_lastAssertionInfo; - std::vector m_unfinishedSections; - std::vector m_activeSections; - TrackerContext m_trackerContext; - FatalConditionHandler m_fatalConditionhandler; bool m_lastAssertionPassed = false; bool m_shouldReportUnexpected = true; bool m_includeSuccessfulResults; @@ -152,6 +168,9 @@ namespace Catch { void seedRng(IConfig const& config); unsigned int rngSeed(); + + RunContext& getResultCapture(); + } // end namespace Catch #endif // CATCH_RUN_CONTEXT_HPP_INCLUDED diff --git a/src/catch2/internal/catch_test_macro_impl.hpp b/src/catch2/internal/catch_test_macro_impl.hpp index e569680b..e05e2c20 100644 --- a/src/catch2/internal/catch_test_macro_impl.hpp +++ b/src/catch2/internal/catch_test_macro_impl.hpp @@ -10,7 +10,6 @@ #include #include -#include #include #include diff --git a/src/catch2/meson.build b/src/catch2/meson.build index 9b84f79a..0961edbe 100644 --- a/src/catch2/meson.build +++ b/src/catch2/meson.build @@ -56,7 +56,6 @@ internal_headers = [ 'generators/catch_generators_random.hpp', 'generators/catch_generators_range.hpp', 'interfaces/catch_interfaces_all.hpp', - 'interfaces/catch_interfaces_capture.hpp', 'interfaces/catch_interfaces_config.hpp', 'interfaces/catch_interfaces_exception.hpp', 'interfaces/catch_interfaces_generatortracker.hpp', @@ -64,6 +63,7 @@ internal_headers = [ 'interfaces/catch_interfaces_reporter_factory.hpp', 'interfaces/catch_interfaces_testcase.hpp', 'internal/catch_assertion_handler.hpp', + 'internal/catch_benchmark_stats_fwd.hpp', 'internal/catch_case_insensitive_comparisons.hpp', 'internal/catch_case_sensitive.hpp', 'internal/catch_clara.hpp', @@ -165,6 +165,7 @@ internal_headers = [ 'catch_template_test_macros.hpp', 'catch_test_case_info.hpp', 'catch_test_macros.hpp', + 'catch_test_run_info.hpp', 'catch_test_spec.hpp', 'catch_timer.hpp', 'catch_tostring.hpp', @@ -178,7 +179,6 @@ internal_sources = files( 'generators/catch_generator_exception.cpp', 'generators/catch_generators.cpp', 'generators/catch_generators_random.cpp', - 'interfaces/catch_interfaces_capture.cpp', 'interfaces/catch_interfaces_config.cpp', 'interfaces/catch_interfaces_exception.cpp', 'interfaces/catch_interfaces_generatortracker.cpp',