Changed the way info messages are handled.

This fixes issue with SCOPED_INFO and makes output more readable.
Needs some refactoring.
This commit is contained in:
Phil Nash
2013-02-02 19:58:04 +00:00
parent d658dea1dd
commit 207b27b3c5
16 changed files with 334 additions and 301 deletions

View File

@@ -10,6 +10,7 @@
#include "catch_expression_decomposer.hpp"
#include "catch_expressionresult_builder.h"
#include "catch_message.h"
#include "catch_interfaces_capture.h"
#include "catch_debugger.hpp"
#include "catch_context.h"
@@ -54,26 +55,6 @@ namespace Catch {
struct TestFailureException{};
class ScopedInfo {
public:
ScopedInfo() : m_resultBuilder( ResultWas::Info ) {
getResultCapture().pushScopedInfo( this );
}
~ScopedInfo() {
getResultCapture().popScopedInfo( this );
}
template<typename T>
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; }
@@ -168,17 +149,24 @@ 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 ) \

View File

@@ -148,7 +148,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;

View File

@@ -28,6 +28,7 @@
#include "catch_tags.hpp"
#include "catch_version.hpp"
#include "catch_line_wrap.hpp"
#include "catch_message.hpp"
#include "../reporters/catch_reporter_basic.hpp"
#include "../reporters/catch_reporter_xml.hpp"

View File

@@ -21,19 +21,25 @@ namespace Catch {
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 pushScopedInfo( ScopedInfo* scopedInfo ) = 0; // !TBD Deprecated
virtual void popScopedInfo( ScopedInfo* scopedInfo ) = 0; // !TBD Deprecated
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;

View File

@@ -14,6 +14,7 @@
#include "catch_config.hpp"
#include "catch_test_case_info.h"
#include "catch_assertionresult.h"
#include "catch_message.h"
#include "catch_option.hpp"
#include <string>
@@ -89,13 +90,24 @@ namespace Catch
struct AssertionStats {
AssertionStats( AssertionResult const& _assertionResult,
std::vector<MessageInfo> 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<MessageInfo> infoMessages;
Totals totals;
};

View File

@@ -0,0 +1,66 @@
/*
* Created by Phil Nash on 1/2/2013.
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
#include <string>
#include "catch_result_type.h"
#include "catch_common.h"
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<typename T>
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
#endif // TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED

View File

@@ -0,0 +1,57 @@
/*
* Created by Phil Nash on 1/2/2013.
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#ifndef TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
#include "catch_message.h"
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
#endif // TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED

View File

@@ -32,6 +32,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 {

View File

@@ -155,43 +155,49 @@ 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<ScopedInfo*>::const_iterator it = m_scopedInfos.begin();
std::vector<ScopedInfo*>::const_iterator itEnd = m_scopedInfos.end();
for(; it != itEnd; ++it )
m_reporter->assertionEnded( AssertionStats( (*it)->buildResult( m_lastAssertionInfo ), m_totals ) );
}
{
std::vector<AssertionResult>::const_iterator it = m_assertionResults.begin();
std::vector<AssertionResult>::const_iterator itEnd = m_assertionResults.end();
for(; it != itEnd; ++it )
m_reporter->assertionEnded( AssertionStats( *it, m_totals ) );
}
m_assertionResults.clear();
// {
// std::vector<ScopedInfo*>::const_iterator it = m_scopedInfos.begin();
// std::vector<ScopedInfo*>::const_iterator itEnd = m_scopedInfos.end();
// for(; it != itEnd; ++it )
// m_reporter->assertionEnded( AssertionStats( (*it)->buildResult( m_lastAssertionInfo ), m_totals ) );
// }
// {
// std::vector<AssertionResult>::const_iterator it = m_assertionResults.begin();
// std::vector<AssertionResult>::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 )
{
if( result.getResultType() == ResultWas::Info ) {
// !TBD: deprecated? - what does this even do?
m_assertionResults.push_back( result );
m_totals.assertions.info++;
}
else
m_reporter->assertionEnded( AssertionStats( result, m_totals ) );
else {
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 );
m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
m_messages.clear();
}
virtual bool sectionStarted (
@@ -229,6 +235,7 @@ namespace Catch {
m_runningTest->endSection( info.name );
m_reporter->sectionEnded( SectionStats( info, assertions, missingAssertions ) );
m_messages.clear();
}
virtual void pushScopedInfo( ScopedInfo* scopedInfo ) {
@@ -239,8 +246,15 @@ namespace Catch {
if( m_scopedInfos.back() == scopedInfo )
m_scopedInfos.pop_back();
}
virtual void pushScopedMessage( ScopedMessageBuilder const& _builder ) {
m_messages.push_back( _builder.build() );
}
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 {
virtual bool shouldDebugBreak() const {
return m_config.shouldDebugBreak();
}
@@ -264,7 +278,7 @@ namespace Catch {
ResultAction::Value actOnCurrentResult( const AssertionResult& result ) {
m_lastResult = result;
testEnded( m_lastResult );
assertionEnded( m_lastResult );
ResultAction::Value action = ResultAction::None;
@@ -312,8 +326,9 @@ namespace Catch {
const Config& m_config;
Totals m_totals;
Ptr<IStreamingReporter> m_reporter;
std::vector<ScopedInfo*> m_scopedInfos;
std::vector<AssertionResult> m_assertionResults;
std::vector<ScopedInfo*> m_scopedInfos; // !TBD: deprecated
std::vector<AssertionResult> m_assertionResults; // !TBD: deprecated
std::vector<MessageInfo> m_messages;
IRunner* m_prevRunner;
IResultCapture* m_prevResultCapture;
const IConfig* m_prevConfig;