mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-26 07:16:10 +01:00
Moved all AssertionHandler logic into RunContext and de-virtualised interface
This makes the assertion handling much less "chatty". AssertionHandler is now just a thin shim over RunContext
This commit is contained in:
parent
5461242ffe
commit
4b614ee1d1
@ -15,6 +15,7 @@
|
|||||||
#include "catch_debugger.h"
|
#include "catch_debugger.h"
|
||||||
#include "catch_interfaces_registry_hub.h"
|
#include "catch_interfaces_registry_hub.h"
|
||||||
#include "catch_capture_matchers.h"
|
#include "catch_capture_matchers.h"
|
||||||
|
#include "catch_run_context.h"
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
@ -57,58 +58,19 @@ namespace Catch {
|
|||||||
StringRef capturedExpression,
|
StringRef capturedExpression,
|
||||||
ResultDisposition::Flags resultDisposition )
|
ResultDisposition::Flags resultDisposition )
|
||||||
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
|
: m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
|
||||||
m_resultCapture( getResultCapture() )
|
m_resultCapture( static_cast<RunContext&>( getResultCapture() ) )
|
||||||
{
|
{}
|
||||||
m_resultCapture.assertionStarting( m_assertionInfo );
|
|
||||||
}
|
|
||||||
AssertionHandler::~AssertionHandler() {
|
AssertionHandler::~AssertionHandler() {
|
||||||
if ( !m_completed ) {
|
if ( !m_completed )
|
||||||
handleMessage(ResultWas::ThrewException, "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE");
|
m_resultCapture.handleIncomplete( m_assertionInfo );
|
||||||
m_resultCapture.exceptionEarlyReported();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
|
void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
|
||||||
|
m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
|
||||||
bool negated = isFalseTest( m_assertionInfo.resultDisposition );
|
|
||||||
bool result = expr.getResult() != negated;
|
|
||||||
|
|
||||||
if(result && !getCurrentContext().getConfig()->includeSuccessfulResults())
|
|
||||||
{
|
|
||||||
m_resultCapture.assertionRun();
|
|
||||||
m_resultCapture.assertionPassed();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle( result ? ResultWas::Ok : ResultWas::ExpressionFailed, &expr, negated );
|
|
||||||
}
|
|
||||||
void AssertionHandler::handle( ResultWas::OfType resultType ) {
|
|
||||||
handle( resultType, nullptr, false );
|
|
||||||
}
|
}
|
||||||
void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const &message) {
|
void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const &message) {
|
||||||
AssertionResultData data( resultType, LazyExpression( false ) );
|
m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );
|
||||||
data.message = message;
|
|
||||||
handle( data, nullptr );
|
|
||||||
}
|
|
||||||
void AssertionHandler::handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated ) {
|
|
||||||
AssertionResultData data( resultType, LazyExpression( negated ) );
|
|
||||||
handle( data, expr );
|
|
||||||
}
|
|
||||||
void AssertionHandler::handle( AssertionResultData const& resultData, ITransientExpression const* expr ) {
|
|
||||||
|
|
||||||
m_resultCapture.assertionRun();
|
|
||||||
|
|
||||||
AssertionResult assertionResult{ m_assertionInfo, resultData };
|
|
||||||
assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
|
|
||||||
|
|
||||||
m_resultCapture.assertionEnded( assertionResult );
|
|
||||||
|
|
||||||
if( !assertionResult.isOk() ) {
|
|
||||||
m_shouldDebugBreak = getCurrentContext().getConfig()->shouldDebugBreak();
|
|
||||||
m_shouldThrow =
|
|
||||||
getCurrentContext().getRunner()->aborting() ||
|
|
||||||
(m_assertionInfo.resultDisposition & ResultDisposition::Normal);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AssertionHandler::allowThrows() const -> bool {
|
auto AssertionHandler::allowThrows() const -> bool {
|
||||||
@ -117,7 +79,7 @@ namespace Catch {
|
|||||||
|
|
||||||
void AssertionHandler::complete() {
|
void AssertionHandler::complete() {
|
||||||
setCompleted();
|
setCompleted();
|
||||||
if( m_shouldDebugBreak ) {
|
if( m_reaction.shouldDebugBreak ) {
|
||||||
|
|
||||||
// If you find your debugger stopping you here then go one level up on the
|
// If you find your debugger stopping you here then go one level up on the
|
||||||
// call-stack for the code that caused it (typically a failed assertion)
|
// call-stack for the code that caused it (typically a failed assertion)
|
||||||
@ -125,7 +87,7 @@ namespace Catch {
|
|||||||
// (To go back to the test and change execution, jump over the throw, next)
|
// (To go back to the test and change execution, jump over the throw, next)
|
||||||
CATCH_BREAK_INTO_DEBUGGER();
|
CATCH_BREAK_INTO_DEBUGGER();
|
||||||
}
|
}
|
||||||
if( m_shouldThrow )
|
if( m_reaction.shouldThrow )
|
||||||
throw Catch::TestFailureException();
|
throw Catch::TestFailureException();
|
||||||
}
|
}
|
||||||
void AssertionHandler::setCompleted() {
|
void AssertionHandler::setCompleted() {
|
||||||
@ -133,22 +95,22 @@ namespace Catch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AssertionHandler::handleUnexpectedInflightException() {
|
void AssertionHandler::handleUnexpectedInflightException() {
|
||||||
handleMessage(ResultWas::ThrewException, Catch::translateActiveException());
|
m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssertionHandler::handleExceptionThrownAsExpected() {
|
void AssertionHandler::handleExceptionThrownAsExpected() {
|
||||||
handle( Catch::ResultWas::Ok );
|
m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
|
||||||
}
|
}
|
||||||
void AssertionHandler::handleExceptionNotThrownAsExpected() {
|
void AssertionHandler::handleExceptionNotThrownAsExpected() {
|
||||||
handle( Catch::ResultWas::Ok );
|
m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssertionHandler::handleUnexpectedExceptionNotThrown() {
|
void AssertionHandler::handleUnexpectedExceptionNotThrown() {
|
||||||
handle( Catch::ResultWas::DidntThrowException );
|
m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssertionHandler::handleThrowingCallSkipped() {
|
void AssertionHandler::handleThrowingCallSkipped() {
|
||||||
handle( Catch::ResultWas::Ok );
|
m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the overload that takes a string and infers the Equals matcher from it
|
// This is the overload that takes a string and infers the Equals matcher from it
|
||||||
|
@ -16,10 +16,12 @@ namespace Catch {
|
|||||||
struct TestFailureException{};
|
struct TestFailureException{};
|
||||||
struct AssertionResultData;
|
struct AssertionResultData;
|
||||||
struct IResultCapture;
|
struct IResultCapture;
|
||||||
|
class RunContext;
|
||||||
|
|
||||||
class LazyExpression {
|
class LazyExpression {
|
||||||
friend class AssertionHandler;
|
friend class AssertionHandler;
|
||||||
friend struct AssertionStats;
|
friend struct AssertionStats;
|
||||||
|
friend class RunContext;
|
||||||
|
|
||||||
ITransientExpression const* m_transientExpression = nullptr;
|
ITransientExpression const* m_transientExpression = nullptr;
|
||||||
bool m_isNegated;
|
bool m_isNegated;
|
||||||
@ -33,12 +35,16 @@ namespace Catch {
|
|||||||
friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
|
friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AssertionReaction {
|
||||||
|
bool shouldDebugBreak = false;
|
||||||
|
bool shouldThrow = false;
|
||||||
|
};
|
||||||
|
|
||||||
class AssertionHandler {
|
class AssertionHandler {
|
||||||
AssertionInfo m_assertionInfo;
|
AssertionInfo m_assertionInfo;
|
||||||
bool m_shouldDebugBreak = false;
|
AssertionReaction m_reaction;
|
||||||
bool m_shouldThrow = false;
|
|
||||||
bool m_completed = false;
|
bool m_completed = false;
|
||||||
IResultCapture& m_resultCapture;
|
RunContext& m_resultCapture;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AssertionHandler
|
AssertionHandler
|
||||||
@ -67,11 +73,6 @@ namespace Catch {
|
|||||||
|
|
||||||
// query
|
// query
|
||||||
auto allowThrows() const -> bool;
|
auto allowThrows() const -> bool;
|
||||||
|
|
||||||
private:
|
|
||||||
void handle( ResultWas::OfType resultType );
|
|
||||||
void handle( ResultWas::OfType resultType, ITransientExpression const* expr, bool negated );
|
|
||||||
void handle( AssertionResultData const& resultData, ITransientExpression const* expr );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
|
void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString );
|
||||||
|
@ -27,8 +27,6 @@ namespace Catch {
|
|||||||
|
|
||||||
virtual ~IResultCapture();
|
virtual ~IResultCapture();
|
||||||
|
|
||||||
virtual void assertionStarting( AssertionInfo const& info ) = 0;
|
|
||||||
virtual void assertionEnded( AssertionResult const& result ) = 0;
|
|
||||||
virtual bool sectionStarted( SectionInfo const& sectionInfo,
|
virtual bool sectionStarted( SectionInfo const& sectionInfo,
|
||||||
Counts& assertions ) = 0;
|
Counts& assertions ) = 0;
|
||||||
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
|
virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
|
||||||
|
@ -40,7 +40,8 @@ namespace Catch {
|
|||||||
m_context(getCurrentMutableContext()),
|
m_context(getCurrentMutableContext()),
|
||||||
m_config(_config),
|
m_config(_config),
|
||||||
m_reporter(std::move(reporter)),
|
m_reporter(std::move(reporter)),
|
||||||
m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal }
|
m_lastAssertionInfo{ "", SourceLineInfo("",0), "", ResultDisposition::Normal },
|
||||||
|
m_includeSuccessfulResults( m_config->includeSuccessfulResults() )
|
||||||
{
|
{
|
||||||
m_context.setRunner(this);
|
m_context.setRunner(this);
|
||||||
m_context.setConfig(m_config);
|
m_context.setConfig(m_config);
|
||||||
@ -109,9 +110,6 @@ namespace Catch {
|
|||||||
return *m_reporter;
|
return *m_reporter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunContext::assertionStarting(AssertionInfo const& info) {
|
|
||||||
m_reporter->assertionStarting( info );
|
|
||||||
}
|
|
||||||
void RunContext::assertionEnded(AssertionResult const & result) {
|
void RunContext::assertionEnded(AssertionResult const & result) {
|
||||||
if (result.getResultType() == ResultWas::Ok) {
|
if (result.getResultType() == ResultWas::Ok) {
|
||||||
m_totals.assertions.passed++;
|
m_totals.assertions.passed++;
|
||||||
@ -223,7 +221,7 @@ namespace Catch {
|
|||||||
tempResult.message = message;
|
tempResult.message = message;
|
||||||
AssertionResult result(m_lastAssertionInfo, tempResult);
|
AssertionResult result(m_lastAssertionInfo, tempResult);
|
||||||
|
|
||||||
getResultCapture().assertionEnded(result);
|
assertionEnded(result);
|
||||||
|
|
||||||
handleUnfinishedSections();
|
handleUnfinishedSections();
|
||||||
|
|
||||||
@ -296,14 +294,9 @@ namespace Catch {
|
|||||||
} catch (...) {
|
} catch (...) {
|
||||||
// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
|
// Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
|
||||||
// are reported without translation at the point of origin.
|
// are reported without translation at the point of origin.
|
||||||
if (m_shouldReportUnexpected) {
|
if( m_shouldReportUnexpected ) {
|
||||||
AssertionHandler handler
|
AssertionReaction dummyReaction;
|
||||||
( m_lastAssertionInfo.macroName,
|
handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );
|
||||||
m_lastAssertionInfo.lineInfo,
|
|
||||||
m_lastAssertionInfo.capturedExpression,
|
|
||||||
m_lastAssertionInfo.resultDisposition );
|
|
||||||
handler.handleUnexpectedInflightException();
|
|
||||||
handler.setCompleted();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_testCaseTracker->close();
|
m_testCaseTracker->close();
|
||||||
@ -333,6 +326,119 @@ namespace Catch {
|
|||||||
m_unfinishedSections.clear();
|
m_unfinishedSections.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RunContext::handleExpr(
|
||||||
|
AssertionInfo const& info,
|
||||||
|
ITransientExpression const& expr,
|
||||||
|
AssertionReaction& reaction
|
||||||
|
) {
|
||||||
|
m_reporter->assertionStarting( info );
|
||||||
|
assertionRun();
|
||||||
|
|
||||||
|
bool negated = isFalseTest( info.resultDisposition );
|
||||||
|
bool result = expr.getResult() != negated;
|
||||||
|
|
||||||
|
if( result ) {
|
||||||
|
if (!m_includeSuccessfulResults) {
|
||||||
|
assertionRun();
|
||||||
|
assertionPassed();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
reportExpr(info, ResultWas::Ok, &expr, negated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );
|
||||||
|
populateReaction( reaction );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void RunContext::reportExpr(
|
||||||
|
AssertionInfo const &info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
ITransientExpression const *expr,
|
||||||
|
bool negated ) {
|
||||||
|
|
||||||
|
m_lastAssertionInfo = info;
|
||||||
|
AssertionResultData data( resultType, LazyExpression( negated ) );
|
||||||
|
|
||||||
|
AssertionResult assertionResult{ info, data };
|
||||||
|
assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
|
||||||
|
|
||||||
|
assertionEnded( assertionResult );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunContext::handleMessage(
|
||||||
|
AssertionInfo const& info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
StringRef const &message,
|
||||||
|
AssertionReaction& reaction
|
||||||
|
) {
|
||||||
|
m_reporter->assertionStarting( info );
|
||||||
|
|
||||||
|
m_lastAssertionInfo = info;
|
||||||
|
assertionRun();
|
||||||
|
|
||||||
|
AssertionResultData data( resultType, LazyExpression( false ) );
|
||||||
|
data.message = message;
|
||||||
|
AssertionResult assertionResult{ m_lastAssertionInfo, data };
|
||||||
|
assertionEnded( assertionResult );
|
||||||
|
if( !assertionResult.isOk() )
|
||||||
|
populateReaction( reaction );
|
||||||
|
}
|
||||||
|
void RunContext::handleUnexpectedExceptionNotThrown(
|
||||||
|
AssertionInfo const& info,
|
||||||
|
AssertionReaction& reaction
|
||||||
|
) {
|
||||||
|
handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunContext::handleUnexpectedInflightException(
|
||||||
|
AssertionInfo const& info,
|
||||||
|
std::string const& message,
|
||||||
|
AssertionReaction& reaction
|
||||||
|
) {
|
||||||
|
m_lastAssertionInfo = info;
|
||||||
|
assertionRun();
|
||||||
|
|
||||||
|
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
|
||||||
|
data.message = message;
|
||||||
|
AssertionResult assertionResult{ info, data };
|
||||||
|
assertionEnded( assertionResult );
|
||||||
|
populateReaction( reaction );
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunContext::populateReaction( AssertionReaction& reaction ) {
|
||||||
|
reaction.shouldDebugBreak = m_config->shouldDebugBreak();
|
||||||
|
reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunContext::handleIncomplete(
|
||||||
|
AssertionInfo const& info
|
||||||
|
) {
|
||||||
|
m_lastAssertionInfo = info;
|
||||||
|
assertionRun();
|
||||||
|
|
||||||
|
AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );
|
||||||
|
data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
|
||||||
|
AssertionResult assertionResult{ info, data };
|
||||||
|
assertionEnded( assertionResult );
|
||||||
|
}
|
||||||
|
void RunContext::handleNonExpr(
|
||||||
|
AssertionInfo const &info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
AssertionReaction &reaction
|
||||||
|
) {
|
||||||
|
m_lastAssertionInfo = info;
|
||||||
|
assertionRun();
|
||||||
|
|
||||||
|
AssertionResultData data( resultType, LazyExpression( false ) );
|
||||||
|
AssertionResult assertionResult{ info, data };
|
||||||
|
assertionEnded( assertionResult );
|
||||||
|
|
||||||
|
if( !assertionResult.isOk() )
|
||||||
|
populateReaction( reaction );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
IResultCapture& getResultCapture() {
|
IResultCapture& getResultCapture() {
|
||||||
if (auto* capture = getCurrentContext().getResultCapture())
|
if (auto* capture = getCurrentContext().getResultCapture())
|
||||||
return *capture;
|
return *capture;
|
||||||
|
@ -75,11 +75,41 @@ namespace Catch {
|
|||||||
IConfigPtr config() const;
|
IConfigPtr config() const;
|
||||||
IStreamingReporter& reporter() const;
|
IStreamingReporter& reporter() const;
|
||||||
|
|
||||||
private: // IResultCapture
|
// Assertion handlers
|
||||||
|
void handleExpr
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
ITransientExpression const& expr,
|
||||||
|
AssertionReaction& reaction );
|
||||||
|
void handleMessage
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
StringRef const &message,
|
||||||
|
AssertionReaction& reaction );
|
||||||
|
void handleUnexpectedExceptionNotThrown
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
AssertionReaction& reaction );
|
||||||
|
void handleUnexpectedInflightException
|
||||||
|
( AssertionInfo const& info,
|
||||||
|
std::string const& message,
|
||||||
|
AssertionReaction& reaction );
|
||||||
|
void handleIncomplete
|
||||||
|
( AssertionInfo const& info );
|
||||||
|
void handleNonExpr
|
||||||
|
( AssertionInfo const &info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
AssertionReaction &reaction );
|
||||||
|
|
||||||
|
void reportExpr
|
||||||
|
(AssertionInfo const &info,
|
||||||
|
ResultWas::OfType resultType,
|
||||||
|
ITransientExpression const *expr,
|
||||||
|
bool negated );
|
||||||
|
|
||||||
void assertionStarting(AssertionInfo const& info) override;
|
void populateReaction( AssertionReaction& reaction );
|
||||||
void assertionEnded(AssertionResult const& result) override;
|
|
||||||
|
public: // IResultCapture
|
||||||
|
|
||||||
|
void assertionEnded(AssertionResult const& result); // devirt
|
||||||
|
|
||||||
bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;
|
bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;
|
||||||
bool testForMissingAssertions(Counts& assertions);
|
bool testForMissingAssertions(Counts& assertions);
|
||||||
@ -103,9 +133,9 @@ namespace Catch {
|
|||||||
|
|
||||||
bool lastAssertionPassed() override;
|
bool lastAssertionPassed() override;
|
||||||
|
|
||||||
void assertionPassed() override;
|
void assertionPassed() override; // devirt
|
||||||
|
|
||||||
void assertionRun() override;
|
void assertionRun() override; // devirt
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// !TBD We need to do this another way!
|
// !TBD We need to do this another way!
|
||||||
@ -138,6 +168,7 @@ namespace Catch {
|
|||||||
TrackerContext m_trackerContext;
|
TrackerContext m_trackerContext;
|
||||||
std::size_t m_prevPassed = 0;
|
std::size_t m_prevPassed = 0;
|
||||||
bool m_shouldReportUnexpected = true;
|
bool m_shouldReportUnexpected = true;
|
||||||
|
bool m_includeSuccessfulResults;
|
||||||
};
|
};
|
||||||
|
|
||||||
IResultCapture& getResultCapture();
|
IResultCapture& getResultCapture();
|
||||||
|
Loading…
Reference in New Issue
Block a user