Home | History | Annotate | Download | only in internal
      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_assertionhandler.h"
     12 #include "catch_interfaces_capture.h"
     13 #include "catch_message.h"
     14 #include "catch_stringref.h"
     15 
     16 #if !defined(CATCH_CONFIG_DISABLE)
     17 
     18 #if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)
     19   #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__
     20 #else
     21   #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"
     22 #endif
     23 
     24 #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
     25 
     26 ///////////////////////////////////////////////////////////////////////////////
     27 // Another way to speed-up compilation is to omit local try-catch for REQUIRE*
     28 // macros.
     29 #define INTERNAL_CATCH_TRY
     30 #define INTERNAL_CATCH_CATCH( capturer )
     31 
     32 #else // CATCH_CONFIG_FAST_COMPILE
     33 
     34 #define INTERNAL_CATCH_TRY try
     35 #define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }
     36 
     37 #endif
     38 
     39 #define INTERNAL_CATCH_REACT( handler ) handler.complete();
     40 
     41 ///////////////////////////////////////////////////////////////////////////////
     42 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \
     43     do { \
     44         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
     45         INTERNAL_CATCH_TRY { \
     46             CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
     47             catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \
     48             CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
     49         } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
     50         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
     51     } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look
     52     // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
     53 
     54 ///////////////////////////////////////////////////////////////////////////////
     55 #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \
     56     INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
     57     if( Catch::getResultCapture().lastAssertionPassed() )
     58 
     59 ///////////////////////////////////////////////////////////////////////////////
     60 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \
     61     INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \
     62     if( !Catch::getResultCapture().lastAssertionPassed() )
     63 
     64 #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
     65 
     66 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... )
     67 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... )
     68 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr )
     69 
     70 #else
     71 
     72 ///////////////////////////////////////////////////////////////////////////////
     73 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \
     74     do { \
     75         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \
     76         try { \
     77             static_cast<void>(__VA_ARGS__); \
     78             catchAssertionHandler.handleExceptionNotThrownAsExpected(); \
     79         } \
     80         catch( ... ) { \
     81             catchAssertionHandler.handleUnexpectedInflightException(); \
     82         } \
     83         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
     84     } while( false )
     85 
     86 ///////////////////////////////////////////////////////////////////////////////
     87 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \
     88     do { \
     89         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \
     90         if( catchAssertionHandler.allowThrows() ) \
     91             try { \
     92                 static_cast<void>(__VA_ARGS__); \
     93                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
     94             } \
     95             catch( ... ) { \
     96                 catchAssertionHandler.handleExceptionThrownAsExpected(); \
     97             } \
     98         else \
     99             catchAssertionHandler.handleThrowingCallSkipped(); \
    100         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
    101     } while( false )
    102 
    103 ///////////////////////////////////////////////////////////////////////////////
    104 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
    105     do { \
    106         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \
    107         if( catchAssertionHandler.allowThrows() ) \
    108             try { \
    109                 static_cast<void>(expr); \
    110                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
    111             } \
    112             catch( exceptionType const& ) { \
    113                 catchAssertionHandler.handleExceptionThrownAsExpected(); \
    114             } \
    115             catch( ... ) { \
    116                 catchAssertionHandler.handleUnexpectedInflightException(); \
    117             } \
    118         else \
    119             catchAssertionHandler.handleThrowingCallSkipped(); \
    120         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
    121     } while( false )
    122 
    123 #endif  // CATCH_CONFIG_DISABLE_EXCEPTIONS
    124 
    125 ///////////////////////////////////////////////////////////////////////////////
    126 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
    127     do { \
    128         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \
    129         catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \
    130         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
    131     } while( false )
    132 
    133 ///////////////////////////////////////////////////////////////////////////////
    134 #define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \
    135     auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \
    136     varName.captureValues( 0, __VA_ARGS__ )
    137 
    138 ///////////////////////////////////////////////////////////////////////////////
    139 #define INTERNAL_CATCH_INFO( macroName, log ) \
    140     Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );
    141 
    142 ///////////////////////////////////////////////////////////////////////////////
    143 #define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \
    144     Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )
    145 
    146 ///////////////////////////////////////////////////////////////////////////////
    147 // Although this is matcher-based, it can be used with just a string
    148 #define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \
    149     do { \
    150         Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
    151         if( catchAssertionHandler.allowThrows() ) \
    152             try { \
    153                 static_cast<void>(__VA_ARGS__); \
    154                 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
    155             } \
    156             catch( ... ) { \
    157                 Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \
    158             } \
    159         else \
    160             catchAssertionHandler.handleThrowingCallSkipped(); \
    161         INTERNAL_CATCH_REACT( catchAssertionHandler ) \
    162     } while( false )
    163 
    164 #endif // CATCH_CONFIG_DISABLE
    165 
    166 #endif // TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
    167