CPP-catch-test
view release on metacpan or search on metacpan
src/catch.hpp view on Meta::CPAN
char const * secondArg;
};
struct AssertionResultData
{
AssertionResultData() : decomposedExpression( CATCH_NULL )
, resultType( ResultWas::Unknown )
, negated( false )
, parenthesized( false ) {}
void negate( bool parenthesize ) {
negated = !negated;
parenthesized = parenthesize;
if( resultType == ResultWas::Ok )
resultType = ResultWas::ExpressionFailed;
else if( resultType == ResultWas::ExpressionFailed )
resultType = ResultWas::Ok;
}
std::string const& reconstructExpression() const {
if( decomposedExpression != CATCH_NULL ) {
decomposedExpression->reconstructExpression( reconstructedExpression );
if( parenthesized ) {
reconstructedExpression.insert( 0, 1, '(' );
reconstructedExpression.append( 1, ')' );
}
if( negated ) {
reconstructedExpression.insert( 0, 1, '!' );
}
decomposedExpression = CATCH_NULL;
}
return reconstructedExpression;
}
mutable DecomposedExpression const* decomposedExpression;
mutable std::string reconstructedExpression;
std::string message;
ResultWas::OfType resultType;
bool negated;
bool parenthesized;
};
class AssertionResult {
public:
AssertionResult();
AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
~AssertionResult();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
AssertionResult( AssertionResult const& ) = default;
AssertionResult( AssertionResult && ) = default;
AssertionResult& operator = ( AssertionResult const& ) = default;
AssertionResult& operator = ( AssertionResult && ) = default;
# endif
bool isOk() const;
bool succeeded() const;
ResultWas::OfType getResultType() const;
bool hasExpression() const;
bool hasMessage() const;
std::string getExpression() const;
std::string getExpressionInMacro() const;
bool hasExpandedExpression() const;
std::string getExpandedExpression() const;
std::string getMessage() const;
SourceLineInfo getSourceInfo() const;
std::string getTestMacroName() const;
void discardDecomposedExpression() const;
void expandDecomposedExpression() const;
protected:
AssertionInfo m_info;
AssertionResultData m_resultData;
};
} // end namespace Catch
// #included from: catch_matchers.hpp
#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
namespace Catch {
namespace Matchers {
namespace Impl {
template<typename ArgT> struct MatchAllOf;
template<typename ArgT> struct MatchAnyOf;
template<typename ArgT> struct MatchNotOf;
class MatcherUntypedBase {
public:
std::string toString() const {
if( m_cachedToString.empty() )
m_cachedToString = describe();
return m_cachedToString;
}
protected:
virtual ~MatcherUntypedBase();
virtual std::string describe() const = 0;
mutable std::string m_cachedToString;
private:
MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
};
template<typename ObjectT>
struct MatcherMethod {
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;
MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
MatchNotOf<ComparatorT> operator ! () const;
};
template<typename ArgT>
struct MatchAllOf : MatcherBase<ArgT> {
virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
if (!m_matchers[i]->match(arg))
return false;
src/catch.hpp view on Meta::CPAN
std::ostream& stream() const { return *m_stream; }
Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
private:
std::ostream* m_stream;
Ptr<IConfig const> m_fullConfig;
};
struct ReporterPreferences {
ReporterPreferences()
: shouldRedirectStdOut( false )
{}
bool shouldRedirectStdOut;
};
template<typename T>
struct LazyStat : Option<T> {
LazyStat() : used( false ) {}
LazyStat& operator=( T const& _value ) {
Option<T>::operator=( _value );
used = false;
return *this;
}
void reset() {
Option<T>::reset();
used = false;
}
bool used;
};
struct TestRunInfo {
TestRunInfo( std::string const& _name ) : name( _name ) {}
std::string name;
};
struct GroupInfo {
GroupInfo( std::string const& _name,
std::size_t _groupIndex,
std::size_t _groupsCount )
: name( _name ),
groupIndex( _groupIndex ),
groupsCounts( _groupsCount )
{}
std::string name;
std::size_t groupIndex;
std::size_t groupsCounts;
};
struct AssertionStats {
AssertionStats( AssertionResult const& _assertionResult,
std::vector<MessageInfo> const& _infoMessages,
Totals const& _totals )
: assertionResult( _assertionResult ),
infoMessages( _infoMessages ),
totals( _totals )
{
if( assertionResult.hasMessage() ) {
// Copy message into messages list.
// !TBD This should have been done earlier, somewhere
MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
builder << assertionResult.getMessage();
builder.m_info.message = builder.m_stream.str();
infoMessages.push_back( builder.m_info );
}
}
virtual ~AssertionStats();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
AssertionStats( AssertionStats const& ) = default;
AssertionStats( AssertionStats && ) = default;
AssertionStats& operator = ( AssertionStats const& ) = default;
AssertionStats& operator = ( AssertionStats && ) = default;
# endif
AssertionResult assertionResult;
std::vector<MessageInfo> infoMessages;
Totals totals;
};
struct SectionStats {
SectionStats( SectionInfo const& _sectionInfo,
Counts const& _assertions,
double _durationInSeconds,
bool _missingAssertions )
: sectionInfo( _sectionInfo ),
assertions( _assertions ),
durationInSeconds( _durationInSeconds ),
missingAssertions( _missingAssertions )
{}
virtual ~SectionStats();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
SectionStats( SectionStats const& ) = default;
SectionStats( SectionStats && ) = default;
SectionStats& operator = ( SectionStats const& ) = default;
SectionStats& operator = ( SectionStats && ) = default;
# endif
SectionInfo sectionInfo;
Counts assertions;
double durationInSeconds;
bool missingAssertions;
};
struct TestCaseStats {
TestCaseStats( TestCaseInfo const& _testInfo,
Totals const& _totals,
std::string const& _stdOut,
std::string const& _stdErr,
bool _aborting )
: testInfo( _testInfo ),
totals( _totals ),
stdOut( _stdOut ),
stdErr( _stdErr ),
aborting( _aborting )
{}
virtual ~TestCaseStats();
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestCaseStats( TestCaseStats const& ) = default;
src/catch.hpp view on Meta::CPAN
namespace Catch {
AssertionInfo::AssertionInfo():macroName(""), capturedExpression(""), resultDisposition(ResultDisposition::Normal), secondArg(""){}
AssertionInfo::AssertionInfo( char const * _macroName,
SourceLineInfo const& _lineInfo,
char const * _capturedExpression,
ResultDisposition::Flags _resultDisposition,
char const * _secondArg)
: macroName( _macroName ),
lineInfo( _lineInfo ),
capturedExpression( _capturedExpression ),
resultDisposition( _resultDisposition ),
secondArg( _secondArg )
{}
AssertionResult::AssertionResult() {}
AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
: m_info( info ),
m_resultData( data )
{}
AssertionResult::~AssertionResult() {}
// Result was a success
bool AssertionResult::succeeded() const {
return Catch::isOk( m_resultData.resultType );
}
// Result was a success, or failure is suppressed
bool AssertionResult::isOk() const {
return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
}
ResultWas::OfType AssertionResult::getResultType() const {
return m_resultData.resultType;
}
bool AssertionResult::hasExpression() const {
return m_info.capturedExpression[0] != 0;
}
bool AssertionResult::hasMessage() const {
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 {
if( isFalseTest( m_info.resultDisposition ) )
return '!' + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
else
return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
}
std::string AssertionResult::getExpressionInMacro() const {
if( m_info.macroName[0] == 0 )
return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg);
else
return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )";
}
bool AssertionResult::hasExpandedExpression() const {
return hasExpression() && getExpandedExpression() != getExpression();
}
std::string AssertionResult::getExpandedExpression() const {
return m_resultData.reconstructExpression();
}
std::string AssertionResult::getMessage() const {
return m_resultData.message;
}
SourceLineInfo AssertionResult::getSourceInfo() const {
return m_info.lineInfo;
}
std::string AssertionResult::getTestMacroName() const {
return m_info.macroName;
}
void AssertionResult::discardDecomposedExpression() const {
m_resultData.decomposedExpression = CATCH_NULL;
}
void AssertionResult::expandDecomposedExpression() const {
m_resultData.reconstructExpression();
}
} // end namespace Catch
// #included from: catch_test_case_info.hpp
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
#include <cctype>
namespace Catch {
inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
if( startsWith( tag, '.' ) ||
tag == "hide" ||
tag == "!hide" )
return TestCaseInfo::IsHidden;
else if( tag == "!throws" )
return TestCaseInfo::Throws;
else if( tag == "!shouldfail" )
return TestCaseInfo::ShouldFail;
else if( tag == "!mayfail" )
return TestCaseInfo::MayFail;
else if( tag == "!nonportable" )
return TestCaseInfo::NonPortable;
else
return TestCaseInfo::None;
}
inline bool isReservedTag( std::string const& tag ) {
return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
}
inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
if( isReservedTag( tag ) ) {
std::ostringstream ss;
ss << Colour(Colour::Red)
<< "Tag name [" << tag << "] not allowed.\n"
<< "Tag names starting with non alpha-numeric characters are reserved\n"
<< Colour(Colour::FileName)
<< _lineInfo << '\n';
throw std::runtime_error(ss.str());
}
}
TestCase makeTestCase( ITestCase* _testCase,
std::string const& _className,
std::string const& _name,
std::string const& _descOrTags,
SourceLineInfo const& _lineInfo )
{
bool isHidden( startsWith( _name, "./" ) ); // Legacy support
// Parse out tags
src/catch.hpp view on Meta::CPAN
m_xml.startElement( "Group" )
.writeAttribute( "name", groupInfo.name );
}
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
StreamingReporterBase::testCaseStarting(testInfo);
m_xml.startElement( "TestCase" )
.writeAttribute( "name", trim( testInfo.name ) )
.writeAttribute( "description", testInfo.description )
.writeAttribute( "tags", testInfo.tagsAsString );
writeSourceInfo( testInfo.lineInfo );
if ( m_config->showDurations() == ShowDurations::Always )
m_testCaseTimer.start();
m_xml.ensureTagClosed();
}
virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
StreamingReporterBase::sectionStarting( sectionInfo );
if( m_sectionDepth++ > 0 ) {
m_xml.startElement( "Section" )
.writeAttribute( "name", trim( sectionInfo.name ) )
.writeAttribute( "description", sectionInfo.description );
writeSourceInfo( sectionInfo.lineInfo );
m_xml.ensureTagClosed();
}
}
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
AssertionResult const& result = assertionStats.assertionResult;
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();
it != itEnd;
++it ) {
if( it->type == ResultWas::Info ) {
m_xml.scopedElement( "Info" )
.writeText( it->message );
} else if ( it->type == ResultWas::Warning ) {
m_xml.scopedElement( "Warning" )
.writeText( it->message );
}
}
}
// Drop out if result was successful but we're not printing them.
if( !includeResults && result.getResultType() != ResultWas::Warning )
return true;
// Print the expression if there is one.
if( result.hasExpression() ) {
m_xml.startElement( "Expression" )
.writeAttribute( "success", result.succeeded() )
.writeAttribute( "type", result.getTestMacroName() );
writeSourceInfo( result.getSourceInfo() );
m_xml.scopedElement( "Original" )
.writeText( result.getExpression() );
m_xml.scopedElement( "Expanded" )
.writeText( result.getExpandedExpression() );
}
// And... Print a result applicable to each result type.
switch( result.getResultType() ) {
case ResultWas::ThrewException:
m_xml.startElement( "Exception" );
writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( result.getMessage() );
m_xml.endElement();
break;
case ResultWas::FatalErrorCondition:
m_xml.startElement( "FatalErrorCondition" );
writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( result.getMessage() );
m_xml.endElement();
break;
case ResultWas::Info:
m_xml.scopedElement( "Info" )
.writeText( result.getMessage() );
break;
case ResultWas::Warning:
// Warning will already have been written
break;
case ResultWas::ExplicitFailure:
m_xml.startElement( "Failure" );
writeSourceInfo( result.getSourceInfo() );
m_xml.writeText( result.getMessage() );
m_xml.endElement();
break;
default:
break;
}
if( result.hasExpression() )
m_xml.endElement();
return true;
}
virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
StreamingReporterBase::sectionEnded( sectionStats );
if( --m_sectionDepth > 0 ) {
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
e.writeAttribute( "successes", sectionStats.assertions.passed );
e.writeAttribute( "failures", sectionStats.assertions.failed );
e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
if ( m_config->showDurations() == ShowDurations::Always )
e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
m_xml.endElement();
}
}
src/catch.hpp view on Meta::CPAN
xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
writeAssertions( sectionNode );
if( !sectionNode.stdOut.empty() )
xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
if( !sectionNode.stdErr.empty() )
xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
}
for( SectionNode::ChildSections::const_iterator
it = sectionNode.childSections.begin(),
itEnd = sectionNode.childSections.end();
it != itEnd;
++it )
if( className.empty() )
writeSection( name, "", **it );
else
writeSection( className, name, **it );
}
void writeAssertions( SectionNode const& sectionNode ) {
for( SectionNode::Assertions::const_iterator
it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
it != itEnd;
++it )
writeAssertion( *it );
}
void writeAssertion( AssertionStats const& stats ) {
AssertionResult const& result = stats.assertionResult;
if( !result.isOk() ) {
std::string elementName;
switch( result.getResultType() ) {
case ResultWas::ThrewException:
case ResultWas::FatalErrorCondition:
elementName = "error";
break;
case ResultWas::ExplicitFailure:
elementName = "failure";
break;
case ResultWas::ExpressionFailed:
elementName = "failure";
break;
case ResultWas::DidntThrowException:
elementName = "failure";
break;
// We should never see these here:
case ResultWas::Info:
case ResultWas::Warning:
case ResultWas::Ok:
case ResultWas::Unknown:
case ResultWas::FailureBit:
case ResultWas::Exception:
elementName = "internalError";
break;
}
XmlWriter::ScopedElement e = xml.scopedElement( elementName );
xml.writeAttribute( "message", result.getExpandedExpression() );
xml.writeAttribute( "type", result.getTestMacroName() );
std::ostringstream oss;
if( !result.getMessage().empty() )
oss << result.getMessage() << '\n';
for( std::vector<MessageInfo>::const_iterator
it = stats.infoMessages.begin(),
itEnd = stats.infoMessages.end();
it != itEnd;
++it )
if( it->type == ResultWas::Info )
oss << it->message << '\n';
oss << "at " << result.getSourceInfo();
xml.writeText( oss.str(), false );
}
}
XmlWriter xml;
Timer suiteTimer;
std::ostringstream stdOutForSuite;
std::ostringstream stdErrForSuite;
unsigned int unexpectedExceptions;
bool m_okToFail;
};
INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
} // end namespace Catch
// #included from: ../reporters/catch_reporter_console.hpp
#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
#include <cfloat>
#include <cstdio>
namespace Catch {
struct ConsoleReporter : StreamingReporterBase {
ConsoleReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ),
m_headerPrinted( false )
{}
virtual ~ConsoleReporter() CATCH_OVERRIDE;
static std::string getDescription() {
return "Reports test results as plain lines of text";
}
virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
stream << "No test cases matched '" << spec << '\'' << std::endl;
}
virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
}
virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
AssertionResult const& result = _assertionStats.assertionResult;
bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
src/catch.hpp view on Meta::CPAN
case ResultWas::FatalErrorCondition:
colour = Colour::Error;
passOrFail = "FAILED";
messageLabel = "due to a fatal error condition";
break;
case ResultWas::DidntThrowException:
colour = Colour::Error;
passOrFail = "FAILED";
messageLabel = "because no exception was thrown where one was expected";
break;
case ResultWas::Info:
messageLabel = "info";
break;
case ResultWas::Warning:
messageLabel = "warning";
break;
case ResultWas::ExplicitFailure:
passOrFail = "FAILED";
colour = Colour::Error;
if( _stats.infoMessages.size() == 1 )
messageLabel = "explicitly with message";
if( _stats.infoMessages.size() > 1 )
messageLabel = "explicitly with messages";
break;
// These cases are here to prevent compiler warnings
case ResultWas::Unknown:
case ResultWas::FailureBit:
case ResultWas::Exception:
passOrFail = "** internal error **";
colour = Colour::Error;
break;
}
}
void print() const {
printSourceInfo();
if( stats.totals.assertions.total() > 0 ) {
if( result.isOk() )
stream << '\n';
printResultType();
printOriginalExpression();
printReconstructedExpression();
}
else {
stream << '\n';
}
printMessage();
}
private:
void printResultType() const {
if( !passOrFail.empty() ) {
Colour colourGuard( colour );
stream << passOrFail << ":\n";
}
}
void printOriginalExpression() const {
if( result.hasExpression() ) {
Colour colourGuard( Colour::OriginalExpression );
stream << " ";
stream << result.getExpressionInMacro();
stream << '\n';
}
}
void printReconstructedExpression() const {
if( result.hasExpandedExpression() ) {
stream << "with expansion:\n";
Colour colourGuard( Colour::ReconstructedExpression );
stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n';
}
}
void printMessage() const {
if( !messageLabel.empty() )
stream << messageLabel << ':' << '\n';
for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
it != itEnd;
++it ) {
// If this assertion is a warning ignore any INFO messages
if( printInfoMessages || it->type != ResultWas::Info )
stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n';
}
}
void printSourceInfo() const {
Colour colourGuard( Colour::FileName );
stream << result.getSourceInfo() << ": ";
}
std::ostream& stream;
AssertionStats const& stats;
AssertionResult const& result;
Colour::Code colour;
std::string passOrFail;
std::string messageLabel;
std::string message;
std::vector<MessageInfo> messages;
bool printInfoMessages;
};
void lazyPrint() {
if( !currentTestRunInfo.used )
lazyPrintRunInfo();
if( !currentGroupInfo.used )
lazyPrintGroupInfo();
if( !m_headerPrinted ) {
printTestCaseAndSectionHeader();
m_headerPrinted = true;
}
}
void lazyPrintRunInfo() {
stream << '\n' << getLineOfChars<'~'>() << '\n';
Colour colour( Colour::SecondaryText );
stream << currentTestRunInfo->name
<< " is a Catch v" << libraryVersion() << " host application.\n"
<< "Run with -? for options\n\n";
if( m_config->rngSeed() != 0 )
stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
currentTestRunInfo.used = true;
( run in 0.521 second using v1.01-cache-2.11-cpan-437f7b0c052 )