From 99575b45db0ec0de2fb84b5e5cce7e93559387e5 Mon Sep 17 00:00:00 2001 From: Omer Ozarslan Date: Fri, 1 Feb 2019 09:11:30 -0600 Subject: [PATCH] Add unscoped info functionality This adds UNSCOPED_INFO macro, creating a log message that is stored until the end of next assertion or the end of test case, whichever comes first. These messages are not scoped locally, unlike messages created by INFO macro. --- include/catch.hpp | 1 + include/internal/catch_capture.hpp | 4 ++++ include/internal/catch_interfaces_capture.h | 3 +++ include/internal/catch_message.cpp | 10 ++++++++-- include/internal/catch_message.h | 3 +++ include/internal/catch_run_context.cpp | 10 ++++++++++ include/internal/catch_run_context.h | 3 +++ 7 files changed, 32 insertions(+), 2 deletions(-) diff --git a/include/catch.hpp b/include/catch.hpp index e4fd40fe..88a9abe6 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -215,6 +215,7 @@ #endif // CATCH_CONFIG_DISABLE_MATCHERS #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) +#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index de21955e..303e891a 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -130,6 +130,10 @@ #define INTERNAL_CATCH_INFO( macroName, log ) \ Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ + Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) + /////////////////////////////////////////////////////////////////////////////// // Although this is matcher-based, it can be used with just a string #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ diff --git a/include/internal/catch_interfaces_capture.h b/include/internal/catch_interfaces_capture.h index 950d498d..36f27a33 100644 --- a/include/internal/catch_interfaces_capture.h +++ b/include/internal/catch_interfaces_capture.h @@ -20,6 +20,7 @@ namespace Catch { struct SectionInfo; struct SectionEndInfo; struct MessageInfo; + struct MessageBuilder; struct Counts; struct BenchmarkInfo; struct BenchmarkStats; @@ -46,6 +47,8 @@ namespace Catch { virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void popScopedMessage( MessageInfo const& message ) = 0; + virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0; + virtual void handleFatalErrorCondition( StringRef message ) = 0; virtual void handleExpr diff --git a/include/internal/catch_message.cpp b/include/internal/catch_message.cpp index 98a4dae1..fa7e8746 100644 --- a/include/internal/catch_message.cpp +++ b/include/internal/catch_message.cpp @@ -47,14 +47,20 @@ namespace Catch { ScopedMessage::ScopedMessage( MessageBuilder const& builder ) - : m_info( builder.m_info ) + : m_info( builder.m_info ), m_moved() { m_info.message = builder.m_stream.str(); getResultCapture().pushScopedMessage( m_info ); } + ScopedMessage::ScopedMessage( ScopedMessage&& old ) + : m_info( old.m_info ), m_moved() + { + old.m_moved = true; + } + ScopedMessage::~ScopedMessage() { - if ( !uncaught_exceptions() ){ + if ( !uncaught_exceptions() && !m_moved ){ getResultCapture().popScopedMessage(m_info); } } diff --git a/include/internal/catch_message.h b/include/internal/catch_message.h index e81069bf..748f5ac5 100644 --- a/include/internal/catch_message.h +++ b/include/internal/catch_message.h @@ -64,9 +64,12 @@ namespace Catch { class ScopedMessage { public: explicit ScopedMessage( MessageBuilder const& builder ); + ScopedMessage( ScopedMessage& duplicate ) = delete; + ScopedMessage( ScopedMessage&& old ); ~ScopedMessage(); MessageInfo m_info; + bool m_moved; }; class Capturer { diff --git a/include/internal/catch_run_context.cpp b/include/internal/catch_run_context.cpp index c4defc9d..bc3a5151 100644 --- a/include/internal/catch_run_context.cpp +++ b/include/internal/catch_run_context.cpp @@ -161,6 +161,9 @@ namespace Catch { // and should be let to clear themselves out. static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); + if (result.getResultType() != ResultWas::Warning) + m_messageScopes.clear(); + // Reset working state resetAssertionInfo(); m_lastResult = result; @@ -215,6 +218,7 @@ namespace Catch { m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); m_messages.clear(); + m_messageScopes.clear(); } void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { @@ -241,6 +245,10 @@ namespace Catch { m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); } + void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) { + m_messageScopes.emplace_back( builder ); + } + std::string RunContext::getCurrentTestName() const { return m_activeTestCase ? m_activeTestCase->getTestCaseInfo().name @@ -301,6 +309,7 @@ namespace Catch { m_lastAssertionPassed = true; ++m_totals.assertions.passed; resetAssertionInfo(); + m_messageScopes.clear(); } bool RunContext::aborting() const { @@ -352,6 +361,7 @@ namespace Catch { m_testCaseTracker->close(); handleUnfinishedSections(); m_messages.clear(); + m_messageScopes.clear(); SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); m_reporter->sectionEnded(testCaseSectionStats); diff --git a/include/internal/catch_run_context.h b/include/internal/catch_run_context.h index 259fecd3..c530a7b2 100644 --- a/include/internal/catch_run_context.h +++ b/include/internal/catch_run_context.h @@ -88,6 +88,8 @@ namespace Catch { void pushScopedMessage( MessageInfo const& message ) override; void popScopedMessage( MessageInfo const& message ) override; + void emplaceUnscopedMessage( MessageBuilder const& builder ) override; + std::string getCurrentTestName() const override; const AssertionResult* getLastResult() const override; @@ -135,6 +137,7 @@ namespace Catch { Totals m_totals; IStreamingReporterPtr 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;