catch_message.hpp
1 2 // Copyright Catch2 Authors 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE.txt or copy at 5 // https://www.boost.org/LICENSE_1_0.txt) 6 7 // SPDX-License-Identifier: BSL-1.0 8 #ifndef CATCH_MESSAGE_HPP_INCLUDED 9 #define CATCH_MESSAGE_HPP_INCLUDED 10 11 #include <catch2/internal/catch_config_prefix_messages.hpp> 12 #include <catch2/internal/catch_result_type.hpp> 13 #include <catch2/internal/catch_reusable_string_stream.hpp> 14 #include <catch2/internal/catch_stream_end_stop.hpp> 15 #include <catch2/internal/catch_message_info.hpp> 16 #include <catch2/catch_tostring.hpp> 17 #include <catch2/interfaces/catch_interfaces_capture.hpp> 18 19 #include <string> 20 #include <vector> 21 22 namespace Catch { 23 24 struct SourceLineInfo; 25 class IResultCapture; 26 27 struct MessageStream { 28 29 template<typename T> 30 MessageStream& operator << ( T const& value ) { 31 m_stream << value; 32 return *this; 33 } 34 35 ReusableStringStream m_stream; 36 }; 37 38 struct MessageBuilder : MessageStream { 39 MessageBuilder( StringRef macroName, 40 SourceLineInfo const& lineInfo, 41 ResultWas::OfType type ): 42 m_info(macroName, lineInfo, type) {} 43 44 template<typename T> 45 MessageBuilder&& operator << ( T const& value ) && { 46 m_stream << value; 47 return CATCH_MOVE(*this); 48 } 49 50 MessageInfo m_info; 51 }; 52 53 class ScopedMessage { 54 public: 55 explicit ScopedMessage( MessageBuilder&& builder ); 56 ScopedMessage( ScopedMessage& duplicate ) = delete; 57 ScopedMessage( ScopedMessage&& old ) noexcept; 58 ~ScopedMessage(); 59 60 MessageInfo m_info; 61 bool m_moved = false; 62 }; 63 64 class Capturer { 65 std::vector<MessageInfo> m_messages; 66 IResultCapture& m_resultCapture; 67 size_t m_captured = 0; 68 public: 69 Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ); 70 71 Capturer(Capturer const&) = delete; 72 Capturer& operator=(Capturer const&) = delete; 73 74 ~Capturer(); 75 76 void captureValue( size_t index, std::string const& value ); 77 78 template<typename T> 79 void captureValues( size_t index, T const& value ) { 80 captureValue( index, Catch::Detail::stringify( value ) ); 81 } 82 83 template<typename T, typename... Ts> 84 void captureValues( size_t index, T const& value, Ts const&... values ) { 85 captureValue( index, Catch::Detail::stringify(value) ); 86 captureValues( index+1, values... ); 87 } 88 }; 89 90 } // end namespace Catch 91 92 /////////////////////////////////////////////////////////////////////////////// 93 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 94 do { \ 95 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \ 96 catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ 97 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 98 } while( false ) 99 100 /////////////////////////////////////////////////////////////////////////////// 101 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \ 102 Catch::Capturer varName( macroName##_catch_sr, \ 103 CATCH_INTERNAL_LINEINFO, \ 104 Catch::ResultWas::Info, \ 105 #__VA_ARGS__##_catch_sr ); \ 106 varName.captureValues( 0, __VA_ARGS__ ) 107 108 /////////////////////////////////////////////////////////////////////////////// 109 #define INTERNAL_CATCH_INFO( macroName, log ) \ 110 const Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 111 112 /////////////////////////////////////////////////////////////////////////////// 113 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \ 114 Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ) 115 116 117 #if defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE) 118 119 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 120 #define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg ) 121 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 122 #define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE", __VA_ARGS__ ) 123 124 #elif defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE) 125 126 #define CATCH_INFO( msg ) (void)(0) 127 #define CATCH_UNSCOPED_INFO( msg ) (void)(0) 128 #define CATCH_WARN( msg ) (void)(0) 129 #define CATCH_CAPTURE( ... ) (void)(0) 130 131 #elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && !defined(CATCH_CONFIG_DISABLE) 132 133 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 134 #define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg ) 135 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 136 #define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE", __VA_ARGS__ ) 137 138 #elif !defined(CATCH_CONFIG_PREFIX_MESSAGES) && defined(CATCH_CONFIG_DISABLE) 139 140 #define INFO( msg ) (void)(0) 141 #define UNSCOPED_INFO( msg ) (void)(0) 142 #define WARN( msg ) (void)(0) 143 #define CAPTURE( ... ) (void)(0) 144 145 #endif // end of user facing macro declarations 146 147 148 149 150 #endif // CATCH_MESSAGE_HPP_INCLUDED