1 /*
2  *  Created by Phil on 8/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 
9 #include "catch_assertionhandler.h"
10 #include "catch_assertionresult.h"
11 #include "catch_interfaces_runner.h"
12 #include "catch_interfaces_config.h"
13 #include "catch_context.h"
14 #include "catch_debugger.h"
15 #include "catch_interfaces_registry_hub.h"
16 #include "catch_capture_matchers.h"
17 #include "catch_run_context.h"
18 #include "catch_enforce.h"
19 
20 namespace Catch {
21 
22     namespace {
operator <<(std::ostream & os,ITransientExpression const & expr)23         auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {
24             expr.streamReconstructedExpression( os );
25             return os;
26         }
27     }
28 
LazyExpression(bool isNegated)29     LazyExpression::LazyExpression( bool isNegated )
30     :   m_isNegated( isNegated )
31     {}
32 
LazyExpression(LazyExpression const & other)33     LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {}
34 
operator bool() const35     LazyExpression::operator bool() const {
36         return m_transientExpression != nullptr;
37     }
38 
operator <<(std::ostream & os,LazyExpression const & lazyExpr)39     auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& {
40         if( lazyExpr.m_isNegated )
41             os << "!";
42 
43         if( lazyExpr ) {
44             if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
45                 os << "(" << *lazyExpr.m_transientExpression << ")";
46             else
47                 os << *lazyExpr.m_transientExpression;
48         }
49         else {
50             os << "{** error - unchecked empty expression requested **}";
51         }
52         return os;
53     }
54 
AssertionHandler(StringRef const & macroName,SourceLineInfo const & lineInfo,StringRef capturedExpression,ResultDisposition::Flags resultDisposition)55     AssertionHandler::AssertionHandler
56         (   StringRef const& macroName,
57             SourceLineInfo const& lineInfo,
58             StringRef capturedExpression,
59             ResultDisposition::Flags resultDisposition )
60     :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
61         m_resultCapture( getResultCapture() )
62     {}
63 
handleExpr(ITransientExpression const & expr)64     void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
65         m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
66     }
handleMessage(ResultWas::OfType resultType,StringRef const & message)67     void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) {
68         m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
69     }
70 
allowThrows() const71     auto AssertionHandler::allowThrows() const -> bool {
72         return getCurrentContext().getConfig()->allowThrows();
73     }
74 
complete()75     void AssertionHandler::complete() {
76         setCompleted();
77         if( m_reaction.shouldDebugBreak ) {
78 
79             // If you find your debugger stopping you here then go one level up on the
80             // call-stack for the code that caused it (typically a failed assertion)
81 
82             // (To go back to the test and change execution, jump over the throw, next)
83             CATCH_BREAK_INTO_DEBUGGER();
84         }
85         if (m_reaction.shouldThrow) {
86 #if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
87             throw Catch::TestFailureException();
88 #else
89             CATCH_ERROR( "Test failure requires aborting test!" );
90 #endif
91         }
92     }
setCompleted()93     void AssertionHandler::setCompleted() {
94         m_completed = true;
95     }
96 
handleUnexpectedInflightException()97     void AssertionHandler::handleUnexpectedInflightException() {
98         m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
99     }
100 
handleExceptionThrownAsExpected()101     void AssertionHandler::handleExceptionThrownAsExpected() {
102         m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
103     }
handleExceptionNotThrownAsExpected()104     void AssertionHandler::handleExceptionNotThrownAsExpected() {
105         m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
106     }
107 
handleUnexpectedExceptionNotThrown()108     void AssertionHandler::handleUnexpectedExceptionNotThrown() {
109         m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
110     }
111 
handleThrowingCallSkipped()112     void AssertionHandler::handleThrowingCallSkipped() {
113         m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
114     }
115 
116     // This is the overload that takes a string and infers the Equals matcher from it
117     // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp
handleExceptionMatchExpr(AssertionHandler & handler,std::string const & str,StringRef const & matcherString)118     void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString  ) {
119         handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );
120     }
121 
122 } // namespace Catch
123