Commit bd8150c5 authored by Niels's avatar Niels

updated Catch

parent bf423363
/* /*
* CATCH v1.0 build 53 (master branch) * CATCH v1.1 build 3 (master branch)
* Generated: 2014-08-20 08:08:19.533804 * Generated: 2015-05-21 06:16:00.388118
* ---------------------------------------------------------- * ----------------------------------------------------------
* 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.
...@@ -13,31 +13,43 @@ ...@@ -13,31 +13,43 @@
#define TWOBLUECUBES_CATCH_HPP_INCLUDED #define TWOBLUECUBES_CATCH_HPP_INCLUDED
#ifdef __clang__
# pragma clang system_header
#elif defined __GNUC__
# pragma GCC system_header
#endif
// #included from: internal/catch_suppress_warnings.h // #included from: internal/catch_suppress_warnings.h
#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED #define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic ignored "-Wglobal-constructors" # ifdef __ICC // icpc defines the __clang__ macro
#pragma clang diagnostic ignored "-Wvariadic-macros" # pragma warning(push)
#pragma clang diagnostic ignored "-Wc99-extensions" # pragma warning(disable: 161 1682)
#pragma clang diagnostic ignored "-Wunused-variable" # else // __ICC
#pragma clang diagnostic push # pragma clang diagnostic ignored "-Wglobal-constructors"
#pragma clang diagnostic ignored "-Wpadded" # pragma clang diagnostic ignored "-Wvariadic-macros"
#pragma clang diagnostic ignored "-Wc++98-compat" # pragma clang diagnostic ignored "-Wc99-extensions"
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" # pragma clang diagnostic ignored "-Wunused-variable"
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
# pragma clang diagnostic ignored "-Wc++98-compat"
# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
# pragma clang diagnostic ignored "-Wswitch-enum"
# endif
#elif defined __GNUC__ #elif defined __GNUC__
#pragma GCC diagnostic ignored "-Wvariadic-macros" # pragma GCC diagnostic ignored "-Wvariadic-macros"
#pragma GCC diagnostic ignored "-Wunused-variable" # pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic push # pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpadded" # pragma GCC diagnostic ignored "-Wpadded"
#endif #endif
#ifdef CATCH_CONFIG_MAIN #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
# define CATCH_CONFIG_RUNNER # define CATCH_IMPL
#endif #endif
#ifdef CATCH_CONFIG_RUNNER #ifdef CATCH_IMPL
# ifndef CLARA_CONFIG_MAIN # ifndef CLARA_CONFIG_MAIN
# define CLARA_CONFIG_MAIN_NOT_DEFINED # define CLARA_CONFIG_MAIN_NOT_DEFINED
# define CLARA_CONFIG_MAIN # define CLARA_CONFIG_MAIN
...@@ -64,7 +76,21 @@ ...@@ -64,7 +76,21 @@
// #included from: catch_compiler_capabilities.h // #included from: catch_compiler_capabilities.h
#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
// Much of the following code is based on Boost (1.53) // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
// The following features are defined:
//
// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
// CATCH_CONFIG_SFINAE : is basic (C++03) SFINAE supported?
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
// A lot of this code is based on Boost (1.53)
#ifdef __clang__ #ifdef __clang__
...@@ -139,6 +165,15 @@ ...@@ -139,6 +165,15 @@
//#define CATCH_CONFIG_SFINAE // Not confirmed //#define CATCH_CONFIG_SFINAE // Not confirmed
#endif #endif
#if (_MSC_VER >= 1600)
#define CATCH_CONFIG_CPP11_NULLPTR
#endif
#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
#define CATCH_CONFIG_CPP11_NOEXCEPT
#define CATCH_CONFIG_CPP11_GENERATED_METHODS
#endif
#endif // _MSC_VER #endif // _MSC_VER
// Use variadic macros if the compiler supports them // Use variadic macros if the compiler supports them
...@@ -156,13 +191,40 @@ ...@@ -156,13 +191,40 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// C++ language feature support // C++ language feature support
// detect language version: // catch all support for C++11
#if (__cplusplus == 201103L) #if (__cplusplus >= 201103L)
# define CATCH_CPP11
# define CATCH_CPP11_OR_GREATER
#elif (__cplusplus >= 201103L)
# define CATCH_CPP11_OR_GREATER # define CATCH_CPP11_OR_GREATER
#endif
# ifndef CATCH_CONFIG_CPP11_NULLPTR
# define CATCH_CONFIG_CPP11_NULLPTR
# endif
# ifndef CATCH_CONFIG_CPP11_NOEXCEPT
# define CATCH_CONFIG_CPP11_NOEXCEPT
# endif
# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
# define CATCH_CONFIG_CPP11_GENERATED_METHODS
# endif
# ifndef CATCH_CONFIG_CPP11_IS_ENUM
# define CATCH_CONFIG_CPP11_IS_ENUM
# endif
# ifndef CATCH_CONFIG_CPP11_TUPLE
# define CATCH_CONFIG_CPP11_TUPLE
# endif
# ifndef CATCH_CONFIG_SFINAE
//# define CATCH_CONFIG_SFINAE // Don't use, for now
# endif
# ifndef CATCH_CONFIG_VARIADIC_MACROS
# define CATCH_CONFIG_VARIADIC_MACROS
# endif
#endif // __cplusplus >= 201103L
// noexcept support: // noexcept support:
#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
...@@ -176,8 +238,16 @@ ...@@ -176,8 +238,16 @@
namespace Catch { namespace Catch {
class NonCopyable { class NonCopyable {
NonCopyable( NonCopyable const& ); #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
void operator = ( NonCopyable const& ); NonCopyable( NonCopyable const& ) = delete;
NonCopyable( NonCopyable && ) = delete;
NonCopyable& operator = ( NonCopyable const& ) = delete;
NonCopyable& operator = ( NonCopyable && ) = delete;
#else
NonCopyable( NonCopyable const& info );
NonCopyable& operator = ( NonCopyable const& );
#endif
protected: protected:
NonCopyable() {} NonCopyable() {}
virtual ~NonCopyable(); virtual ~NonCopyable();
...@@ -215,6 +285,7 @@ namespace Catch { ...@@ -215,6 +285,7 @@ namespace Catch {
void toLowerInPlace( std::string& s ); void toLowerInPlace( std::string& s );
std::string toLower( std::string const& s ); std::string toLower( std::string const& s );
std::string trim( std::string const& str ); std::string trim( std::string const& str );
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
struct pluralise { struct pluralise {
pluralise( std::size_t count, std::string const& label ); pluralise( std::size_t count, std::string const& label );
...@@ -230,13 +301,14 @@ namespace Catch { ...@@ -230,13 +301,14 @@ namespace Catch {
SourceLineInfo(); SourceLineInfo();
SourceLineInfo( char const* _file, std::size_t _line ); SourceLineInfo( char const* _file, std::size_t _line );
SourceLineInfo( SourceLineInfo const& other ); SourceLineInfo( SourceLineInfo const& other );
# ifdef CATCH_CPP11_OR_GREATER # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
SourceLineInfo( SourceLineInfo && ) = default; SourceLineInfo( SourceLineInfo && ) = default;
SourceLineInfo& operator = ( SourceLineInfo const& ) = default; SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
SourceLineInfo& operator = ( SourceLineInfo && ) = default; SourceLineInfo& operator = ( SourceLineInfo && ) = default;
# endif # endif
bool empty() const; bool empty() const;
bool operator == ( SourceLineInfo const& other ) const; bool operator == ( SourceLineInfo const& other ) const;
bool operator < ( SourceLineInfo const& other ) const;
std::string file; std::string file;
std::size_t line; std::size_t line;
...@@ -467,7 +539,7 @@ namespace Catch { ...@@ -467,7 +539,7 @@ namespace Catch {
struct ITestCaseRegistry { struct ITestCaseRegistry {
virtual ~ITestCaseRegistry(); virtual ~ITestCaseRegistry();
virtual std::vector<TestCase> const& getAllTests() const = 0; virtual std::vector<TestCase> const& getAllTests() const = 0;
virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const = 0; virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const = 0;
}; };
} }
...@@ -603,7 +675,9 @@ namespace Catch { ...@@ -603,7 +675,9 @@ namespace Catch {
Exception = 0x100 | FailureBit, Exception = 0x100 | FailureBit,
ThrewException = Exception | 1, ThrewException = Exception | 1,
DidntThrowException = Exception | 2 DidntThrowException = Exception | 2,
FatalErrorCondition = 0x200 | FailureBit
}; }; }; };
...@@ -616,11 +690,11 @@ namespace Catch { ...@@ -616,11 +690,11 @@ namespace Catch {
// ResultDisposition::Flags enum // ResultDisposition::Flags enum
struct ResultDisposition { enum Flags { struct ResultDisposition { enum Flags {
Normal = 0x00, Normal = 0x01,
ContinueOnFailure = 0x01, // Failures fail test, but execution continues ContinueOnFailure = 0x02, // Failures fail test, but execution continues
FalseTest = 0x02, // Prefix expression with ! FalseTest = 0x04, // Prefix expression with !
SuppressFail = 0x04 // Failures are reported but do not fail the test SuppressFail = 0x08 // Failures are reported but do not fail the test
}; }; }; };
inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
...@@ -668,7 +742,7 @@ namespace Catch { ...@@ -668,7 +742,7 @@ namespace Catch {
AssertionResult(); AssertionResult();
AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
~AssertionResult(); ~AssertionResult();
# ifdef CATCH_CPP11_OR_GREATER # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
AssertionResult( AssertionResult const& ) = default; AssertionResult( AssertionResult const& ) = default;
AssertionResult( AssertionResult && ) = default; AssertionResult( AssertionResult && ) = default;
AssertionResult& operator = ( AssertionResult const& ) = default; AssertionResult& operator = ( AssertionResult const& ) = default;
...@@ -1034,9 +1108,52 @@ inline id performOptionalSelector( id obj, SEL sel ) { ...@@ -1034,9 +1108,52 @@ inline id performOptionalSelector( id obj, SEL sel ) {
#endif #endif
#ifdef CATCH_CONFIG_CPP11_TUPLE
#include <tuple>
#endif
#ifdef CATCH_CONFIG_CPP11_IS_ENUM
#include <type_traits>
#endif
namespace Catch { namespace Catch {
// Why we're here.
template<typename T>
std::string toString( T const& value );
// Built in overloads
std::string toString( std::string const& value );
std::string toString( std::wstring const& value );
std::string toString( const char* const value );
std::string toString( char* const value );
std::string toString( const wchar_t* const value );
std::string toString( wchar_t* const value );
std::string toString( int value );
std::string toString( unsigned long value );
std::string toString( unsigned int value );
std::string toString( const double value );
std::string toString( const float value );
std::string toString( bool value );
std::string toString( char value );
std::string toString( signed char value );
std::string toString( unsigned char value );
#ifdef CATCH_CONFIG_CPP11_NULLPTR
std::string toString( std::nullptr_t );
#endif
#ifdef __OBJC__
std::string toString( NSString const * const& nsstring );
std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
std::string toString( NSObject* const& nsObject );
#endif
namespace Detail { namespace Detail {
extern std::string unprintableString;
// SFINAE is currently disabled by default for all compilers. // SFINAE is currently disabled by default for all compilers.
// If the non SFINAE version of IsStreamInsertable is ambiguous for you // If the non SFINAE version of IsStreamInsertable is ambiguous for you
// and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE // and your compiler supports SFINAE, try #defining CATCH_CONFIG_SFINAE
...@@ -1077,10 +1194,38 @@ namespace Detail { ...@@ -1077,10 +1194,38 @@ namespace Detail {
#endif #endif
#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
template<typename T,
bool IsEnum = std::is_enum<T>::value
>
struct EnumStringMaker
{
static std::string convert( T const& ) { return unprintableString; }
};
template<typename T>
struct EnumStringMaker<T,true>
{
static std::string convert( T const& v )
{
return ::Catch::toString(
static_cast<typename std::underlying_type<T>::type>(v)
);
}
};
#endif
template<bool C> template<bool C>
struct StringMakerBase { struct StringMakerBase {
#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
template<typename T> template<typename T>
static std::string convert( T const& ) { return "{?}"; } static std::string convert( T const& v )
{
return EnumStringMaker<T>::convert( v );
}
#else
template<typename T>
static std::string convert( T const& ) { return unprintableString; }
#endif
}; };
template<> template<>
...@@ -1102,9 +1247,6 @@ namespace Detail { ...@@ -1102,9 +1247,6 @@ namespace Detail {
} // end namespace Detail } // end namespace Detail
template<typename T>
std::string toString( T const& value );
template<typename T> template<typename T>
struct StringMaker : struct StringMaker :
Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {}; Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
...@@ -1135,12 +1277,59 @@ namespace Detail { ...@@ -1135,12 +1277,59 @@ namespace Detail {
std::string rangeToString( InputIterator first, InputIterator last ); std::string rangeToString( InputIterator first, InputIterator last );
} }
//template<typename T, typename Allocator>
//struct StringMaker<std::vector<T, Allocator> > {
// static std::string convert( std::vector<T,Allocator> const& v ) {
// return Detail::rangeToString( v.begin(), v.end() );
// }
//};
template<typename T, typename Allocator> template<typename T, typename Allocator>
struct StringMaker<std::vector<T, Allocator> > { std::string toString( std::vector<T,Allocator> const& v ) {
static std::string convert( std::vector<T,Allocator> const& v ) { return Detail::rangeToString( v.begin(), v.end() );
return Detail::rangeToString( v.begin(), v.end() ); }
#ifdef CATCH_CONFIG_CPP11_TUPLE
// toString for tuples
namespace TupleDetail {
template<
typename Tuple,
std::size_t N = 0,
bool = (N < std::tuple_size<Tuple>::value)
>
struct ElementPrinter {
static void print( const Tuple& tuple, std::ostream& os )
{
os << ( N ? ", " : " " )
<< Catch::toString(std::get<N>(tuple));
ElementPrinter<Tuple,N+1>::print(tuple,os);
}
};
template<
typename Tuple,
std::size_t N
>
struct ElementPrinter<Tuple,N,false> {
static void print( const Tuple&, std::ostream& ) {}
};
}
template<typename ...Types>
struct StringMaker<std::tuple<Types...>> {
static std::string convert( const std::tuple<Types...>& tuple )
{
std::ostringstream os;
os << '{';
TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
os << " }";
return os.str();
} }
}; };
#endif // CATCH_CONFIG_CPP11_TUPLE
namespace Detail { namespace Detail {
template<typename T> template<typename T>
...@@ -1161,44 +1350,15 @@ std::string toString( T const& value ) { ...@@ -1161,44 +1350,15 @@ std::string toString( T const& value ) {
return StringMaker<T>::convert( value ); return StringMaker<T>::convert( value );
} }
// Built in overloads
std::string toString( std::string const& value );
std::string toString( std::wstring const& value );
std::string toString( const char* const value );
std::string toString( char* const value );
std::string toString( const wchar_t* const value );
std::string toString( wchar_t* const value );
std::string toString( int value );
std::string toString( unsigned long value );
std::string toString( unsigned int value );
std::string toString( const double value );
std::string toString( const float value );
std::string toString( bool value );
std::string toString( char value );
std::string toString( signed char value );
std::string toString( unsigned char value );
#ifdef CATCH_CONFIG_CPP11_NULLPTR
std::string toString( std::nullptr_t );
#endif
#ifdef __OBJC__
std::string toString( NSString const * const& nsstring );
std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
std::string toString( NSObject* const& nsObject );
#endif
namespace Detail { namespace Detail {
template<typename InputIterator> template<typename InputIterator>
std::string rangeToString( InputIterator first, InputIterator last ) { std::string rangeToString( InputIterator first, InputIterator last ) {
std::ostringstream oss; std::ostringstream oss;
oss << "{ "; oss << "{ ";
if( first != last ) { if( first != last ) {
oss << toString( *first ); oss << Catch::toString( *first );
for( ++first ; first != last ; ++first ) { for( ++first ; first != last ; ++first )
oss << ", " << toString( *first ); oss << ", " << Catch::toString( *first );
}
} }
oss << " }"; oss << " }";
return oss.str(); return oss.str();
...@@ -1214,13 +1374,13 @@ namespace Catch { ...@@ -1214,13 +1374,13 @@ namespace Catch {
template<typename T> template<typename T>
class ExpressionLhs { class ExpressionLhs {
ExpressionLhs& operator = ( ExpressionLhs const& ); ExpressionLhs& operator = ( ExpressionLhs const& );
# ifdef CATCH_CPP11_OR_GREATER # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
ExpressionLhs& operator = ( ExpressionLhs && ) = delete; ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
# endif # endif
public: public:
ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {} ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {}
# ifdef CATCH_CPP11_OR_GREATER # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
ExpressionLhs( ExpressionLhs const& ) = default; ExpressionLhs( ExpressionLhs const& ) = default;
ExpressionLhs( ExpressionLhs && ) = default; ExpressionLhs( ExpressionLhs && ) = default;
# endif # endif
...@@ -1395,6 +1555,8 @@ namespace Catch { ...@@ -1395,6 +1555,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();
...@@ -1575,7 +1737,7 @@ namespace Catch { ...@@ -1575,7 +1737,7 @@ namespace Catch {
std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \ std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
__catchResult \ __catchResult \
.setLhs( Catch::toString( arg ) ) \ .setLhs( Catch::toString( arg ) ) \
.setRhs( matcherAsString == "{?}" ? #matcher : matcherAsString ) \ .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
.setOp( "matches" ) \ .setOp( "matches" ) \
.setResultType( ::Catch::Matchers::matcher.match( arg ) ); \ .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
__catchResult.captureExpression(); \ __catchResult.captureExpression(); \
...@@ -1636,6 +1798,9 @@ namespace Catch { ...@@ -1636,6 +1798,9 @@ namespace Catch {
bool allPassed() const { bool allPassed() const {
return failed == 0 && failedButOk == 0; return failed == 0 && failedButOk == 0;
} }
bool allOk() const {
return failed == 0;
}
std::size_t passed; std::size_t passed;
std::size_t failed; std::size_t failed;
...@@ -1688,7 +1853,7 @@ namespace Catch { ...@@ -1688,7 +1853,7 @@ namespace Catch {
public: public:
Timer() : m_ticks( 0 ) {} Timer() : m_ticks( 0 ) {}
void start(); void start();
unsigned int getElapsedNanoseconds() const; unsigned int getElapsedMicroseconds() const;
unsigned int getElapsedMilliseconds() const; unsigned int getElapsedMilliseconds() const;
double getElapsedSeconds() const; double getElapsedSeconds() const;
...@@ -1702,7 +1867,7 @@ namespace Catch { ...@@ -1702,7 +1867,7 @@ namespace Catch {
namespace Catch { namespace Catch {
class Section { class Section : NonCopyable {
public: public:
Section( SectionInfo const& info ); Section( SectionInfo const& info );
~Section(); ~Section();
...@@ -1711,15 +1876,6 @@ namespace Catch { ...@@ -1711,15 +1876,6 @@ namespace Catch {
operator bool() const; operator bool() const;
private: private:
#ifdef CATCH_CPP11_OR_GREATER
Section( Section const& ) = delete;
Section( Section && ) = delete;
Section& operator = ( Section const& ) = delete;
Section& operator = ( Section && ) = delete;
#else
Section( Section const& info );
Section& operator = ( Section const& );
#endif
SectionInfo m_info; SectionInfo m_info;
std::string m_name; std::string m_name;
...@@ -2694,7 +2850,7 @@ return @ desc; \ ...@@ -2694,7 +2850,7 @@ return @ desc; \
#endif #endif
#ifdef CATCH_CONFIG_RUNNER #ifdef CATCH_IMPL
// #included from: internal/catch_impl.hpp // #included from: internal/catch_impl.hpp
#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
...@@ -2706,7 +2862,7 @@ return @ desc; \ ...@@ -2706,7 +2862,7 @@ return @ desc; \
#pragma clang diagnostic ignored "-Wweak-vtables" #pragma clang diagnostic ignored "-Wweak-vtables"
#endif #endif
// #included from: catch_runner.hpp // #included from: ../catch_runner.hpp
#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
// #included from: internal/catch_commandline.hpp // #included from: internal/catch_commandline.hpp
...@@ -2962,6 +3118,11 @@ namespace Catch { ...@@ -2962,6 +3118,11 @@ namespace Catch {
Always, Always,
Never Never
}; }; }; };
struct RunTests { enum InWhatOrder {
InDeclarationOrder,
InLexicographicalOrder,
InRandomOrder
}; };
class TestSpec; class TestSpec;
...@@ -2979,6 +3140,9 @@ namespace Catch { ...@@ -2979,6 +3140,9 @@ namespace Catch {
virtual bool showInvisibles() const = 0; virtual bool showInvisibles() const = 0;
virtual ShowDurations::OrNot showDurations() const = 0; virtual ShowDurations::OrNot showDurations() const = 0;
virtual TestSpec const& testSpec() const = 0; virtual TestSpec const& testSpec() const = 0;
virtual RunTests::InWhatOrder runOrder() const = 0;
virtual unsigned int rngSeed() const = 0;
virtual bool forceColour() const = 0;
}; };
} }
...@@ -3004,12 +3168,16 @@ namespace Catch { ...@@ -3004,12 +3168,16 @@ namespace Catch {
private: private:
bool isOwned; bool isOwned;
}; };
std::ostream& cout();
std::ostream& cerr();
} }
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <ctime>
#ifndef CATCH_CONFIG_CONSOLE_WIDTH #ifndef CATCH_CONFIG_CONSOLE_WIDTH
#define CATCH_CONFIG_CONSOLE_WIDTH 80 #define CATCH_CONFIG_CONSOLE_WIDTH 80
...@@ -3029,10 +3197,13 @@ namespace Catch { ...@@ -3029,10 +3197,13 @@ namespace Catch {
noThrow( false ), noThrow( false ),
showHelp( false ), showHelp( false ),
showInvisibles( false ), showInvisibles( false ),
forceColour( false ),
abortAfter( -1 ), abortAfter( -1 ),
rngSeed( 0 ),
verbosity( Verbosity::Normal ), verbosity( Verbosity::Normal ),
warnings( WarnAbout::Nothing ), warnings( WarnAbout::Nothing ),
showDurations( ShowDurations::DefaultForReporter ) showDurations( ShowDurations::DefaultForReporter ),
runOrder( RunTests::InDeclarationOrder )
{} {}
bool listTests; bool listTests;
...@@ -3045,12 +3216,15 @@ namespace Catch { ...@@ -3045,12 +3216,15 @@ namespace Catch {
bool noThrow; bool noThrow;
bool showHelp; bool showHelp;
bool showInvisibles; bool showInvisibles;
bool forceColour;
int abortAfter; int abortAfter;
unsigned int rngSeed;
Verbosity::Level verbosity; Verbosity::Level verbosity;
WarnAbout::What warnings; WarnAbout::What warnings;
ShowDurations::OrNot showDurations; ShowDurations::OrNot showDurations;
RunTests::InWhatOrder runOrder;
std::string reporterName; std::string reporterName;
std::string outputFilename; std::string outputFilename;
...@@ -3068,12 +3242,12 @@ namespace Catch { ...@@ -3068,12 +3242,12 @@ namespace Catch {
public: public:
Config() Config()
: m_os( std::cout.rdbuf() ) : m_os( Catch::cout().rdbuf() )
{} {}
Config( ConfigData const& data ) Config( ConfigData const& data )
: m_data( data ), : m_data( data ),
m_os( std::cout.rdbuf() ) m_os( Catch::cout().rdbuf() )
{ {
if( !data.testsOrTags.empty() ) { if( !data.testsOrTags.empty() ) {
TestSpecParser parser( ITagAliasRegistry::get() ); TestSpecParser parser( ITagAliasRegistry::get() );
...@@ -3084,7 +3258,7 @@ namespace Catch { ...@@ -3084,7 +3258,7 @@ namespace Catch {
} }
virtual ~Config() { virtual ~Config() {
m_os.rdbuf( std::cout.rdbuf() ); m_os.rdbuf( Catch::cout().rdbuf() );
m_stream.release(); m_stream.release();
} }
...@@ -3106,7 +3280,7 @@ namespace Catch { ...@@ -3106,7 +3280,7 @@ namespace Catch {
bool shouldDebugBreak() const { return m_data.shouldDebugBreak; } bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
void setStreamBuf( std::streambuf* buf ) { void setStreamBuf( std::streambuf* buf ) {
m_os.rdbuf( buf ? buf : std::cout.rdbuf() ); m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() );
} }
void useStream( std::string const& streamName ) { void useStream( std::string const& streamName ) {
...@@ -3132,6 +3306,9 @@ namespace Catch { ...@@ -3132,6 +3306,9 @@ namespace Catch {
virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; } virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; } virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; } virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
virtual unsigned int rngSeed() const { return m_data.rngSeed; }
virtual bool forceColour() const { return m_data.forceColour; }
private: private:
ConfigData m_data; ConfigData m_data;
...@@ -3393,7 +3570,7 @@ namespace Clara { ...@@ -3393,7 +3570,7 @@ namespace Clara {
template<typename ConfigT> template<typename ConfigT>
struct IArgFunction { struct IArgFunction {
virtual ~IArgFunction() {} virtual ~IArgFunction() {}
# ifdef CATCH_CPP11_OR_GREATER # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
IArgFunction() = default; IArgFunction() = default;
IArgFunction( IArgFunction const& ) = default; IArgFunction( IArgFunction const& ) = default;
# endif # endif
...@@ -3760,7 +3937,7 @@ namespace Clara { ...@@ -3760,7 +3937,7 @@ namespace Clara {
m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
{ {
if( other.m_floatingArg.get() ) if( other.m_floatingArg.get() )
m_floatingArg = ArgAutoPtr( new Arg( *other.m_floatingArg ) ); m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
} }
CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
...@@ -3788,7 +3965,7 @@ namespace Clara { ...@@ -3788,7 +3965,7 @@ namespace Clara {
ArgBuilder operator[]( UnpositionalTag ) { ArgBuilder operator[]( UnpositionalTag ) {
if( m_floatingArg.get() ) if( m_floatingArg.get() )
throw std::logic_error( "Only one unpositional argument can be added" ); throw std::logic_error( "Only one unpositional argument can be added" );
m_floatingArg = ArgAutoPtr( new Arg() ); m_floatingArg.reset( new Arg() );
ArgBuilder builder( m_floatingArg.get() ); ArgBuilder builder( m_floatingArg.get() );
return builder; return builder;
} }
...@@ -3930,7 +4107,7 @@ namespace Clara { ...@@ -3930,7 +4107,7 @@ namespace Clara {
if( it == itEnd ) { if( it == itEnd ) {
if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
unusedTokens.push_back( token ); unusedTokens.push_back( token );
else if( m_throwOnUnrecognisedTokens ) else if( errors.empty() && m_throwOnUnrecognisedTokens )
errors.push_back( "unrecognised option: " + token.data ); errors.push_back( "unrecognised option: " + token.data );
} }
} }
...@@ -4028,7 +4205,28 @@ namespace Catch { ...@@ -4028,7 +4205,28 @@ namespace Catch {
config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions ); config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
else else
throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" ); throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
}
inline void setOrder( ConfigData& config, std::string const& order ) {
if( startsWith( "declared", order ) )
config.runOrder = RunTests::InDeclarationOrder;
else if( startsWith( "lexical", order ) )
config.runOrder = RunTests::InLexicographicalOrder;
else if( startsWith( "random", order ) )
config.runOrder = RunTests::InRandomOrder;
else
throw std::runtime_error( "Unrecognised ordering: '" + order + "'" );
}
inline void setRngSeed( ConfigData& config, std::string const& seed ) {
if( seed == "time" ) {
config.rngSeed = static_cast<unsigned int>( std::time(0) );
}
else {
std::stringstream ss;
ss << seed;
ss >> config.rngSeed;
if( ss.fail() )
throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" );
}
} }
inline void setVerbosity( ConfigData& config, int level ) { inline void setVerbosity( ConfigData& config, int level ) {
// !TBD: accept strings? // !TBD: accept strings?
...@@ -4140,6 +4338,18 @@ namespace Catch { ...@@ -4140,6 +4338,18 @@ namespace Catch {
.describe( "list all reporters" ) .describe( "list all reporters" )
.bind( &ConfigData::listReporters ); .bind( &ConfigData::listReporters );
cli["--order"]
.describe( "test case order (defaults to decl)" )
.bind( &setOrder, "decl|lex|rand" );
cli["--rng-seed"]
.describe( "set a specific seed for random numbers" )
.bind( &setRngSeed, "'time'|number" );
cli["--force-colour"]
.describe( "force colourised output" )
.bind( &ConfigData::forceColour );
return cli; return cli;
} }
...@@ -4313,10 +4523,6 @@ namespace Catch { ...@@ -4313,10 +4523,6 @@ namespace Catch {
namespace Catch { namespace Catch {
namespace Detail {
struct IColourImpl;
}
struct Colour { struct Colour {
enum Code { enum Code {
None = 0, None = 0,
...@@ -4362,7 +4568,6 @@ namespace Catch { ...@@ -4362,7 +4568,6 @@ namespace Catch {
static void use( Code _colourCode ); static void use( Code _colourCode );
private: private:
static Detail::IColourImpl* impl();
bool m_moved; bool m_moved;
}; };
...@@ -4456,7 +4661,7 @@ namespace Catch ...@@ -4456,7 +4661,7 @@ namespace Catch
} }
virtual ~AssertionStats(); virtual ~AssertionStats();
# ifdef CATCH_CPP11_OR_GREATER # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
AssertionStats( AssertionStats const& ) = default; AssertionStats( AssertionStats const& ) = default;
AssertionStats( AssertionStats && ) = default; AssertionStats( AssertionStats && ) = default;
AssertionStats& operator = ( AssertionStats const& ) = default; AssertionStats& operator = ( AssertionStats const& ) = default;
...@@ -4479,7 +4684,7 @@ namespace Catch ...@@ -4479,7 +4684,7 @@ namespace Catch
missingAssertions( _missingAssertions ) missingAssertions( _missingAssertions )
{} {}
virtual ~SectionStats(); virtual ~SectionStats();
# ifdef CATCH_CPP11_OR_GREATER # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
SectionStats( SectionStats const& ) = default; SectionStats( SectionStats const& ) = default;
SectionStats( SectionStats && ) = default; SectionStats( SectionStats && ) = default;
SectionStats& operator = ( SectionStats const& ) = default; SectionStats& operator = ( SectionStats const& ) = default;
...@@ -4506,7 +4711,7 @@ namespace Catch ...@@ -4506,7 +4711,7 @@ namespace Catch
{} {}
virtual ~TestCaseStats(); virtual ~TestCaseStats();
# ifdef CATCH_CPP11_OR_GREATER # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestCaseStats( TestCaseStats const& ) = default; TestCaseStats( TestCaseStats const& ) = default;
TestCaseStats( TestCaseStats && ) = default; TestCaseStats( TestCaseStats && ) = default;
TestCaseStats& operator = ( TestCaseStats const& ) = default; TestCaseStats& operator = ( TestCaseStats const& ) = default;
...@@ -4534,7 +4739,7 @@ namespace Catch ...@@ -4534,7 +4739,7 @@ namespace Catch
{} {}
virtual ~TestGroupStats(); virtual ~TestGroupStats();
# ifdef CATCH_CPP11_OR_GREATER # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestGroupStats( TestGroupStats const& ) = default; TestGroupStats( TestGroupStats const& ) = default;
TestGroupStats( TestGroupStats && ) = default; TestGroupStats( TestGroupStats && ) = default;
TestGroupStats& operator = ( TestGroupStats const& ) = default; TestGroupStats& operator = ( TestGroupStats const& ) = default;
...@@ -4556,7 +4761,7 @@ namespace Catch ...@@ -4556,7 +4761,7 @@ namespace Catch
{} {}
virtual ~TestRunStats(); virtual ~TestRunStats();
# ifndef CATCH_CPP11_OR_GREATER # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
TestRunStats( TestRunStats const& _other ) TestRunStats( TestRunStats const& _other )
: runInfo( _other.runInfo ), : runInfo( _other.runInfo ),
totals( _other.totals ), totals( _other.totals ),
...@@ -4592,11 +4797,14 @@ namespace Catch ...@@ -4592,11 +4797,14 @@ namespace Catch
virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
// The return value indicates if the messages buffer should be cleared:
virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
virtual void sectionEnded( SectionStats const& sectionStats ) = 0; virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
}; };
struct IReporterFactory { struct IReporterFactory {
...@@ -4624,9 +4832,9 @@ namespace Catch { ...@@ -4624,9 +4832,9 @@ namespace Catch {
TestSpec testSpec = config.testSpec(); TestSpec testSpec = config.testSpec();
if( config.testSpec().hasFilters() ) if( config.testSpec().hasFilters() )
std::cout << "Matching test cases:\n"; Catch::cout() << "Matching test cases:\n";
else { else {
std::cout << "All available test cases:\n"; Catch::cout() << "All available test cases:\n";
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
} }
...@@ -4647,15 +4855,15 @@ namespace Catch { ...@@ -4647,15 +4855,15 @@ namespace Catch {
: Colour::None; : Colour::None;
Colour colourGuard( colour ); Colour colourGuard( colour );
std::cout << Text( testCaseInfo.name, nameAttr ) << std::endl; Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
if( !testCaseInfo.tags.empty() ) if( !testCaseInfo.tags.empty() )
std::cout << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
} }
if( !config.testSpec().hasFilters() ) if( !config.testSpec().hasFilters() )
std::cout << pluralise( matchedTests, "test case" ) << "\n" << std::endl; Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
else else
std::cout << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl; Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
return matchedTests; return matchedTests;
} }
...@@ -4671,7 +4879,7 @@ namespace Catch { ...@@ -4671,7 +4879,7 @@ namespace Catch {
++it ) { ++it ) {
matchedTests++; matchedTests++;
TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
std::cout << testCaseInfo.name << std::endl; Catch::cout() << testCaseInfo.name << std::endl;
} }
return matchedTests; return matchedTests;
} }
...@@ -4697,9 +4905,9 @@ namespace Catch { ...@@ -4697,9 +4905,9 @@ namespace Catch {
inline std::size_t listTags( Config const& config ) { inline std::size_t listTags( Config const& config ) {
TestSpec testSpec = config.testSpec(); TestSpec testSpec = config.testSpec();
if( config.testSpec().hasFilters() ) if( config.testSpec().hasFilters() )
std::cout << "Tags for matching test cases:\n"; Catch::cout() << "Tags for matching test cases:\n";
else { else {
std::cout << "All available tags:\n"; Catch::cout() << "All available tags:\n";
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
} }
...@@ -4733,14 +4941,14 @@ namespace Catch { ...@@ -4733,14 +4941,14 @@ namespace Catch {
.setInitialIndent( 0 ) .setInitialIndent( 0 )
.setIndent( oss.str().size() ) .setIndent( oss.str().size() )
.setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
std::cout << oss.str() << wrapper << "\n"; Catch::cout() << oss.str() << wrapper << "\n";
} }
std::cout << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl; Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
return tagCounts.size(); return tagCounts.size();
} }
inline std::size_t listReporters( Config const& /*config*/ ) { inline std::size_t listReporters( Config const& /*config*/ ) {
std::cout << "Available reports:\n"; Catch::cout() << "Available reporters:\n";
IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
std::size_t maxNameLen = 0; std::size_t maxNameLen = 0;
...@@ -4752,13 +4960,13 @@ namespace Catch { ...@@ -4752,13 +4960,13 @@ namespace Catch {
.setInitialIndent( 0 ) .setInitialIndent( 0 )
.setIndent( 7+maxNameLen ) .setIndent( 7+maxNameLen )
.setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
std::cout << " " Catch::cout() << " "
<< it->first << it->first
<< ":" << ":"
<< std::string( maxNameLen - it->first.size() + 2, ' ' ) << std::string( maxNameLen - it->first.size() + 2, ' ' )
<< wrapper << "\n"; << wrapper << "\n";
} }
std::cout << std::endl; Catch::cout() << std::endl;
return factories.size(); return factories.size();
} }
...@@ -4915,6 +5123,81 @@ using SectionTracking::TestCaseTracker; ...@@ -4915,6 +5123,81 @@ 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 {
void reset() {}
};
} // 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() : m_isSet( true ) {
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
signal( signalDefs[i].id, handleSignal );
}
~FatalConditionHandler() {
reset();
}
void reset() {
if( m_isSet ) {
for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
signal( signalDefs[i].id, SIG_DFL );
m_isSet = false;
}
}
bool m_isSet;
};
} // namespace Catch
#endif // not Windows
#include <set> #include <set>
#include <string> #include <string>
...@@ -5102,6 +5385,37 @@ namespace Catch { ...@@ -5102,6 +5385,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 {
...@@ -5123,12 +5437,12 @@ namespace Catch { ...@@ -5123,12 +5437,12 @@ namespace Catch {
Timer timer; Timer timer;
timer.start(); timer.start();
if( m_reporter->getPreferences().shouldRedirectStdOut ) { if( m_reporter->getPreferences().shouldRedirectStdOut ) {
StreamRedirect coutRedir( std::cout, redirectedCout ); StreamRedirect coutRedir( Catch::cout(), redirectedCout );
StreamRedirect cerrRedir( std::cerr, redirectedCerr ); StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
m_activeTestCase->invoke(); invokeActiveTestCase();
} }
else { else {
m_activeTestCase->invoke(); invokeActiveTestCase();
} }
duration = timer.getElapsedSeconds(); duration = timer.getElapsedSeconds();
} }
...@@ -5136,20 +5450,9 @@ namespace Catch { ...@@ -5136,20 +5450,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 +5468,32 @@ namespace Catch { ...@@ -5165,7 +5468,32 @@ namespace Catch {
m_reporter->sectionEnded( testCaseSectionStats ); m_reporter->sectionEnded( testCaseSectionStats );
} }
void invokeActiveTestCase() {
FatalConditionHandler fatalConditionHandler; // Handle signals
m_activeTestCase->invoke();
fatalConditionHandler.reset();
}
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 )
...@@ -5253,7 +5581,7 @@ namespace Catch { ...@@ -5253,7 +5581,7 @@ namespace Catch {
Totals totals; Totals totals;
context.testGroupStarting( "", 1, 1 ); // deprecated? context.testGroupStarting( "all tests", 1, 1 ); // deprecated?
TestSpec testSpec = m_config->testSpec(); TestSpec testSpec = m_config->testSpec();
if( !testSpec.hasFilters() ) if( !testSpec.hasFilters() )
...@@ -5276,7 +5604,15 @@ namespace Catch { ...@@ -5276,7 +5604,15 @@ namespace Catch {
m_testsAlreadyRun.insert( *it ); m_testsAlreadyRun.insert( *it );
} }
} }
context.testGroupEnded( "", totals, 1, 1 ); std::vector<TestCase> skippedTestCases;
getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, skippedTestCases, true );
for( std::vector<TestCase>::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end();
it != itEnd;
++it )
m_reporter->skipTest( *it );
context.testGroupEnded( "all tests", totals, 1, 1 );
return totals; return totals;
} }
...@@ -5313,7 +5649,7 @@ namespace Catch { ...@@ -5313,7 +5649,7 @@ namespace Catch {
std::set<TestCase> m_testsAlreadyRun; std::set<TestCase> m_testsAlreadyRun;
}; };
class Session { class Session : NonCopyable {
static bool alreadyInstantiated; static bool alreadyInstantiated;
public: public:
...@@ -5324,7 +5660,7 @@ namespace Catch { ...@@ -5324,7 +5660,7 @@ namespace Catch {
: m_cli( makeCommandLineParser() ) { : m_cli( makeCommandLineParser() ) {
if( alreadyInstantiated ) { if( alreadyInstantiated ) {
std::string msg = "Only one instance of Catch::Session can ever be used"; std::string msg = "Only one instance of Catch::Session can ever be used";
std::cerr << msg << std::endl; Catch::cerr() << msg << std::endl;
throw std::logic_error( msg ); throw std::logic_error( msg );
} }
alreadyInstantiated = true; alreadyInstantiated = true;
...@@ -5334,15 +5670,15 @@ namespace Catch { ...@@ -5334,15 +5670,15 @@ namespace Catch {
} }
void showHelp( std::string const& processName ) { void showHelp( std::string const& processName ) {
std::cout << "\nCatch v" << libraryVersion.majorVersion << "." Catch::cout() << "\nCatch v" << libraryVersion.majorVersion << "."
<< libraryVersion.minorVersion << " build " << libraryVersion.minorVersion << " build "
<< libraryVersion.buildNumber; << libraryVersion.buildNumber;
if( libraryVersion.branchName != std::string( "master" ) ) if( libraryVersion.branchName != std::string( "master" ) )
std::cout << " (" << libraryVersion.branchName << " branch)"; Catch::cout() << " (" << libraryVersion.branchName << " branch)";
std::cout << "\n"; Catch::cout() << "\n";
m_cli.usage( std::cout, processName ); m_cli.usage( Catch::cout(), processName );
std::cout << "For more detail usage please see the project docs\n" << std::endl; Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
} }
int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { int applyCommandLine( int argc, char* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
...@@ -5356,11 +5692,11 @@ namespace Catch { ...@@ -5356,11 +5692,11 @@ namespace Catch {
catch( std::exception& ex ) { catch( std::exception& ex ) {
{ {
Colour colourGuard( Colour::Red ); Colour colourGuard( Colour::Red );
std::cerr << "\nError(s) in input:\n" Catch::cerr() << "\nError(s) in input:\n"
<< Text( ex.what(), TextAttributes().setIndent(2) ) << Text( ex.what(), TextAttributes().setIndent(2) )
<< "\n\n"; << "\n\n";
} }
m_cli.usage( std::cout, m_configData.processName ); m_cli.usage( Catch::cout(), m_configData.processName );
return (std::numeric_limits<int>::max)(); return (std::numeric_limits<int>::max)();
} }
return 0; return 0;
...@@ -5386,6 +5722,9 @@ namespace Catch { ...@@ -5386,6 +5722,9 @@ namespace Catch {
try try
{ {
config(); // Force config to be constructed config(); // Force config to be constructed
std::srand( m_configData.rngSeed );
Runner runner( m_config ); Runner runner( m_config );
// Handle list request // Handle list request
...@@ -5395,7 +5734,7 @@ namespace Catch { ...@@ -5395,7 +5734,7 @@ namespace Catch {
return static_cast<int>( runner.runTests().assertions.failed ); return static_cast<int>( runner.runTests().assertions.failed );
} }
catch( std::exception& ex ) { catch( std::exception& ex ) {
std::cerr << ex.what() << std::endl; Catch::cerr() << ex.what() << std::endl;
return (std::numeric_limits<int>::max)(); return (std::numeric_limits<int>::max)();
} }
} }
...@@ -5436,10 +5775,18 @@ namespace Catch { ...@@ -5436,10 +5775,18 @@ namespace Catch {
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <iostream> #include <iostream>
#include <algorithm>
namespace Catch { namespace Catch {
class TestRegistry : public ITestCaseRegistry { class TestRegistry : public ITestCaseRegistry {
struct LexSort {
bool operator() (TestCase i,TestCase j) const { return (i<j);}
};
struct RandomNumberGenerator {
int operator()( int n ) const { return std::rand() % n; }
};
public: public:
TestRegistry() : m_unnamedCount( 0 ) {} TestRegistry() : m_unnamedCount( 0 ) {}
virtual ~TestRegistry(); virtual ~TestRegistry();
...@@ -5462,7 +5809,7 @@ namespace Catch { ...@@ -5462,7 +5809,7 @@ namespace Catch {
TestCase const& prev = *m_functions.find( testCase ); TestCase const& prev = *m_functions.find( testCase );
{ {
Colour colourGuard( Colour::Red ); Colour colourGuard( Colour::Red );
std::cerr << "error: TEST_CASE( \"" << name << "\" ) already defined.\n" Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
<< "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n" << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
<< "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl; << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
} }
...@@ -5478,18 +5825,38 @@ namespace Catch { ...@@ -5478,18 +5825,38 @@ namespace Catch {
return m_nonHiddenFunctions; return m_nonHiddenFunctions;
} }
virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases ) const { virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const {
for( std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(), for( std::vector<TestCase>::const_iterator it = m_functionsInOrder.begin(),
itEnd = m_functionsInOrder.end(); itEnd = m_functionsInOrder.end();
it != itEnd; it != itEnd;
++it ) { ++it ) {
if( testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() ) ) bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() );
if( includeTest != negated )
matchingTestCases.push_back( *it ); matchingTestCases.push_back( *it );
} }
sortTests( config, matchingTestCases );
} }
private: private:
static void sortTests( IConfig const& config, std::vector<TestCase>& matchingTestCases ) {
switch( config.runOrder() ) {
case RunTests::InLexicographicalOrder:
std::sort( matchingTestCases.begin(), matchingTestCases.end(), LexSort() );
break;
case RunTests::InRandomOrder:
{
RandomNumberGenerator rng;
std::random_shuffle( matchingTestCases.begin(), matchingTestCases.end(), rng );
}
break;
case RunTests::InDeclarationOrder:
// already in declaration order
break;
}
}
std::set<TestCase> m_functions; std::set<TestCase> m_functions;
std::vector<TestCase> m_functionsInOrder; std::vector<TestCase> m_functionsInOrder;
std::vector<TestCase> m_nonHiddenFunctions; std::vector<TestCase> m_nonHiddenFunctions;
...@@ -5613,7 +5980,7 @@ namespace Catch { ...@@ -5613,7 +5980,7 @@ namespace Catch {
throw; throw;
} }
@catch (NSException *exception) { @catch (NSException *exception) {
return toString( [exception description] ); return Catch::toString( [exception description] );
} }
#else #else
throw; throw;
...@@ -5760,6 +6127,7 @@ namespace Catch { ...@@ -5760,6 +6127,7 @@ namespace Catch {
#include <stdexcept> #include <stdexcept>
#include <cstdio> #include <cstdio>
#include <iostream>
namespace Catch { namespace Catch {
...@@ -5823,6 +6191,15 @@ namespace Catch { ...@@ -5823,6 +6191,15 @@ namespace Catch {
isOwned = false; isOwned = false;
} }
} }
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions
std::ostream& cout() {
return std::cout;
}
std::ostream& cerr() {
return std::cerr;
}
#endif
} }
namespace Catch { namespace Catch {
...@@ -5872,7 +6249,7 @@ namespace Catch { ...@@ -5872,7 +6249,7 @@ namespace Catch {
std::string testName = getResultCapture()->getCurrentTestName(); std::string testName = getResultCapture()->getCurrentTestName();
std::map<std::string, IGeneratorsForTest*>::const_iterator it = std::map<std::string, IGeneratorsForTest*>::const_iterator it =
m_generatorsByTestName.find( testName ); m_generatorsByTestName.find( testName );
return it != m_generatorsByTestName.end() return it != m_generatorsByTestName.end()
? it->second ? it->second
: NULL; : NULL;
...@@ -5908,8 +6285,8 @@ namespace Catch { ...@@ -5908,8 +6285,8 @@ namespace Catch {
} }
Stream createStream( std::string const& streamName ) { Stream createStream( std::string const& streamName ) {
if( streamName == "stdout" ) return Stream( std::cout.rdbuf(), false ); if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false );
if( streamName == "stderr" ) return Stream( std::cerr.rdbuf(), false ); if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false );
if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true ); if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
throw std::domain_error( "Unknown stream: " + streamName ); throw std::domain_error( "Unknown stream: " + streamName );
...@@ -5924,14 +6301,35 @@ namespace Catch { ...@@ -5924,14 +6301,35 @@ 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
namespace Catch { namespace Detail { namespace Catch {
struct IColourImpl { namespace {
virtual ~IColourImpl() {}
virtual void use( Colour::Code _colourCode ) = 0;
};
}}
#if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// struct IColourImpl {
virtual ~IColourImpl() {}
virtual void use( Colour::Code _colourCode ) = 0;
};
struct NoColourImpl : IColourImpl {
void use( Colour::Code ) {}
static IColourImpl* instance() {
static NoColourImpl s_instance;
return &s_instance;
}
};
} // anon namespace
} // namespace Catch
#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
# ifdef CATCH_PLATFORM_WINDOWS
# define CATCH_CONFIG_COLOUR_WINDOWS
# else
# define CATCH_CONFIG_COLOUR_ANSI
# endif
#endif
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
#ifndef NOMINMAX #ifndef NOMINMAX
#define NOMINMAX #define NOMINMAX
...@@ -5946,7 +6344,7 @@ namespace Catch { namespace Detail { ...@@ -5946,7 +6344,7 @@ namespace Catch { namespace Detail {
namespace Catch { namespace Catch {
namespace { namespace {
class Win32ColourImpl : public Detail::IColourImpl { class Win32ColourImpl : public IColourImpl {
public: public:
Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
{ {
...@@ -5983,11 +6381,7 @@ namespace { ...@@ -5983,11 +6381,7 @@ namespace {
WORD originalAttributes; WORD originalAttributes;
}; };
inline bool shouldUseColourForPlatform() { IColourImpl* platformColourInstance() {
return true;
}
static Detail::IColourImpl* platformColourInstance() {
static Win32ColourImpl s_instance; static Win32ColourImpl s_instance;
return &s_instance; return &s_instance;
} }
...@@ -5995,7 +6389,7 @@ namespace { ...@@ -5995,7 +6389,7 @@ namespace {
} // end anon namespace } // end anon namespace
} // end namespace Catch } // end namespace Catch
#else // Not Windows - assumed to be POSIX compatible ////////////////////////// #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
#include <unistd.h> #include <unistd.h>
...@@ -6006,7 +6400,7 @@ namespace { ...@@ -6006,7 +6400,7 @@ namespace {
// Thanks to Adam Strzelecki for original contribution // Thanks to Adam Strzelecki for original contribution
// (http://github.com/nanoant) // (http://github.com/nanoant)
// https://github.com/philsquared/Catch/pull/131 // https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public Detail::IColourImpl { class PosixColourImpl : public IColourImpl {
public: public:
virtual void use( Colour::Code _colourCode ) { virtual void use( Colour::Code _colourCode ) {
switch( _colourCode ) { switch( _colourCode ) {
...@@ -6027,53 +6421,48 @@ namespace { ...@@ -6027,53 +6421,48 @@ namespace {
case Colour::Bright: throw std::logic_error( "not a colour" ); case Colour::Bright: throw std::logic_error( "not a colour" );
} }
} }
static IColourImpl* instance() {
static PosixColourImpl s_instance;
return &s_instance;
}
private: private:
void setColour( const char* _escapeCode ) { void setColour( const char* _escapeCode ) {
std::cout << '\033' << _escapeCode; Catch::cout() << '\033' << _escapeCode;
} }
}; };
inline bool shouldUseColourForPlatform() { IColourImpl* platformColourInstance() {
return isatty(STDOUT_FILENO); Ptr<IConfig const> config = getCurrentContext().getConfig();
} return (config && config->forceColour()) || isatty(STDOUT_FILENO)
? PosixColourImpl::instance()
static Detail::IColourImpl* platformColourInstance() { : NoColourImpl::instance();
static PosixColourImpl s_instance;
return &s_instance;
} }
} // end anon namespace } // end anon namespace
} // end namespace Catch } // end namespace Catch
#endif // not Windows #else // not Windows or ANSI ///////////////////////////////////////////////
namespace Catch { namespace Catch {
namespace { static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
struct NoColourImpl : Detail::IColourImpl {
void use( Colour::Code ) {}
static IColourImpl* instance() { } // end namespace Catch
static NoColourImpl s_instance;
return &s_instance; #endif // Windows/ ANSI/ None
}
}; namespace Catch {
static bool shouldUseColour() {
return shouldUseColourForPlatform() && !isDebuggerActive();
}
}
Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; } Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
Colour::~Colour(){ if( !m_moved ) use( None ); } Colour::~Colour(){ if( !m_moved ) use( None ); }
void Colour::use( Code _colourCode ) {
impl()->use( _colourCode );
}
Detail::IColourImpl* Colour::impl() { void Colour::use( Code _colourCode ) {
return shouldUseColour() static IColourImpl* impl = isDebuggerActive()
? platformColourInstance() ? NoColourImpl::instance()
: NoColourImpl::instance(); : platformColourInstance();
impl->use( _colourCode );
} }
} // end namespace Catch } // end namespace Catch
...@@ -6238,7 +6627,7 @@ namespace Catch { ...@@ -6238,7 +6627,7 @@ namespace Catch {
namespace Catch { namespace Catch {
inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
if( tag == "." || if( startsWith( tag, "." ) ||
tag == "hide" || tag == "hide" ||
tag == "!hide" ) tag == "!hide" )
return TestCaseInfo::IsHidden; return TestCaseInfo::IsHidden;
...@@ -6258,13 +6647,13 @@ namespace Catch { ...@@ -6258,13 +6647,13 @@ namespace Catch {
if( isReservedTag( tag ) ) { if( isReservedTag( tag ) ) {
{ {
Colour colourGuard( Colour::Red ); Colour colourGuard( Colour::Red );
std::cerr Catch::cerr()
<< "Tag name [" << tag << "] not allowed.\n" << "Tag name [" << tag << "] not allowed.\n"
<< "Tag names starting with non alpha-numeric characters are reserved\n"; << "Tag names starting with non alpha-numeric characters are reserved\n";
} }
{ {
Colour colourGuard( Colour::FileName ); Colour colourGuard( Colour::FileName );
std::cerr << _lineInfo << std::endl; Catch::cerr() << _lineInfo << std::endl;
} }
exit(1); exit(1);
} }
...@@ -6292,14 +6681,15 @@ namespace Catch { ...@@ -6292,14 +6681,15 @@ namespace Catch {
} }
else { else {
if( c == ']' ) { if( c == ']' ) {
enforceNotReservedTag( tag, _lineInfo ); TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
if( prop == TestCaseInfo::IsHidden )
inTag = false;
if( tag == "hide" || tag == "." )
isHidden = true; isHidden = true;
else else if( prop == TestCaseInfo::None )
tags.insert( tag ); enforceNotReservedTag( tag, _lineInfo );
tags.insert( tag );
tag.clear(); tag.clear();
inTag = false;
} }
else else
tag += c; tag += c;
...@@ -6417,7 +6807,7 @@ namespace Catch { ...@@ -6417,7 +6807,7 @@ namespace Catch {
namespace Catch { namespace Catch {
// These numbers are maintained by a script // These numbers are maintained by a script
Version libraryVersion( 1, 0, 53, "master" ); Version libraryVersion( 1, 1, 3, "master" );
} }
// #included from: catch_message.hpp // #included from: catch_message.hpp
...@@ -6501,6 +6891,7 @@ namespace Catch ...@@ -6501,6 +6891,7 @@ namespace Catch
virtual void testCaseEnded( TestCaseStats const& testCaseStats ); virtual void testCaseEnded( TestCaseStats const& testCaseStats );
virtual void testGroupEnded( TestGroupStats const& testGroupStats ); virtual void testGroupEnded( TestGroupStats const& testGroupStats );
virtual void testRunEnded( TestRunStats const& testRunStats ); virtual void testRunEnded( TestRunStats const& testRunStats );
virtual void skipTest( TestCaseInfo const& );
private: private:
Ptr<IReporter> m_legacyReporter; Ptr<IReporter> m_legacyReporter;
...@@ -6574,6 +6965,8 @@ namespace Catch ...@@ -6574,6 +6965,8 @@ namespace Catch
void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
m_legacyReporter->EndTesting( testRunStats.totals ); m_legacyReporter->EndTesting( testRunStats.totals );
} }
void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
}
} }
// #included from: catch_timer.hpp // #included from: catch_timer.hpp
...@@ -6596,11 +6989,11 @@ namespace Catch { ...@@ -6596,11 +6989,11 @@ namespace Catch {
uint64_t getCurrentTicks() { uint64_t getCurrentTicks() {
static uint64_t hz=0, hzo=0; static uint64_t hz=0, hzo=0;
if (!hz) { if (!hz) {
QueryPerformanceFrequency((LARGE_INTEGER*)&hz); QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
QueryPerformanceCounter((LARGE_INTEGER*)&hzo); QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
} }
uint64_t t; uint64_t t;
QueryPerformanceCounter((LARGE_INTEGER*)&t); QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
return ((t-hzo)*1000000)/hz; return ((t-hzo)*1000000)/hz;
} }
#else #else
...@@ -6615,14 +7008,14 @@ namespace Catch { ...@@ -6615,14 +7008,14 @@ namespace Catch {
void Timer::start() { void Timer::start() {
m_ticks = getCurrentTicks(); m_ticks = getCurrentTicks();
} }
unsigned int Timer::getElapsedNanoseconds() const { unsigned int Timer::getElapsedMicroseconds() const {
return static_cast<unsigned int>(getCurrentTicks() - m_ticks); return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
} }
unsigned int Timer::getElapsedMilliseconds() const { unsigned int Timer::getElapsedMilliseconds() const {
return static_cast<unsigned int>((getCurrentTicks() - m_ticks)/1000); return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
} }
double Timer::getElapsedSeconds() const { double Timer::getElapsedSeconds() const {
return (getCurrentTicks() - m_ticks)/1000000.0; return getElapsedMicroseconds()/1000000.0;
} }
} // namespace Catch } // namespace Catch
...@@ -6660,6 +7053,20 @@ namespace Catch { ...@@ -6660,6 +7053,20 @@ namespace Catch {
return start != std::string::npos ? str.substr( start, 1+end-start ) : ""; return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
} }
bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
bool replaced = false;
std::size_t i = str.find( replaceThis );
while( i != std::string::npos ) {
replaced = true;
str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
if( i < str.size()-withThis.size() )
i = str.find( replaceThis, i+withThis.size() );
else
i = std::string::npos;
}
return replaced;
}
pluralise::pluralise( std::size_t count, std::string const& label ) pluralise::pluralise( std::size_t count, std::string const& label )
: m_count( count ), : m_count( count ),
m_label( label ) m_label( label )
...@@ -6687,6 +7094,9 @@ namespace Catch { ...@@ -6687,6 +7094,9 @@ namespace Catch {
bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
return line == other.line && file == other.file; return line == other.line && file == other.file;
} }
bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
return line < other.line || ( line == other.line && file < other.file );
}
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
#ifndef __GNUG__ #ifndef __GNUG__
...@@ -6781,7 +7191,7 @@ namespace Catch { ...@@ -6781,7 +7191,7 @@ namespace Catch {
size = sizeof(info); size = sizeof(info);
if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) { if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) {
std::cerr << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
return false; return false;
} }
...@@ -6822,7 +7232,7 @@ namespace Catch { ...@@ -6822,7 +7232,7 @@ namespace Catch {
namespace Catch { namespace Catch {
void writeToDebugConsole( std::string const& text ) { void writeToDebugConsole( std::string const& text ) {
// !TBD: Need a version for Mac/ XCode and other IDEs // !TBD: Need a version for Mac/ XCode and other IDEs
std::cout << text; Catch::cout() << text;
} }
} }
#endif // Platform #endif // Platform
...@@ -6834,6 +7244,8 @@ namespace Catch { ...@@ -6834,6 +7244,8 @@ namespace Catch {
namespace Detail { namespace Detail {
std::string unprintableString = "{?}";
namespace { namespace {
struct Endianness { struct Endianness {
enum Arch { Big, Little }; enum Arch { Big, Little };
...@@ -6892,7 +7304,7 @@ std::string toString( std::wstring const& value ) { ...@@ -6892,7 +7304,7 @@ std::string toString( std::wstring const& value ) {
s.reserve( value.size() ); s.reserve( value.size() );
for(size_t i = 0; i < value.size(); ++i ) for(size_t i = 0; i < value.size(); ++i )
s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?'; s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
return toString( s ); return Catch::toString( s );
} }
std::string toString( const char* const value ) { std::string toString( const char* const value ) {
...@@ -6916,20 +7328,21 @@ std::string toString( wchar_t* const value ) ...@@ -6916,20 +7328,21 @@ std::string toString( wchar_t* const value )
std::string toString( int value ) { std::string toString( int value ) {
std::ostringstream oss; std::ostringstream oss;
oss << value; oss << value;
if( value >= 255 )
oss << " (0x" << std::hex << value << ")";
return oss.str(); return oss.str();
} }
std::string toString( unsigned long value ) { std::string toString( unsigned long value ) {
std::ostringstream oss; std::ostringstream oss;
if( value > 8192 ) oss << value;
oss << "0x" << std::hex << value; if( value >= 255 )
else oss << " (0x" << std::hex << value << ")";
oss << value;
return oss.str(); return oss.str();
} }
std::string toString( unsigned int value ) { std::string toString( unsigned int value ) {
return toString( static_cast<unsigned long>( value ) ); return Catch::toString( static_cast<unsigned long>( value ) );
} }
template<typename T> template<typename T>
...@@ -7055,7 +7468,7 @@ namespace Catch { ...@@ -7055,7 +7468,7 @@ namespace Catch {
if( !result.isOk() ) { if( !result.isOk() ) {
if( getCurrentContext().getConfig()->shouldDebugBreak() ) if( getCurrentContext().getConfig()->shouldDebugBreak() )
m_shouldDebugBreak = true; m_shouldDebugBreak = true;
if( getCurrentContext().getRunner()->aborting() || m_assertionInfo.resultDisposition == ResultDisposition::Normal ) if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
m_shouldThrow = true; m_shouldThrow = true;
} }
} }
...@@ -7195,7 +7608,7 @@ namespace Catch { ...@@ -7195,7 +7608,7 @@ namespace Catch {
} }
catch( std::exception& ex ) { catch( std::exception& ex ) {
Colour colourGuard( Colour::Red ); Colour colourGuard( Colour::Red );
std::cerr << ex.what() << std::endl; Catch::cerr() << ex.what() << std::endl;
exit(1); exit(1);
} }
} }
...@@ -7208,6 +7621,8 @@ namespace Catch { ...@@ -7208,6 +7621,8 @@ namespace Catch {
// #included from: catch_reporter_bases.hpp // #included from: catch_reporter_bases.hpp
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
#include <cstring>
namespace Catch { namespace Catch {
struct StreamingReporterBase : SharedImpl<IStreamingReporter> { struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
...@@ -7240,7 +7655,6 @@ namespace Catch { ...@@ -7240,7 +7655,6 @@ namespace Catch {
} }
virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) { virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
currentTestCaseInfo.reset(); currentTestCaseInfo.reset();
assert( m_sectionStack.empty() );
} }
virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) { virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
currentGroupInfo.reset(); currentGroupInfo.reset();
...@@ -7251,6 +7665,11 @@ namespace Catch { ...@@ -7251,6 +7665,11 @@ namespace Catch {
currentTestRunInfo.reset(); currentTestRunInfo.reset();
} }
virtual void skipTest( TestCaseInfo const& ) {
// Don't do anything with this by default.
// It can optionally be overridden in the derived class.
}
Ptr<IConfig> m_config; Ptr<IConfig> m_config;
std::ostream& stream; std::ostream& stream;
...@@ -7380,6 +7799,8 @@ namespace Catch { ...@@ -7380,6 +7799,8 @@ namespace Catch {
} }
virtual void testRunEndedCumulative() = 0; virtual void testRunEndedCumulative() = 0;
virtual void skipTest( TestCaseInfo const& ) {}
Ptr<IConfig> m_config; Ptr<IConfig> m_config;
std::ostream& stream; std::ostream& stream;
std::vector<AssertionStats> m_assertions; std::vector<AssertionStats> m_assertions;
...@@ -7395,6 +7816,16 @@ namespace Catch { ...@@ -7395,6 +7816,16 @@ namespace Catch {
}; };
template<char C>
char const* getLineOfChars() {
static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
if( !*line ) {
memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
}
return line;
}
} // end namespace Catch } // end namespace Catch
// #included from: ../internal/catch_reporter_registrars.hpp // #included from: ../internal/catch_reporter_registrars.hpp
...@@ -7464,7 +7895,6 @@ namespace Catch { ...@@ -7464,7 +7895,6 @@ namespace Catch {
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
#include <sstream> #include <sstream>
#include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
...@@ -7507,7 +7937,7 @@ namespace Catch { ...@@ -7507,7 +7937,7 @@ namespace Catch {
XmlWriter() XmlWriter()
: m_tagIsOpen( false ), : m_tagIsOpen( false ),
m_needsNewline( false ), m_needsNewline( false ),
m_os( &std::cout ) m_os( &Catch::cout() )
{} {}
XmlWriter( std::ostream& os ) XmlWriter( std::ostream& os )
...@@ -7521,27 +7951,6 @@ namespace Catch { ...@@ -7521,27 +7951,6 @@ namespace Catch {
endElement(); endElement();
} }
//# ifndef CATCH_CPP11_OR_GREATER
// XmlWriter& operator = ( XmlWriter const& other ) {
// XmlWriter temp( other );
// swap( temp );
// return *this;
// }
//# else
// XmlWriter( XmlWriter const& ) = default;
// XmlWriter( XmlWriter && ) = default;
// XmlWriter& operator = ( XmlWriter const& ) = default;
// XmlWriter& operator = ( XmlWriter && ) = default;
//# endif
//
// void swap( XmlWriter& other ) {
// std::swap( m_tagIsOpen, other.m_tagIsOpen );
// std::swap( m_needsNewline, other.m_needsNewline );
// std::swap( m_tags, other.m_tags );
// std::swap( m_indent, other.m_indent );
// std::swap( m_os, other.m_os );
// }
XmlWriter& startElement( std::string const& name ) { XmlWriter& startElement( std::string const& name ) {
ensureTagClosed(); ensureTagClosed();
newlineIfNecessary(); newlineIfNecessary();
...@@ -7677,81 +8086,90 @@ namespace Catch { ...@@ -7677,81 +8086,90 @@ namespace Catch {
} }
namespace Catch { namespace Catch {
class XmlReporter : public SharedImpl<IReporter> { class XmlReporter : public StreamingReporterBase {
public: public:
XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} XmlReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ),
m_sectionDepth( 0 )
{}
virtual ~XmlReporter();
static std::string getDescription() { static std::string getDescription() {
return "Reports test results as an XML document"; return "Reports test results as an XML document";
} }
virtual ~XmlReporter();
private: // IReporter
virtual bool shouldRedirectStdout() const { public: // StreamingReporterBase
return true; virtual ReporterPreferences getPreferences() const {
ReporterPreferences prefs;
prefs.shouldRedirectStdOut = true;
return prefs;
} }
virtual void StartTesting() { virtual void noMatchingTestCases( std::string const& s ) {
m_xml.setStream( m_config.stream() ); StreamingReporterBase::noMatchingTestCases( s );
m_xml.startElement( "Catch" );
if( !m_config.fullConfig()->name().empty() )
m_xml.writeAttribute( "name", m_config.fullConfig()->name() );
} }
virtual void EndTesting( const Totals& totals ) { virtual void testRunStarting( TestRunInfo const& testInfo ) {
m_xml.scopedElement( "OverallResults" ) StreamingReporterBase::testRunStarting( testInfo );
.writeAttribute( "successes", totals.assertions.passed ) m_xml.setStream( stream );
.writeAttribute( "failures", totals.assertions.failed ) m_xml.startElement( "Catch" );
.writeAttribute( "expectedFailures", totals.assertions.failedButOk ); if( !m_config->name().empty() )
m_xml.endElement(); m_xml.writeAttribute( "name", m_config->name() );
} }
virtual void StartGroup( const std::string& groupName ) { virtual void testGroupStarting( GroupInfo const& groupInfo ) {
StreamingReporterBase::testGroupStarting( groupInfo );
m_xml.startElement( "Group" ) m_xml.startElement( "Group" )
.writeAttribute( "name", groupName ); .writeAttribute( "name", groupInfo.name );
} }
virtual void EndGroup( const std::string&, const Totals& totals ) { virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
m_xml.scopedElement( "OverallResults" ) StreamingReporterBase::testCaseStarting(testInfo);
.writeAttribute( "successes", totals.assertions.passed ) m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
.writeAttribute( "failures", totals.assertions.failed )
.writeAttribute( "expectedFailures", totals.assertions.failedButOk ); if ( m_config->showDurations() == ShowDurations::Always )
m_xml.endElement(); m_testCaseTimer.start();
} }
virtual void StartSection( const std::string& sectionName, const std::string& description ) { virtual void sectionStarting( SectionInfo const& sectionInfo ) {
StreamingReporterBase::sectionStarting( sectionInfo );
if( m_sectionDepth++ > 0 ) { if( m_sectionDepth++ > 0 ) {
m_xml.startElement( "Section" ) m_xml.startElement( "Section" )
.writeAttribute( "name", trim( sectionName ) ) .writeAttribute( "name", trim( sectionInfo.name ) )
.writeAttribute( "description", description ); .writeAttribute( "description", sectionInfo.description );
} }
} }
virtual void NoAssertionsInSection( const std::string& ) {}
virtual void NoAssertionsInTestCase( const std::string& ) {}
virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { virtual void assertionStarting( AssertionInfo const& ) { }
if( --m_sectionDepth > 0 ) {
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", assertions.passed )
.writeAttribute( "failures", assertions.failed )
.writeAttribute( "expectedFailures", assertions.failedButOk );
m_xml.endElement();
}
}
virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { virtual bool assertionEnded( AssertionStats const& assertionStats ) {
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) ); const AssertionResult& assertionResult = assertionStats.assertionResult;
m_currentTestSuccess = true;
}
virtual void Result( const Catch::AssertionResult& assertionResult ) { // Print any info messages in <Info> tags.
if( !m_config.fullConfig()->includeSuccessfulResults() && assertionResult.getResultType() == ResultWas::Ok ) if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
return; 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( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
return true;
// Print the expression if there is one.
if( assertionResult.hasExpression() ) { if( assertionResult.hasExpression() ) {
m_xml.startElement( "Expression" ) m_xml.startElement( "Expression" )
.writeAttribute( "success", assertionResult.succeeded() ) .writeAttribute( "success", assertionResult.succeeded() )
.writeAttribute( "type", assertionResult.getTestMacroName() )
.writeAttribute( "filename", assertionResult.getSourceInfo().file ) .writeAttribute( "filename", assertionResult.getSourceInfo().file )
.writeAttribute( "line", assertionResult.getSourceInfo().line ); .writeAttribute( "line", assertionResult.getSourceInfo().line );
...@@ -7759,58 +8177,96 @@ namespace Catch { ...@@ -7759,58 +8177,96 @@ namespace Catch {
.writeText( assertionResult.getExpression() ); .writeText( assertionResult.getExpression() );
m_xml.scopedElement( "Expanded" ) m_xml.scopedElement( "Expanded" )
.writeText( assertionResult.getExpandedExpression() ); .writeText( assertionResult.getExpandedExpression() );
m_currentTestSuccess &= assertionResult.succeeded();
} }
// And... Print a result applicable to each result type.
switch( assertionResult.getResultType() ) { switch( assertionResult.getResultType() ) {
case ResultWas::ThrewException: case ResultWas::ThrewException:
m_xml.scopedElement( "Exception" ) m_xml.scopedElement( "Exception" )
.writeAttribute( "filename", assertionResult.getSourceInfo().file ) .writeAttribute( "filename", assertionResult.getSourceInfo().file )
.writeAttribute( "line", assertionResult.getSourceInfo().line ) .writeAttribute( "line", assertionResult.getSourceInfo().line )
.writeText( assertionResult.getMessage() ); .writeText( assertionResult.getMessage() );
m_currentTestSuccess = false; break;
case ResultWas::FatalErrorCondition:
m_xml.scopedElement( "Fatal Error Condition" )
.writeAttribute( "filename", assertionResult.getSourceInfo().file )
.writeAttribute( "line", assertionResult.getSourceInfo().line )
.writeText( assertionResult.getMessage() );
break; break;
case ResultWas::Info: case ResultWas::Info:
m_xml.scopedElement( "Info" ) m_xml.scopedElement( "Info" )
.writeText( assertionResult.getMessage() ); .writeText( assertionResult.getMessage() );
break; break;
case ResultWas::Warning: case ResultWas::Warning:
m_xml.scopedElement( "Warning" ) // Warning will already have been written
.writeText( assertionResult.getMessage() );
break; break;
case ResultWas::ExplicitFailure: case ResultWas::ExplicitFailure:
m_xml.scopedElement( "Failure" ) m_xml.scopedElement( "Failure" )
.writeText( assertionResult.getMessage() ); .writeText( assertionResult.getMessage() );
m_currentTestSuccess = false;
break; break;
case ResultWas::Unknown: default:
case ResultWas::Ok:
case ResultWas::FailureBit:
case ResultWas::ExpressionFailed:
case ResultWas::Exception:
case ResultWas::DidntThrowException:
break; break;
} }
if( assertionResult.hasExpression() ) if( assertionResult.hasExpression() )
m_xml.endElement(); m_xml.endElement();
return true;
}
virtual void sectionEnded( SectionStats const& sectionStats ) {
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();
}
}
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
StreamingReporterBase::testCaseEnded( testCaseStats );
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
if ( m_config->showDurations() == ShowDurations::Always )
e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
m_xml.endElement();
} }
virtual void Aborted() { virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
// !TBD StreamingReporterBase::testGroupEnded( testGroupStats );
// TODO: Check testGroupStats.aborting and act accordingly.
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", testGroupStats.totals.assertions.passed )
.writeAttribute( "failures", testGroupStats.totals.assertions.failed )
.writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
m_xml.endElement();
} }
virtual void EndTestCase( const Catch::TestCaseInfo&, const Totals&, const std::string&, const std::string& ) { virtual void testRunEnded( TestRunStats const& testRunStats ) {
m_xml.scopedElement( "OverallResult" ).writeAttribute( "success", m_currentTestSuccess ); StreamingReporterBase::testRunEnded( testRunStats );
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", testRunStats.totals.assertions.passed )
.writeAttribute( "failures", testRunStats.totals.assertions.failed )
.writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
m_xml.endElement(); m_xml.endElement();
} }
private: private:
ReporterConfig m_config; Timer m_testCaseTimer;
bool m_currentTestSuccess;
XmlWriter m_xml; XmlWriter m_xml;
int m_sectionDepth; int m_sectionDepth;
}; };
INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
} // end namespace Catch } // end namespace Catch
// #included from: ../reporters/catch_reporter_junit.hpp // #included from: ../reporters/catch_reporter_junit.hpp
...@@ -7937,7 +8393,7 @@ namespace Catch { ...@@ -7937,7 +8393,7 @@ namespace Catch {
xml.writeAttribute( "classname", className ); xml.writeAttribute( "classname", className );
xml.writeAttribute( "name", name ); xml.writeAttribute( "name", name );
} }
xml.writeAttribute( "time", toString( sectionNode.stats.durationInSeconds ) ); xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
writeAssertions( sectionNode ); writeAssertions( sectionNode );
...@@ -7970,6 +8426,7 @@ namespace Catch { ...@@ -7970,6 +8426,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:
...@@ -8028,8 +8485,6 @@ namespace Catch { ...@@ -8028,8 +8485,6 @@ namespace Catch {
// #included from: ../reporters/catch_reporter_console.hpp // #included from: ../reporters/catch_reporter_console.hpp
#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
#include <cstring>
namespace Catch { namespace Catch {
struct ConsoleReporter : StreamingReporterBase { struct ConsoleReporter : StreamingReporterBase {
...@@ -8164,6 +8619,11 @@ namespace Catch { ...@@ -8164,6 +8619,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";
...@@ -8281,6 +8741,9 @@ namespace Catch { ...@@ -8281,6 +8741,9 @@ namespace Catch {
stream << " host application.\n" stream << " host application.\n"
<< "Run with -? for options\n\n"; << "Run with -? for options\n\n";
if( m_config->rngSeed() != 0 )
stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
currentTestRunInfo.used = true; currentTestRunInfo.used = true;
} }
void lazyPrintGroupInfo() { void lazyPrintGroupInfo() {
...@@ -8452,15 +8915,6 @@ namespace Catch { ...@@ -8452,15 +8915,6 @@ namespace Catch {
void printSummaryDivider() { void printSummaryDivider() {
stream << getLineOfChars<'-'>() << "\n"; stream << getLineOfChars<'-'>() << "\n";
} }
template<char C>
static char const* getLineOfChars() {
static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
if( !*line ) {
memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
}
return line;
}
private: private:
bool m_headerPrinted; bool m_headerPrinted;
...@@ -8569,6 +9023,13 @@ namespace Catch { ...@@ -8569,6 +9023,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" );
...@@ -8798,8 +9259,6 @@ namespace Catch { ...@@ -8798,8 +9259,6 @@ namespace Catch {
Matchers::Impl::StdString::EndsWith::~EndsWith() {} Matchers::Impl::StdString::EndsWith::~EndsWith() {}
void Config::dummy() {} void Config::dummy() {}
INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
} }
#ifdef __clang__ #ifdef __clang__
...@@ -8988,9 +9447,13 @@ using Catch::Detail::Approx; ...@@ -8988,9 +9447,13 @@ using Catch::Detail::Approx;
#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
#ifdef __clang__ #ifdef __clang__
#pragma clang diagnostic pop # ifdef __ICC // icpc defines the __clang__ macro
# pragma warning(pop)
# else
# pragma clang diagnostic pop
# endif
#elif defined __GNUC__ #elif defined __GNUC__
#pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif
#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment