diff --git a/include/catch.hpp b/include/catch.hpp index 0a49cb3162..017619ce13 100644 --- a/include/catch.hpp +++ b/include/catch.hpp @@ -130,7 +130,7 @@ #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) +#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ ) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) @@ -190,7 +190,7 @@ #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) -#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) +#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ ) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) diff --git a/include/internal/catch_capture.hpp b/include/internal/catch_capture.hpp index bbbc7e79a8..258cee61a6 100644 --- a/include/internal/catch_capture.hpp +++ b/include/internal/catch_capture.hpp @@ -121,6 +121,11 @@ INTERNAL_CATCH_REACT( catchAssertionHandler ) \ } while( false ) +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ + auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \ + varName.captureValues( 0, __VA_ARGS__ ) + /////////////////////////////////////////////////////////////////////////////// #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 ); diff --git a/include/internal/catch_message.cpp b/include/internal/catch_message.cpp index 89fa96d80a..df905bf6b4 100644 --- a/include/internal/catch_message.cpp +++ b/include/internal/catch_message.cpp @@ -10,6 +10,8 @@ #include "catch_interfaces_capture.h" #include "catch_uncaught_exceptions.h" +#include + namespace Catch { MessageInfo::MessageInfo( StringRef const& _macroName, @@ -55,4 +57,36 @@ namespace Catch { getResultCapture().popScopedMessage(m_info); } } + + + Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) { + auto start = std::string::npos; + for( size_t pos = 0; pos <= names.size(); ++pos ) { + char c = names[pos]; + if( pos == names.size() || c == ' ' || c == '\t' || c == ',' || c == ']' ) { + if( start != std::string::npos ) { + m_messages.push_back( MessageInfo( macroName, lineInfo, resultType ) ); + m_messages.back().message = names.substr( start, pos-start) + " := "; + start = std::string::npos; + } + } + else if( c != '[' && c != ']' && start == std::string::npos ) + start = pos; + } + } + Capturer::~Capturer() { + if ( !uncaught_exceptions() ){ + assert( m_captured == m_messages.size() ); + for( size_t i = 0; i < m_captured; ++i ) + m_resultCapture.popScopedMessage( m_messages[i] ); + } + } + + void Capturer::captureValue( size_t index, StringRef value ) { + assert( index < m_messages.size() ); + m_messages[index].message += value; + m_resultCapture.pushScopedMessage( m_messages[index] ); + m_captured++; + } + } // end namespace Catch diff --git a/include/internal/catch_message.h b/include/internal/catch_message.h index 96f098f6a3..73f9efd162 100644 --- a/include/internal/catch_message.h +++ b/include/internal/catch_message.h @@ -8,11 +8,14 @@ #ifndef TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED -#include #include "catch_result_type.h" #include "catch_common.h" #include "catch_stream.h" -#include "catch_stringref.h" +#include "catch_interfaces_capture.h" +#include "catch_tostring.h" + +#include +#include namespace Catch { @@ -66,6 +69,28 @@ namespace Catch { MessageInfo m_info; }; + class Capturer { + std::vector m_messages; + IResultCapture& m_resultCapture = getResultCapture(); + size_t m_captured = 0; + public: + Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); + ~Capturer(); + + void captureValue( size_t index, StringRef value ); + + template + void captureValues( size_t index, T&& value ) { + captureValue( index, Catch::Detail::stringify( value ) ); + } + + template + void captureValues( size_t index, T&& value, Ts&&... values ) { + captureValues( index, value ); + captureValues( index+1, values... ); + } + }; + } // end namespace Catch #endif // TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED