1 /* 2 * Created by Phil on 18/10/2010. 3 * Copyright 2010 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_HPP_INCLUDED 9 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED 10 11 #include "catch_result_builder.h" 12 #include "catch_message.h" 13 #include "catch_interfaces_capture.h" 14 #include "catch_debugger.h" 15 #include "catch_common.h" 16 #include "catch_tostring.h" 17 #include "catch_interfaces_runner.h" 18 #include "catch_compiler_capabilities.h" 19 20 21 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) 22 # define CATCH_INTERNAL_STRINGIFY(expr) #expr 23 #else 24 # define CATCH_INTERNAL_STRINGIFY(expr) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" 25 #endif 26 27 #if defined(CATCH_CONFIG_FAST_COMPILE) 28 /////////////////////////////////////////////////////////////////////////////// 29 // We can speedup compilation significantly by breaking into debugger lower in 30 // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER 31 // macro in each assertion 32 #define INTERNAL_CATCH_REACT( resultBuilder ) \ 33 resultBuilder.react(); 34 35 /////////////////////////////////////////////////////////////////////////////// 36 // Another way to speed-up compilation is to omit local try-catch for REQUIRE* 37 // macros. 38 // This can potentially cause false negative, if the test code catches 39 // the exception before it propagates back up to the runner. 40 #define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ 41 do { \ 42 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \ 43 __catchResult.setExceptionGuard(); \ 44 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 45 ( __catchResult <= expr ).endExpression(); \ 46 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 47 __catchResult.unsetExceptionGuard(); \ 48 INTERNAL_CATCH_REACT( __catchResult ) \ 49 } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look 50 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. 51 52 #define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ 53 do { \ 54 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 55 __catchResult.setExceptionGuard(); \ 56 __catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \ 57 __catchResult.unsetExceptionGuard(); \ 58 INTERNAL_CATCH_REACT( __catchResult ) \ 59 } while( Catch::alwaysFalse() ) 60 61 #else 62 /////////////////////////////////////////////////////////////////////////////// 63 // In the event of a failure works out if the debugger needs to be invoked 64 // and/or an exception thrown and takes appropriate action. 65 // This needs to be done as a macro so the debugger will stop in the user 66 // source code rather than in Catch library code 67 #define INTERNAL_CATCH_REACT( resultBuilder ) \ 68 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ 69 resultBuilder.react(); 70 #endif 71 72 73 /////////////////////////////////////////////////////////////////////////////// 74 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ 75 do { \ 76 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \ 77 try { \ 78 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 79 ( __catchResult <= expr ).endExpression(); \ 80 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 81 } \ 82 catch( ... ) { \ 83 __catchResult.useActiveException( resultDisposition ); \ 84 } \ 85 INTERNAL_CATCH_REACT( __catchResult ) \ 86 } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look 87 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. 88 89 /////////////////////////////////////////////////////////////////////////////// 90 #define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ 91 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ 92 if( Catch::getResultCapture().lastAssertionPassed() ) 93 94 /////////////////////////////////////////////////////////////////////////////// 95 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ 96 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ 97 if( !Catch::getResultCapture().lastAssertionPassed() ) 98 99 /////////////////////////////////////////////////////////////////////////////// 100 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ 101 do { \ 102 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition ); \ 103 try { \ 104 static_cast<void>(expr); \ 105 __catchResult.captureResult( Catch::ResultWas::Ok ); \ 106 } \ 107 catch( ... ) { \ 108 __catchResult.useActiveException( resultDisposition ); \ 109 } \ 110 INTERNAL_CATCH_REACT( __catchResult ) \ 111 } while( Catch::alwaysFalse() ) 112 113 /////////////////////////////////////////////////////////////////////////////// 114 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ 115 do { \ 116 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr), resultDisposition, CATCH_INTERNAL_STRINGIFY(matcher) ); \ 117 if( __catchResult.allowThrows() ) \ 118 try { \ 119 static_cast<void>(expr); \ 120 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ 121 } \ 122 catch( ... ) { \ 123 __catchResult.captureExpectedException( matcher ); \ 124 } \ 125 else \ 126 __catchResult.captureResult( Catch::ResultWas::Ok ); \ 127 INTERNAL_CATCH_REACT( __catchResult ) \ 128 } while( Catch::alwaysFalse() ) 129 130 /////////////////////////////////////////////////////////////////////////////// 131 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 132 do { \ 133 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ 134 if( __catchResult.allowThrows() ) \ 135 try { \ 136 static_cast<void>(expr); \ 137 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ 138 } \ 139 catch( exceptionType ) { \ 140 __catchResult.captureResult( Catch::ResultWas::Ok ); \ 141 } \ 142 catch( ... ) { \ 143 __catchResult.useActiveException( resultDisposition ); \ 144 } \ 145 else \ 146 __catchResult.captureResult( Catch::ResultWas::Ok ); \ 147 INTERNAL_CATCH_REACT( __catchResult ) \ 148 } while( Catch::alwaysFalse() ) 149 150 151 /////////////////////////////////////////////////////////////////////////////// 152 #ifdef CATCH_CONFIG_VARIADIC_MACROS 153 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 154 do { \ 155 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ 156 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ 157 __catchResult.captureResult( messageType ); \ 158 INTERNAL_CATCH_REACT( __catchResult ) \ 159 } while( Catch::alwaysFalse() ) 160 #else 161 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \ 162 do { \ 163 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ 164 __catchResult << log + ::Catch::StreamEndStop(); \ 165 __catchResult.captureResult( messageType ); \ 166 INTERNAL_CATCH_REACT( __catchResult ) \ 167 } while( Catch::alwaysFalse() ) 168 #endif 169 170 /////////////////////////////////////////////////////////////////////////////// 171 #define INTERNAL_CATCH_INFO( macroName, log ) \ 172 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; 173 174 /////////////////////////////////////////////////////////////////////////////// 175 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 176 do { \ 177 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ 178 try { \ 179 __catchResult.captureMatch( arg, matcher, CATCH_INTERNAL_STRINGIFY(matcher) ); \ 180 } catch( ... ) { \ 181 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ 182 } \ 183 INTERNAL_CATCH_REACT( __catchResult ) \ 184 } while( Catch::alwaysFalse() ) 185 186 #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED 187