Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/include/internal/catch_assertionhandler.cpp
diff options
context:
space:
mode:
authorPhil Nash2017-08-08 17:53:01 +0100
committerPhil Nash2017-08-08 17:53:01 +0100
commitf247ce5bff025281d4a7e9fa76aa78eb8479ddfe (patch)
tree45de7761cc0a728936161d96e785ae397106c72c /include/internal/catch_assertionhandler.cpp
parentf8148ebae1e07c5609ed0af5993694e2972d0dfd (diff)
downloadcatch3-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.cpp135
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