From a2773810db4ec00ca1846a80a1d6f2ef351db9eb Mon Sep 17 00:00:00 2001 From: Phil Nash Date: Sat, 2 Feb 2013 20:37:58 +0000 Subject: [PATCH] Build 17 - includes reworking of message/ info handling --- README | 10 +- include/internal/catch_version.hpp | 2 +- single_include/catch.hpp | 273 ++++++++++++++++++++--------- 3 files changed, 195 insertions(+), 90 deletions(-) diff --git a/README b/README index b7a90aa4..5c8f882e 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -CATCH v0.9 build 16 (integration branch) +CATCH v0.9 build 17 (integration branch) --------------------------------------------- CATCH is an automated test framework for C, C++ and Objective-C. @@ -6,9 +6,9 @@ CATCH is an automated test framework for C, C++ and Objective-C. This branch may contain code that is experimental or not yet fully tested. The latest stable version can be found on the Master branch. -For documentation see the wiki at: +For documentation see the wiki at: https://github.com/philsquared/Catch/wiki -Issues and bugs can be raised at: +Issues and bugs can be raised at: https://github.com/philsquared/Catch/issues -For discussion or questions please use: - https://groups.google.com/forum/?fromgroups#!forum/catch-forum \ No newline at end of file +For discussion or questions please use: + https://groups.google.com/forum/?fromgroups#!forum/catch-forum diff --git a/include/internal/catch_version.hpp b/include/internal/catch_version.hpp index 6989a932..42bf18ff 100644 --- a/include/internal/catch_version.hpp +++ b/include/internal/catch_version.hpp @@ -13,7 +13,7 @@ namespace Catch { // These numbers are maintained by a script - Version libraryVersion( 0, 9, 16, "integration" ); + Version libraryVersion( 0, 9, 17, "integration" ); } #endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED diff --git a/single_include/catch.hpp b/single_include/catch.hpp index bac4dd72..0700af82 100644 --- a/single_include/catch.hpp +++ b/single_include/catch.hpp @@ -1,6 +1,6 @@ /* - * CATCH v0.9 build 16 (integration branch) - * Generated: 2013-01-26 20:18:07.076275 + * CATCH v0.9 build 17 (integration branch) + * Generated: 2013-02-02 20:37:06.007152 * ---------------------------------------------------------- * This file has been merged from multiple headers. Please don't edit it directly * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. @@ -656,6 +656,9 @@ namespace Catch { inline bool isOk( ResultWas::OfType resultType ) { return ( resultType & ResultWas::FailureBit ) == 0; } + inline bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } // ResultAction::Value enum struct ResultAction { enum Value { @@ -1019,6 +1022,61 @@ public: } // end namespace Catch +// #included from: catch_message.h +#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + SourceLineInfo lineInfo; + ResultWas::OfType type; + std::string message; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const { + return sequence == other.sequence; + } + bool operator < ( MessageInfo const& other ) const { + return sequence < other.sequence; + } + private: + static unsigned int globalCount; + }; + + class MessageBuilder : public MessageInfo { + public: + MessageBuilder( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + MessageInfo build() const; + + template + MessageBuilder& operator << ( T const& _value ) { + stream << _value; + return *this; + } + private: + std::ostringstream stream; + }; + + class ScopedMessageBuilder : public MessageBuilder { + public: + ScopedMessageBuilder( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + ~ScopedMessageBuilder(); + }; + +} // end namespace Catch + // #included from: catch_interfaces_capture.h #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED @@ -1031,19 +1089,17 @@ public: namespace Catch { struct Counts { - Counts() : passed( 0 ), failed( 0 ), info( 0 ) {} + Counts() : passed( 0 ), failed( 0 ) {} Counts operator - ( const Counts& other ) const { Counts diff; diff.passed = passed - other.passed; diff.failed = failed - other.failed; - diff.info = info - other.info; return diff; } Counts& operator += ( const Counts& other ) { passed += other.passed; failed += other.failed; - info += other.info; return *this; } @@ -1053,7 +1109,6 @@ namespace Catch { std::size_t passed; std::size_t failed; - std::size_t info; }; struct Totals { @@ -1089,24 +1144,27 @@ namespace Catch { namespace Catch { class TestCase; - class ScopedInfo; class ExpressionResultBuilder; class AssertionResult; struct AssertionInfo; struct SectionInfo; + class MessageBuilder; + class ScopedMessageBuilder; struct IResultCapture { virtual ~IResultCapture(); - virtual void testEnded( AssertionResult const& result ) = 0; + virtual void assertionEnded( AssertionResult const& result ) = 0; virtual bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) = 0; virtual void sectionEnded( SectionInfo const& name, Counts const& assertions ) = 0; - virtual void pushScopedInfo( ScopedInfo* scopedInfo ) = 0; - virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0; + virtual void pushScopedMessage( ScopedMessageBuilder const& _builder ) = 0; + virtual void popScopedMessage( ScopedMessageBuilder const& _builder ) = 0; + virtual bool shouldDebugBreak() const = 0; + virtual void acceptMessage( const MessageBuilder& messageBuilder ) = 0; virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& assertionResult, AssertionInfo const& assertionInfo ) = 0; virtual std::string getCurrentTestName() const = 0; @@ -2017,13 +2075,24 @@ namespace Catch struct AssertionStats { AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, Totals const& _totals ) : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), totals( _totals ) - {} + { + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + infoMessages.push_back( builder.build() ); + } + } virtual ~AssertionStats(); AssertionResult assertionResult; + std::vector infoMessages; Totals totals; }; @@ -2441,27 +2510,6 @@ namespace Catch { struct TestFailureException{}; -class ScopedInfo { -public: - ScopedInfo() : m_resultBuilder( ResultWas::Info ) { - getResultCapture().pushScopedInfo( this ); - } - ~ScopedInfo() { - getResultCapture().popScopedInfo( this ); - } - template - ScopedInfo& operator << ( const T& value ) { - m_resultBuilder << value; - return *this; - } - AssertionResult buildResult( const AssertionInfo& assertionInfo ) const { - return m_resultBuilder.buildResult( assertionInfo ); - } - -private: - ExpressionResultBuilder m_resultBuilder; -}; - // This is just here to avoid compiler warnings with macro constants and boolean literals inline bool isTrue( bool value ){ return value; } @@ -2555,17 +2603,23 @@ inline bool isTrue( bool value ){ return value; } } while( Catch::isTrue( false ) ) /////////////////////////////////////////////////////////////////////////////// -#define INTERNAL_CATCH_MSG( reason, resultType, resultDisposition, macroName ) \ +#define INTERNAL_CATCH_INFO( log, macroName ) \ + do { \ + Catch::getResultCapture().acceptMessage( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); \ + } while( Catch::isTrue( false ) ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_MSG( log, messageType, resultDisposition, macroName ) \ do { \ INTERNAL_CATCH_ACCEPT_INFO( "", macroName, resultDisposition ); \ - INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( resultType ) << reason, resultDisposition, true ) \ + INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( messageType ) << log, resultDisposition, true ) \ } while( Catch::isTrue( false ) ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_SCOPED_INFO( log, macroName ) \ - INTERNAL_CATCH_ACCEPT_INFO( "", macroName, Catch::ResultDisposition::Normal ); \ - Catch::ScopedInfo INTERNAL_CATCH_UNIQUE_NAME( info ); \ - INTERNAL_CATCH_UNIQUE_NAME( info ) << log + Catch::ScopedMessageBuilder INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ); \ + INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) << log; \ + Catch::getResultCapture().pushScopedMessage( INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) ) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \ @@ -3505,7 +3559,7 @@ namespace Catch { virtual void parseIntoConfig( const Command& cmd, ConfigData& config ) = 0; virtual std::string argsSynopsis() const = 0; virtual std::string optionSummary() const = 0; - virtual std::string optionDescription() const { return ""; }; + virtual std::string optionDescription() const { return ""; } std::string optionNames() const { std::string names; @@ -4429,43 +4483,28 @@ namespace Catch { private: // IResultCapture + virtual void acceptMessage( const MessageBuilder& messageBuilder ) { + m_messages.push_back( messageBuilder.build() ); + } + virtual ResultAction::Value acceptExpression( const ExpressionResultBuilder& assertionResult, const AssertionInfo& assertionInfo ) { m_lastAssertionInfo = assertionInfo; return actOnCurrentResult( assertionResult.buildResult( assertionInfo ) ); } - virtual void testEnded( const AssertionResult& result ) { + virtual void assertionEnded( const AssertionResult& result ) { if( result.getResultType() == ResultWas::Ok ) { m_totals.assertions.passed++; } else if( !result.isOk() ) { m_totals.assertions.failed++; - - { - std::vector::const_iterator it = m_scopedInfos.begin(); - std::vector::const_iterator itEnd = m_scopedInfos.end(); - for(; it != itEnd; ++it ) - m_reporter->assertionEnded( AssertionStats( (*it)->buildResult( m_lastAssertionInfo ), m_totals ) ); - } - { - std::vector::const_iterator it = m_assertionResults.begin(); - std::vector::const_iterator itEnd = m_assertionResults.end(); - for(; it != itEnd; ++it ) - m_reporter->assertionEnded( AssertionStats( *it, m_totals ) ); - } - m_assertionResults.clear(); } - if( result.getResultType() == ResultWas::Info ) - { - m_assertionResults.push_back( result ); - m_totals.assertions.info++; - } - else - m_reporter->assertionEnded( AssertionStats( result, m_totals ) ); + m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ); - // Reset AssertionInfo - m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after this line}" , m_lastAssertionInfo.resultDisposition ); + // Reset working state + m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); + m_messages.clear(); } virtual bool sectionStarted ( @@ -4502,15 +4541,15 @@ namespace Catch { m_runningTest->endSection( info.name ); m_reporter->sectionEnded( SectionStats( info, assertions, missingAssertions ) ); + m_messages.clear(); } - virtual void pushScopedInfo( ScopedInfo* scopedInfo ) { - m_scopedInfos.push_back( scopedInfo ); + virtual void pushScopedMessage( ScopedMessageBuilder const& _builder ) { + m_messages.push_back( _builder.build() ); } - virtual void popScopedInfo( ScopedInfo* scopedInfo ) { - if( m_scopedInfos.back() == scopedInfo ) - m_scopedInfos.pop_back(); + virtual void popScopedMessage( ScopedMessageBuilder const& _builder ) { + m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), _builder ), m_messages.end() ); } virtual bool shouldDebugBreak() const { @@ -4537,7 +4576,7 @@ namespace Catch { ResultAction::Value actOnCurrentResult( const AssertionResult& result ) { m_lastResult = result; - testEnded( m_lastResult ); + assertionEnded( m_lastResult ); ResultAction::Value action = ResultAction::None; @@ -4573,7 +4612,6 @@ namespace Catch { exResult << translateActiveException(); actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) ); } - m_assertionResults.clear(); } private: @@ -4585,8 +4623,7 @@ namespace Catch { const Config& m_config; Totals m_totals; Ptr m_reporter; - std::vector m_scopedInfos; - std::vector m_assertionResults; + std::vector m_messages; IRunner* m_prevRunner; IResultCapture* m_prevResultCapture; const IConfig* m_prevConfig; @@ -5777,7 +5814,7 @@ namespace Catch { namespace Catch { // These numbers are maintained by a script - Version libraryVersion( 0, 9, 16, "integration" ); + Version libraryVersion( 0, 9, 17, "integration" ); } // #included from: catch_line_wrap.hpp @@ -5837,6 +5874,52 @@ namespace Catch { } // end namespace Catch +// #included from: catch_message.hpp +#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED + +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + MessageBuilder::MessageBuilder( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : MessageInfo( _macroName, _lineInfo, _type ) + {} + + MessageInfo MessageBuilder::build() const { + MessageInfo message = *this; + message.message = stream.str(); + return message; + } + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessageBuilder::ScopedMessageBuilder + ( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : MessageBuilder( _macroName, _lineInfo, _type ) + {} + + ScopedMessageBuilder::~ScopedMessageBuilder() { + getResultCapture().popScopedMessage( *this ); + } + +} // end namespace Catch + // #included from: ../reporters/catch_reporter_basic.hpp #define TWOBLUECUBES_CATCH_REPORTER_BASIC_HPP_INCLUDED @@ -6900,14 +6983,18 @@ namespace Catch { stats( _stats ), result( _stats.assertionResult ), colour( TextColour::None ), - message( result.getMessage() ) + message( result.getMessage() ), + messages( _stats.infoMessages ) { switch( result.getResultType() ) { case ResultWas::Ok: colour = TextColour::Success; passOrFail = "PASSED"; - if( result.hasMessage() ) + //if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; break; case ResultWas::ExpressionFailed: if( result.isOk() ) { @@ -6918,9 +7005,13 @@ namespace Catch { colour = TextColour::Error; passOrFail = "FAILED"; } - if( result.hasMessage() ){ + if( _stats.infoMessages.size() == 1 ) messageLabel = "with message"; - } + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; +// if( result.hasMessage() ){ +// messageLabel = "with message"; +// } break; case ResultWas::ThrewException: colour = TextColour::Error; @@ -6941,13 +7032,21 @@ namespace Catch { case ResultWas::ExplicitFailure: passOrFail = "FAILED"; colour = TextColour::Error; - messageLabel = "explicitly with message"; +// messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() == 1 ) + messageLabel = "explicitly with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "explicitly with messages"; break; case ResultWas::Exception: passOrFail = "FAILED"; colour = TextColour::Error; - if( result.hasMessage() ) + if( _stats.infoMessages.size() == 1 ) messageLabel = "with message"; + if( _stats.infoMessages.size() > 1 ) + messageLabel = "with messages"; +// if( result.hasMessage() ) +// messageLabel = "with message"; break; // These cases are here to prevent compiler warnings @@ -6998,8 +7097,13 @@ namespace Catch { void printMessage() const { if( !messageLabel.empty() ) stream << messageLabel << ":" << "\n"; - if( !message.empty() ) - stream << wrapLongStrings( message ) << "\n"; + for( std::vector::const_iterator it = messages.begin(), itEnd = messages.end(); + it != itEnd; + ++it ) { + stream << wrapLongStrings( it->message ) << "\n"; + } +// if( !message.empty() ) +// stream << wrapLongStrings( message ) << "\n"; } void printSourceInfo() const { TextColour colourGuard( TextColour::FileName ); @@ -7017,6 +7121,7 @@ namespace Catch { std::string passOrFail; std::string messageLabel; std::string message; + std::vector messages; }; void lazyPrint() { @@ -7279,12 +7384,12 @@ int main (int argc, char * const argv[]) { #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" ) #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" ) -#define CATCH_INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CATCH_INFO" ) +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN" ) #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL" ) #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED" ) #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "CATCH_SCOPED_INFO" ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CAPTURE" ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "CATCH_SCOPED_CAPTURE" ) #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) @@ -7322,12 +7427,12 @@ int main (int argc, char * const argv[]) { #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" ) #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" ) -#define INFO( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "INFO" ) +#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) #define WARN( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN" ) #define FAIL( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL" ) #define SUCCEED( msg ) INTERNAL_CATCH_MSG( msg, Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED" ) #define SCOPED_INFO( msg ) INTERNAL_CATCH_SCOPED_INFO( msg, "SCOPED_INFO" ) -#define CAPTURE( msg ) INTERNAL_CATCH_MSG( #msg " := " << msg, Catch::ResultWas::Info, Catch::ResultDisposition::ContinueOnFailure, "CAPTURE" ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_SCOPED_INFO( #msg " := " << msg, "SCOPED_CAPTURE" ) #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )