diff options
| author | Phil Nash | 2017-08-08 17:53:01 +0100 |
|---|---|---|
| committer | Phil Nash | 2017-08-08 17:53:01 +0100 |
| commit | f247ce5bff025281d4a7e9fa76aa78eb8479ddfe (patch) | |
| tree | 45de7761cc0a728936161d96e785ae397106c72c /include/internal/catch_assertionhandler.cpp | |
| parent | f8148ebae1e07c5609ed0af5993694e2972d0dfd (diff) | |
| download | catch3-f247ce5bff025281d4a7e9fa76aa78eb8479ddfe.tar.gz | |
First cut of new AssertionHandler/ Decomposer
- integrated into INTERNAL_CATCH_TEST. Needs more work to fully replace existing stuff
Diffstat (limited to 'include/internal/catch_assertionhandler.cpp')
| -rw-r--r-- | include/internal/catch_assertionhandler.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/include/internal/catch_assertionhandler.cpp b/include/internal/catch_assertionhandler.cpp new file mode 100644 index 00000000..a71a2dc2 --- /dev/null +++ b/include/internal/catch_assertionhandler.cpp @@ -0,0 +1,135 @@ +/* + * Created by Phil on 8/8/2017. + * Copyright 2017 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "catch_assertionhandler.h" +#include "catch_assertionresult.h" +#include "catch_interfaces_capture.h" +#include "catch_interfaces_runner.h" +#include "catch_context.h" +#include "catch_debugger.h" +#include "catch_interfaces_registry_hub.h" + +#include <iostream> // !TBD + +namespace Catch { + + auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { + expr.streamReconstructedExpression( os ); + return os; + } + + LazyExpression::LazyExpression( bool isNegated ) + : m_isNegated( isNegated ) + {} + + LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} + + LazyExpression::operator bool() const { + return m_transientExpression != nullptr; + } + + auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { + if( lazyExpr.m_isNegated ) + os << "!"; + + if( lazyExpr ) { + if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) + os << "(" << *lazyExpr.m_transientExpression << ")"; + else + os << *lazyExpr.m_transientExpression; + } + else { + os << "{** error - unchecked empty expression requested **}"; + } + return os; + } + + AssertionHandler::AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ) + : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition } + { + getCurrentContext().getResultCapture()->assertionStarting( m_assertionInfo ); + } + + void AssertionHandler::handle( ITransientExpression const& expr ) { + + bool negated = isFalseTest( m_assertionInfo.resultDisposition ); + bool result = expr.getResult() != negated; + + AssertionResultData data( result ? ResultWas::Ok : ResultWas::ExpressionFailed, LazyExpression( negated ) ); + + // Deprecated +// data.negated = negated; +// data.parenthesized = negated && expr.isBinaryExpression(); // !TBD: needed? +// data.decomposedExpression = nullptr; // !TBD +// data.reconstructedExpression = ""; // !TBD + + + getResultCapture().assertionRun(); + + AssertionResult assertionResult{ m_assertionInfo, data }; + assertionResult.m_resultData.lazyExpression.m_transientExpression = &expr; + + getResultCapture().assertionEnded( assertionResult ); + + if( !assertionResult.isOk() ) { + m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak(); + m_shouldThrow = + getCurrentContext().getRunner()->aborting() || + (m_assertionInfo.resultDisposition & ResultDisposition::Normal); + } + } + + auto AssertionHandler::shouldDebugBreak() const -> bool { + return m_shouldDebugBreak; + } + void AssertionHandler::reactWithDebugBreak() const { + if (m_shouldDebugBreak) { + /////////////////////////////////////////////////////////////////// + // To inspect the state during test, you need to go one level up the callstack + // To go back to the test and change execution, jump over the reactWithoutDebugBreak() call + /////////////////////////////////////////////////////////////////// + CATCH_BREAK_INTO_DEBUGGER(); + } + reactWithoutDebugBreak(); + } + void AssertionHandler::reactWithoutDebugBreak() const { + if( m_shouldThrow ) + throw Catch::TestFailureException(); + } + + void AssertionHandler::useActiveException( ResultDisposition::Flags resultDisposition ) { + m_assertionInfo.resultDisposition = resultDisposition; + useActiveException(); + } + void AssertionHandler::useActiveException() { + bool negated = isFalseTest( m_assertionInfo.resultDisposition ); + + AssertionResultData data( ResultWas::ThrewException, LazyExpression( negated ) ); + data.message = Catch::translateActiveException(); + + //data.decomposedExpression = &expr; // for lazy reconstruction + + AssertionResult result( m_assertionInfo, data ); + + getResultCapture().assertionEnded( result ); + + // !TBD: factor this out? handleResult()? + if( !result.isOk() ) { + if( getCurrentContext().getConfig()->shouldDebugBreak() ) + m_shouldDebugBreak = true; + if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) + m_shouldThrow = true; + } + + } + +} // namespace Catch |