v1.8.2 release

This commit is contained in:
Martin Hořeňovský 2017-03-13 21:29:30 +01:00
parent f69f821853
commit 0c015aa887
4 changed files with 195 additions and 99 deletions

View File

@ -4,7 +4,7 @@
[![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=master)](https://travis-ci.org/philsquared/Catch) [![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=master)](https://travis-ci.org/philsquared/Catch)
[![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/master?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/master) [![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/master?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/master)
<a href="https://github.com/philsquared/Catch/releases/download/v1.8.1/catch.hpp">The latest, single header, version can be downloaded directly using this link</a> <a href="https://github.com/philsquared/Catch/releases/download/v1.8.2/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
## What's the Catch? ## What's the Catch?

View File

@ -1,3 +1,42 @@
# 1.8.2
### Improvements and minor changes
* TAP reporter now behaves as if `-s` was always set
* This should be more consistent with the protocol desired behaviour.
* Compact reporter now obeys `-d yes` argument (#780)
* The format is "XXX.123 s: <section-name>" (3 decimal places are always present).
* Before it did not report the durations at all.
* XML reporter now behaves the same way as Console reporter in regards to `INFO`
* This means it reports `INFO` messages on success, if output on success (`-s`) is enabled.
* Previously it only reported `INFO` messages on failure.
* `CAPTURE(expr)` now stringifies `expr` in the same way assertion macros do (#639)
* Listeners are now finally [documented](event-listeners.md).
* Listeners provide a way to hook into events generated by running your tests, including start and end of run, every test case, every section and every assertion.
### Fixes:
* Catch no longer attempts to reconstruct expression that led to a fatal error (#810)
* This fixes possible signal/SEH loop when processing expressions, where the signal was triggered by expression decomposition.
* Fixed (C4265) missing virtual destructor warning in Matchers (#844)
* `std::string`s are now taken by `const&` everywhere (#842).
* Previously some places were taking them by-value.
* Catch should no longer change errno (#835).
* This was caused by libstdc++ bug that we now work around.
* Catch now provides `FAIL_CHECK( ... )` macro (#765).
* Same as `FAIL( ... )`, but does not abort the test.
* Functions like `fabs`, `tolower`, `memset`, `isalnum` are now used with `std::` qualification (#543).
* Clara no longer assumes first argument (binary name) is always present (#729)
* If it is missing, empty string is used as default.
* Clara no longer reads 1 character past argument string (#830)
### Other notes:
* We have added VS 2013 and 2015 to our CI
* Catch Classic (1.x.x) now contains its own, forked, version of Clara (the argument parser).
# 1.8.1 # 1.8.1
### Fixes ### Fixes

View File

@ -37,7 +37,7 @@ namespace Catch {
return os; return os;
} }
Version libraryVersion( 1, 8, 1, "", 0 ); Version libraryVersion( 1, 8, 2, "", 0 );
} }

View File

@ -1,6 +1,6 @@
/* /*
* Catch v1.8.1 * Catch v1.8.2
* Generated: 2017-03-01 16:04:19.016511 * Generated: 2017-03-13 21:18:33.619572
* ---------------------------------------------------------- * ----------------------------------------------------------
* 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.
@ -1021,16 +1021,24 @@ namespace Matchers {
} }
protected: protected:
virtual ~MatcherUntypedBase();
virtual std::string describe() const = 0; virtual std::string describe() const = 0;
mutable std::string m_cachedToString; mutable std::string m_cachedToString;
private: private:
MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
}; };
template<typename ObjectT, typename ComparatorT = ObjectT> template<typename ObjectT>
struct MatcherBase : MatcherUntypedBase { struct MatcherMethod {
virtual bool match( ObjectT const& arg ) const = 0; virtual bool match( ObjectT const& arg ) const = 0;
};
template<typename PtrT>
struct MatcherMethod<PtrT*> {
virtual bool match( PtrT* arg ) const = 0;
};
template<typename ObjectT, typename ComparatorT = ObjectT>
struct MatcherBase : MatcherUntypedBase, MatcherMethod<ObjectT> {
MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const; MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const; MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
@ -2893,7 +2901,7 @@ namespace Matchers {
}; };
struct StringMatcherBase : MatcherBase<std::string> { struct StringMatcherBase : MatcherBase<std::string> {
StringMatcherBase( std::string operation, CasedString const& comparator ); StringMatcherBase( std::string const& operation, CasedString const& comparator );
virtual std::string describe() const CATCH_OVERRIDE; virtual std::string describe() const CATCH_OVERRIDE;
CasedString m_comparator; CasedString m_comparator;
@ -3032,7 +3040,7 @@ namespace Matchers {
namespace Catch { namespace Catch {
struct TagAlias { struct TagAlias {
TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
std::string tag; std::string tag;
SourceLineInfo lineInfo; SourceLineInfo lineInfo;
@ -3304,64 +3312,67 @@ namespace Catch {
namespace Impl { namespace Impl {
namespace NSStringMatchers { namespace NSStringMatchers {
template<typename MatcherT> struct StringHolder : MatcherBase<NSString*>{
struct StringHolder : MatcherImpl<MatcherT, NSString*>{
StringHolder( NSString* substr ) : m_substr( [substr copy] ){} StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
StringHolder() { StringHolder() {
arcSafeRelease( m_substr ); arcSafeRelease( m_substr );
} }
virtual bool match( NSString* arg ) const CATCH_OVERRIDE {
return false;
}
NSString* m_substr; NSString* m_substr;
}; };
struct Equals : StringHolder<Equals> { struct Equals : StringHolder {
Equals( NSString* substr ) : StringHolder( substr ){} Equals( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const CATCH_OVERRIDE {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str isEqualToString:m_substr]; [str isEqualToString:m_substr];
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "equals string: " + Catch::toString( m_substr ); return "equals string: " + Catch::toString( m_substr );
} }
}; };
struct Contains : StringHolder<Contains> { struct Contains : StringHolder {
Contains( NSString* substr ) : StringHolder( substr ){} Contains( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location != NSNotFound; [str rangeOfString:m_substr].location != NSNotFound;
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "contains string: " + Catch::toString( m_substr ); return "contains string: " + Catch::toString( m_substr );
} }
}; };
struct StartsWith : StringHolder<StartsWith> { struct StartsWith : StringHolder {
StartsWith( NSString* substr ) : StringHolder( substr ){} StartsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == 0; [str rangeOfString:m_substr].location == 0;
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "starts with: " + Catch::toString( m_substr ); return "starts with: " + Catch::toString( m_substr );
} }
}; };
struct EndsWith : StringHolder<EndsWith> { struct EndsWith : StringHolder {
EndsWith( NSString* substr ) : StringHolder( substr ){} EndsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const { virtual bool match( NSString* str ) const {
return (str != nil || m_substr == nil ) && return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == [str length] - [m_substr length]; [str rangeOfString:m_substr].location == [str length] - [m_substr length];
} }
virtual std::string toString() const { virtual std::string describe() const CATCH_OVERRIDE {
return "ends with: " + Catch::toString( m_substr ); return "ends with: " + Catch::toString( m_substr );
} }
}; };
@ -4020,6 +4031,7 @@ namespace Catch {
#include <vector> #include <vector>
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include <cctype>
// Use optional outer namespace // Use optional outer namespace
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
@ -4362,7 +4374,7 @@ namespace Clara {
_dest = _source; _dest = _source;
} }
char toLowerCh(char c) { char toLowerCh(char c) {
return static_cast<char>( ::tolower( c ) ); return static_cast<char>( std::tolower( c ) );
} }
inline void convertInto( std::string const& _source, bool& _dest ) { inline void convertInto( std::string const& _source, bool& _dest ) {
std::string sourceLC = _source; std::string sourceLC = _source;
@ -4516,12 +4528,13 @@ namespace Clara {
} }
void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) { void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
for( std::size_t i = 0; i <= arg.size(); ++i ) { for( std::size_t i = 0; i < arg.size(); ++i ) {
char c = arg[i]; char c = arg[i];
if( c == '"' ) if( c == '"' )
inQuotes = !inQuotes; inQuotes = !inQuotes;
mode = handleMode( i, c, arg, tokens ); mode = handleMode( i, c, arg, tokens );
} }
mode = handleMode( arg.size(), '\0', arg, tokens );
} }
Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
switch( mode ) { switch( mode ) {
@ -4554,6 +4567,7 @@ namespace Clara {
default: from = i; return ShortOpt; default: from = i; return ShortOpt;
} }
} }
Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
return mode; return mode;
@ -4885,7 +4899,7 @@ namespace Clara {
} }
std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const { std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
std::string processName = args[0]; std::string processName = args.empty() ? std::string() : args[0];
std::size_t lastSlash = processName.find_last_of( "/\\" ); std::size_t lastSlash = processName.find_last_of( "/\\" );
if( lastSlash != std::string::npos ) if( lastSlash != std::string::npos )
processName = processName.substr( lastSlash+1 ); processName = processName.substr( lastSlash+1 );
@ -6292,7 +6306,6 @@ namespace Catch {
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
reset();
reportFatal(signalDefs[i].name); reportFatal(signalDefs[i].name);
} }
} }
@ -6634,10 +6647,14 @@ namespace Catch {
} }
virtual void handleFatalErrorCondition( std::string const& message ) { virtual void handleFatalErrorCondition( std::string const& message ) {
ResultBuilder resultBuilder = makeUnexpectedResultBuilder(); // Don't rebuild the result -- the stringification itself can cause more fatal errors
resultBuilder.setResultType( ResultWas::FatalErrorCondition ); // Instead, fake a result data.
resultBuilder << message; AssertionResultData tempResult;
resultBuilder.captureExpression(); tempResult.resultType = ResultWas::FatalErrorCondition;
tempResult.message = message;
AssertionResult result(m_lastAssertionInfo, tempResult);
getResultCapture().assertionEnded(result);
handleUnfinishedSections(); handleUnfinishedSections();
@ -7581,6 +7598,23 @@ namespace Catch {
// #included from: catch_console_colour_impl.hpp // #included from: catch_console_colour_impl.hpp
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
// #included from: catch_errno_guard.hpp
#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
#include <cerrno>
namespace Catch {
class ErrnoGuard {
public:
ErrnoGuard():m_oldErrno(errno){}
~ErrnoGuard() { errno = m_oldErrno; }
private:
int m_oldErrno;
};
}
namespace Catch { namespace Catch {
namespace { namespace {
@ -7716,6 +7750,7 @@ namespace {
}; };
IColourImpl* platformColourInstance() { IColourImpl* platformColourInstance() {
ErrnoGuard guard;
Ptr<IConfig const> config = getCurrentContext().getConfig(); Ptr<IConfig const> config = getCurrentContext().getConfig();
UseColour::YesOrNo colourMode = config UseColour::YesOrNo colourMode = config
? config->useColour() ? config->useColour()
@ -8138,7 +8173,7 @@ namespace Catch {
return os; return os;
} }
Version libraryVersion( 1, 8, 1, "", 0 ); Version libraryVersion( 1, 8, 2, "", 0 );
} }
@ -8567,6 +8602,9 @@ namespace Catch {
// be strace, for example) in /proc/$PID/status, so just get it from // be strace, for example) in /proc/$PID/status, so just get it from
// there instead. // there instead.
bool isDebuggerActive(){ bool isDebuggerActive(){
// Libstdc++ has a bug, where std::ifstream sets errno to 0
// This way our users can properly assert over errno values
ErrnoGuard guard;
std::ifstream in("/proc/self/status"); std::ifstream in("/proc/self/status");
for( std::string line; std::getline(in, line); ) { for( std::string line; std::getline(in, line); ) {
static const int PREFIX_LEN = 11; static const int PREFIX_LEN = 11;
@ -9064,7 +9102,7 @@ namespace Matchers {
: std::string(); : std::string();
} }
StringMatcherBase::StringMatcherBase( std::string operation, CasedString const& comparator ) StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
: m_comparator( comparator ), : m_comparator( comparator ),
m_operation( operation ) { m_operation( operation ) {
} }
@ -9265,10 +9303,34 @@ Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingRepo
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
#include <cstring> #include <cstring>
#include <cfloat>
#include <cstdio>
#include <assert.h> #include <assert.h>
namespace Catch { namespace Catch {
namespace {
// Because formatting using c++ streams is stateful, drop down to C is required
// Alternatively we could use stringstream, but its performance is... not good.
std::string getFormattedDuration( double duration ) {
// Max exponent + 1 is required to represent the whole part
// + 1 for decimal point
// + 3 for the 3 decimal places
// + 1 for null terminator
const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
char buffer[maxDoubleSize];
// Save previous errno, to prevent sprintf from overwriting it
ErrnoGuard guard;
#ifdef _MSC_VER
sprintf_s(buffer, "%.3f", duration);
#else
sprintf(buffer, "%.3f", duration);
#endif
return std::string(buffer);
}
}
struct StreamingReporterBase : SharedImpl<IStreamingReporter> { struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
StreamingReporterBase( ReporterConfig const& _config ) StreamingReporterBase( ReporterConfig const& _config )
@ -9594,9 +9656,13 @@ namespace Catch {
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
// Deprecated - use the form without INTERNAL_
#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
#define CATCH_REGISTER_LISTENER( listenerType ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
// #included from: ../internal/catch_xmlwriter.hpp // #included from: ../internal/catch_xmlwriter.hpp
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
@ -9921,73 +9987,76 @@ namespace Catch {
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
const AssertionResult& assertionResult = assertionStats.assertionResult;
// Print any info messages in <Info> tags. AssertionResult const& result = assertionStats.assertionResult;
if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
if( includeResults ) {
// Print any info messages in <Info> tags.
for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
it != itEnd; it != itEnd;
++it ) { ++it ) {
if( it->type == ResultWas::Info ) { if( it->type == ResultWas::Info ) {
m_xml.scopedElement( "Info" ) m_xml.scopedElement( "Info" )
.writeText( it->message ); .writeText( it->message );
} else if ( it->type == ResultWas::Warning ) { } else if ( it->type == ResultWas::Warning ) {
m_xml.scopedElement( "Warning" ) m_xml.scopedElement( "Warning" )
.writeText( it->message ); .writeText( it->message );
} }
} }
} }
// Drop out if result was successful but we're not printing them. // Drop out if result was successful but we're not printing them.
if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) ) if( !includeResults && result.getResultType() != ResultWas::Warning )
return true; return true;
// Print the expression if there is one. // Print the expression if there is one.
if( assertionResult.hasExpression() ) { if( result.hasExpression() ) {
m_xml.startElement( "Expression" ) m_xml.startElement( "Expression" )
.writeAttribute( "success", assertionResult.succeeded() ) .writeAttribute( "success", result.succeeded() )
.writeAttribute( "type", assertionResult.getTestMacroName() ); .writeAttribute( "type", result.getTestMacroName() );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.scopedElement( "Original" ) m_xml.scopedElement( "Original" )
.writeText( assertionResult.getExpression() ); .writeText( result.getExpression() );
m_xml.scopedElement( "Expanded" ) m_xml.scopedElement( "Expanded" )
.writeText( assertionResult.getExpandedExpression() ); .writeText( result.getExpandedExpression() );
} }
// And... Print a result applicable to each result type. // And... Print a result applicable to each result type.
switch( assertionResult.getResultType() ) { switch( result.getResultType() ) {
case ResultWas::ThrewException: case ResultWas::ThrewException:
m_xml.startElement( "Exception" ); m_xml.startElement( "Exception" );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() ); m_xml.writeText( result.getMessage() );
m_xml.endElement(); m_xml.endElement();
break; break;
case ResultWas::FatalErrorCondition: case ResultWas::FatalErrorCondition:
m_xml.startElement( "FatalErrorCondition" ); m_xml.startElement( "FatalErrorCondition" );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() ); m_xml.writeText( result.getMessage() );
m_xml.endElement(); m_xml.endElement();
break; break;
case ResultWas::Info: case ResultWas::Info:
m_xml.scopedElement( "Info" ) m_xml.scopedElement( "Info" )
.writeText( assertionResult.getMessage() ); .writeText( result.getMessage() );
break; break;
case ResultWas::Warning: case ResultWas::Warning:
// Warning will already have been written // Warning will already have been written
break; break;
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
m_xml.startElement( "Failure" ); m_xml.startElement( "Failure" );
writeSourceInfo( assertionResult.getSourceInfo() ); writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( assertionResult.getMessage() ); m_xml.writeText( result.getMessage() );
m_xml.endElement(); m_xml.endElement();
break; break;
default: default:
break; break;
} }
if( assertionResult.hasExpression() ) if( result.hasExpression() )
m_xml.endElement(); m_xml.endElement();
return true; return true;
@ -10299,25 +10368,6 @@ namespace Catch {
namespace Catch { namespace Catch {
namespace {
// Because formatting using c++ streams is stateful, drop down to C is required
// Alternatively we could use stringstream, but its performance is... not good.
std::string getFormattedDuration( double duration ) {
// Max exponent + 1 is required to represent the whole part
// + 1 for decimal point
// + 3 for the 3 decimal places
// + 1 for null terminator
const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
char buffer[maxDoubleSize];
#ifdef _MSC_VER
sprintf_s(buffer, "%.3f", duration);
#else
sprintf(buffer, "%.3f", duration);
#endif
return std::string(buffer);
}
}
struct ConsoleReporter : StreamingReporterBase { struct ConsoleReporter : StreamingReporterBase {
ConsoleReporter( ReporterConfig const& _config ) ConsoleReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ), : StreamingReporterBase( _config ),
@ -10339,18 +10389,15 @@ namespace Catch {
virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
AssertionResult const& result = _assertionStats.assertionResult; AssertionResult const& result = _assertionStats.assertionResult;
bool printInfoMessages = true; bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
// Drop out if result was successful and we're not printing those // Drop out if result was successful but we're not printing them.
if( !m_config->includeSuccessfulResults() && result.isOk() ) { if( !includeResults && result.getResultType() != ResultWas::Warning )
if( result.getResultType() != ResultWas::Warning ) return false;
return false;
printInfoMessages = false;
}
lazyPrint(); lazyPrint();
AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); AssertionPrinter printer( stream, _assertionStats, includeResults );
printer.print(); printer.print();
stream << std::endl; stream << std::endl;
return true; return true;
@ -10769,8 +10816,7 @@ namespace Catch {
stream << "No test cases matched '" << spec << '\'' << std::endl; stream << "No test cases matched '" << spec << '\'' << std::endl;
} }
virtual void assertionStarting( AssertionInfo const& ) { virtual void assertionStarting( AssertionInfo const& ) {}
}
virtual bool assertionEnded( AssertionStats const& _assertionStats ) { virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
AssertionResult const& result = _assertionStats.assertionResult; AssertionResult const& result = _assertionStats.assertionResult;
@ -10791,6 +10837,12 @@ namespace Catch {
return true; return true;
} }
virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE {
if (m_config->showDurations() == ShowDurations::Always) {
stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
}
}
virtual void testRunEnded( TestRunStats const& _testRunStats ) { virtual void testRunEnded( TestRunStats const& _testRunStats ) {
printTotals( _testRunStats.totals ); printTotals( _testRunStats.totals );
stream << '\n' << std::endl; stream << '\n' << std::endl;
@ -10896,7 +10948,7 @@ namespace Catch {
stream << result.getSourceInfo() << ':'; stream << result.getSourceInfo() << ':';
} }
void printResultType( Colour::Code colour, std::string passOrFail ) const { void printResultType( Colour::Code colour, std::string const& passOrFail ) const {
if( !passOrFail.empty() ) { if( !passOrFail.empty() ) {
{ {
Colour colourGuard( colour ); Colour colourGuard( colour );
@ -10906,7 +10958,7 @@ namespace Catch {
} }
} }
void printIssue( std::string issue ) const { void printIssue( std::string const& issue ) const {
stream << ' ' << issue; stream << ' ' << issue;
} }
@ -11077,6 +11129,7 @@ namespace Catch {
TestSpec::NamePattern::~NamePattern() {} TestSpec::NamePattern::~NamePattern() {}
TestSpec::TagPattern::~TagPattern() {} TestSpec::TagPattern::~TagPattern() {}
TestSpec::ExcludedPattern::~ExcludedPattern() {} TestSpec::ExcludedPattern::~ExcludedPattern() {}
Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {}
void Config::dummy() {} void Config::dummy() {}
@ -11162,8 +11215,8 @@ int main (int argc, char * const argv[]) {
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg ) #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" ) #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CATCH_CAPTURE" )
#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" ) #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CATCH_CAPTURE" )
#ifdef CATCH_CONFIG_VARIADIC_MACROS #ifdef CATCH_CONFIG_VARIADIC_MACROS
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
@ -11172,6 +11225,7 @@ int main (int argc, char * const argv[]) {
#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ ) #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "CATCH_FAIL_CHECK", __VA_ARGS__ )
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ ) #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
#else #else
#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
@ -11180,6 +11234,7 @@ int main (int argc, char * const argv[]) {
#define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg ) #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
#define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "CATCH_FAIL_CHECK", msg )
#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg ) #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
#endif #endif
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
@ -11231,24 +11286,26 @@ int main (int argc, char * const argv[]) {
#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) #define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg ) #define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" ) #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) #define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CAPTURE" )
#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" ) #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << Catch::toString(msg), "CAPTURE" )
#ifdef CATCH_CONFIG_VARIADIC_MACROS #ifdef CATCH_CONFIG_VARIADIC_MACROS
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ ) #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ ) #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "FAIL_CHECK", __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
#else #else
#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
#define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
#define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg ) #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
#define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, "FAIL_CHECK", msg )
#define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg ) #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
#endif #endif
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )