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_exception.hpp" 14 #include "catch_matchers_floating.h" 15 #include "catch_matchers_generic.hpp" 16 #include "catch_matchers_string.h" 17 #include "catch_matchers_vector.h" 18 #include "catch_stringref.h" 19 20 namespace Catch { 21 22 template<typename ArgT, typename MatcherT> 23 class MatchExpr : public ITransientExpression { 24 ArgT const& m_arg; 25 MatcherT m_matcher; 26 StringRef m_matcherString; 27 public: MatchExpr(ArgT const & arg,MatcherT const & matcher,StringRef const & matcherString)28 MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) 29 : ITransientExpression{ true, matcher.match( arg ) }, 30 m_arg( arg ), 31 m_matcher( matcher ), 32 m_matcherString( matcherString ) 33 {} 34 streamReconstructedExpression(std::ostream & os)35 void streamReconstructedExpression( std::ostream &os ) const override { 36 auto matcherAsString = m_matcher.toString(); 37 os << Catch::Detail::stringify( m_arg ) << ' '; 38 if( matcherAsString == Detail::unprintableString ) 39 os << m_matcherString; 40 else 41 os << matcherAsString; 42 } 43 }; 44 45 using StringMatcher = Matchers::Impl::MatcherBase<std::string>; 46 47 void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString ); 48 49 template<typename ArgT, typename MatcherT> 50 auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString ) -> MatchExpr<ArgT, MatcherT> { 51 return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString ); 52 } 53 54 } // namespace Catch 55 56 57 /////////////////////////////////////////////////////////////////////////////// 58 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 59 do { \ 60 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 61 INTERNAL_CATCH_TRY { \ 62 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \ 63 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ 64 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 65 } while( false ) 66 67 68 /////////////////////////////////////////////////////////////////////////////// 69 #define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ 70 do { \ 71 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 72 if( catchAssertionHandler.allowThrows() ) \ 73 try { \ 74 static_cast<void>(__VA_ARGS__ ); \ 75 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ 76 } \ 77 catch( exceptionType const& ex ) { \ 78 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \ 79 } \ 80 catch( ... ) { \ 81 catchAssertionHandler.handleUnexpectedInflightException(); \ 82 } \ 83 else \ 84 catchAssertionHandler.handleThrowingCallSkipped(); \ 85 INTERNAL_CATCH_REACT( catchAssertionHandler ) \ 86 } while( false ) 87 88 #endif // TWOBLUECUBES_CATCH_CAPTURE_MATCHERS_HPP_INCLUDED 89