mirror of
https://github.com/catchorg/Catch2.git
synced 2024-11-26 07:16:10 +01:00
v1.1 build 2 (develop branch)
- Signal hander support
This commit is contained in:
parent
05743eeaa1
commit
93b61e1194
@ -1,6 +1,6 @@
|
|||||||
![catch logo](catch-logo-small.png)
|
![catch logo](catch-logo-small.png)
|
||||||
|
|
||||||
*v1.1 build 1 (develop branch)*
|
*v1.1 build 2 (develop branch)*
|
||||||
|
|
||||||
Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch)
|
Build status (on Travis CI) [![Build Status](https://travis-ci.org/philsquared/Catch.png)](https://travis-ci.org/philsquared/Catch)
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
// These numbers are maintained by a script
|
// These numbers are maintained by a script
|
||||||
Version libraryVersion( 1, 1, 1, "develop" );
|
Version libraryVersion( 1, 1, 2, "develop" );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
|
#endif // TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* CATCH v1.1 build 1 (develop branch)
|
* CATCH v1.1 build 2 (develop branch)
|
||||||
* Generated: 2014-08-20 19:07:01.206746
|
* Generated: 2014-08-22 19:34:41.932570
|
||||||
* ----------------------------------------------------------
|
* ----------------------------------------------------------
|
||||||
* This file has been merged from multiple headers. Please don't edit it directly
|
* This file has been merged from multiple headers. Please don't edit it directly
|
||||||
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
|
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
|
||||||
@ -603,7 +603,9 @@ namespace Catch {
|
|||||||
Exception = 0x100 | FailureBit,
|
Exception = 0x100 | FailureBit,
|
||||||
|
|
||||||
ThrewException = Exception | 1,
|
ThrewException = Exception | 1,
|
||||||
DidntThrowException = Exception | 2
|
DidntThrowException = Exception | 2,
|
||||||
|
|
||||||
|
FatalErrorCondition = 0x200 | FailureBit
|
||||||
|
|
||||||
}; };
|
}; };
|
||||||
|
|
||||||
@ -1395,6 +1397,8 @@ namespace Catch {
|
|||||||
|
|
||||||
virtual std::string getCurrentTestName() const = 0;
|
virtual std::string getCurrentTestName() const = 0;
|
||||||
virtual const AssertionResult* getLastResult() const = 0;
|
virtual const AssertionResult* getLastResult() const = 0;
|
||||||
|
|
||||||
|
virtual void handleFatalErrorCondition( std::string const& message ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
IResultCapture& getResultCapture();
|
IResultCapture& getResultCapture();
|
||||||
@ -4915,6 +4919,71 @@ using SectionTracking::TestCaseTracker;
|
|||||||
|
|
||||||
} // namespace Catch
|
} // namespace Catch
|
||||||
|
|
||||||
|
// #included from: catch_fatal_condition.hpp
|
||||||
|
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
// Report the error condition then exit the process
|
||||||
|
inline void fatal( std::string const& message, int exitCode ) {
|
||||||
|
IContext& context = Catch::getCurrentContext();
|
||||||
|
IResultCapture* resultCapture = context.getResultCapture();
|
||||||
|
resultCapture->handleFatalErrorCondition( message );
|
||||||
|
|
||||||
|
if( Catch::alwaysTrue() ) // avoids "no return" warnings
|
||||||
|
exit( exitCode );
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
struct FatalConditionHandler {};
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
namespace Catch {
|
||||||
|
|
||||||
|
struct SignalDefs { int id; const char* name; };
|
||||||
|
extern SignalDefs signalDefs[];
|
||||||
|
SignalDefs signalDefs[] = {
|
||||||
|
{ SIGINT, "SIGINT - Terminal interrupt signal" },
|
||||||
|
{ SIGILL, "SIGILL - Illegal instruction signal" },
|
||||||
|
{ SIGFPE, "SIGFPE - Floating point error signal" },
|
||||||
|
{ SIGSEGV, "SIGSEGV - Segmentation violation signal" },
|
||||||
|
{ SIGTERM, "SIGTERM - Termination request signal" },
|
||||||
|
{ SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FatalConditionHandler {
|
||||||
|
|
||||||
|
static void handleSignal( int sig ) {
|
||||||
|
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
||||||
|
if( sig == signalDefs[i].id )
|
||||||
|
fatal( signalDefs[i].name, -sig );
|
||||||
|
fatal( "<unknown signal>", -sig );
|
||||||
|
}
|
||||||
|
|
||||||
|
FatalConditionHandler() {
|
||||||
|
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
||||||
|
signal( signalDefs[i].id, handleSignal );
|
||||||
|
}
|
||||||
|
~FatalConditionHandler() {
|
||||||
|
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
|
||||||
|
signal( signalDefs[i].id, SIG_DFL );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Catch
|
||||||
|
|
||||||
|
#endif // not Windows
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -5102,6 +5171,37 @@ namespace Catch {
|
|||||||
return &m_lastResult;
|
return &m_lastResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void handleFatalErrorCondition( std::string const& message ) {
|
||||||
|
ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
|
||||||
|
resultBuilder.setResultType( ResultWas::FatalErrorCondition );
|
||||||
|
resultBuilder << message;
|
||||||
|
resultBuilder.captureExpression();
|
||||||
|
|
||||||
|
handleUnfinishedSections();
|
||||||
|
|
||||||
|
// Recreate section for test case (as we will lose the one that was in scope)
|
||||||
|
TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
|
||||||
|
SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
|
||||||
|
|
||||||
|
Counts assertions;
|
||||||
|
assertions.failed = 1;
|
||||||
|
SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
|
||||||
|
m_reporter->sectionEnded( testCaseSectionStats );
|
||||||
|
|
||||||
|
TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
|
||||||
|
|
||||||
|
Totals deltaTotals;
|
||||||
|
deltaTotals.testCases.failed = 1;
|
||||||
|
m_reporter->testCaseEnded( TestCaseStats( testInfo,
|
||||||
|
deltaTotals,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
false ) );
|
||||||
|
m_totals.testCases.failed++;
|
||||||
|
testGroupEnded( "", m_totals, 1, 1 );
|
||||||
|
m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// !TBD We need to do this another way!
|
// !TBD We need to do this another way!
|
||||||
bool aborting() const {
|
bool aborting() const {
|
||||||
@ -5125,10 +5225,10 @@ namespace Catch {
|
|||||||
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
|
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
|
||||||
StreamRedirect coutRedir( std::cout, redirectedCout );
|
StreamRedirect coutRedir( std::cout, redirectedCout );
|
||||||
StreamRedirect cerrRedir( std::cerr, redirectedCerr );
|
StreamRedirect cerrRedir( std::cerr, redirectedCerr );
|
||||||
m_activeTestCase->invoke();
|
invokeActiveTestCase();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_activeTestCase->invoke();
|
invokeActiveTestCase();
|
||||||
}
|
}
|
||||||
duration = timer.getElapsedSeconds();
|
duration = timer.getElapsedSeconds();
|
||||||
}
|
}
|
||||||
@ -5136,20 +5236,9 @@ namespace Catch {
|
|||||||
// This just means the test was aborted due to failure
|
// This just means the test was aborted due to failure
|
||||||
}
|
}
|
||||||
catch(...) {
|
catch(...) {
|
||||||
ResultBuilder exResult( m_lastAssertionInfo.macroName.c_str(),
|
makeUnexpectedResultBuilder().useActiveException();
|
||||||
m_lastAssertionInfo.lineInfo,
|
|
||||||
m_lastAssertionInfo.capturedExpression.c_str(),
|
|
||||||
m_lastAssertionInfo.resultDisposition );
|
|
||||||
exResult.useActiveException();
|
|
||||||
}
|
}
|
||||||
// If sections ended prematurely due to an exception we stored their
|
handleUnfinishedSections();
|
||||||
// infos here so we can tear them down outside the unwind process.
|
|
||||||
for( std::vector<UnfinishedSections>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
|
|
||||||
itEnd = m_unfinishedSections.rend();
|
|
||||||
it != itEnd;
|
|
||||||
++it )
|
|
||||||
sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
|
|
||||||
m_unfinishedSections.clear();
|
|
||||||
m_messages.clear();
|
m_messages.clear();
|
||||||
|
|
||||||
Counts assertions = m_totals.assertions - prevAssertions;
|
Counts assertions = m_totals.assertions - prevAssertions;
|
||||||
@ -5165,7 +5254,31 @@ namespace Catch {
|
|||||||
m_reporter->sectionEnded( testCaseSectionStats );
|
m_reporter->sectionEnded( testCaseSectionStats );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void invokeActiveTestCase() {
|
||||||
|
FatalConditionHandler fatalConditionHandler; // Handle signals
|
||||||
|
m_activeTestCase->invoke();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
ResultBuilder makeUnexpectedResultBuilder() const {
|
||||||
|
return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
|
||||||
|
m_lastAssertionInfo.lineInfo,
|
||||||
|
m_lastAssertionInfo.capturedExpression.c_str(),
|
||||||
|
m_lastAssertionInfo.resultDisposition );
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleUnfinishedSections() {
|
||||||
|
// If sections ended prematurely due to an exception we stored their
|
||||||
|
// infos here so we can tear them down outside the unwind process.
|
||||||
|
for( std::vector<UnfinishedSections>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
|
||||||
|
itEnd = m_unfinishedSections.rend();
|
||||||
|
it != itEnd;
|
||||||
|
++it )
|
||||||
|
sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
|
||||||
|
m_unfinishedSections.clear();
|
||||||
|
}
|
||||||
|
|
||||||
struct UnfinishedSections {
|
struct UnfinishedSections {
|
||||||
UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
|
UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
|
||||||
: info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
|
: info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
|
||||||
@ -6417,7 +6530,7 @@ namespace Catch {
|
|||||||
namespace Catch {
|
namespace Catch {
|
||||||
|
|
||||||
// These numbers are maintained by a script
|
// These numbers are maintained by a script
|
||||||
Version libraryVersion( 1, 1, 1, "develop" );
|
Version libraryVersion( 1, 1, 2, "develop" );
|
||||||
}
|
}
|
||||||
|
|
||||||
// #included from: catch_message.hpp
|
// #included from: catch_message.hpp
|
||||||
@ -7770,6 +7883,13 @@ namespace Catch {
|
|||||||
.writeText( assertionResult.getMessage() );
|
.writeText( assertionResult.getMessage() );
|
||||||
m_currentTestSuccess = false;
|
m_currentTestSuccess = false;
|
||||||
break;
|
break;
|
||||||
|
case ResultWas::FatalErrorCondition:
|
||||||
|
m_xml.scopedElement( "Fatal Error Condition" )
|
||||||
|
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
|
||||||
|
.writeAttribute( "line", assertionResult.getSourceInfo().line )
|
||||||
|
.writeText( assertionResult.getMessage() );
|
||||||
|
m_currentTestSuccess = false;
|
||||||
|
break;
|
||||||
case ResultWas::Info:
|
case ResultWas::Info:
|
||||||
m_xml.scopedElement( "Info" )
|
m_xml.scopedElement( "Info" )
|
||||||
.writeText( assertionResult.getMessage() );
|
.writeText( assertionResult.getMessage() );
|
||||||
@ -7970,6 +8090,7 @@ namespace Catch {
|
|||||||
std::string elementName;
|
std::string elementName;
|
||||||
switch( result.getResultType() ) {
|
switch( result.getResultType() ) {
|
||||||
case ResultWas::ThrewException:
|
case ResultWas::ThrewException:
|
||||||
|
case ResultWas::FatalErrorCondition:
|
||||||
elementName = "error";
|
elementName = "error";
|
||||||
break;
|
break;
|
||||||
case ResultWas::ExplicitFailure:
|
case ResultWas::ExplicitFailure:
|
||||||
@ -8164,6 +8285,11 @@ namespace Catch {
|
|||||||
passOrFail = "FAILED";
|
passOrFail = "FAILED";
|
||||||
messageLabel = "due to unexpected exception with message";
|
messageLabel = "due to unexpected exception with message";
|
||||||
break;
|
break;
|
||||||
|
case ResultWas::FatalErrorCondition:
|
||||||
|
colour = Colour::Error;
|
||||||
|
passOrFail = "FAILED";
|
||||||
|
messageLabel = "due to a fatal error condition";
|
||||||
|
break;
|
||||||
case ResultWas::DidntThrowException:
|
case ResultWas::DidntThrowException:
|
||||||
colour = Colour::Error;
|
colour = Colour::Error;
|
||||||
passOrFail = "FAILED";
|
passOrFail = "FAILED";
|
||||||
@ -8569,6 +8695,13 @@ namespace Catch {
|
|||||||
printExpressionWas();
|
printExpressionWas();
|
||||||
printRemainingMessages();
|
printRemainingMessages();
|
||||||
break;
|
break;
|
||||||
|
case ResultWas::FatalErrorCondition:
|
||||||
|
printResultType( Colour::Error, failedString() );
|
||||||
|
printIssue( "fatal error condition with message:" );
|
||||||
|
printMessage();
|
||||||
|
printExpressionWas();
|
||||||
|
printRemainingMessages();
|
||||||
|
break;
|
||||||
case ResultWas::DidntThrowException:
|
case ResultWas::DidntThrowException:
|
||||||
printResultType( Colour::Error, failedString() );
|
printResultType( Colour::Error, failedString() );
|
||||||
printIssue( "expected exception, got none" );
|
printIssue( "expected exception, got none" );
|
||||||
|
Loading…
Reference in New Issue
Block a user