Merge branch 'master' into dev-modernize

This includes the performance commits done recently
This commit is contained in:
Martin Hořeňovský 2017-06-26 19:08:42 +02:00
commit c5bac73cad
7 changed files with 62 additions and 34 deletions

View File

@ -1,3 +1,19 @@
# 1.9.5
### Fixes
* Truthy expressions are now reconstructed properly, not as booleans (#914)
* Various warnings are no longer erroneously suppressed in test files (files that include `catch.hpp`, but do not define `CATCH_CONFIG_MAIN` or `CATCH_CONFIG_RUNNER`) (#871)
* Catch no longer fails to link when main is compiled as C++, but linked against Objective-C (#855)
* Fixed incorrect gcc version detection when deciding to use `__COUNTER__` (#928)
* Previously any GCC with minor version less than 3 would be incorrectly classified as not supporting `__COUNTER__`.
* Suppressed C4996 warning caused by upcoming updated to MSVC 2017, marking `std::uncaught_exception` as deprecated. (#927)
### Improvements
* CMake integration script now incorporates debug messages and registers tests in an improved way (#911)
* Various documentation improvements
# 1.9.4 # 1.9.4
### Fixes ### Fixes

View File

@ -17,7 +17,7 @@ There are four reporters built in to the single include:
* `console` writes as lines of text, formatted to a typical terminal width, with colours if a capable terminal is detected. * `console` writes as lines of text, formatted to a typical terminal width, with colours if a capable terminal is detected.
* `compact` similar to `console` but optimised for minimal output - each entry on one line * `compact` similar to `console` but optimised for minimal output - each entry on one line
* `junit` writes xml that corresponds to Ant's [junitreport](http://help.catchsoftware.com/display/ET/JUnit+Format) target. Useful for build systems that understand Junit. * `junit` writes xml that corresponds to Ant's [junitreport](http://help.catchsoftware.com/display/ET/JUnit+Format) target. Useful for build systems that understand Junit. If you are using Jenkins with Catch 1.x, you can improve quality of output by applying changes in [#923](https://github.com/philsquared/Catch/pull/923).
Because of the way the junit format is structured the run must complete before anything is written. Because of the way the junit format is structured the run must complete before anything is written.
* `xml` writes an xml format tailored to Catch. Unlike `junit` this is a streaming format so results are delivered progressively. * `xml` writes an xml format tailored to Catch. Unlike `junit` this is a streaming format so results are delivered progressively.

View File

@ -40,15 +40,17 @@ namespace Catch {
struct AssertionInfo struct AssertionInfo
{ {
AssertionInfo() {} AssertionInfo() {}
AssertionInfo( std::string const& _macroName, AssertionInfo( char const * _macroName,
SourceLineInfo const& _lineInfo, SourceLineInfo const& _lineInfo,
std::string const& _capturedExpression, char const * _capturedExpression,
ResultDisposition::Flags _resultDisposition ); ResultDisposition::Flags _resultDisposition,
char const * _secondArg = "");
std::string macroName; char const * macroName;
SourceLineInfo lineInfo; SourceLineInfo lineInfo;
std::string capturedExpression; char const * capturedExpression;
ResultDisposition::Flags resultDisposition; ResultDisposition::Flags resultDisposition;
char const * secondArg;
}; };
struct AssertionResultData struct AssertionResultData

View File

@ -13,14 +13,16 @@
namespace Catch { namespace Catch {
AssertionInfo::AssertionInfo( std::string const& _macroName, AssertionInfo::AssertionInfo( char const * _macroName,
SourceLineInfo const& _lineInfo, SourceLineInfo const& _lineInfo,
std::string const& _capturedExpression, char const * _capturedExpression,
ResultDisposition::Flags _resultDisposition ) ResultDisposition::Flags _resultDisposition,
char const * _secondArg)
: macroName( _macroName ), : macroName( _macroName ),
lineInfo( _lineInfo ), lineInfo( _lineInfo ),
capturedExpression( _capturedExpression ), capturedExpression( _capturedExpression ),
resultDisposition( _resultDisposition ) resultDisposition( _resultDisposition ),
secondArg( _secondArg )
{} {}
AssertionResult::AssertionResult() {} AssertionResult::AssertionResult() {}
@ -47,24 +49,30 @@ namespace Catch {
} }
bool AssertionResult::hasExpression() const { bool AssertionResult::hasExpression() const {
return !m_info.capturedExpression.empty(); return m_info.capturedExpression[0] != 0;
} }
bool AssertionResult::hasMessage() const { bool AssertionResult::hasMessage() const {
return !m_resultData.message.empty(); return !m_resultData.message.empty();
} }
std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) {
return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"')
? capturedExpression
: std::string(capturedExpression) + ", " + secondArg;
}
std::string AssertionResult::getExpression() const { std::string AssertionResult::getExpression() const {
if( isFalseTest( m_info.resultDisposition ) ) if( isFalseTest( m_info.resultDisposition ) )
return '!' + m_info.capturedExpression; return '!' + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
else else
return m_info.capturedExpression; return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
} }
std::string AssertionResult::getExpressionInMacro() const { std::string AssertionResult::getExpressionInMacro() const {
if( m_info.macroName.empty() ) if( m_info.macroName[0] == 0 )
return m_info.capturedExpression; return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
else else
return m_info.macroName + "( " + m_info.capturedExpression + " )"; return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )";
} }
bool AssertionResult::hasExpandedExpression() const { bool AssertionResult::hasExpandedExpression() const {

View File

@ -47,7 +47,7 @@ namespace Catch {
template<typename T> template<typename T>
ResultBuilder& operator << ( T const& value ) { ResultBuilder& operator << ( T const& value ) {
m_stream.oss << value; m_stream().oss << value;
return *this; return *this;
} }
@ -80,7 +80,12 @@ namespace Catch {
private: private:
AssertionInfo m_assertionInfo; AssertionInfo m_assertionInfo;
AssertionResultData m_data; AssertionResultData m_data;
CopyableStream m_stream;
static CopyableStream &m_stream()
{
static CopyableStream s;
return s;
}
bool m_shouldDebugBreak = false; bool m_shouldDebugBreak = false;
bool m_shouldThrow = false; bool m_shouldThrow = false;

View File

@ -18,23 +18,20 @@
namespace Catch { 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, ResultBuilder::ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo, SourceLineInfo const& lineInfo,
char const* capturedExpression, char const* capturedExpression,
ResultDisposition::Flags resultDisposition, ResultDisposition::Flags resultDisposition,
char const* secondArg ) char const* secondArg )
: m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ) : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition, secondArg )
{} {
m_stream().oss.str("");
}
ResultBuilder::~ResultBuilder() { ResultBuilder::~ResultBuilder() {
#if defined(CATCH_CONFIG_FAST_COMPILE) #if defined(CATCH_CONFIG_FAST_COMPILE)
if ( m_guardException ) { if ( m_guardException ) {
m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; m_stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
captureResult( ResultWas::ThrewException ); captureResult( ResultWas::ThrewException );
getCurrentContext().getResultCapture()->exceptionEarlyReported(); getCurrentContext().getResultCapture()->exceptionEarlyReported();
} }
@ -57,7 +54,7 @@ namespace Catch {
void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
m_assertionInfo.resultDisposition = resultDisposition; m_assertionInfo.resultDisposition = resultDisposition;
m_stream.oss << Catch::translateActiveException(); m_stream().oss << Catch::translateActiveException();
captureResult( ResultWas::ThrewException ); captureResult( ResultWas::ThrewException );
} }
@ -79,7 +76,7 @@ namespace Catch {
assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
AssertionResultData data = m_data; AssertionResultData data = m_data;
data.resultType = ResultWas::Ok; data.resultType = ResultWas::Ok;
data.reconstructedExpression = m_assertionInfo.capturedExpression; data.reconstructedExpression = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg);
std::string actualMessage = Catch::translateActiveException(); std::string actualMessage = Catch::translateActiveException();
if( !matcher.match( actualMessage ) ) { if( !matcher.match( actualMessage ) ) {
@ -145,13 +142,13 @@ namespace Catch {
data.negate( expr.isBinaryExpression() ); data.negate( expr.isBinaryExpression() );
} }
data.message = m_stream.oss.str(); data.message = m_stream().oss.str();
data.decomposedExpression = &expr; // for lazy reconstruction data.decomposedExpression = &expr; // for lazy reconstruction
return AssertionResult( m_assertionInfo, data ); return AssertionResult( m_assertionInfo, data );
} }
void ResultBuilder::reconstructExpression( std::string& dest ) const { void ResultBuilder::reconstructExpression( std::string& dest ) const {
dest = m_assertionInfo.capturedExpression; dest = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg);
} }
void ResultBuilder::setExceptionGuard() { void ResultBuilder::setExceptionGuard() {

View File

@ -147,7 +147,7 @@ namespace Catch {
static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
// Reset working state // Reset working state
m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
m_lastResult = result; m_lastResult = result;
} }
@ -277,7 +277,7 @@ namespace Catch {
double duration = 0; double duration = 0;
m_shouldReportUnexpected = true; m_shouldReportUnexpected = true;
try { try {
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal ); m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
seedRng( *m_config ); seedRng( *m_config );
@ -329,9 +329,9 @@ namespace Catch {
private: private:
ResultBuilder makeUnexpectedResultBuilder() const { ResultBuilder makeUnexpectedResultBuilder() const {
return ResultBuilder( m_lastAssertionInfo.macroName.c_str(), return ResultBuilder( m_lastAssertionInfo.macroName,
m_lastAssertionInfo.lineInfo, m_lastAssertionInfo.lineInfo,
m_lastAssertionInfo.capturedExpression.c_str(), m_lastAssertionInfo.capturedExpression,
m_lastAssertionInfo.resultDisposition ); m_lastAssertionInfo.resultDisposition );
} }