summaryrefslogtreecommitdiff
path: root/src/catch.hpp
diff options
context:
space:
mode:
authorAndrei Karas <akaras@inbox.ru>2016-01-20 16:30:52 +0300
committerAndrei Karas <akaras@inbox.ru>2016-01-20 16:31:34 +0300
commita058af57bddd4a4394401cc75d33461e17aab8c1 (patch)
tree8f77cf6be6d271de6b4b6f340154fd6f3d2c0535 /src/catch.hpp
parent7e7109fa019b3a7ac95d2cdb139948603d541b20 (diff)
downloadplus-a058af57bddd4a4394401cc75d33461e17aab8c1.tar.gz
plus-a058af57bddd4a4394401cc75d33461e17aab8c1.tar.bz2
plus-a058af57bddd4a4394401cc75d33461e17aab8c1.tar.xz
plus-a058af57bddd4a4394401cc75d33461e17aab8c1.zip
Update catch from git.
Diffstat (limited to 'src/catch.hpp')
-rw-r--r--src/catch.hpp2615
1 files changed, 1701 insertions, 914 deletions
diff --git a/src/catch.hpp b/src/catch.hpp
index de61226cf..3b759681e 100644
--- a/src/catch.hpp
+++ b/src/catch.hpp
@@ -1,6 +1,6 @@
/*
- * Catch v1.2.1
- * Generated: 2015-06-30 18:23:27.961086
+ * Catch v1.3.2
+ * Generated: 2015-12-28 15:07:07.166291
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@@ -21,8 +21,6 @@
// #included from: internal/catch_suppress_warnings.h
-#define TWOBLUECUBES_CATCH_SUPPRESS_WARNINGS_H_INCLUDED
-
#ifdef __clang__
# ifdef __ICC // icpc defines the __clang__ macro
# pragma warning(push)
@@ -37,6 +35,7 @@
# pragma clang diagnostic ignored "-Wc++98-compat"
# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
# pragma clang diagnostic ignored "-Wswitch-enum"
+# pragma clang diagnostic ignored "-Wcovered-switch-default"
# endif
#elif defined __GNUC__
# pragma GCC diagnostic ignored "-Wvariadic-macros"
@@ -44,7 +43,6 @@
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wpadded"
#endif
-
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
# define CATCH_IMPL
#endif
@@ -84,11 +82,19 @@
// 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_LONG_LONG : is long long supported?
+// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
+// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
+// ****************
+// Note to maintainers: if new toggles are added please document them
+// in configuration.md, too
+// ****************
+
// In general each macro has a _NO_<feature name> form
// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
// Many features, at point of detection, define an _INTERNAL_ macro, so they
@@ -130,10 +136,13 @@
// GCC
#ifdef __GNUC__
-#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) )
+#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
#endif
+// - otherwise more recent versions define __cplusplus >= 201103L
+// and will get picked up below
+
#endif // __GNUC__
////////////////////////////////////////////////////////////////////////////////
@@ -142,6 +151,7 @@
#if (_MSC_VER >= 1600)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
+# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
#endif
#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
@@ -151,6 +161,8 @@
#endif // _MSC_VER
+////////////////////////////////////////////////////////////////////////////////
+
// Use variadic macros if the compiler supports them
#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
@@ -165,7 +177,7 @@
// C++ language feature support
// catch all support for C++11
-#if (__cplusplus >= 201103L)
+#if defined(__cplusplus) && __cplusplus >= 201103L
# define CATCH_CPP11_OR_GREATER
@@ -193,6 +205,17 @@
# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
# endif
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
+# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
+# endif
+
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
+# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
+# endif
+# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
+# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
+# endif
+
#endif // __cplusplus >= 201103L
// Now set the actual defines based on the above + anything the user has configured
@@ -212,7 +235,16 @@
# define CATCH_CONFIG_CPP11_TUPLE
#endif
#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
-#define CATCH_CONFIG_VARIADIC_MACROS
+# define CATCH_CONFIG_VARIADIC_MACROS
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_LONG_LONG
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_OVERRIDE
+#endif
+#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
+# define CATCH_CONFIG_CPP11_UNIQUE_PTR
#endif
// noexcept support:
@@ -224,8 +256,36 @@
# define CATCH_NOEXCEPT_IS(x)
#endif
+// nullptr support
+#ifdef CATCH_CONFIG_CPP11_NULLPTR
+# define CATCH_NULL nullptr
+#else
+# define CATCH_NULL NULL
+#endif
+
+// override support
+#ifdef CATCH_CONFIG_CPP11_OVERRIDE
+# define CATCH_OVERRIDE override
+#else
+# define CATCH_OVERRIDE
+#endif
+
+// unique_ptr support
+#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
+# define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
+#else
+# define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
+#endif
+
namespace Catch {
+ struct IConfig;
+
+ struct CaseSensitive { enum Choice {
+ Yes,
+ No
+ }; };
+
class NonCopyable {
#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
NonCopyable( NonCopyable const& ) = delete;
@@ -312,6 +372,9 @@ namespace Catch {
void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
+ void seedRng( IConfig const& config );
+ unsigned int rngSeed();
+
// Use this in variadic streaming macros to allow
// >> +StreamEndStop
// as well as
@@ -397,7 +460,7 @@ namespace Catch {
template<typename T>
class Ptr {
public:
- Ptr() : m_p( NULL ){}
+ Ptr() : m_p( CATCH_NULL ){}
Ptr( T* p ) : m_p( p ){
if( m_p )
m_p->addRef();
@@ -413,7 +476,7 @@ namespace Catch {
void reset() {
if( m_p )
m_p->release();
- m_p = NULL;
+ m_p = CATCH_NULL;
}
Ptr& operator = ( T* p ){
Ptr temp( p );
@@ -426,12 +489,11 @@ namespace Catch {
return *this;
}
void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
- T* get() { return m_p; }
- const T* get() const{ return m_p; }
+ T* get() const{ return m_p; }
T& operator*() const { return *m_p; }
T* operator->() const { return m_p; }
- bool operator !() const { return m_p == NULL; }
- operator SafeBool::type() const { return SafeBool::makeSafe( m_p != NULL ); }
+ bool operator !() const { return m_p == CATCH_NULL; }
+ operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
private:
T* m_p;
@@ -528,9 +590,13 @@ namespace Catch {
struct ITestCaseRegistry {
virtual ~ITestCaseRegistry();
virtual std::vector<TestCase> const& getAllTests() const = 0;
- virtual void getFilteredTests( TestSpec const& testSpec, IConfig const& config, std::vector<TestCase>& matchingTestCases, bool negated = false ) const = 0;
-
+ virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
};
+
+ bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
+ std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
+ std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
+
}
namespace Catch {
@@ -563,27 +629,32 @@ struct NameAndDesc {
const char* description;
};
+void registerTestCase
+ ( ITestCase* testCase,
+ char const* className,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo );
+
struct AutoReg {
- AutoReg( TestFunction function,
- SourceLineInfo const& lineInfo,
- NameAndDesc const& nameAndDesc );
+ AutoReg
+ ( TestFunction function,
+ SourceLineInfo const& lineInfo,
+ NameAndDesc const& nameAndDesc );
template<typename C>
- AutoReg( void (C::*method)(),
- char const* className,
- NameAndDesc const& nameAndDesc,
- SourceLineInfo const& lineInfo ) {
- registerTestCase( new MethodTestCase<C>( method ),
- className,
- nameAndDesc,
- lineInfo );
- }
-
- void registerTestCase( ITestCase* testCase,
- char const* className,
- NameAndDesc const& nameAndDesc,
- SourceLineInfo const& lineInfo );
+ AutoReg
+ ( void (C::*method)(),
+ char const* className,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo ) {
+
+ registerTestCase
+ ( new MethodTestCase<C>( method ),
+ className,
+ nameAndDesc,
+ lineInfo );
+ }
~AutoReg();
@@ -592,6 +663,11 @@ private:
void operator= ( AutoReg const& );
};
+void registerTestCaseFunction
+ ( TestFunction function,
+ SourceLineInfo const& lineInfo,
+ NameAndDesc const& nameAndDesc );
+
} // end namespace Catch
#ifdef CATCH_CONFIG_VARIADIC_MACROS
@@ -615,6 +691,10 @@ private:
} \
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
+ Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
+
#else
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
@@ -636,6 +716,9 @@ private:
} \
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
+ ///////////////////////////////////////////////////////////////////////////////
+ #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
+ Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
#endif
// #included from: internal/catch_capture.hpp
@@ -758,6 +841,323 @@ namespace Catch {
} // end namespace Catch
+// #included from: catch_matchers.hpp
+#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
+
+namespace Catch {
+namespace Matchers {
+ namespace Impl {
+
+ namespace Generic {
+ template<typename ExpressionT> class AllOf;
+ template<typename ExpressionT> class AnyOf;
+ template<typename ExpressionT> class Not;
+ }
+
+ template<typename ExpressionT>
+ struct Matcher : SharedImpl<IShared>
+ {
+ typedef ExpressionT ExpressionType;
+
+ virtual ~Matcher() {}
+ virtual Ptr<Matcher> clone() const = 0;
+ virtual bool match( ExpressionT const& expr ) const = 0;
+ virtual std::string toString() const = 0;
+
+ Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const;
+ Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const;
+ Generic::Not<ExpressionT> operator ! () const;
+ };
+
+ template<typename DerivedT, typename ExpressionT>
+ struct MatcherImpl : Matcher<ExpressionT> {
+
+ virtual Ptr<Matcher<ExpressionT> > clone() const {
+ return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
+ }
+ };
+
+ namespace Generic {
+ template<typename ExpressionT>
+ class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
+ public:
+ explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
+ Not( Not const& other ) : m_matcher( other.m_matcher ) {}
+
+ virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE {
+ return !m_matcher->match( expr );
+ }
+
+ virtual std::string toString() const CATCH_OVERRIDE {
+ return "not " + m_matcher->toString();
+ }
+ private:
+ Ptr< Matcher<ExpressionT> > m_matcher;
+ };
+
+ template<typename ExpressionT>
+ class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
+ public:
+
+ AllOf() {}
+ AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
+
+ AllOf& add( Matcher<ExpressionT> const& matcher ) {
+ m_matchers.push_back( matcher.clone() );
+ return *this;
+ }
+ virtual bool match( ExpressionT const& expr ) const
+ {
+ for( std::size_t i = 0; i < m_matchers.size(); ++i )
+ if( !m_matchers[i]->match( expr ) )
+ return false;
+ return true;
+ }
+ virtual std::string toString() const {
+ std::ostringstream oss;
+ oss << "( ";
+ for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+ if( i != 0 )
+ oss << " and ";
+ oss << m_matchers[i]->toString();
+ }
+ oss << " )";
+ return oss.str();
+ }
+
+ AllOf operator && ( Matcher<ExpressionT> const& other ) const {
+ AllOf allOfExpr( *this );
+ allOfExpr.add( other );
+ return allOfExpr;
+ }
+
+ private:
+ std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
+ };
+
+ template<typename ExpressionT>
+ class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
+ public:
+
+ AnyOf() {}
+ AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
+
+ AnyOf& add( Matcher<ExpressionT> const& matcher ) {
+ m_matchers.push_back( matcher.clone() );
+ return *this;
+ }
+ virtual bool match( ExpressionT const& expr ) const
+ {
+ for( std::size_t i = 0; i < m_matchers.size(); ++i )
+ if( m_matchers[i]->match( expr ) )
+ return true;
+ return false;
+ }
+ virtual std::string toString() const {
+ std::ostringstream oss;
+ oss << "( ";
+ for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
+ if( i != 0 )
+ oss << " or ";
+ oss << m_matchers[i]->toString();
+ }
+ oss << " )";
+ return oss.str();
+ }
+
+ AnyOf operator || ( Matcher<ExpressionT> const& other ) const {
+ AnyOf anyOfExpr( *this );
+ anyOfExpr.add( other );
+ return anyOfExpr;
+ }
+
+ private:
+ std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
+ };
+
+ } // namespace Generic
+
+ template<typename ExpressionT>
+ Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const {
+ Generic::AllOf<ExpressionT> allOfExpr;
+ allOfExpr.add( *this );
+ allOfExpr.add( other );
+ return allOfExpr;
+ }
+
+ template<typename ExpressionT>
+ Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const {
+ Generic::AnyOf<ExpressionT> anyOfExpr;
+ anyOfExpr.add( *this );
+ anyOfExpr.add( other );
+ return anyOfExpr;
+ }
+
+ template<typename ExpressionT>
+ Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
+ return Generic::Not<ExpressionT>( *this );
+ }
+
+ namespace StdString {
+
+ inline std::string makeString( std::string const& str ) { return str; }
+ inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
+
+ struct CasedString
+ {
+ CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
+ : m_caseSensitivity( caseSensitivity ),
+ m_str( adjustString( str ) )
+ {}
+ std::string adjustString( std::string const& str ) const {
+ return m_caseSensitivity == CaseSensitive::No
+ ? toLower( str )
+ : str;
+
+ }
+ std::string toStringSuffix() const
+ {
+ return m_caseSensitivity == CaseSensitive::No
+ ? " (case insensitive)"
+ : "";
+ }
+ CaseSensitive::Choice m_caseSensitivity;
+ std::string m_str;
+ };
+
+ struct Equals : MatcherImpl<Equals, std::string> {
+ Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
+ : m_data( str, caseSensitivity )
+ {}
+ Equals( Equals const& other ) : m_data( other.m_data ){}
+
+ virtual ~Equals();
+
+ virtual bool match( std::string const& expr ) const {
+ return m_data.m_str == m_data.adjustString( expr );;
+ }
+ virtual std::string toString() const {
+ return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
+ }
+
+ CasedString m_data;
+ };
+
+ struct Contains : MatcherImpl<Contains, std::string> {
+ Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
+ : m_data( substr, caseSensitivity ){}
+ Contains( Contains const& other ) : m_data( other.m_data ){}
+
+ virtual ~Contains();
+
+ virtual bool match( std::string const& expr ) const {
+ return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
+ }
+ virtual std::string toString() const {
+ return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
+ }
+
+ CasedString m_data;
+ };
+
+ struct StartsWith : MatcherImpl<StartsWith, std::string> {
+ StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
+ : m_data( substr, caseSensitivity ){}
+
+ StartsWith( StartsWith const& other ) : m_data( other.m_data ){}
+
+ virtual ~StartsWith();
+
+ virtual bool match( std::string const& expr ) const {
+ return m_data.adjustString( expr ).find( m_data.m_str ) == 0;
+ }
+ virtual std::string toString() const {
+ return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
+ }
+
+ CasedString m_data;
+ };
+
+ struct EndsWith : MatcherImpl<EndsWith, std::string> {
+ EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
+ : m_data( substr, caseSensitivity ){}
+ EndsWith( EndsWith const& other ) : m_data( other.m_data ){}
+
+ virtual ~EndsWith();
+
+ virtual bool match( std::string const& expr ) const {
+ return m_data.adjustString( expr ).find( m_data.m_str ) == expr.size() - m_data.m_str.size();
+ }
+ virtual std::string toString() const {
+ return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
+ }
+
+ CasedString m_data;
+ };
+ } // namespace StdString
+ } // namespace Impl
+
+ // The following functions create the actual matcher objects.
+ // This allows the types to be inferred
+ template<typename ExpressionT>
+ inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) {
+ return Impl::Generic::Not<ExpressionT>( m );
+ }
+
+ template<typename ExpressionT>
+ inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2 ) {
+ return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2,
+ Impl::Matcher<ExpressionT> const& m3 ) {
+ return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2 ) {
+ return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
+ }
+ template<typename ExpressionT>
+ inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
+ Impl::Matcher<ExpressionT> const& m2,
+ Impl::Matcher<ExpressionT> const& m3 ) {
+ return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
+ }
+
+ inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
+ return Impl::StdString::Equals( str, caseSensitivity );
+ }
+ inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
+ return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity );
+ }
+ inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
+ return Impl::StdString::Contains( substr, caseSensitivity );
+ }
+ inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
+ return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity );
+ }
+ inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
+ return Impl::StdString::StartsWith( substr );
+ }
+ inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
+ return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
+ }
+ inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
+ return Impl::StdString::EndsWith( substr );
+ }
+ inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
+ return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
+ }
+
+} // namespace Matchers
+
+using namespace Matchers;
+
+} // namespace Catch
+
namespace Catch {
struct TestFailureException{};
@@ -784,7 +1184,8 @@ namespace Catch {
ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo,
char const* capturedExpression,
- ResultDisposition::Flags resultDisposition );
+ ResultDisposition::Flags resultDisposition,
+ char const* secondArg = "" );
template<typename T>
ExpressionLhs<T const&> operator <= ( T const& operand );
@@ -813,6 +1214,9 @@ namespace Catch {
void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
void captureResult( ResultWas::OfType resultType );
void captureExpression();
+ void captureExpectedException( std::string const& expectedMessage );
+ void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher );
+ void handleResult( AssertionResult const& result );
void react();
bool shouldDebugBreak() const;
bool allowThrows() const;
@@ -991,13 +1395,51 @@ namespace Internal {
return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
}
+#ifdef CATCH_CONFIG_CPP11_LONG_LONG
+ // long long to unsigned X
+ template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
+ return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
+ }
+
+ // unsigned long long to X
+ template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
+ return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
+ return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
+ return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+ }
+ template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
+ return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
+ }
+
+ // pointer to long long (when comparing against NULL)
+ template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
+ }
+ template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
+ return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
+ }
+#endif // CATCH_CONFIG_CPP11_LONG_LONG
+
#ifdef CATCH_CONFIG_CPP11_NULLPTR
// pointer to nullptr_t (when comparing against nullptr)
template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
- return Evaluator<T*, T*, Op>::evaluate( NULL, rhs );
+ return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
}
template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
- return Evaluator<T*, T*, Op>::evaluate( lhs, NULL );
+ return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
}
#endif // CATCH_CONFIG_CPP11_NULLPTR
@@ -1095,6 +1537,11 @@ std::string toString( char value );
std::string toString( signed char value );
std::string toString( unsigned char value );
+#ifdef CATCH_CONFIG_CPP11_LONG_LONG
+std::string toString( long long value );
+std::string toString( unsigned long long value );
+#endif
+
#ifdef CATCH_CONFIG_CPP11_NULLPTR
std::string toString( std::nullptr_t );
#endif
@@ -1107,7 +1554,7 @@ std::string toString( std::nullptr_t );
namespace Detail {
- extern std::string unprintableString;
+ extern const std::string unprintableString;
struct BorgType {
template<typename T> BorgType( T const& );
@@ -1190,7 +1637,7 @@ struct StringMaker<T*> {
template<typename U>
static std::string convert( U* p ) {
if( !p )
- return INTERNAL_CATCH_STRINGIFY( NULL );
+ return "NULL";
else
return Detail::rawMemoryToString( p );
}
@@ -1200,7 +1647,7 @@ template<typename R, typename C>
struct StringMaker<R C::*> {
static std::string convert( R C::* p ) {
if( !p )
- return INTERNAL_CATCH_STRINGIFY( NULL );
+ return "NULL";
else
return Detail::rawMemoryToString( p );
}
@@ -1472,6 +1919,7 @@ namespace Catch {
class AssertionResult;
struct AssertionInfo;
struct SectionInfo;
+ struct SectionEndInfo;
struct MessageInfo;
class ScopedMessageBuilder;
struct Counts;
@@ -1483,7 +1931,8 @@ namespace Catch {
virtual void assertionEnded( AssertionResult const& result ) = 0;
virtual bool sectionStarted( SectionInfo const& sectionInfo,
Counts& assertions ) = 0;
- virtual void sectionEnded( SectionInfo const& name, Counts const& assertions, double _durationInSeconds ) = 0;
+ virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
+ virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
virtual void pushScopedMessage( MessageInfo const& message ) = 0;
virtual void popScopedMessage( MessageInfo const& message ) = 0;
@@ -1604,16 +2053,16 @@ namespace Catch {
} while( Catch::alwaysFalse() )
///////////////////////////////////////////////////////////////////////////////
-#define INTERNAL_CATCH_THROWS( expr, resultDisposition, macroName ) \
+#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
do { \
- Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
if( __catchResult.allowThrows() ) \
try { \
expr; \
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
} \
catch( ... ) { \
- __catchResult.captureResult( Catch::ResultWas::Ok ); \
+ __catchResult.captureExpectedException( matcher ); \
} \
else \
__catchResult.captureResult( Catch::ResultWas::Ok ); \
@@ -1666,14 +2115,14 @@ namespace Catch {
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
do { \
- Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
+ Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
try { \
- std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
+ std::string matcherAsString = (matcher).toString(); \
__catchResult \
.setLhs( Catch::toString( arg ) ) \
.setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
.setOp( "matches" ) \
- .setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
+ .setResultType( (matcher).match( arg ) ); \
__catchResult.captureExpression(); \
} catch( ... ) { \
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
@@ -1687,21 +2136,6 @@ namespace Catch {
// #included from: catch_section_info.h
#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
-namespace Catch {
-
- struct SectionInfo {
- SectionInfo
- ( SourceLineInfo const& _lineInfo,
- std::string const& _name,
- std::string const& _description = std::string() );
-
- std::string name;
- std::string description;
- SourceLineInfo lineInfo;
- };
-
-} // end namespace Catch
-
// #included from: catch_totals.hpp
#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
@@ -1772,6 +2206,31 @@ namespace Catch {
};
}
+namespace Catch {
+
+ struct SectionInfo {
+ SectionInfo
+ ( SourceLineInfo const& _lineInfo,
+ std::string const& _name,
+ std::string const& _description = std::string() );
+
+ std::string name;
+ std::string description;
+ SourceLineInfo lineInfo;
+ };
+
+ struct SectionEndInfo {
+ SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
+ : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
+ {}
+
+ SectionInfo sectionInfo;
+ Counts prevAssertions;
+ double durationInSeconds;
+ };
+
+} // end namespace Catch
+
// #included from: catch_timer.h
#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
@@ -2012,6 +2471,8 @@ using namespace Generators;
#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
#include <string>
+#include <vector>
+
// #included from: catch_interfaces_registry_hub.h
#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
@@ -2036,7 +2497,8 @@ namespace Catch {
struct IMutableRegistryHub {
virtual ~IMutableRegistryHub();
- virtual void registerReporter( std::string const& name, IReporterFactory* factory ) = 0;
+ virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
+ virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
virtual void registerTest( TestCase const& testInfo ) = 0;
virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
};
@@ -2048,14 +2510,16 @@ namespace Catch {
}
-
namespace Catch {
typedef std::string(*exceptionTranslateFunction)();
+ struct IExceptionTranslator;
+ typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
+
struct IExceptionTranslator {
virtual ~IExceptionTranslator();
- virtual std::string translate() const = 0;
+ virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
};
struct IExceptionTranslatorRegistry {
@@ -2073,9 +2537,12 @@ namespace Catch {
: m_translateFunction( translateFunction )
{}
- virtual std::string translate() const {
+ virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
try {
- throw;
+ if( it == itEnd )
+ throw;
+ else
+ return (*it)->translate( it+1, itEnd );
}
catch( T& ex ) {
return m_translateFunction( ex );
@@ -2182,231 +2649,6 @@ inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
} // end namespace Catch
-// #included from: internal/catch_matchers.hpp
-#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
-
-namespace Catch {
-namespace Matchers {
- namespace Impl {
-
- template<typename ExpressionT>
- struct Matcher : SharedImpl<IShared>
- {
- typedef ExpressionT ExpressionType;
-
- virtual ~Matcher() {}
- virtual Ptr<Matcher> clone() const = 0;
- virtual bool match( ExpressionT const& expr ) const = 0;
- virtual std::string toString() const = 0;
- };
-
- template<typename DerivedT, typename ExpressionT>
- struct MatcherImpl : Matcher<ExpressionT> {
-
- virtual Ptr<Matcher<ExpressionT> > clone() const {
- return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
- }
- };
-
- namespace Generic {
-
- template<typename ExpressionT>
- class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
- public:
-
- AllOf() {}
- AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
-
- AllOf& add( Matcher<ExpressionT> const& matcher ) {
- m_matchers.push_back( matcher.clone() );
- return *this;
- }
- virtual bool match( ExpressionT const& expr ) const
- {
- for( std::size_t i = 0; i < m_matchers.size(); ++i )
- if( !m_matchers[i]->match( expr ) )
- return false;
- return true;
- }
- virtual std::string toString() const {
- std::ostringstream oss;
- oss << "( ";
- for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
- if( i != 0 )
- oss << " and ";
- oss << m_matchers[i]->toString();
- }
- oss << " )";
- return oss.str();
- }
-
- private:
- std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
- };
-
- template<typename ExpressionT>
- class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
- public:
-
- AnyOf() {}
- AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
-
- AnyOf& add( Matcher<ExpressionT> const& matcher ) {
- m_matchers.push_back( matcher.clone() );
- return *this;
- }
- virtual bool match( ExpressionT const& expr ) const
- {
- for( std::size_t i = 0; i < m_matchers.size(); ++i )
- if( m_matchers[i]->match( expr ) )
- return true;
- return false;
- }
- virtual std::string toString() const {
- std::ostringstream oss;
- oss << "( ";
- for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
- if( i != 0 )
- oss << " or ";
- oss << m_matchers[i]->toString();
- }
- oss << " )";
- return oss.str();
- }
-
- private:
- std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
- };
-
- }
-
- namespace StdString {
-
- inline std::string makeString( std::string const& str ) { return str; }
- inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
-
- struct Equals : MatcherImpl<Equals, std::string> {
- Equals( std::string const& str ) : m_str( str ){}
- Equals( Equals const& other ) : m_str( other.m_str ){}
-
- virtual ~Equals();
-
- virtual bool match( std::string const& expr ) const {
- return m_str == expr;
- }
- virtual std::string toString() const {
- return "equals: \"" + m_str + "\"";
- }
-
- std::string m_str;
- };
-
- struct Contains : MatcherImpl<Contains, std::string> {
- Contains( std::string const& substr ) : m_substr( substr ){}
- Contains( Contains const& other ) : m_substr( other.m_substr ){}
-
- virtual ~Contains();
-
- virtual bool match( std::string const& expr ) const {
- return expr.find( m_substr ) != std::string::npos;
- }
- virtual std::string toString() const {
- return "contains: \"" + m_substr + "\"";
- }
-
- std::string m_substr;
- };
-
- struct StartsWith : MatcherImpl<StartsWith, std::string> {
- StartsWith( std::string const& substr ) : m_substr( substr ){}
- StartsWith( StartsWith const& other ) : m_substr( other.m_substr ){}
-
- virtual ~StartsWith();
-
- virtual bool match( std::string const& expr ) const {
- return expr.find( m_substr ) == 0;
- }
- virtual std::string toString() const {
- return "starts with: \"" + m_substr + "\"";
- }
-
- std::string m_substr;
- };
-
- struct EndsWith : MatcherImpl<EndsWith, std::string> {
- EndsWith( std::string const& substr ) : m_substr( substr ){}
- EndsWith( EndsWith const& other ) : m_substr( other.m_substr ){}
-
- virtual ~EndsWith();
-
- virtual bool match( std::string const& expr ) const {
- return expr.find( m_substr ) == expr.size() - m_substr.size();
- }
- virtual std::string toString() const {
- return "ends with: \"" + m_substr + "\"";
- }
-
- std::string m_substr;
- };
- } // namespace StdString
- } // namespace Impl
-
- // The following functions create the actual matcher objects.
- // This allows the types to be inferred
- template<typename ExpressionT>
- inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
- Impl::Matcher<ExpressionT> const& m2 ) {
- return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
- }
- template<typename ExpressionT>
- inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
- Impl::Matcher<ExpressionT> const& m2,
- Impl::Matcher<ExpressionT> const& m3 ) {
- return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
- }
- template<typename ExpressionT>
- inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
- Impl::Matcher<ExpressionT> const& m2 ) {
- return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
- }
- template<typename ExpressionT>
- inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
- Impl::Matcher<ExpressionT> const& m2,
- Impl::Matcher<ExpressionT> const& m3 ) {
- return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
- }
-
- inline Impl::StdString::Equals Equals( std::string const& str ) {
- return Impl::StdString::Equals( str );
- }
- inline Impl::StdString::Equals Equals( const char* str ) {
- return Impl::StdString::Equals( Impl::StdString::makeString( str ) );
- }
- inline Impl::StdString::Contains Contains( std::string const& substr ) {
- return Impl::StdString::Contains( substr );
- }
- inline Impl::StdString::Contains Contains( const char* substr ) {
- return Impl::StdString::Contains( Impl::StdString::makeString( substr ) );
- }
- inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
- return Impl::StdString::StartsWith( substr );
- }
- inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
- return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
- }
- inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
- return Impl::StdString::EndsWith( substr );
- }
- inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
- return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
- }
-
-} // namespace Matchers
-
-using namespace Matchers;
-
-} // namespace Catch
-
// #included from: internal/catch_interfaces_tag_alias_registry.h
#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
@@ -2440,12 +2682,12 @@ namespace Catch {
template<typename T>
class Option {
public:
- Option() : nullableValue( NULL ) {}
+ Option() : nullableValue( CATCH_NULL ) {}
Option( T const& _value )
: nullableValue( new( storage ) T( _value ) )
{}
Option( Option const& _other )
- : nullableValue( _other ? new( storage ) T( *_other ) : NULL )
+ : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
{}
~Option() {
@@ -2469,7 +2711,7 @@ namespace Catch {
void reset() {
if( nullableValue )
nullableValue->~T();
- nullableValue = NULL;
+ nullableValue = CATCH_NULL;
}
T& operator*() { return *nullableValue; }
@@ -2481,10 +2723,10 @@ namespace Catch {
return nullableValue ? *nullableValue : defaultValue;
}
- bool some() const { return nullableValue != NULL; }
- bool none() const { return nullableValue == NULL; }
+ bool some() const { return nullableValue != CATCH_NULL; }
+ bool none() const { return nullableValue == CATCH_NULL; }
- bool operator !() const { return nullableValue == NULL; }
+ bool operator !() const { return nullableValue == CATCH_NULL; }
operator SafeBool::type() const {
return SafeBool::makeSafe( some() );
}
@@ -2542,6 +2784,8 @@ namespace Catch {
TestCaseInfo( TestCaseInfo const& other );
+ friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
+
bool isHidden() const;
bool throws() const;
bool okToFail() const;
@@ -2654,7 +2898,7 @@ namespace Catch {
inline size_t registerTestMethods() {
size_t noTestMethods = 0;
- int noClasses = objc_getClassList( NULL, 0 );
+ int noClasses = objc_getClassList( CATCH_NULL, 0 );
Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
objc_getClassList( classes, noClasses );
@@ -2796,7 +3040,7 @@ return @ desc; \
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
-// #included from: ../catch_runner.hpp
+// #included from: ../catch_session.hpp
#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
// #included from: internal/catch_commandline.hpp
@@ -2821,6 +3065,67 @@ return @ desc; \
#pragma clang diagnostic ignored "-Wpadded"
#endif
+// #included from: catch_wildcard_pattern.hpp
+#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
+
+namespace Catch
+{
+ class WildcardPattern {
+ enum WildcardPosition {
+ NoWildcard = 0,
+ WildcardAtStart = 1,
+ WildcardAtEnd = 2,
+ WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
+ };
+
+ public:
+
+ WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
+ : m_caseSensitivity( caseSensitivity ),
+ m_wildcard( NoWildcard ),
+ m_pattern( adjustCase( pattern ) )
+ {
+ if( startsWith( m_pattern, "*" ) ) {
+ m_pattern = m_pattern.substr( 1 );
+ m_wildcard = WildcardAtStart;
+ }
+ if( endsWith( m_pattern, "*" ) ) {
+ m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
+ m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
+ }
+ }
+ virtual ~WildcardPattern();
+ virtual bool matches( std::string const& str ) const {
+ switch( m_wildcard ) {
+ case NoWildcard:
+ return m_pattern == adjustCase( str );
+ case WildcardAtStart:
+ return endsWith( adjustCase( str ), m_pattern );
+ case WildcardAtEnd:
+ return startsWith( adjustCase( str ), m_pattern );
+ case WildcardAtBothEnds:
+ return contains( adjustCase( str ), m_pattern );
+ }
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunreachable-code"
+#endif
+ throw std::logic_error( "Unknown enum" );
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+ }
+ private:
+ std::string adjustCase( std::string const& str ) const {
+ return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
+ }
+ CaseSensitive::Choice m_caseSensitivity;
+ WildcardPosition m_wildcard;
+ std::string m_pattern;
+ };
+}
+
#include <string>
#include <vector>
@@ -2832,50 +3137,18 @@ namespace Catch {
virtual bool matches( TestCaseInfo const& testCase ) const = 0;
};
class NamePattern : public Pattern {
- enum WildcardPosition {
- NoWildcard = 0,
- WildcardAtStart = 1,
- WildcardAtEnd = 2,
- WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
- };
-
public:
- NamePattern( std::string const& name ) : m_name( toLower( name ) ), m_wildcard( NoWildcard ) {
- if( startsWith( m_name, "*" ) ) {
- m_name = m_name.substr( 1 );
- m_wildcard = WildcardAtStart;
- }
- if( endsWith( m_name, "*" ) ) {
- m_name = m_name.substr( 0, m_name.size()-1 );
- m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
- }
- }
+ NamePattern( std::string const& name )
+ : m_wildcardPattern( toLower( name ), CaseSensitive::No )
+ {}
virtual ~NamePattern();
virtual bool matches( TestCaseInfo const& testCase ) const {
- switch( m_wildcard ) {
- case NoWildcard:
- return m_name == toLower( testCase.name );
- case WildcardAtStart:
- return endsWith( toLower( testCase.name ), m_name );
- case WildcardAtEnd:
- return startsWith( toLower( testCase.name ), m_name );
- case WildcardAtBothEnds:
- return contains( toLower( testCase.name ), m_name );
- }
-
-#ifdef __clang__
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunreachable-code"
-#endif
- throw std::logic_error( "Unknown enum" );
-#ifdef __clang__
-#pragma clang diagnostic pop
-#endif
+ return m_wildcardPattern.matches( toLower( testCase.name ) );
}
private:
- std::string m_name;
- WildcardPosition m_wildcard;
+ WildcardPattern m_wildcardPattern;
};
+
class TagPattern : public Pattern {
public:
TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
@@ -2886,6 +3159,7 @@ namespace Catch {
private:
std::string m_tag;
};
+
class ExcludedPattern : public Pattern {
public:
ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
@@ -3083,28 +3357,62 @@ namespace Catch {
// #included from: catch_stream.h
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
-#include <streambuf>
+// #included from: catch_streambuf.h
+#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
-#ifdef __clang__
-#pragma clang diagnostic ignored "-Wpadded"
-#endif
+#include <streambuf>
namespace Catch {
- class Stream {
+ class StreamBufBase : public std::streambuf {
public:
- Stream();
- Stream( std::streambuf* _streamBuf, bool _isOwned );
- void release();
+ virtual ~StreamBufBase() CATCH_NOEXCEPT;
+ };
+}
- std::streambuf* streamBuf;
+#include <streambuf>
+#include <ostream>
+#include <fstream>
- private:
- bool isOwned;
- };
+namespace Catch {
std::ostream& cout();
std::ostream& cerr();
+
+ struct IStream {
+ virtual ~IStream() CATCH_NOEXCEPT;
+ virtual std::ostream& stream() const = 0;
+ };
+
+ class FileStream : public IStream {
+ mutable std::ofstream m_ofs;
+ public:
+ FileStream( std::string const& filename );
+ virtual ~FileStream() CATCH_NOEXCEPT;
+ public: // IStream
+ virtual std::ostream& stream() const CATCH_OVERRIDE;
+ };
+
+ class CoutStream : public IStream {
+ mutable std::ostream m_os;
+ public:
+ CoutStream();
+ virtual ~CoutStream() CATCH_NOEXCEPT;
+
+ public: // IStream
+ virtual std::ostream& stream() const CATCH_OVERRIDE;
+ };
+
+ class DebugOutStream : public IStream {
+ std::auto_ptr<StreamBufBase> m_streamBuf;
+ mutable std::ostream m_os;
+ public:
+ DebugOutStream();
+ virtual ~DebugOutStream() CATCH_NOEXCEPT;
+
+ public: // IStream
+ virtual std::ostream& stream() const CATCH_OVERRIDE;
+ };
}
#include <memory>
@@ -3132,6 +3440,7 @@ namespace Catch {
showHelp( false ),
showInvisibles( false ),
forceColour( false ),
+ filenamesAsTags( false ),
abortAfter( -1 ),
rngSeed( 0 ),
verbosity( Verbosity::Normal ),
@@ -3151,6 +3460,7 @@ namespace Catch {
bool showHelp;
bool showInvisibles;
bool forceColour;
+ bool filenamesAsTags;
int abortAfter;
unsigned int rngSeed;
@@ -3160,11 +3470,11 @@ namespace Catch {
ShowDurations::OrNot showDurations;
RunTests::InWhatOrder runOrder;
- std::string reporterName;
std::string outputFilename;
std::string name;
std::string processName;
+ std::vector<std::string> reporterNames;
std::vector<std::string> testsOrTags;
};
@@ -3176,12 +3486,11 @@ namespace Catch {
public:
Config()
- : m_os( Catch::cout().rdbuf() )
{}
Config( ConfigData const& data )
: m_data( data ),
- m_os( Catch::cout().rdbuf() )
+ m_stream( openStream() )
{
if( !data.testsOrTags.empty() ) {
TestSpecParser parser( ITagAliasRegistry::get() );
@@ -3192,12 +3501,6 @@ namespace Catch {
}
virtual ~Config() {
- m_os.rdbuf( Catch::cout().rdbuf() );
- m_stream.release();
- }
-
- void setFilename( std::string const& filename ) {
- m_data.outputFilename = filename;
}
std::string const& getFilename() const {
@@ -3213,18 +3516,7 @@ namespace Catch {
bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
- void setStreamBuf( std::streambuf* buf ) {
- m_os.rdbuf( buf ? buf : Catch::cout().rdbuf() );
- }
-
- void useStream( std::string const& streamName ) {
- Stream stream = createStream( streamName );
- setStreamBuf( stream.streamBuf );
- m_stream.release();
- m_stream = stream;
- }
-
- std::string getReporterName() const { return m_data.reporterName; }
+ std::vector<std::string> getReporterNames() const { return m_data.reporterNames; }
int abortAfter() const { return m_data.abortAfter; }
@@ -3235,7 +3527,7 @@ namespace Catch {
// IConfig interface
virtual bool allowThrows() const { return !m_data.noThrow; }
- virtual std::ostream& stream() const { return m_os; }
+ virtual std::ostream& stream() const { return m_stream->stream(); }
virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
@@ -3245,10 +3537,22 @@ namespace Catch {
virtual bool forceColour() const { return m_data.forceColour; }
private:
+
+ IStream const* openStream() {
+ if( m_data.outputFilename.empty() )
+ return new CoutStream();
+ else if( m_data.outputFilename[0] == '%' ) {
+ if( m_data.outputFilename == "%debug" )
+ return new DebugOutStream();
+ else
+ throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
+ }
+ else
+ return new FileStream( m_data.outputFilename );
+ }
ConfigData m_data;
- Stream m_stream;
- mutable std::ostream m_os;
+ std::auto_ptr<IStream const> m_stream;
TestSpec m_testSpec;
};
@@ -3517,11 +3821,11 @@ namespace Clara {
template<typename ConfigT>
class BoundArgFunction {
public:
- BoundArgFunction() : functionObj( NULL ) {}
+ BoundArgFunction() : functionObj( CATCH_NULL ) {}
BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
- BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : NULL ) {}
+ BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CATCH_NULL ) {}
BoundArgFunction& operator = ( BoundArgFunction const& other ) {
- IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : NULL;
+ IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CATCH_NULL;
delete functionObj;
functionObj = newFunctionObj;
return *this;
@@ -3537,7 +3841,7 @@ namespace Clara {
bool takesArg() const { return functionObj->takesArg(); }
bool isSet() const {
- return functionObj != NULL;
+ return functionObj != CATCH_NULL;
}
private:
IArgFunction<ConfigT>* functionObj;
@@ -3755,12 +4059,7 @@ namespace Clara {
}
};
- // NOTE: std::auto_ptr is deprecated in c++11/c++0x
-#if defined(__cplusplus) && __cplusplus > 199711L
- typedef std::unique_ptr<Arg> ArgAutoPtr;
-#else
- typedef std::auto_ptr<Arg> ArgAutoPtr;
-#endif
+ typedef CATCH_AUTO_PTR( Arg ) ArgAutoPtr;
friend void addOptName( Arg& arg, std::string const& optName )
{
@@ -3836,8 +4135,8 @@ namespace Clara {
m_arg->description = description;
return *this;
}
- ArgBuilder& detail( std::string const& detail ) {
- m_arg->detail = detail;
+ ArgBuilder& detail( std::string const& _detail ) {
+ m_arg->detail = _detail;
return *this;
}
@@ -3920,14 +4219,14 @@ namespace Clara {
maxWidth = (std::max)( maxWidth, it->commands().size() );
for( it = itBegin; it != itEnd; ++it ) {
- Detail::Text usage( it->commands(), Detail::TextAttributes()
+ Detail::Text usageText( it->commands(), Detail::TextAttributes()
.setWidth( maxWidth+indent )
.setIndent( indent ) );
Detail::Text desc( it->description, Detail::TextAttributes()
.setWidth( width - maxWidth - 3 ) );
- for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
- std::string usageCol = i < usage.size() ? usage[i] : "";
+ for( std::size_t i = 0; i < (std::max)( usageText.size(), desc.size() ); ++i ) {
+ std::string usageCol = i < usageText.size() ? usageText[i] : "";
os << usageCol;
if( i < desc.size() && !desc[i].empty() )
@@ -4133,6 +4432,7 @@ namespace Catch {
config.abortAfter = x;
}
inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
+ inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
inline void addWarning( ConfigData& config, std::string const& _warning ) {
if( _warning == "NoAssertions" )
@@ -4226,7 +4526,7 @@ namespace Catch {
cli["-r"]["--reporter"]
// .placeholder( "name[:filename]" )
.describe( "reporter to use (defaults to console)" )
- .bind( &ConfigData::reporterName, "name" );
+ .bind( &addReporterName, "name" );
cli["-n"]["--name"]
.describe( "suite name" )
@@ -4263,6 +4563,10 @@ namespace Catch {
.describe( "load test names to run from a file" )
.bind( &loadTestNamesFromFile, "filename" );
+ cli["-#"]["--filenames-as-tags"]
+ .describe( "adds a tag for the filename" )
+ .bind( &ConfigData::filenamesAsTags );
+
// Less common commands which don't have a short form
cli["--list-test-names-only"]
.describe( "list all/matching test cases names only" )
@@ -4520,18 +4824,18 @@ namespace Catch {
namespace Catch
{
struct ReporterConfig {
- explicit ReporterConfig( Ptr<IConfig> const& _fullConfig )
+ explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
: m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
- ReporterConfig( Ptr<IConfig> const& _fullConfig, std::ostream& _stream )
+ ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
: m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
std::ostream& stream() const { return *m_stream; }
- Ptr<IConfig> fullConfig() const { return m_fullConfig; }
+ Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
private:
std::ostream* m_stream;
- Ptr<IConfig> m_fullConfig;
+ Ptr<IConfig const> m_fullConfig;
};
struct ReporterPreferences {
@@ -4733,6 +5037,7 @@ namespace Catch
// The return value indicates if the messages buffer should be cleared:
virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
+
virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
@@ -4741,20 +5046,24 @@ namespace Catch
virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
};
- struct IReporterFactory {
+ struct IReporterFactory : IShared {
virtual ~IReporterFactory();
virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
virtual std::string getDescription() const = 0;
};
struct IReporterRegistry {
- typedef std::map<std::string, IReporterFactory*> FactoryMap;
+ typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
+ typedef std::vector<Ptr<IReporterFactory> > Listeners;
virtual ~IReporterRegistry();
- virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const = 0;
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
virtual FactoryMap const& getFactories() const = 0;
+ virtual Listeners const& getListeners() const = 0;
};
+ Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
+
}
#include <limits>
@@ -4777,8 +5086,7 @@ namespace Catch {
nameAttr.setInitialIndent( 2 ).setIndent( 4 );
tagsAttr.setIndent( 6 );
- std::vector<TestCase> matchedTestCases;
- getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
it != itEnd;
++it ) {
@@ -4806,8 +5114,7 @@ namespace Catch {
if( !config.testSpec().hasFilters() )
testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
std::size_t matchedTests = 0;
- std::vector<TestCase> matchedTestCases;
- getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
it != itEnd;
++it ) {
@@ -4847,8 +5154,7 @@ namespace Catch {
std::map<std::string, TagInfo> tagCounts;
- std::vector<TestCase> matchedTestCases;
- getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, config, matchedTestCases );
+ std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
it != itEnd;
++it ) {
@@ -4919,7 +5225,7 @@ namespace Catch {
} // end namespace Catch
-// #included from: internal/catch_runner_impl.hpp
+// #included from: internal/catch_run_context.hpp
#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
// #included from: catch_test_case_tracker.hpp
@@ -4928,137 +5234,300 @@ namespace Catch {
#include <map>
#include <string>
#include <assert.h>
+#include <vector>
namespace Catch {
-namespace SectionTracking {
+namespace TestCaseTracking {
- class TrackedSection {
+ struct ITracker : SharedImpl<> {
+ virtual ~ITracker();
- typedef std::map<std::string, TrackedSection> TrackedSections;
+ // static queries
+ virtual std::string name() const = 0;
+
+ // dynamic queries
+ virtual bool isComplete() const = 0; // Successfully completed or failed
+ virtual bool isSuccessfullyCompleted() const = 0;
+ virtual bool isOpen() const = 0; // Started but not complete
+ virtual bool hasChildren() const = 0;
+
+ virtual ITracker& parent() = 0;
+
+ // actions
+ virtual void close() = 0; // Successfully complete
+ virtual void fail() = 0;
+ virtual void markAsNeedingAnotherRun() = 0;
+
+ virtual void addChild( Ptr<ITracker> const& child ) = 0;
+ virtual ITracker* findChild( std::string const& name ) = 0;
+ virtual void openChild() = 0;
+ };
+
+ class TrackerContext {
- public:
enum RunState {
NotStarted,
Executing,
- ExecutingChildren,
- Completed
+ CompletedCycle
};
- TrackedSection( std::string const& name, TrackedSection* parent )
- : m_name( name ), m_runState( NotStarted ), m_parent( parent )
- {}
+ Ptr<ITracker> m_rootTracker;
+ ITracker* m_currentTracker;
+ RunState m_runState;
- RunState runState() const { return m_runState; }
+ public:
- TrackedSection* findChild( std::string const& childName );
- TrackedSection* acquireChild( std::string const& childName );
+ static TrackerContext& instance() {
+ static TrackerContext s_instance;
+ return s_instance;
+ }
- void enter() {
- if( m_runState == NotStarted )
- m_runState = Executing;
+ TrackerContext()
+ : m_currentTracker( CATCH_NULL ),
+ m_runState( NotStarted )
+ {}
+
+ ITracker& startRun();
+
+ void endRun() {
+ m_rootTracker.reset();
+ m_currentTracker = CATCH_NULL;
+ m_runState = NotStarted;
}
- void leave();
- TrackedSection* getParent() {
- return m_parent;
+ void startCycle() {
+ m_currentTracker = m_rootTracker.get();
+ m_runState = Executing;
}
- bool hasChildren() const {
- return !m_children.empty();
+ void completeCycle() {
+ m_runState = CompletedCycle;
}
- private:
- std::string m_name;
- RunState m_runState;
- TrackedSections m_children;
- TrackedSection* m_parent;
+ bool completedCycle() const {
+ return m_runState == CompletedCycle;
+ }
+ ITracker& currentTracker() {
+ return *m_currentTracker;
+ }
+ void setCurrentTracker( ITracker* tracker ) {
+ m_currentTracker = tracker;
+ }
};
- inline TrackedSection* TrackedSection::findChild( std::string const& childName ) {
- TrackedSections::iterator it = m_children.find( childName );
- return it != m_children.end()
- ? &it->second
- : NULL;
- }
- inline TrackedSection* TrackedSection::acquireChild( std::string const& childName ) {
- if( TrackedSection* child = findChild( childName ) )
- return child;
- m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
- return findChild( childName );
- }
- inline void TrackedSection::leave() {
- for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
- it != itEnd;
- ++it )
- if( it->second.runState() != Completed ) {
- m_runState = ExecutingChildren;
- return;
+ class TrackerBase : public ITracker {
+ protected:
+ enum CycleState {
+ NotStarted,
+ Executing,
+ ExecutingChildren,
+ NeedsAnotherRun,
+ CompletedSuccessfully,
+ Failed
+ };
+ class TrackerHasName {
+ std::string m_name;
+ public:
+ TrackerHasName( std::string const& name ) : m_name( name ) {}
+ bool operator ()( Ptr<ITracker> const& tracker ) {
+ return tracker->name() == m_name;
}
- m_runState = Completed;
- }
-
- class TestCaseTracker {
+ };
+ typedef std::vector<Ptr<ITracker> > Children;
+ std::string m_name;
+ TrackerContext& m_ctx;
+ ITracker* m_parent;
+ Children m_children;
+ CycleState m_runState;
public:
- TestCaseTracker( std::string const& testCaseName )
- : m_testCase( testCaseName, NULL ),
- m_currentSection( &m_testCase ),
- m_completedASectionThisRun( false )
+ TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent )
+ : m_name( name ),
+ m_ctx( ctx ),
+ m_parent( parent ),
+ m_runState( NotStarted )
{}
+ virtual ~TrackerBase();
- bool enterSection( std::string const& name ) {
- TrackedSection* child = m_currentSection->acquireChild( name );
- if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )
- return false;
+ virtual std::string name() const CATCH_OVERRIDE {
+ return m_name;
+ }
+ virtual bool isComplete() const CATCH_OVERRIDE {
+ return m_runState == CompletedSuccessfully || m_runState == Failed;
+ }
+ virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
+ return m_runState == CompletedSuccessfully;
+ }
+ virtual bool isOpen() const CATCH_OVERRIDE {
+ return m_runState != NotStarted && !isComplete();
+ }
+ virtual bool hasChildren() const CATCH_OVERRIDE {
+ return !m_children.empty();
+ }
- m_currentSection = child;
- m_currentSection->enter();
- return true;
+ virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
+ m_children.push_back( child );
+ }
+
+ virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE {
+ Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) );
+ return( it != m_children.end() )
+ ? it->get()
+ : CATCH_NULL;
}
- void leaveSection() {
- m_currentSection->leave();
- m_currentSection = m_currentSection->getParent();
- assert( m_currentSection != NULL );
- m_completedASectionThisRun = true;
+ virtual ITracker& parent() CATCH_OVERRIDE {
+ assert( m_parent ); // Should always be non-null except for root
+ return *m_parent;
}
- bool currentSectionHasChildren() const {
- return m_currentSection->hasChildren();
+ virtual void openChild() CATCH_OVERRIDE {
+ if( m_runState != ExecutingChildren ) {
+ m_runState = ExecutingChildren;
+ if( m_parent )
+ m_parent->openChild();
+ }
}
- bool isCompleted() const {
- return m_testCase.runState() == TrackedSection::Completed;
+ void open() {
+ m_runState = Executing;
+ moveToThis();
+ if( m_parent )
+ m_parent->openChild();
}
- class Guard {
- public:
- Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {
- m_tracker.enterTestCase();
+ virtual void close() CATCH_OVERRIDE {
+
+ // Close any still open children (e.g. generators)
+ while( &m_ctx.currentTracker() != this )
+ m_ctx.currentTracker().close();
+
+ switch( m_runState ) {
+ case NotStarted:
+ case CompletedSuccessfully:
+ case Failed:
+ throw std::logic_error( "Illogical state" );
+
+ case NeedsAnotherRun:
+ break;;
+
+ case Executing:
+ m_runState = CompletedSuccessfully;
+ break;
+ case ExecutingChildren:
+ if( m_children.empty() || m_children.back()->isComplete() )
+ m_runState = CompletedSuccessfully;
+ break;
+
+ default:
+ throw std::logic_error( "Unexpected state" );
+ }
+ moveToParent();
+ m_ctx.completeCycle();
+ }
+ virtual void fail() CATCH_OVERRIDE {
+ m_runState = Failed;
+ if( m_parent )
+ m_parent->markAsNeedingAnotherRun();
+ moveToParent();
+ m_ctx.completeCycle();
+ }
+ virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
+ m_runState = NeedsAnotherRun;
+ }
+ private:
+ void moveToParent() {
+ assert( m_parent );
+ m_ctx.setCurrentTracker( m_parent );
+ }
+ void moveToThis() {
+ m_ctx.setCurrentTracker( this );
+ }
+ };
+
+ class SectionTracker : public TrackerBase {
+ public:
+ SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent )
+ : TrackerBase( name, ctx, parent )
+ {}
+ virtual ~SectionTracker();
+
+ static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) {
+ SectionTracker* section = CATCH_NULL;
+
+ ITracker& currentTracker = ctx.currentTracker();
+ if( ITracker* childTracker = currentTracker.findChild( name ) ) {
+ section = dynamic_cast<SectionTracker*>( childTracker );
+ assert( section );
}
- ~Guard() {
- m_tracker.leaveTestCase();
+ else {
+ section = new SectionTracker( name, ctx, &currentTracker );
+ currentTracker.addChild( section );
}
- private:
- Guard( Guard const& );
- void operator = ( Guard const& );
- TestCaseTracker& m_tracker;
- };
+ if( !ctx.completedCycle() && !section->isComplete() ) {
- private:
- void enterTestCase() {
- m_currentSection = &m_testCase;
- m_completedASectionThisRun = false;
- m_testCase.enter();
+ section->open();
+ }
+ return *section;
+ }
+ };
+
+ class IndexTracker : public TrackerBase {
+ int m_size;
+ int m_index;
+ public:
+ IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size )
+ : TrackerBase( name, ctx, parent ),
+ m_size( size ),
+ m_index( -1 )
+ {}
+ virtual ~IndexTracker();
+
+ static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) {
+ IndexTracker* tracker = CATCH_NULL;
+
+ ITracker& currentTracker = ctx.currentTracker();
+ if( ITracker* childTracker = currentTracker.findChild( name ) ) {
+ tracker = dynamic_cast<IndexTracker*>( childTracker );
+ assert( tracker );
+ }
+ else {
+ tracker = new IndexTracker( name, ctx, &currentTracker, size );
+ currentTracker.addChild( tracker );
+ }
+
+ if( !ctx.completedCycle() && !tracker->isComplete() ) {
+ if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
+ tracker->moveNext();
+ tracker->open();
+ }
+
+ return *tracker;
}
- void leaveTestCase() {
- m_testCase.leave();
+
+ int index() const { return m_index; }
+
+ void moveNext() {
+ m_index++;
+ m_children.clear();
}
- TrackedSection m_testCase;
- TrackedSection* m_currentSection;
- bool m_completedASectionThisRun;
+ virtual void close() CATCH_OVERRIDE {
+ TrackerBase::close();
+ if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
+ m_runState = Executing;
+ }
};
-} // namespace SectionTracking
+ inline ITracker& TrackerContext::startRun() {
+ m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL );
+ m_currentTracker = CATCH_NULL;
+ m_runState = Executing;
+ return *m_rootTracker;
+ }
+
+} // namespace TestCaseTracking
-using SectionTracking::TestCaseTracker;
+using TestCaseTracking::ITracker;
+using TestCaseTracking::TrackerContext;
+using TestCaseTracking::SectionTracker;
+using TestCaseTracking::IndexTracker;
} // namespace Catch
@@ -5174,15 +5643,12 @@ namespace Catch {
public:
- explicit RunContext( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> const& reporter )
- : m_runInfo( config->name() ),
+ explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
+ : m_runInfo( _config->name() ),
m_context( getCurrentMutableContext() ),
- m_activeTestCase( NULL ),
- m_config( config ),
- m_reporter( reporter ),
- m_prevRunner( m_context.getRunner() ),
- m_prevResultCapture( m_context.getResultCapture() ),
- m_prevConfig( m_context.getConfig() )
+ m_activeTestCase( CATCH_NULL ),
+ m_config( _config ),
+ m_reporter( reporter )
{
m_context.setRunner( this );
m_context.setConfig( m_config );
@@ -5192,10 +5658,6 @@ namespace Catch {
virtual ~RunContext() {
m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
- m_context.setRunner( m_prevRunner );
- m_context.setConfig( NULL );
- m_context.setResultCapture( m_prevResultCapture );
- m_context.setConfig( m_prevConfig );
}
void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
@@ -5216,14 +5678,17 @@ namespace Catch {
m_reporter->testCaseStarting( testInfo );
m_activeTestCase = &testCase;
- m_testCaseTracker = TestCaseTracker( testInfo.name );
do {
+ m_trackerContext.startRun();
do {
+ m_trackerContext.startCycle();
+ m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name );
runCurrentTest( redirectedCout, redirectedCerr );
}
- while( !m_testCaseTracker->isCompleted() && !aborting() );
+ while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
}
+ // !TBD: deprecated - this will be replaced by indexed trackers
while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
Totals deltaTotals = m_totals.delta( prevTotals );
@@ -5234,8 +5699,8 @@ namespace Catch {
redirectedCerr,
aborting() ) );
- m_activeTestCase = NULL;
- m_testCaseTracker.reset();
+ m_activeTestCase = CATCH_NULL;
+ m_testCaseTracker = CATCH_NULL;
return deltaTotals;
}
@@ -5270,8 +5735,10 @@ namespace Catch {
std::ostringstream oss;
oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
- if( !m_testCaseTracker->enterSection( oss.str() ) )
+ ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() );
+ if( !sectionTracker.isOpen() )
return false;
+ m_activeSections.push_back( &sectionTracker );
m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
@@ -5282,30 +5749,40 @@ namespace Catch {
return true;
}
bool testForMissingAssertions( Counts& assertions ) {
- if( assertions.total() != 0 ||
- !m_config->warnAboutMissingAssertions() ||
- m_testCaseTracker->currentSectionHasChildren() )
+ if( assertions.total() != 0 )
+ return false;
+ if( !m_config->warnAboutMissingAssertions() )
+ return false;
+ if( m_trackerContext.currentTracker().hasChildren() )
return false;
m_totals.assertions.failed++;
assertions.failed++;
return true;
}
- virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
- if( std::uncaught_exception() ) {
- m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
- return;
- }
-
- Counts assertions = m_totals.assertions - prevAssertions;
+ virtual void sectionEnded( SectionEndInfo const& endInfo ) {
+ Counts assertions = m_totals.assertions - endInfo.prevAssertions;
bool missingAssertions = testForMissingAssertions( assertions );
- m_testCaseTracker->leaveSection();
+ if( !m_activeSections.empty() ) {
+ m_activeSections.back()->close();
+ m_activeSections.pop_back();
+ }
- m_reporter->sectionEnded( SectionStats( info, assertions, _durationInSeconds, missingAssertions ) );
+ m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
m_messages.clear();
}
+ virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
+ if( m_unfinishedSections.empty() )
+ m_activeSections.back()->fail();
+ else
+ m_activeSections.back()->close();
+ m_activeSections.pop_back();
+
+ m_unfinishedSections.push_back( endInfo );
+ }
+
virtual void pushScopedMessage( MessageInfo const& message ) {
m_messages.push_back( message );
}
@@ -5371,7 +5848,8 @@ namespace Catch {
double duration = 0;
try {
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
- TestCaseTracker::Guard guard( *m_testCaseTracker );
+
+ seedRng( *m_config );
Timer timer;
timer.start();
@@ -5391,6 +5869,7 @@ namespace Catch {
catch(...) {
makeUnexpectedResultBuilder().useActiveException();
}
+ m_testCaseTracker->close();
handleUnfinishedSections();
m_messages.clear();
@@ -5425,39 +5904,29 @@ namespace Catch {
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(),
+ for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
itEnd = m_unfinishedSections.rend();
it != itEnd;
++it )
- sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
+ sectionEnded( *it );
m_unfinishedSections.clear();
}
- struct UnfinishedSections {
- UnfinishedSections( SectionInfo const& _info, Counts const& _prevAssertions, double _durationInSeconds )
- : info( _info ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
- {}
-
- SectionInfo info;
- Counts prevAssertions;
- double durationInSeconds;
- };
-
TestRunInfo m_runInfo;
IMutableContext& m_context;
TestCase const* m_activeTestCase;
- Option<TestCaseTracker> m_testCaseTracker;
+ ITracker* m_testCaseTracker;
+ ITracker* m_currentSectionTracker;
AssertionResult m_lastResult;
Ptr<IConfig const> m_config;
Totals m_totals;
Ptr<IStreamingReporter> m_reporter;
std::vector<MessageInfo> m_messages;
- IRunner* m_prevRunner;
- IResultCapture* m_prevResultCapture;
- Ptr<IConfig const> m_prevConfig;
AssertionInfo m_lastAssertionInfo;
- std::vector<UnfinishedSections> m_unfinishedSections;
+ std::vector<SectionEndInfo> m_unfinishedSections;
+ std::vector<ITracker*> m_activeSections;
+ TrackerContext m_trackerContext;
};
IResultCapture& getResultCapture() {
@@ -5505,89 +5974,87 @@ namespace Catch {
namespace Catch {
- class Runner {
-
- public:
- Runner( Ptr<Config> const& config )
- : m_config( config )
- {
- openStream();
- makeReporter();
+ Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
+ Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
+ if( !reporter ) {
+ std::ostringstream oss;
+ oss << "No reporter registered with name: '" << reporterName << "'";
+ throw std::domain_error( oss.str() );
}
+ return reporter;
+ }
- Totals runTests() {
-
- RunContext context( m_config.get(), m_reporter );
+ Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
+ std::vector<std::string> reporters = config->getReporterNames();
+ if( reporters.empty() )
+ reporters.push_back( "console" );
- Totals totals;
+ Ptr<IStreamingReporter> reporter;
+ for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
+ it != itEnd;
+ ++it )
+ reporter = addReporter( reporter, createReporter( *it, config ) );
+ return reporter;
+ }
+ Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
+ IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
+ for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
+ it != itEnd;
+ ++it )
+ reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
+ return reporters;
+ }
- context.testGroupStarting( "all tests", 1, 1 ); // deprecated?
+ Totals runTests( Ptr<Config> const& config ) {
- TestSpec testSpec = m_config->testSpec();
- if( !testSpec.hasFilters() )
- testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
+ Ptr<IConfig const> iconfig = config.get();
- std::vector<TestCase> testCases;
- getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, testCases );
+ Ptr<IStreamingReporter> reporter = makeReporter( config );
+ reporter = addListeners( iconfig, reporter );
- int testsRunForGroup = 0;
- for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
- it != itEnd;
- ++it ) {
- testsRunForGroup++;
- if( m_testsAlreadyRun.find( *it ) == m_testsAlreadyRun.end() ) {
+ RunContext context( iconfig, reporter );
- if( context.aborting() )
- break;
+ Totals totals;
- totals += context.runTest( *it );
- m_testsAlreadyRun.insert( *it );
- }
- }
- std::vector<TestCase> skippedTestCases;
- getRegistryHub().getTestCaseRegistry().getFilteredTests( testSpec, *m_config, skippedTestCases, true );
+ context.testGroupStarting( config->name(), 1, 1 );
- for( std::vector<TestCase>::const_iterator it = skippedTestCases.begin(), itEnd = skippedTestCases.end();
- it != itEnd;
- ++it )
- m_reporter->skipTest( *it );
+ TestSpec testSpec = config->testSpec();
+ if( !testSpec.hasFilters() )
+ testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
- context.testGroupEnded( "all tests", totals, 1, 1 );
- return totals;
+ std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
+ for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
+ it != itEnd;
+ ++it ) {
+ if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
+ totals += context.runTest( *it );
+ else
+ reporter->skipTest( *it );
}
- private:
- void openStream() {
- // Open output file, if specified
- if( !m_config->getFilename().empty() ) {
- m_ofs.open( m_config->getFilename().c_str() );
- if( m_ofs.fail() ) {
- std::ostringstream oss;
- oss << "Unable to open file: '" << m_config->getFilename() << "'";
- throw std::domain_error( oss.str() );
- }
- m_config->setStreamBuf( m_ofs.rdbuf() );
- }
- }
- void makeReporter() {
- std::string reporterName = m_config->getReporterName().empty()
- ? "console"
- : m_config->getReporterName();
+ context.testGroupEnded( iconfig->name(), totals, 1, 1 );
+ return totals;
+ }
- m_reporter = getRegistryHub().getReporterRegistry().create( reporterName, m_config.get() );
- if( !m_reporter ) {
- std::ostringstream oss;
- oss << "No reporter registered with name: '" << reporterName << "'";
- throw std::domain_error( oss.str() );
- }
- }
+ void applyFilenamesAsTags( IConfig const& config ) {
+ std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
+ for(std::size_t i = 0; i < tests.size(); ++i ) {
+ TestCase& test = const_cast<TestCase&>( tests[i] );
+ std::set<std::string> tags = test.tags;
- private:
- Ptr<Config> m_config;
- std::ofstream m_ofs;
- Ptr<IStreamingReporter> m_reporter;
- std::set<TestCase> m_testsAlreadyRun;
- };
+ std::string filename = test.lineInfo.file;
+ std::string::size_type lastSlash = filename.find_last_of( "\\/" );
+ if( lastSlash != std::string::npos )
+ filename = filename.substr( lastSlash+1 );
+
+ std::string::size_type lastDot = filename.find_last_of( "." );
+ if( lastDot != std::string::npos )
+ filename = filename.substr( 0, lastDot );
+
+ tags.insert( "#" + filename );
+ setTags( test, tags );
+ }
+ }
class Session : NonCopyable {
static bool alreadyInstantiated;
@@ -5616,7 +6083,7 @@ namespace Catch {
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* const argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
try {
m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
@@ -5643,7 +6110,7 @@ namespace Catch {
m_config.reset();
}
- int run( int argc, char* const argv[] ) {
+ int run( int argc, char const* const argv[] ) {
int returnCode = applyCommandLine( argc, argv );
if( returnCode == 0 )
@@ -5659,15 +6126,16 @@ namespace Catch {
{
config(); // Force config to be constructed
- std::srand( m_configData.rngSeed );
+ seedRng( *m_config );
- Runner runner( m_config );
+ if( m_configData.filenamesAsTags )
+ applyFilenamesAsTags( *m_config );
// Handle list request
if( Option<std::size_t> listed = list( config() ) )
return static_cast<int>( *listed );
- return static_cast<int>( runner.runTests().assertions.failed );
+ return static_cast<int>( runTests( m_config ).assertions.failed );
}
catch( std::exception& ex ) {
Catch::cerr() << ex.what() << std::endl;
@@ -5689,7 +6157,6 @@ namespace Catch {
m_config = new Config( m_configData );
return *m_config;
}
-
private:
Clara::CommandLine<ConfigData> m_cli;
std::vector<Clara::Parser::Token> m_unusedTokens;
@@ -5715,16 +6182,76 @@ namespace Catch {
namespace Catch {
- 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; }
- };
+ struct LexSort {
+ bool operator() (TestCase i,TestCase j) const { return (i<j);}
+ };
+ struct RandomNumberGenerator {
+ int operator()( int n ) const { return std::rand() % n; }
+ };
+
+ inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
+
+ std::vector<TestCase> sorted = unsortedTestCases;
+
+ switch( config.runOrder() ) {
+ case RunTests::InLexicographicalOrder:
+ std::sort( sorted.begin(), sorted.end(), LexSort() );
+ break;
+ case RunTests::InRandomOrder:
+ {
+ seedRng( config );
+
+ RandomNumberGenerator rng;
+ std::random_shuffle( sorted.begin(), sorted.end(), rng );
+ }
+ break;
+ case RunTests::InDeclarationOrder:
+ // already in declaration order
+ break;
+ }
+ return sorted;
+ }
+ bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
+ return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
+ }
+
+ void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
+ std::set<TestCase> seenFunctions;
+ for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
+ it != itEnd;
+ ++it ) {
+ std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
+ if( !prev.second ){
+ Catch::cerr()
+ << Colour( Colour::Red )
+ << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
+ << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
+ << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
+ exit(1);
+ }
+ }
+ }
+
+ std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
+ std::vector<TestCase> filtered;
+ filtered.reserve( testCases.size() );
+ for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
+ it != itEnd;
+ ++it )
+ if( matchTest( *it, testSpec, config ) )
+ filtered.push_back( *it );
+ return filtered;
+ }
+ std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
+ return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
+ }
+ class TestRegistry : public ITestCaseRegistry {
public:
- TestRegistry() : m_unnamedCount( 0 ) {}
+ TestRegistry()
+ : m_currentSortOrder( RunTests::InDeclarationOrder ),
+ m_unnamedCount( 0 )
+ {}
virtual ~TestRegistry();
virtual void registerTest( TestCase const& testCase ) {
@@ -5734,69 +6261,29 @@ namespace Catch {
oss << "Anonymous test case " << ++m_unnamedCount;
return registerTest( testCase.withName( oss.str() ) );
}
-
- if( m_functions.find( testCase ) == m_functions.end() ) {
- m_functions.insert( testCase );
- m_functionsInOrder.push_back( testCase );
- if( !testCase.isHidden() )
- m_nonHiddenFunctions.push_back( testCase );
- }
- else {
- TestCase const& prev = *m_functions.find( testCase );
- {
- Colour colourGuard( Colour::Red );
- Catch::cerr() << "error: TEST_CASE( \"" << name << "\" ) already defined.\n"
- << "\tFirst seen at " << prev.getTestCaseInfo().lineInfo << "\n"
- << "\tRedefined at " << testCase.getTestCaseInfo().lineInfo << std::endl;
- }
- exit(1);
- }
+ m_functions.push_back( testCase );
}
virtual std::vector<TestCase> const& getAllTests() const {
- return m_functionsInOrder;
+ return m_functions;
}
+ virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
+ if( m_sortedFunctions.empty() )
+ enforceNoDuplicateTestCases( m_functions );
- virtual std::vector<TestCase> const& getAllNonHiddenTests() const {
- return m_nonHiddenFunctions;
- }
-
- 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(),
- itEnd = m_functionsInOrder.end();
- it != itEnd;
- ++it ) {
- bool includeTest = testSpec.matches( *it ) && ( config.allowThrows() || !it->throws() );
- if( includeTest != negated )
- matchingTestCases.push_back( *it );
+ if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
+ m_sortedFunctions = sortTests( config, m_functions );
+ m_currentSortOrder = config.runOrder();
}
- sortTests( config, matchingTestCases );
+ return m_sortedFunctions;
}
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::vector<TestCase> m_functionsInOrder;
- std::vector<TestCase> m_nonHiddenFunctions;
+ std::vector<TestCase> m_functions;
+ mutable RunTests::InWhatOrder m_currentSortOrder;
+ mutable std::vector<TestCase> m_sortedFunctions;
size_t m_unnamedCount;
+ std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
};
///////////////////////////////////////////////////////////////////////////
@@ -5829,29 +6316,38 @@ namespace Catch {
return className;
}
- ///////////////////////////////////////////////////////////////////////////
+ void registerTestCase
+ ( ITestCase* testCase,
+ char const* classOrQualifiedMethodName,
+ NameAndDesc const& nameAndDesc,
+ SourceLineInfo const& lineInfo ) {
- AutoReg::AutoReg( TestFunction function,
- SourceLineInfo const& lineInfo,
- NameAndDesc const& nameAndDesc ) {
+ getMutableRegistryHub().registerTest
+ ( makeTestCase
+ ( testCase,
+ extractClassName( classOrQualifiedMethodName ),
+ nameAndDesc.name,
+ nameAndDesc.description,
+ lineInfo ) );
+ }
+ void registerTestCaseFunction
+ ( TestFunction function,
+ SourceLineInfo const& lineInfo,
+ NameAndDesc const& nameAndDesc ) {
registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
}
- AutoReg::~AutoReg() {}
-
- void AutoReg::registerTestCase( ITestCase* testCase,
- char const* classOrQualifiedMethodName,
- NameAndDesc const& nameAndDesc,
- SourceLineInfo const& lineInfo ) {
+ ///////////////////////////////////////////////////////////////////////////
- getMutableRegistryHub().registerTest
- ( makeTestCase( testCase,
- extractClassName( classOrQualifiedMethodName ),
- nameAndDesc.name,
- nameAndDesc.description,
- lineInfo ) );
+ AutoReg::AutoReg
+ ( TestFunction function,
+ SourceLineInfo const& lineInfo,
+ NameAndDesc const& nameAndDesc ) {
+ registerTestCaseFunction( function, lineInfo, nameAndDesc );
}
+ AutoReg::~AutoReg() {}
+
} // end namespace Catch
// #included from: catch_reporter_registry.hpp
@@ -5865,27 +6361,32 @@ namespace Catch {
public:
- virtual ~ReporterRegistry() {
- deleteAllValues( m_factories );
- }
+ virtual ~ReporterRegistry() CATCH_OVERRIDE {}
- virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig> const& config ) const {
+ virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
FactoryMap::const_iterator it = m_factories.find( name );
if( it == m_factories.end() )
- return NULL;
+ return CATCH_NULL;
return it->second->create( ReporterConfig( config ) );
}
- void registerReporter( std::string const& name, IReporterFactory* factory ) {
+ void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
m_factories.insert( std::make_pair( name, factory ) );
}
+ void registerListener( Ptr<IReporterFactory> const& factory ) {
+ m_listeners.push_back( factory );
+ }
- FactoryMap const& getFactories() const {
+ virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
return m_factories;
}
+ virtual Listeners const& getListeners() const CATCH_OVERRIDE {
+ return m_listeners;
+ }
private:
FactoryMap m_factories;
+ Listeners m_listeners;
};
}
@@ -5913,13 +6414,13 @@ namespace Catch {
#ifdef __OBJC__
// In Objective-C try objective-c exceptions first
@try {
- throw;
+ return tryTranslators();
}
@catch (NSException *exception) {
return Catch::toString( [exception description] );
}
#else
- throw;
+ return tryTranslators();
#endif
}
catch( TestFailureException& ) {
@@ -5935,20 +6436,15 @@ namespace Catch {
return msg;
}
catch(...) {
- return tryTranslators( m_translators.begin() );
+ return "Unknown exception";
}
}
- std::string tryTranslators( std::vector<const IExceptionTranslator*>::const_iterator it ) const {
- if( it == m_translators.end() )
- return "Unknown exception";
-
- try {
- return (*it)->translate();
- }
- catch(...) {
- return tryTranslators( it+1 );
- }
+ std::string tryTranslators() const {
+ if( m_translators.empty() )
+ throw;
+ else
+ return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
}
private:
@@ -5968,24 +6464,27 @@ namespace Catch {
public: // IRegistryHub
RegistryHub() {
}
- virtual IReporterRegistry const& getReporterRegistry() const {
+ virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
return m_reporterRegistry;
}
- virtual ITestCaseRegistry const& getTestCaseRegistry() const {
+ virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
return m_testCaseRegistry;
}
- virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
+ virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
return m_exceptionTranslatorRegistry;
}
public: // IMutableRegistryHub
- virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
+ virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
m_reporterRegistry.registerReporter( name, factory );
}
- virtual void registerTest( TestCase const& testInfo ) {
+ virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
+ m_reporterRegistry.registerListener( factory );
+ }
+ virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
m_testCaseRegistry.registerTest( testInfo );
}
- virtual void registerTranslator( const IExceptionTranslator* translator ) {
+ virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
m_exceptionTranslatorRegistry.registerTranslator( translator );
}
@@ -5997,7 +6496,7 @@ namespace Catch {
// Single, global, instance
inline RegistryHub*& getTheRegistryHub() {
- static RegistryHub* theRegistryHub = NULL;
+ static RegistryHub* theRegistryHub = CATCH_NULL;
if( !theRegistryHub )
theRegistryHub = new RegistryHub();
return theRegistryHub;
@@ -6012,7 +6511,7 @@ namespace Catch {
}
void cleanUp() {
delete getTheRegistryHub();
- getTheRegistryHub() = NULL;
+ getTheRegistryHub() = CATCH_NULL;
cleanUpContext();
}
std::string translateActiveException() {
@@ -6048,19 +6547,6 @@ namespace Catch {
// #included from: catch_stream.hpp
#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
-// #included from: catch_streambuf.h
-#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
-
-#include <streambuf>
-
-namespace Catch {
-
- class StreamBufBase : public std::streambuf {
- public:
- virtual ~StreamBufBase() CATCH_NOEXCEPT;
- };
-}
-
#include <stdexcept>
#include <cstdio>
#include <iostream>
@@ -6105,6 +6591,19 @@ namespace Catch {
///////////////////////////////////////////////////////////////////////////
+ FileStream::FileStream( std::string const& filename ) {
+ m_ofs.open( filename.c_str() );
+ if( m_ofs.fail() ) {
+ std::ostringstream oss;
+ oss << "Unable to open file: '" << filename << "'";
+ throw std::domain_error( oss.str() );
+ }
+ }
+
+ std::ostream& FileStream::stream() const {
+ return m_ofs;
+ }
+
struct OutputDebugWriter {
void operator()( std::string const&str ) {
@@ -6112,23 +6611,26 @@ namespace Catch {
}
};
- Stream::Stream()
- : streamBuf( NULL ), isOwned( false )
+ DebugOutStream::DebugOutStream()
+ : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
+ m_os( m_streamBuf.get() )
{}
- Stream::Stream( std::streambuf* _streamBuf, bool _isOwned )
- : streamBuf( _streamBuf ), isOwned( _isOwned )
+ std::ostream& DebugOutStream::stream() const {
+ return m_os;
+ }
+
+ // Store the streambuf from cout up-front because
+ // cout may get redirected when running tests
+ CoutStream::CoutStream()
+ : m_os( Catch::cout().rdbuf() )
{}
- void Stream::release() {
- if( isOwned ) {
- delete streamBuf;
- streamBuf = NULL;
- isOwned = false;
- }
+ std::ostream& CoutStream::stream() const {
+ return m_os;
}
-#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions
+#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
std::ostream& cout() {
return std::cout;
}
@@ -6142,7 +6644,7 @@ namespace Catch {
class Context : public IMutableContext {
- Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
+ Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
Context( Context const& );
void operator=( Context const& );
@@ -6188,7 +6690,7 @@ namespace Catch {
m_generatorsByTestName.find( testName );
return it != m_generatorsByTestName.end()
? it->second
- : NULL;
+ : CATCH_NULL;
}
IGeneratorsForTest& getGeneratorsForCurrentTest() {
@@ -6209,7 +6711,7 @@ namespace Catch {
};
namespace {
- Context* currentContext = NULL;
+ Context* currentContext = CATCH_NULL;
}
IMutableContext& getCurrentMutableContext() {
if( !currentContext )
@@ -6220,17 +6722,9 @@ namespace Catch {
return getCurrentMutableContext();
}
- Stream createStream( std::string const& streamName ) {
- if( streamName == "stdout" ) return Stream( Catch::cout().rdbuf(), false );
- if( streamName == "stderr" ) return Stream( Catch::cerr().rdbuf(), false );
- if( streamName == "debug" ) return Stream( new StreamBufImpl<OutputDebugWriter>, true );
-
- throw std::domain_error( "Unknown stream: " + streamName );
- }
-
void cleanUpContext() {
delete currentContext;
- currentContext = NULL;
+ currentContext = CATCH_NULL;
}
}
@@ -6286,12 +6780,13 @@ namespace {
{
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
- originalAttributes = csbiInfo.wAttributes;
+ originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
+ originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
}
virtual void use( Colour::Code _colourCode ) {
switch( _colourCode ) {
- case Colour::None: return setTextAttribute( originalAttributes );
+ case Colour::None: return setTextAttribute( originalForegroundAttributes );
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
case Colour::Red: return setTextAttribute( FOREGROUND_RED );
case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
@@ -6311,10 +6806,11 @@ namespace {
private:
void setTextAttribute( WORD _textAttribute ) {
- SetConsoleTextAttribute( stdoutHandle, _textAttribute );
+ SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
}
HANDLE stdoutHandle;
- WORD originalAttributes;
+ WORD originalForegroundAttributes;
+ WORD originalBackgroundAttributes;
};
IColourImpl* platformColourInstance() {
@@ -6640,6 +7136,21 @@ namespace Catch {
return TestCase( _testCase, info );
}
+ void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
+ {
+ testCaseInfo.tags = tags;
+ testCaseInfo.lcaseTags.clear();
+
+ std::ostringstream oss;
+ for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
+ oss << "[" << *it << "]";
+ std::string lcaseTag = toLower( *it );
+ testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
+ testCaseInfo.lcaseTags.insert( lcaseTag );
+ }
+ testCaseInfo.tagsAsString = oss.str();
+ }
+
TestCaseInfo::TestCaseInfo( std::string const& _name,
std::string const& _className,
std::string const& _description,
@@ -6648,18 +7159,10 @@ namespace Catch {
: name( _name ),
className( _className ),
description( _description ),
- tags( _tags ),
lineInfo( _lineInfo ),
properties( None )
{
- std::ostringstream oss;
- for( std::set<std::string>::const_iterator it = _tags.begin(), itEnd = _tags.end(); it != itEnd; ++it ) {
- oss << "[" << *it << "]";
- std::string lcaseTag = toLower( *it );
- properties = static_cast<SpecialProperties>( properties | parseSpecialTag( lcaseTag ) );
- lcaseTags.insert( lcaseTag );
- }
- tagsAsString = oss.str();
+ setTags( *this, _tags );
}
TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
@@ -6767,7 +7270,7 @@ namespace Catch {
return os;
}
- Version libraryVersion( 1, 2, 1, "", 0 );
+ Version libraryVersion( 1, 3, 2, "", 0 );
}
@@ -6960,7 +7463,7 @@ namespace Catch {
#else
uint64_t getCurrentTicks() {
timeval t;
- gettimeofday(&t,NULL);
+ gettimeofday(&t,CATCH_NULL);
return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
}
#endif
@@ -7059,6 +7562,14 @@ namespace Catch {
return line < other.line || ( line == other.line && file < other.file );
}
+ void seedRng( IConfig const& config ) {
+ if( config.rngSeed() != 0 )
+ std::srand( config.rngSeed() );
+ }
+ unsigned int rngSeed() {
+ return getCurrentContext().getConfig()->rngSeed();
+ }
+
std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
#ifndef __GNUG__
os << info.file << "(" << info.line << ")";
@@ -7098,8 +7609,13 @@ namespace Catch {
}
Section::~Section() {
- if( m_sectionIncluded )
- getResultCapture().sectionEnded( m_info, m_assertions, m_timer.getElapsedSeconds() );
+ if( m_sectionIncluded ) {
+ SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
+ if( std::uncaught_exception() )
+ getResultCapture().sectionEndedEarly( endInfo );
+ else
+ getResultCapture().sectionEnded( endInfo );
+ }
}
// This indicates whether the section should be executed or not
@@ -7151,7 +7667,7 @@ namespace Catch {
// Call sysctl.
size = sizeof(info);
- if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0) != 0 ) {
+ if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
return false;
}
@@ -7205,9 +7721,11 @@ namespace Catch {
namespace Detail {
- std::string unprintableString = "{?}";
+ const std::string unprintableString = "{?}";
namespace {
+ const int hexThreshold = 255;
+
struct Endianness {
enum Arch { Big, Little };
@@ -7289,7 +7807,7 @@ std::string toString( wchar_t* const value )
std::string toString( int value ) {
std::ostringstream oss;
oss << value;
- if( value >= 255 )
+ if( value > Detail::hexThreshold )
oss << " (0x" << std::hex << value << ")";
return oss.str();
}
@@ -7297,7 +7815,7 @@ std::string toString( int value ) {
std::string toString( unsigned long value ) {
std::ostringstream oss;
oss << value;
- if( value >= 255 )
+ if( value > Detail::hexThreshold )
oss << " (0x" << std::hex << value << ")";
return oss.str();
}
@@ -7347,6 +7865,23 @@ std::string toString( unsigned char value ) {
return toString( static_cast<char>( value ) );
}
+#ifdef CATCH_CONFIG_CPP11_LONG_LONG
+std::string toString( long long value ) {
+ std::ostringstream oss;
+ oss << value;
+ if( value > Detail::hexThreshold )
+ oss << " (0x" << std::hex << value << ")";
+ return oss.str();
+}
+std::string toString( unsigned long long value ) {
+ std::ostringstream oss;
+ oss << value;
+ if( value > Detail::hexThreshold )
+ oss << " (0x" << std::hex << value << ")";
+ return oss.str();
+}
+#endif
+
#ifdef CATCH_CONFIG_CPP11_NULLPTR
std::string toString( std::nullptr_t ) {
return "nullptr";
@@ -7376,11 +7911,17 @@ std::string toString( std::nullptr_t ) {
namespace Catch {
+ std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
+ return secondArg.empty() || secondArg == "\"\""
+ ? capturedExpression
+ : capturedExpression + ", " + secondArg;
+ }
ResultBuilder::ResultBuilder( char const* macroName,
SourceLineInfo const& lineInfo,
char const* capturedExpression,
- ResultDisposition::Flags resultDisposition )
- : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition ),
+ ResultDisposition::Flags resultDisposition,
+ char const* secondArg )
+ : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
m_shouldDebugBreak( false ),
m_shouldThrow( false )
{}
@@ -7421,9 +7962,35 @@ namespace Catch {
setResultType( resultType );
captureExpression();
}
+ void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
+ if( expectedMessage.empty() )
+ captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() );
+ else
+ captureExpectedException( Matchers::Equals( expectedMessage ) );
+ }
+
+ void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) {
+
+ assert( m_exprComponents.testFalse == false );
+ AssertionResultData data = m_data;
+ data.resultType = ResultWas::Ok;
+ data.reconstructedExpression = m_assertionInfo.capturedExpression;
+
+ std::string actualMessage = Catch::translateActiveException();
+ if( !matcher.match( actualMessage ) ) {
+ data.resultType = ResultWas::ExpressionFailed;
+ data.reconstructedExpression = actualMessage;
+ }
+ AssertionResult result( m_assertionInfo, data );
+ handleResult( result );
+ }
void ResultBuilder::captureExpression() {
AssertionResult result = build();
+ handleResult( result );
+ }
+ void ResultBuilder::handleResult( AssertionResult const& result )
+ {
getResultCapture().assertionEnded( result );
if( !result.isOk() ) {
@@ -7576,6 +8143,137 @@ namespace Catch {
} // end namespace Catch
+// #included from: ../reporters/catch_reporter_multi.hpp
+#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
+
+namespace Catch {
+
+class MultipleReporters : public SharedImpl<IStreamingReporter> {
+ typedef std::vector<Ptr<IStreamingReporter> > Reporters;
+ Reporters m_reporters;
+
+public:
+ void add( Ptr<IStreamingReporter> const& reporter ) {
+ m_reporters.push_back( reporter );
+ }
+
+public: // IStreamingReporter
+
+ virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
+ return m_reporters[0]->getPreferences();
+ }
+
+ virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->noMatchingTestCases( spec );
+ }
+
+ virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testRunStarting( testRunInfo );
+ }
+
+ virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testGroupStarting( groupInfo );
+ }
+
+ virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testCaseStarting( testInfo );
+ }
+
+ virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->sectionStarting( sectionInfo );
+ }
+
+ virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->assertionStarting( assertionInfo );
+ }
+
+ // The return value indicates if the messages buffer should be cleared:
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
+ bool clearBuffer = false;
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ clearBuffer |= (*it)->assertionEnded( assertionStats );
+ return clearBuffer;
+ }
+
+ virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->sectionEnded( sectionStats );
+ }
+
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testCaseEnded( testCaseStats );
+ }
+
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testGroupEnded( testGroupStats );
+ }
+
+ virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->testRunEnded( testRunStats );
+ }
+
+ virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
+ for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
+ it != itEnd;
+ ++it )
+ (*it)->skipTest( testInfo );
+ }
+};
+
+Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
+ Ptr<IStreamingReporter> resultingReporter;
+
+ if( existingReporter ) {
+ MultipleReporters* multi = dynamic_cast<MultipleReporters*>( existingReporter.get() );
+ if( !multi ) {
+ multi = new MultipleReporters;
+ resultingReporter = Ptr<IStreamingReporter>( multi );
+ if( existingReporter )
+ multi->add( existingReporter );
+ }
+ else
+ resultingReporter = existingReporter;
+ multi->add( additionalReporter );
+ }
+ else
+ resultingReporter = additionalReporter;
+
+ return resultingReporter;
+}
+
+} // end namespace Catch
+
// #included from: ../reporters/catch_reporter_xml.hpp
#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
@@ -7591,47 +8289,53 @@ namespace Catch {
StreamingReporterBase( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
stream( _config.stream() )
- {}
+ {
+ m_reporterPrefs.shouldRedirectStdOut = false;
+ }
- virtual ~StreamingReporterBase();
+ virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
+ return m_reporterPrefs;
+ }
- virtual void noMatchingTestCases( std::string const& ) {}
+ virtual ~StreamingReporterBase() CATCH_OVERRIDE;
- virtual void testRunStarting( TestRunInfo const& _testRunInfo ) {
+ virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
+
+ virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
currentTestRunInfo = _testRunInfo;
}
- virtual void testGroupStarting( GroupInfo const& _groupInfo ) {
+ virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
currentGroupInfo = _groupInfo;
}
- virtual void testCaseStarting( TestCaseInfo const& _testInfo ) {
+ virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
currentTestCaseInfo = _testInfo;
}
- virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
+ virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
m_sectionStack.push_back( _sectionInfo );
}
- virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) {
+ virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
m_sectionStack.pop_back();
}
- virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) {
+ virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
currentTestCaseInfo.reset();
}
- virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) {
+ virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
currentGroupInfo.reset();
}
- virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) {
+ virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
currentTestCaseInfo.reset();
currentGroupInfo.reset();
currentTestRunInfo.reset();
}
- virtual void skipTest( TestCaseInfo const& ) {
+ virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
// Don't do anything with this by default.
// It can optionally be overridden in the derived class.
}
- Ptr<IConfig> m_config;
+ Ptr<IConfig const> m_config;
std::ostream& stream;
LazyStat<TestRunInfo> currentTestRunInfo;
@@ -7639,6 +8343,7 @@ namespace Catch {
LazyStat<TestCaseInfo> currentTestCaseInfo;
std::vector<SectionInfo> m_sectionStack;
+ ReporterPreferences m_reporterPrefs;
};
struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
@@ -7689,15 +8394,21 @@ namespace Catch {
CumulativeReporterBase( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
stream( _config.stream() )
- {}
+ {
+ m_reporterPrefs.shouldRedirectStdOut = false;
+ }
~CumulativeReporterBase();
- virtual void testRunStarting( TestRunInfo const& ) {}
- virtual void testGroupStarting( GroupInfo const& ) {}
+ virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
+ return m_reporterPrefs;
+ }
+
+ virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
+ virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
- virtual void testCaseStarting( TestCaseInfo const& ) {}
+ virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
- virtual void sectionStarting( SectionInfo const& sectionInfo ) {
+ virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
Ptr<SectionNode> node;
if( m_sectionStack.empty() ) {
@@ -7722,7 +8433,7 @@ namespace Catch {
m_deepestSection = node;
}
- virtual void assertionStarting( AssertionInfo const& ) {}
+ virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
virtual bool assertionEnded( AssertionStats const& assertionStats ) {
assert( !m_sectionStack.empty() );
@@ -7730,13 +8441,13 @@ namespace Catch {
sectionNode.assertions.push_back( assertionStats );
return true;
}
- virtual void sectionEnded( SectionStats const& sectionStats ) {
+ virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
assert( !m_sectionStack.empty() );
SectionNode& node = *m_sectionStack.back();
node.stats = sectionStats;
m_sectionStack.pop_back();
}
- virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
assert( m_sectionStack.size() == 0 );
node->children.push_back( m_rootSection );
@@ -7747,12 +8458,12 @@ namespace Catch {
m_deepestSection->stdOut = testCaseStats.stdOut;
m_deepestSection->stdErr = testCaseStats.stdErr;
}
- virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
node->children.swap( m_testCases );
m_testGroups.push_back( node );
}
- virtual void testRunEnded( TestRunStats const& testRunStats ) {
+ virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
Ptr<TestRunNode> node = new TestRunNode( testRunStats );
node->children.swap( m_testGroups );
m_testRuns.push_back( node );
@@ -7760,9 +8471,9 @@ namespace Catch {
}
virtual void testRunEndedCumulative() = 0;
- virtual void skipTest( TestCaseInfo const& ) {}
+ virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
- Ptr<IConfig> m_config;
+ Ptr<IConfig const> m_config;
std::ostream& stream;
std::vector<AssertionStats> m_assertions;
std::vector<std::vector<Ptr<SectionNode> > > m_sections;
@@ -7774,6 +8485,7 @@ namespace Catch {
Ptr<SectionNode> m_rootSection;
Ptr<SectionNode> m_deepestSection;
std::vector<Ptr<SectionNode> > m_sectionStack;
+ ReporterPreferences m_reporterPrefs;
};
@@ -7787,6 +8499,17 @@ namespace Catch {
return line;
}
+ struct TestEventListenerBase : StreamingReporterBase {
+ TestEventListenerBase( ReporterConfig const& _config )
+ : StreamingReporterBase( _config )
+ {}
+
+ virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
+ virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
+ return false;
+ }
+ };
+
} // end namespace Catch
// #included from: ../internal/catch_reporter_registrars.hpp
@@ -7817,7 +8540,7 @@ namespace Catch {
template<typename T>
class ReporterRegistrar {
- class ReporterFactory : public IReporterFactory {
+ class ReporterFactory : public SharedImpl<IReporterFactory> {
// *** Please Note ***:
// - If you end up here looking at a compiler error because it's trying to register
@@ -7845,22 +8568,102 @@ namespace Catch {
getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
}
};
+
+ template<typename T>
+ class ListenerRegistrar {
+
+ class ListenerFactory : public SharedImpl<IReporterFactory> {
+
+ virtual IStreamingReporter* create( ReporterConfig const& config ) const {
+ return new T( config );
+ }
+ virtual std::string getDescription() const {
+ return "";
+ }
+ };
+
+ public:
+
+ ListenerRegistrar() {
+ getMutableRegistryHub().registerListener( new ListenerFactory() );
+ }
+ };
}
#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
+#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
+ namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
+
// #included from: ../internal/catch_xmlwriter.hpp
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
#include <sstream>
#include <string>
#include <vector>
+#include <iomanip>
namespace Catch {
+ class XmlEncode {
+ public:
+ enum ForWhat { ForTextNodes, ForAttributes };
+
+ XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
+ : m_str( str ),
+ m_forWhat( forWhat )
+ {}
+
+ void encodeTo( std::ostream& os ) const {
+
+ // Apostrophe escaping not necessary if we always use " to write attributes
+ // (see: http://www.w3.org/TR/xml/#syntax)
+
+ for( std::size_t i = 0; i < m_str.size(); ++ i ) {
+ char c = m_str[i];
+ switch( c ) {
+ case '<': os << "&lt;"; break;
+ case '&': os << "&amp;"; break;
+
+ case '>':
+ // See: http://www.w3.org/TR/xml/#syntax
+ if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
+ os << "&gt;";
+ else
+ os << c;
+ break;
+
+ case '\"':
+ if( m_forWhat == ForAttributes )
+ os << "&quot;";
+ else
+ os << c;
+ break;
+
+ default:
+ // Escape control chars - based on contribution by @espenalb in PR #465
+ if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
+ os << "&#x" << std::uppercase << std::hex << static_cast<int>( c );
+ else
+ os << c;
+ }
+ }
+ }
+
+ friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
+ xmlEncode.encodeTo( os );
+ return os;
+ }
+
+ private:
+ std::string m_str;
+ ForWhat m_forWhat;
+ };
+
class XmlWriter {
public:
@@ -7872,7 +8675,7 @@ namespace Catch {
ScopedElement( ScopedElement const& other )
: m_writer( other.m_writer ){
- other.m_writer = NULL;
+ other.m_writer = CATCH_NULL;
}
~ScopedElement() {
@@ -7943,11 +8746,8 @@ namespace Catch {
}
XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
- if( !name.empty() && !attribute.empty() ) {
- stream() << " " << name << "=\"";
- writeEncodedText( attribute );
- stream() << "\"";
- }
+ if( !name.empty() && !attribute.empty() )
+ stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\"";
return *this;
}
@@ -7958,9 +8758,9 @@ namespace Catch {
template<typename T>
XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
- if( !name.empty() )
- stream() << " " << name << "=\"" << attribute << "\"";
- return *this;
+ std::ostringstream oss;
+ oss << attribute;
+ return writeAttribute( name, oss.str() );
}
XmlWriter& writeText( std::string const& text, bool indent = true ) {
@@ -7969,7 +8769,7 @@ namespace Catch {
ensureTagClosed();
if( tagWasOpen && indent )
stream() << m_indent;
- writeEncodedText( text );
+ stream() << XmlEncode( text );
m_needsNewline = true;
}
return *this;
@@ -8014,30 +8814,6 @@ namespace Catch {
}
}
- void writeEncodedText( std::string const& text ) {
- static const char* charsToEncode = "<&\"";
- std::string mtext = text;
- std::string::size_type pos = mtext.find_first_of( charsToEncode );
- while( pos != std::string::npos ) {
- stream() << mtext.substr( 0, pos );
-
- switch( mtext[pos] ) {
- case '<':
- stream() << "&lt;";
- break;
- case '&':
- stream() << "&amp;";
- break;
- case '\"':
- stream() << "&quot;";
- break;
- }
- mtext = mtext.substr( pos+1 );
- pos = mtext.find_first_of( charsToEncode );
- }
- stream() << mtext;
- }
-
bool m_tagIsOpen;
bool m_needsNewline;
std::vector<std::string> m_tags;
@@ -8046,32 +8822,44 @@ namespace Catch {
};
}
+// #included from: catch_reenable_warnings.h
+
+#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
+
+#ifdef __clang__
+# ifdef __ICC // icpc defines the __clang__ macro
+# pragma warning(pop)
+# else
+# pragma clang diagnostic pop
+# endif
+#elif defined __GNUC__
+# pragma GCC diagnostic pop
+#endif
+
+
namespace Catch {
class XmlReporter : public StreamingReporterBase {
public:
XmlReporter( ReporterConfig const& _config )
: StreamingReporterBase( _config ),
m_sectionDepth( 0 )
- {}
+ {
+ m_reporterPrefs.shouldRedirectStdOut = true;
+ }
- virtual ~XmlReporter();
+ virtual ~XmlReporter() CATCH_OVERRIDE;
static std::string getDescription() {
return "Reports test results as an XML document";
}
public: // StreamingReporterBase
- virtual ReporterPreferences getPreferences() const {
- ReporterPreferences prefs;
- prefs.shouldRedirectStdOut = true;
- return prefs;
- }
- virtual void noMatchingTestCases( std::string const& s ) {
+ virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
StreamingReporterBase::noMatchingTestCases( s );
}
- virtual void testRunStarting( TestRunInfo const& testInfo ) {
+ virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
StreamingReporterBase::testRunStarting( testInfo );
m_xml.setStream( stream );
m_xml.startElement( "Catch" );
@@ -8079,13 +8867,13 @@ namespace Catch {
m_xml.writeAttribute( "name", m_config->name() );
}
- virtual void testGroupStarting( GroupInfo const& groupInfo ) {
+ virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
StreamingReporterBase::testGroupStarting( groupInfo );
m_xml.startElement( "Group" )
.writeAttribute( "name", groupInfo.name );
}
- virtual void testCaseStarting( TestCaseInfo const& testInfo ) {
+ virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
StreamingReporterBase::testCaseStarting(testInfo);
m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
@@ -8093,7 +8881,7 @@ namespace Catch {
m_testCaseTimer.start();
}
- virtual void sectionStarting( SectionInfo const& sectionInfo ) {
+ virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
StreamingReporterBase::sectionStarting( sectionInfo );
if( m_sectionDepth++ > 0 ) {
m_xml.startElement( "Section" )
@@ -8102,9 +8890,9 @@ namespace Catch {
}
}
- virtual void assertionStarting( AssertionInfo const& ) { }
+ virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
- virtual bool assertionEnded( AssertionStats const& assertionStats ) {
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
const AssertionResult& assertionResult = assertionStats.assertionResult;
// Print any info messages in <Info> tags.
@@ -8175,7 +8963,7 @@ namespace Catch {
return true;
}
- virtual void sectionEnded( SectionStats const& sectionStats ) {
+ virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
StreamingReporterBase::sectionEnded( sectionStats );
if( --m_sectionDepth > 0 ) {
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
@@ -8190,7 +8978,7 @@ namespace Catch {
}
}
- virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
StreamingReporterBase::testCaseEnded( testCaseStats );
XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
@@ -8201,7 +8989,7 @@ namespace Catch {
m_xml.endElement();
}
- virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
StreamingReporterBase::testGroupEnded( testGroupStats );
// TODO: Check testGroupStats.aborting and act accordingly.
m_xml.scopedElement( "OverallResults" )
@@ -8211,7 +8999,7 @@ namespace Catch {
m_xml.endElement();
}
- virtual void testRunEnded( TestRunStats const& testRunStats ) {
+ virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
StreamingReporterBase::testRunEnded( testRunStats );
m_xml.scopedElement( "OverallResults" )
.writeAttribute( "successes", testRunStats.totals.assertions.passed )
@@ -8242,28 +9030,24 @@ namespace Catch {
JunitReporter( ReporterConfig const& _config )
: CumulativeReporterBase( _config ),
xml( _config.stream() )
- {}
+ {
+ m_reporterPrefs.shouldRedirectStdOut = true;
+ }
- ~JunitReporter();
+ virtual ~JunitReporter() CATCH_OVERRIDE;
static std::string getDescription() {
return "Reports test results in an XML format that looks like Ant's junitreport target";
}
- virtual void noMatchingTestCases( std::string const& /*spec*/ ) {}
-
- virtual ReporterPreferences getPreferences() const {
- ReporterPreferences prefs;
- prefs.shouldRedirectStdOut = true;
- return prefs;
- }
+ virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
- virtual void testRunStarting( TestRunInfo const& runInfo ) {
+ virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
CumulativeReporterBase::testRunStarting( runInfo );
xml.startElement( "testsuites" );
}
- virtual void testGroupStarting( GroupInfo const& groupInfo ) {
+ virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
suiteTimer.start();
stdOutForSuite.str("");
stdErrForSuite.str("");
@@ -8271,25 +9055,25 @@ namespace Catch {
CumulativeReporterBase::testGroupStarting( groupInfo );
}
- virtual bool assertionEnded( AssertionStats const& assertionStats ) {
+ virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
unexpectedExceptions++;
return CumulativeReporterBase::assertionEnded( assertionStats );
}
- virtual void testCaseEnded( TestCaseStats const& testCaseStats ) {
+ virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
stdOutForSuite << testCaseStats.stdOut;
stdErrForSuite << testCaseStats.stdErr;
CumulativeReporterBase::testCaseEnded( testCaseStats );
}
- virtual void testGroupEnded( TestGroupStats const& testGroupStats ) {
+ virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
double suiteTime = suiteTimer.getElapsedSeconds();
CumulativeReporterBase::testGroupEnded( testGroupStats );
writeGroup( *m_testGroups.back(), suiteTime );
}
- virtual void testRunEndedCumulative() {
+ virtual void testRunEndedCumulative() CATCH_OVERRIDE {
xml.endElement();
}
@@ -8454,24 +9238,19 @@ namespace Catch {
m_headerPrinted( false )
{}
- virtual ~ConsoleReporter();
+ virtual ~ConsoleReporter() CATCH_OVERRIDE;
static std::string getDescription() {
return "Reports test results as plain lines of text";
}
- virtual ReporterPreferences getPreferences() const {
- ReporterPreferences prefs;
- prefs.shouldRedirectStdOut = false;
- return prefs;
- }
- virtual void noMatchingTestCases( std::string const& spec ) {
+ virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
stream << "No test cases matched '" << spec << "'" << std::endl;
}
- virtual void assertionStarting( AssertionInfo const& ) {
+ virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
}
- virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
+ virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
AssertionResult const& result = _assertionStats.assertionResult;
bool printInfoMessages = true;
@@ -8491,11 +9270,11 @@ namespace Catch {
return true;
}
- virtual void sectionStarting( SectionInfo const& _sectionInfo ) {
+ virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
m_headerPrinted = false;
StreamingReporterBase::sectionStarting( _sectionInfo );
}
- virtual void sectionEnded( SectionStats const& _sectionStats ) {
+ virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
if( _sectionStats.missingAssertions ) {
lazyPrint();
Colour colour( Colour::ResultError );
@@ -8517,11 +9296,11 @@ namespace Catch {
StreamingReporterBase::sectionEnded( _sectionStats );
}
- virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) {
+ virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
StreamingReporterBase::testCaseEnded( _testCaseStats );
m_headerPrinted = false;
}
- virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) {
+ virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
if( currentGroupInfo.used ) {
printSummaryDivider();
stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
@@ -8530,7 +9309,7 @@ namespace Catch {
}
StreamingReporterBase::testGroupEnded( _testGroupStats );
}
- virtual void testRunEnded( TestRunStats const& _testRunStats ) {
+ virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
printTotalsDivider( _testRunStats.totals );
printTotals( _testRunStats.totals );
stream << std::endl;
@@ -9169,8 +9948,14 @@ namespace Catch {
} // end namespace Catch
namespace Catch {
+ // These are all here to avoid warnings about not having any out of line
+ // virtual methods
NonCopyable::~NonCopyable() {}
IShared::~IShared() {}
+ IStream::~IStream() CATCH_NOEXCEPT {}
+ FileStream::~FileStream() CATCH_NOEXCEPT {}
+ CoutStream::~CoutStream() CATCH_NOEXCEPT {}
+ DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
IContext::~IContext() {}
IResultCapture::~IResultCapture() {}
@@ -9204,6 +9989,7 @@ namespace Catch {
FreeFunctionTestCase::~FreeFunctionTestCase() {}
IGeneratorInfo::~IGeneratorInfo() {}
IGeneratorsForTest::~IGeneratorsForTest() {}
+ WildcardPattern::~WildcardPattern() {}
TestSpec::Pattern::~Pattern() {}
TestSpec::NamePattern::~NamePattern() {}
TestSpec::TagPattern::~TagPattern() {}
@@ -9215,6 +10001,13 @@ namespace Catch {
Matchers::Impl::StdString::EndsWith::~EndsWith() {}
void Config::dummy() {}
+
+ namespace TestCaseTracking {
+ ITracker::~ITracker() {}
+ TrackerBase::~TrackerBase() {}
+ SectionTracker::~SectionTracker() {}
+ IndexTracker::~IndexTracker() {}
+ }
}
#ifdef __clang__
@@ -9230,7 +10023,7 @@ namespace Catch {
#ifndef __OBJC__
// Standard C/C++ main entry point
-int main (int argc, char * const argv[]) {
+int main (int argc, char * argv[]) {
return Catch::Session().run( argc, argv );
}
@@ -9268,8 +10061,9 @@ int main (int argc, char * const argv[]) {
#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
-#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS" )
+#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
+#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" )
#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
@@ -9280,6 +10074,7 @@ int main (int argc, char * const argv[]) {
#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
+#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
@@ -9295,6 +10090,7 @@ int main (int argc, char * const argv[]) {
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
+ #define CATCH_REGISTER_TEST_CASE( ... ) INTERNAL_CATCH_REGISTER_TESTCASE( __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
@@ -9302,6 +10098,7 @@ int main (int argc, char * const argv[]) {
#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
#define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
+ #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
@@ -9321,11 +10118,11 @@ int main (int argc, char * const argv[]) {
#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
#endif
-#define CATCH_GIVEN( desc ) CATCH_SECTION( "Given: " desc, "" )
-#define CATCH_WHEN( desc ) CATCH_SECTION( " When: " desc, "" )
-#define CATCH_AND_WHEN( desc ) CATCH_SECTION( " And: " desc, "" )
-#define CATCH_THEN( desc ) CATCH_SECTION( " Then: " desc, "" )
-#define CATCH_AND_THEN( desc ) CATCH_SECTION( " And: " desc, "" )
+#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
+#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
+#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
+#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
+#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
#else
@@ -9333,8 +10130,9 @@ int main (int argc, char * const argv[]) {
#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
-#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "REQUIRE_THROWS" )
+#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
+#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
@@ -9343,8 +10141,9 @@ int main (int argc, char * const argv[]) {
#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
-#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS" )
+#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
+#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
@@ -9360,6 +10159,7 @@ int main (int argc, char * const argv[]) {
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
+ #define REGISTER_TEST_CASE( ... ) INTERNAL_CATCH_REGISTER_TESTCASE( __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
#define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
@@ -9367,6 +10167,7 @@ int main (int argc, char * const argv[]) {
#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
#define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
+ #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
#define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
#define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
@@ -9390,27 +10191,13 @@ int main (int argc, char * const argv[]) {
#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
#endif
-#define GIVEN( desc ) SECTION( " Given: " desc, "" )
-#define WHEN( desc ) SECTION( " When: " desc, "" )
-#define AND_WHEN( desc ) SECTION( "And when: " desc, "" )
-#define THEN( desc ) SECTION( " Then: " desc, "" )
-#define AND_THEN( desc ) SECTION( " And: " desc, "" )
+#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
+#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
+#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
+#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
+#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
using Catch::Detail::Approx;
-// #included from: internal/catch_reenable_warnings.h
-
-#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
-
-#ifdef __clang__
-# ifdef __ICC // icpc defines the __clang__ macro
-# pragma warning(pop)
-# else
-# pragma clang diagnostic pop
-# endif
-#elif defined __GNUC__
-# pragma GCC diagnostic pop
-#endif
-
#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED