mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 12:17:11 +01:00 
			
		
		
		
	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:
		| @@ -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 ) \ | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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;         | ||||
|   | ||||
| @@ -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; | ||||
|     }; | ||||
|  | ||||
|   | ||||
							
								
								
									
										66
									
								
								include/internal/catch_message.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								include/internal/catch_message.h
									
									
									
									
									
										Normal 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 | ||||
							
								
								
									
										57
									
								
								include/internal/catch_message.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								include/internal/catch_message.hpp
									
									
									
									
									
										Normal 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 | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash