1 /* 2 * Created by Phil on 9/8/2017 3 * Copyright 2017 Two Blue Cubes Ltd. All rights reserved. 4 * 5 * Distributed under the Boost Software License, Version 1.0. (See accompanying 6 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 7 */ 8 #ifndef TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED 9 #define TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED 10 11 #include "catch_capture.hpp" 12 #include "catch_matchers.h" 13 #include "catch_matchers_floating.h" 14 #include "catch_matchers_generic.hpp" 15 #include "catch_matchers_string.h" 16 #include "catch_matchers_vector.h" 17 #include "catch_stringref.h" 18 19 namespace Catch { 20 21 template<typename ArgT, typename MatcherT> 22 class MatchExpr : public ITransientExpression { 23 ArgT const& m_arg; 24 MatcherT m_matcher; 25 StringRef m_matcherString; 26 public: MatchExpr(ArgT const & arg,MatcherT const & matcher,StringRef const & matcherString)27 MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) 28 : ITransientExpression{ true, matcher.match( arg ) }, 29 m_arg( arg ), 30 m_matcher( matcher ), 31 m_matcherString( matcherString ) 32 {} 33 streamReconstructedExpression(std::ostream & os)34 void streamReconstructedExpression( std::ostream &os ) const override { 35 auto matcherAsString = m_matcher.toString(); 36 os << Catch::Detail::stringify( m_arg ) << ' '; 37 if( matcherAsString == Detail::unprintableString ) 38 os << m_matcherString; 39 else 40 os << matcherAsString; 41 } 42 }; 43 44 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 45 46 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ); 47 48 template<typename ArgT, typename MatcherT> 49 auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> { 50 return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString ); 51 } 52 53 } // namespace Catch 54 55 56 /////////////////////////////////////////////////////////////////////////////// 57 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 58 do { \ 59 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 60 INTERNAL_CATCH_TRY { \ 61 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ 62 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 63 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 64 } while( false ) 65 66 67 /////////////////////////////////////////////////////////////////////////////// 68 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 69 do { \ 70 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 71 if( catchAssertionHandler.allowThrows() ) \ 72 try { \ 73 static_cast<void>(__VA_ARGS__ ); \ 74 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 75 } \ 76 catch( exceptionType const& ex ) { \ 77 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ 78 } \ 79 catch( ... ) { \ 80 catchAssertionHandler.handleUnexpectedInflightException(); \ 81 } \ 82 else \ 83 catchAssertionHandler.handleThrowingCallSkipped(); \ 84 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 85 } while( false ) 86 87 #endif // TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED 88