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