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.
This commit is contained in:
Omer Ozarslan 2019-02-01 09:11:30 -06:00 committed by Martin Hořeňovský
parent 1a03918455
commit 99575b45db
7 changed files with 32 additions and 2 deletions

View File

@ -215,6 +215,7 @@
#endif // CATCH_CONFIG_DISABLE_MATCHERS #endif // CATCH_CONFIG_DISABLE_MATCHERS
#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #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 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__ ) #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )

View File

@ -130,6 +130,10 @@
#define INTERNAL_CATCH_INFO( macroName, log ) \ #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 ); 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 // Although this is matcher-based, it can be used with just a string
#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \

View File

@ -20,6 +20,7 @@ namespace Catch {
struct SectionInfo; struct SectionInfo;
struct SectionEndInfo; struct SectionEndInfo;
struct MessageInfo; struct MessageInfo;
struct MessageBuilder;
struct Counts; struct Counts;
struct BenchmarkInfo; struct BenchmarkInfo;
struct BenchmarkStats; struct BenchmarkStats;
@ -46,6 +47,8 @@ namespace Catch {
virtual void pushScopedMessage( MessageInfo const& message ) = 0; virtual void pushScopedMessage( MessageInfo const& message ) = 0;
virtual void popScopedMessage( 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 handleFatalErrorCondition( StringRef message ) = 0;
virtual void handleExpr virtual void handleExpr

View File

@ -47,14 +47,20 @@ namespace Catch {
ScopedMessage::ScopedMessage( MessageBuilder const& builder ) ScopedMessage::ScopedMessage( MessageBuilder const& builder )
: m_info( builder.m_info ) : m_info( builder.m_info ), m_moved()
{ {
m_info.message = builder.m_stream.str(); m_info.message = builder.m_stream.str();
getResultCapture().pushScopedMessage( m_info ); getResultCapture().pushScopedMessage( m_info );
} }
ScopedMessage::ScopedMessage( ScopedMessage&& old )
: m_info( old.m_info ), m_moved()
{
old.m_moved = true;
}
ScopedMessage::~ScopedMessage() { ScopedMessage::~ScopedMessage() {
if ( !uncaught_exceptions() ){ if ( !uncaught_exceptions() && !m_moved ){
getResultCapture().popScopedMessage(m_info); getResultCapture().popScopedMessage(m_info);
} }
} }

View File

@ -64,9 +64,12 @@ namespace Catch {
class ScopedMessage { class ScopedMessage {
public: public:
explicit ScopedMessage( MessageBuilder const& builder ); explicit ScopedMessage( MessageBuilder const& builder );
ScopedMessage( ScopedMessage& duplicate ) = delete;
ScopedMessage( ScopedMessage&& old );
~ScopedMessage(); ~ScopedMessage();
MessageInfo m_info; MessageInfo m_info;
bool m_moved;
}; };
class Capturer { class Capturer {

View File

@ -161,6 +161,9 @@ namespace Catch {
// and should be let to clear themselves out. // and should be let to clear themselves out.
static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
if (result.getResultType() != ResultWas::Warning)
m_messageScopes.clear();
// Reset working state // Reset working state
resetAssertionInfo(); resetAssertionInfo();
m_lastResult = result; m_lastResult = result;
@ -215,6 +218,7 @@ namespace Catch {
m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
m_messages.clear(); m_messages.clear();
m_messageScopes.clear();
} }
void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { 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()); 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 { std::string RunContext::getCurrentTestName() const {
return m_activeTestCase return m_activeTestCase
? m_activeTestCase->getTestCaseInfo().name ? m_activeTestCase->getTestCaseInfo().name
@ -301,6 +309,7 @@ namespace Catch {
m_lastAssertionPassed = true; m_lastAssertionPassed = true;
++m_totals.assertions.passed; ++m_totals.assertions.passed;
resetAssertionInfo(); resetAssertionInfo();
m_messageScopes.clear();
} }
bool RunContext::aborting() const { bool RunContext::aborting() const {
@ -352,6 +361,7 @@ namespace Catch {
m_testCaseTracker->close(); m_testCaseTracker->close();
handleUnfinishedSections(); handleUnfinishedSections();
m_messages.clear(); m_messages.clear();
m_messageScopes.clear();
SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
m_reporter->sectionEnded(testCaseSectionStats); m_reporter->sectionEnded(testCaseSectionStats);

View File

@ -88,6 +88,8 @@ namespace Catch {
void pushScopedMessage( MessageInfo const& message ) override; void pushScopedMessage( MessageInfo const& message ) override;
void popScopedMessage( MessageInfo const& message ) override; void popScopedMessage( MessageInfo const& message ) override;
void emplaceUnscopedMessage( MessageBuilder const& builder ) override;
std::string getCurrentTestName() const override; std::string getCurrentTestName() const override;
const AssertionResult* getLastResult() const override; const AssertionResult* getLastResult() const override;
@ -135,6 +137,7 @@ namespace Catch {
Totals m_totals; Totals m_totals;
IStreamingReporterPtr m_reporter; IStreamingReporterPtr m_reporter;
std::vector<MessageInfo> m_messages; std::vector<MessageInfo> m_messages;
std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */
AssertionInfo m_lastAssertionInfo; AssertionInfo m_lastAssertionInfo;
std::vector<SectionEndInfo> m_unfinishedSections; std::vector<SectionEndInfo> m_unfinishedSections;
std::vector<ITracker*> m_activeSections; std::vector<ITracker*> m_activeSections;