catch2/include/internal/catch_result_builder.hpp

162 lines
6.7 KiB
C++

/*
* Created by Phil on 28/5/2014.
* Copyright 2014 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)
*/
#ifndef TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
#include "catch_result_builder.h"
#include "catch_context.h"
#include "catch_interfaces_config.h"
#include "catch_interfaces_runner.h"
#include "catch_interfaces_capture.h"
#include "catch_interfaces_registry_hub.h"
#include "catch_wildcard_pattern.hpp"
namespace Catch {
std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
return secondArg.empty() || secondArg == "\"\""
? capturedExpression
: capturedExpression + ", " + secondArg;
}
ResultBuilder::ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo,
char const* capturedExpression,
ResultDisposition::Flags resultDisposition,
char const* secondArg )
: m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
m_shouldDebugBreak( false ),
m_shouldThrow( false )
{}
ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
m_data.resultType = result;
return *this;
}
ResultBuilder& ResultBuilder::setResultType( bool result ) {
m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
return *this;
}
ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) {
m_exprComponents.lhs = lhs;
return *this;
}
ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) {
m_exprComponents.rhs = rhs;
return *this;
}
ResultBuilder& ResultBuilder::setOp( std::string const& op ) {
m_exprComponents.op = op;
return *this;
}
void ResultBuilder::endExpression() {
m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition );
captureExpression();
}
void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
m_assertionInfo.resultDisposition = resultDisposition;
m_stream.oss << Catch::translateActiveException();
captureResult( ResultWas::ThrewException );
}
void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
setResultType( resultType );
captureExpression();
}
void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
if( expectedMessage.empty() )
captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() );
else
captureExpectedException( Matchers::Equals( expectedMessage ) );
}
void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) {
assert( m_exprComponents.testFalse == false );
AssertionResultData data = m_data;
data.resultType = ResultWas::Ok;
data.reconstructedExpression = m_assertionInfo.capturedExpression;
std::string actualMessage = Catch::translateActiveException();
if( !matcher.match( actualMessage ) ) {
data.resultType = ResultWas::ExpressionFailed;
data.reconstructedExpression = actualMessage;
}
AssertionResult result( m_assertionInfo, data );
handleResult( result );
}
void ResultBuilder::captureExpression() {
AssertionResult result = build();
handleResult( result );
}
void ResultBuilder::handleResult( AssertionResult const& result )
{
getResultCapture().assertionEnded( result );
if( !result.isOk() ) {
if( getCurrentContext().getConfig()->shouldDebugBreak() )
m_shouldDebugBreak = true;
if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
m_shouldThrow = true;
}
}
void ResultBuilder::react() {
if( m_shouldThrow )
throw Catch::TestFailureException();
}
bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
AssertionResult ResultBuilder::build() const
{
assert( m_data.resultType != ResultWas::Unknown );
AssertionResultData data = m_data;
// Flip bool results if testFalse is set
if( m_exprComponents.testFalse ) {
if( data.resultType == ResultWas::Ok )
data.resultType = ResultWas::ExpressionFailed;
else if( data.resultType == ResultWas::ExpressionFailed )
data.resultType = ResultWas::Ok;
}
data.message = m_stream.oss.str();
data.reconstructedExpression = reconstructExpression();
if( m_exprComponents.testFalse ) {
if( m_exprComponents.op == "" )
data.reconstructedExpression = "!" + data.reconstructedExpression;
else
data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
}
return AssertionResult( m_assertionInfo, data );
}
std::string ResultBuilder::reconstructExpression() const {
if( m_exprComponents.op == "" )
return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
else if( m_exprComponents.op == "matches" )
return m_exprComponents.lhs + " " + m_exprComponents.rhs;
else if( m_exprComponents.op != "!" ) {
if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
m_exprComponents.lhs.find("\n") == std::string::npos &&
m_exprComponents.rhs.find("\n") == std::string::npos )
return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
else
return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
}
else
return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}";
}
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED