2011-05-24 08:23:02 +01:00
/*
2015-08-07 17:30:34 +01:00
* Catch v1.2.1-develop.12
* Generated: 2015-08-07 17:29:52.878958
2012-05-22 22:22:22 +01:00
* ----------------------------------------------------------
2012-05-09 19:37:51 +01:00
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
2011-05-24 08:23:02 +01:00
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
2012-05-09 19:37:51 +01:00
#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_HPP_INCLUDED
2012-06-02 23:12:42 +01:00
2015-05-21 06:16:15 +01:00
#ifdef __clang__
# pragma clang system_header
#elif defined __GNUC__
# pragma GCC system_header
#endif
2014-05-20 18:50:59 +01:00
// #included from: internal/catch_suppress_warnings.h
2012-08-16 18:48:50 +01:00
#ifdef __clang__
2015-03-04 08:23:40 +00:00
# ifdef __ICC // icpc defines the __clang__ macro
# pragma warning(push)
# pragma warning(disable: 161 1682)
# else // __ICC
# pragma clang diagnostic ignored "-Wglobal-constructors"
# pragma clang diagnostic ignored "-Wvariadic-macros"
# pragma clang diagnostic ignored "-Wc99-extensions"
# pragma clang diagnostic ignored "-Wunused-variable"
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wpadded"
# pragma clang diagnostic ignored "-Wc++98-compat"
# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
2015-05-21 06:16:15 +01:00
# pragma clang diagnostic ignored "-Wswitch-enum"
2015-03-04 08:23:40 +00:00
# endif
2014-07-27 15:16:10 +02:00
#elif defined __GNUC__
2015-03-04 08:23:40 +00:00
# pragma GCC diagnostic ignored "-Wvariadic-macros"
# pragma GCC diagnostic ignored "-Wunused-variable"
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wpadded"
2012-08-16 18:48:50 +01:00
#endif
2014-12-21 00:21:23 +00:00
#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
# define CATCH_IMPL
2014-03-10 18:02:18 +00:00
#endif
2014-12-21 00:21:23 +00:00
#ifdef CATCH_IMPL
2014-03-06 21:53:34 +00:00
# ifndef CLARA_CONFIG_MAIN
# define CLARA_CONFIG_MAIN_NOT_DEFINED
# define CLARA_CONFIG_MAIN
# endif
#endif
2012-08-09 07:47:30 +01:00
// #included from: internal/catch_notimplemented_exception.h
#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
2011-05-24 08:23:02 +01:00
// #included from: catch_common.h
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
2011-05-24 08:23:02 +01:00
#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
#include <sstream>
#include <stdexcept>
#include <algorithm>
2013-04-24 19:10:02 +01:00
// #included from: catch_compiler_capabilities.h
#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
2015-05-19 18:40:00 +01:00
// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
// The following features are defined:
//
// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
2015-07-23 23:06:26 +01:00
// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
2015-08-07 17:30:34 +01:00
// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
2015-05-19 18:40:00 +01:00
// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
2015-06-30 18:26:09 +01:00
// 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
// can be combined, en-mass, with the _NO_ forms later.
// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
2013-04-24 19:10:02 +01:00
2013-12-14 14:34:05 +00:00
#ifdef __clang__
2014-04-23 18:19:49 +01:00
# if __has_feature(cxx_nullptr)
2015-06-30 18:26:09 +01:00
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
2014-04-23 18:19:49 +01:00
# endif
2013-12-14 14:34:05 +00:00
2014-04-23 18:19:49 +01:00
# if __has_feature(cxx_noexcept)
2015-06-30 18:26:09 +01:00
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
2014-04-23 18:19:49 +01:00
# endif
2013-12-14 14:34:05 +00:00
#endif // __clang__
2013-04-24 19:10:02 +01:00
////////////////////////////////////////////////////////////////////////////////
// Borland
#ifdef __BORLANDC__
#endif // __BORLANDC__
////////////////////////////////////////////////////////////////////////////////
// EDG
#ifdef __EDG_VERSION__
#endif // __EDG_VERSION__
////////////////////////////////////////////////////////////////////////////////
// Digital Mars
#ifdef __DMC__
#endif // __DMC__
////////////////////////////////////////////////////////////////////////////////
// GCC
#ifdef __GNUC__
2015-08-03 07:40:52 +01:00
#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
2015-06-30 18:26:09 +01:00
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
2013-12-14 14:34:05 +00:00
#endif
2015-08-03 07:40:52 +01:00
// - otherwise more recent versions define __cplusplus >= 201103L
// and will get picked up below
2013-04-24 19:10:02 +01:00
#endif // __GNUC__
////////////////////////////////////////////////////////////////////////////////
// Visual C++
#ifdef _MSC_VER
2015-05-19 22:37:23 +01:00
#if (_MSC_VER >= 1600)
2015-06-30 18:26:09 +01:00
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
2015-05-19 22:37:23 +01:00
#endif
2015-05-19 18:40:00 +01:00
#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
2015-06-30 18:26:09 +01:00
#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
2015-05-19 18:40:00 +01:00
#endif
2013-04-24 19:10:02 +01:00
#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 ) || \
( defined __GNUC__ && __GNUC__ >= 3 ) || \
( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
2013-06-07 19:07:50 +01:00
2015-06-30 18:26:09 +01:00
#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
2013-06-07 19:07:50 +01:00
2013-04-24 19:10:02 +01:00
#endif
2014-04-18 08:49:35 +01:00
////////////////////////////////////////////////////////////////////////////////
// C++ language feature support
2015-05-19 18:40:00 +01:00
// catch all support for C++11
#if (__cplusplus >= 201103L)
2014-04-18 08:49:35 +01:00
# define CATCH_CPP11_OR_GREATER
2015-05-19 18:40:00 +01:00
2015-06-30 18:26:09 +01:00
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
2015-05-19 18:40:00 +01:00
# endif
2015-06-30 18:26:09 +01:00
# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
2015-05-19 18:40:00 +01:00
# endif
2015-06-30 18:26:09 +01:00
# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
2015-05-19 18:40:00 +01:00
# endif
2015-06-30 18:26:09 +01:00
# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
2015-05-19 18:40:00 +01:00
# endif
2015-06-30 18:26:09 +01:00
# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
2015-05-19 18:40:00 +01:00
# endif
2015-06-30 18:26:09 +01:00
# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
2015-05-19 18:40:00 +01:00
# endif
2015-07-23 23:06:26 +01:00
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
# endif
2015-08-07 17:30:34 +01:00
# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
# endif
2015-05-19 18:40:00 +01:00
#endif // __cplusplus >= 201103L
2014-04-18 08:49:35 +01:00
2015-06-30 18:26:09 +01:00
// Now set the actual defines based on the above + anything the user has configured
#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_NULLPTR
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_NOEXCEPT
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_GENERATED_METHODS
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_IS_ENUM
#endif
#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
# define CATCH_CONFIG_CPP11_TUPLE
#endif
#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
2015-07-23 23:06:26 +01:00
# 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)
# define CATCH_CONFIG_CPP11_LONG_LONG
2015-06-30 18:26:09 +01:00
#endif
2015-08-07 17:30:34 +01:00
#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE)
# define CATCH_CONFIG_CPP11_OVERRIDE
#endif
2015-06-30 18:26:09 +01:00
2014-04-18 08:49:35 +01:00
// noexcept support:
2014-04-23 18:19:49 +01:00
#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
# define CATCH_NOEXCEPT noexcept
# define CATCH_NOEXCEPT_IS(x) noexcept(x)
#else
2014-04-18 08:49:35 +01:00
# define CATCH_NOEXCEPT throw()
# define CATCH_NOEXCEPT_IS(x)
#endif
2015-07-02 08:21:38 +01:00
// nullptr support
#ifdef CATCH_CONFIG_CPP11_NULLPTR
# define CATCH_NULL nullptr
#else
# define CATCH_NULL NULL
#endif
2015-08-07 17:30:34 +01:00
// override support
#ifdef CATCH_CONFIG_CPP11_OVERRIDE
# define CATCH_OVERRIDE override
#else
# define CATCH_OVERRIDE
#endif
2012-05-16 15:09:17 +01:00
namespace Catch {
2015-07-02 23:03:13 +01:00
struct IConfig ;
2015-07-15 23:03:11 +01:00
struct CaseSensitive { enum Choice {
Yes ,
No
}; };
2013-03-08 09:30:25 +00:00
class NonCopyable {
2015-05-19 18:40:00 +01:00
#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2014-10-21 07:25:26 +01:00
NonCopyable ( NonCopyable const & ) = delete ;
NonCopyable ( NonCopyable && ) = delete ;
NonCopyable & operator = ( NonCopyable const & ) = delete ;
NonCopyable & operator = ( NonCopyable && ) = delete ;
#else
NonCopyable ( NonCopyable const & info );
NonCopyable & operator = ( NonCopyable const & );
#endif
2013-03-08 09:30:25 +00:00
protected :
NonCopyable () {}
virtual ~ NonCopyable ();
};
2011-05-24 08:23:02 +01:00
2012-05-31 19:40:26 +01:00
class SafeBool {
public :
typedef void ( SafeBool ::* type )() const ;
static type makeSafe ( bool value ) {
return value ? & SafeBool :: trueValue : 0 ;
}
private :
void trueValue () const {}
};
2011-05-24 08:23:02 +01:00
template < typename ContainerT >
2012-05-09 19:04:00 +01:00
inline void deleteAll ( ContainerT & container ) {
2011-05-24 08:23:02 +01:00
typename ContainerT :: const_iterator it = container . begin ();
typename ContainerT :: const_iterator itEnd = container . end ();
for (; it != itEnd ; ++ it )
delete * it ;
}
template < typename AssociativeContainerT >
2012-05-09 19:04:00 +01:00
inline void deleteAllValues ( AssociativeContainerT & container ) {
2011-05-24 08:23:02 +01:00
typename AssociativeContainerT :: const_iterator it = container . begin ();
typename AssociativeContainerT :: const_iterator itEnd = container . end ();
for (; it != itEnd ; ++ it )
delete it -> second ;
}
2013-12-03 18:53:55 +00:00
bool startsWith ( std :: string const & s , std :: string const & prefix );
bool endsWith ( std :: string const & s , std :: string const & suffix );
bool contains ( std :: string const & s , std :: string const & infix );
void toLowerInPlace ( std :: string & s );
std :: string toLower ( std :: string const & s );
std :: string trim ( std :: string const & str );
2014-12-21 00:21:23 +00:00
bool replaceInPlace ( std :: string & str , std :: string const & replaceThis , std :: string const & withThis );
2012-08-24 08:23:50 +01:00
struct pluralise {
2013-12-03 18:53:55 +00:00
pluralise ( std :: size_t count , std :: string const & label );
2012-08-24 08:23:50 +01:00
2013-12-03 18:53:55 +00:00
friend std :: ostream & operator << ( std :: ostream & os , pluralise const & pluraliser );
2012-08-24 08:23:50 +01:00
std :: size_t m_count ;
std :: string m_label ;
};
2012-08-23 20:08:50 +01:00
2012-05-16 15:09:17 +01:00
struct SourceLineInfo {
2013-12-03 18:53:55 +00:00
SourceLineInfo ();
2013-12-04 20:25:14 +00:00
SourceLineInfo ( char const * _file , std :: size_t _line );
2013-12-03 18:53:55 +00:00
SourceLineInfo ( SourceLineInfo const & other );
2015-05-19 18:40:00 +01:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2014-04-18 08:49:35 +01:00
SourceLineInfo ( SourceLineInfo && ) = default ;
SourceLineInfo & operator = ( SourceLineInfo const & ) = default ;
SourceLineInfo & operator = ( SourceLineInfo && ) = default ;
# endif
2013-12-03 18:53:55 +00:00
bool empty () const ;
bool operator == ( SourceLineInfo const & other ) const ;
2015-03-04 08:23:40 +00:00
bool operator < ( SourceLineInfo const & other ) const ;
2013-12-03 18:53:55 +00:00
2012-02-15 18:37:21 +00:00
std :: string file ;
std :: size_t line ;
};
2013-12-03 18:53:55 +00:00
std :: ostream & operator << ( std :: ostream & os , SourceLineInfo const & info );
2012-02-15 18:37:21 +00:00
2013-04-24 19:10:02 +01:00
// This is just here to avoid compiler warnings with macro constants and boolean literals
inline bool isTrue ( bool value ){ return value ; }
2014-06-02 07:48:03 +01:00
inline bool alwaysTrue () { return true ; }
inline bool alwaysFalse () { return false ; }
2013-04-24 19:10:02 +01:00
2013-12-03 18:53:55 +00:00
void throwLogicError ( std :: string const & message , SourceLineInfo const & locationInfo );
2013-12-14 14:34:05 +00:00
2015-07-02 23:03:13 +01:00
void seedRng ( IConfig const & config );
unsigned int rngSeed ();
2013-12-14 14:34:05 +00:00
// Use this in variadic streaming macros to allow
// >> +StreamEndStop
// as well as
// >> stuff +StreamEndStop
struct StreamEndStop {
std :: string operator + () {
return std :: string ();
}
};
template < typename T >
T const & operator + ( T const & value , StreamEndStop ) {
return value ;
}
2011-05-24 08:23:02 +01:00
}
2012-08-13 07:46:10 +01:00
#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
2011-05-24 08:23:02 +01:00
2012-08-09 07:47:30 +01:00
#include <ostream>
namespace Catch {
class NotImplementedException : public std :: exception
{
public :
2013-04-24 19:10:02 +01:00
NotImplementedException ( SourceLineInfo const & lineInfo );
2014-05-20 18:50:59 +01:00
NotImplementedException ( NotImplementedException const & ) {}
2012-08-09 07:47:30 +01:00
2014-04-18 08:49:35 +01:00
virtual ~ NotImplementedException () CATCH_NOEXCEPT {}
2012-08-09 07:47:30 +01:00
2014-04-18 08:49:35 +01:00
virtual const char * what () const CATCH_NOEXCEPT ;
2012-08-09 07:47:30 +01:00
private :
std :: string m_what ;
SourceLineInfo m_lineInfo ;
};
} // end namespace Catch
///////////////////////////////////////////////////////////////////////////////
#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
// #included from: internal/catch_context.h
#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
2012-08-31 08:10:36 +01:00
// #included from: catch_interfaces_generators.h
#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
2012-08-09 07:47:30 +01:00
2012-08-31 08:10:36 +01:00
#include <string>
2012-02-25 09:39:45 +00:00
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-08-31 08:10:36 +01:00
struct IGeneratorInfo {
virtual ~ IGeneratorInfo ();
virtual bool moveNext () = 0 ;
virtual std :: size_t getCurrentIndex () const = 0 ;
2012-02-25 09:39:45 +00:00
};
2012-08-31 08:10:36 +01:00
struct IGeneratorsForTest {
virtual ~ IGeneratorsForTest ();
2012-05-16 15:09:17 +01:00
2013-04-24 19:10:02 +01:00
virtual IGeneratorInfo & getGeneratorInfo ( std :: string const & fileInfo , std :: size_t size ) = 0 ;
2012-08-31 08:10:36 +01:00
virtual bool moveNext () = 0 ;
2012-02-25 09:39:45 +00:00
};
2012-08-31 08:10:36 +01:00
IGeneratorsForTest * createGeneratorsForTest ();
} // end namespace Catch
2012-05-05 19:35:35 +01:00
// #included from: catch_ptr.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
2012-05-05 19:35:35 +01:00
2013-03-13 12:19:30 +00:00
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
#endif
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-05-05 19:35:35 +01:00
// An intrusive reference counting smart pointer.
// T must implement addRef() and release() methods
// typically implementing the IShared interface
template < typename T >
2012-05-16 15:09:17 +01:00
class Ptr {
2012-05-05 19:35:35 +01:00
public :
2015-07-02 08:21:38 +01:00
Ptr () : m_p ( CATCH_NULL ){}
2012-05-05 19:35:35 +01:00
Ptr ( T * p ) : m_p ( p ){
2012-07-28 20:37:07 +01:00
if ( m_p )
m_p -> addRef ();
2012-05-05 19:35:35 +01:00
}
2012-12-01 23:57:18 +00:00
Ptr ( Ptr const & other ) : m_p ( other . m_p ){
2012-07-28 20:37:07 +01:00
if ( m_p )
m_p -> addRef ();
2012-05-05 19:35:35 +01:00
}
~ Ptr (){
if ( m_p )
m_p -> release ();
}
2012-12-06 08:44:51 +00:00
void reset () {
if ( m_p )
m_p -> release ();
2015-07-02 08:21:38 +01:00
m_p = CATCH_NULL ;
2012-12-06 08:44:51 +00:00
}
2012-05-05 19:35:35 +01:00
Ptr & operator = ( T * p ){
Ptr temp ( p );
swap ( temp );
return * this ;
}
2012-12-01 23:57:18 +00:00
Ptr & operator = ( Ptr const & other ){
2012-05-05 19:35:35 +01:00
Ptr temp ( other );
swap ( temp );
return * this ;
}
2012-12-01 23:57:18 +00:00
void swap ( Ptr & other ) { std :: swap ( m_p , other . m_p ); }
2015-08-03 07:40:52 +01:00
T * get () const { return m_p ; }
2012-12-01 23:57:18 +00:00
T & operator * () const { return * m_p ; }
T * operator -> () const { return m_p ; }
2015-07-02 08:21:38 +01:00
bool operator ! () const { return m_p == CATCH_NULL ; }
operator SafeBool :: type () const { return SafeBool :: makeSafe ( m_p != CATCH_NULL ); }
2012-05-05 19:35:35 +01:00
private :
T * m_p ;
};
struct IShared : NonCopyable {
2012-08-13 07:46:10 +01:00
virtual ~ IShared ();
2012-12-01 23:57:18 +00:00
virtual void addRef () const = 0 ;
virtual void release () const = 0 ;
2012-05-05 19:35:35 +01:00
};
2012-12-01 23:57:18 +00:00
template < typename T = IShared >
2012-05-05 19:35:35 +01:00
struct SharedImpl : T {
SharedImpl () : m_rc ( 0 ){}
2012-12-01 23:57:18 +00:00
virtual void addRef () const {
2012-05-05 19:35:35 +01:00
++ m_rc ;
}
2012-12-01 23:57:18 +00:00
virtual void release () const {
2012-05-05 19:35:35 +01:00
if ( -- m_rc == 0 )
delete this ;
}
2012-12-01 23:57:18 +00:00
mutable unsigned int m_rc ;
2012-05-05 19:35:35 +01:00
};
} // end namespace Catch
2013-03-13 12:19:30 +00:00
#ifdef __clang__
#pragma clang diagnostic pop
#endif
2013-06-07 19:07:50 +01:00
#include <memory>
#include <vector>
#include <stdlib.h>
namespace Catch {
class TestCase ;
class Stream ;
struct IResultCapture ;
struct IRunner ;
struct IGeneratorsForTest ;
struct IConfig ;
struct IContext
{
virtual ~ IContext ();
2014-05-20 18:50:59 +01:00
virtual IResultCapture * getResultCapture () = 0 ;
virtual IRunner * getRunner () = 0 ;
2013-06-07 19:07:50 +01:00
virtual size_t getGeneratorIndex ( std :: string const & fileInfo , size_t totalSize ) = 0 ;
virtual bool advanceGeneratorsForCurrentTest () = 0 ;
virtual Ptr < IConfig const > getConfig () const = 0 ;
};
struct IMutableContext : IContext
{
virtual ~ IMutableContext ();
virtual void setResultCapture ( IResultCapture * resultCapture ) = 0 ;
virtual void setRunner ( IRunner * runner ) = 0 ;
virtual void setConfig ( Ptr < IConfig const > const & config ) = 0 ;
};
IContext & getCurrentContext ();
IMutableContext & getCurrentMutableContext ();
void cleanUpContext ();
Stream createStream ( std :: string const & streamName );
}
// #included from: internal/catch_test_registry.hpp
#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
// #included from: catch_interfaces_testcase.h
#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
2012-06-02 23:12:42 +01:00
#include <vector>
namespace Catch {
2012-08-23 20:08:50 +01:00
2014-05-16 18:54:48 +01:00
class TestSpec ;
2012-08-23 20:08:50 +01:00
2012-08-16 18:48:50 +01:00
struct ITestCase : IShared {
2012-06-02 23:12:42 +01:00
virtual void invoke () const = 0 ;
2012-08-16 18:48:50 +01:00
protected :
virtual ~ ITestCase ();
2012-06-02 23:12:42 +01:00
};
2012-12-01 23:57:18 +00:00
class TestCase ;
2014-04-15 18:44:37 +01:00
struct IConfig ;
2012-06-02 23:12:42 +01:00
struct ITestCaseRegistry {
2012-08-13 07:46:10 +01:00
virtual ~ ITestCaseRegistry ();
2013-04-24 19:10:02 +01:00
virtual std :: vector < TestCase > const & getAllTests () const = 0 ;
2015-08-07 17:30:34 +01:00
virtual std :: vector < TestCase > const & getAllTestsSorted ( IConfig const & config ) const = 0 ;
2012-06-02 23:12:42 +01:00
};
2015-08-07 17:30:34 +01:00
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 );
2012-06-02 23:12:42 +01:00
}
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-05-24 08:23:02 +01:00
template < typename C >
2012-08-16 18:48:50 +01:00
class MethodTestCase : public SharedImpl < ITestCase > {
2012-05-16 15:09:17 +01:00
2012-05-11 08:17:16 +01:00
public :
MethodTestCase ( void ( C ::* method )() ) : m_method ( method ) {}
2011-05-24 08:23:02 +01:00
2012-05-11 08:17:16 +01:00
virtual void invoke () const {
2011-05-24 08:23:02 +01:00
C obj ;
( obj . * m_method )();
}
private :
2012-08-16 18:48:50 +01:00
virtual ~ MethodTestCase () {}
2011-05-24 08:23:02 +01:00
void ( C ::* m_method )();
};
typedef void ( * TestFunction )();
2013-03-16 20:21:51 +00:00
struct NameAndDesc {
NameAndDesc ( const char * _name = "" , const char * _description = "" )
: name ( _name ), description ( _description )
{}
const char * name ;
const char * description ;
};
2012-05-16 15:09:17 +01:00
struct AutoReg {
2012-05-11 08:17:16 +01:00
AutoReg ( TestFunction function ,
2013-03-16 20:21:51 +00:00
SourceLineInfo const & lineInfo ,
NameAndDesc const & nameAndDesc );
2011-05-24 08:23:02 +01:00
template < typename C >
2012-05-11 08:17:16 +01:00
AutoReg ( void ( C ::* method )(),
2013-03-16 20:21:51 +00:00
char const * className ,
NameAndDesc const & nameAndDesc ,
SourceLineInfo const & lineInfo ) {
registerTestCase ( new MethodTestCase < C > ( method ),
className ,
nameAndDesc ,
lineInfo );
2011-05-24 08:23:02 +01:00
}
2012-05-11 08:17:16 +01:00
void registerTestCase ( ITestCase * testCase ,
2013-03-16 20:21:51 +00:00
char const * className ,
NameAndDesc const & nameAndDesc ,
SourceLineInfo const & lineInfo );
2011-05-24 08:23:02 +01:00
2012-05-11 08:17:16 +01:00
~ AutoReg ();
2011-05-24 08:23:02 +01:00
private :
2013-04-24 19:10:02 +01:00
AutoReg ( AutoReg const & );
void operator = ( AutoReg const & );
2011-05-24 08:23:02 +01:00
};
} // end namespace Catch
2013-03-16 20:21:51 +00:00
#ifdef CATCH_CONFIG_VARIADIC_MACROS
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE( ... ) \
2013-06-07 19:07:50 +01:00
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
2011-05-24 08:23:02 +01:00
2013-03-16 20:21:51 +00:00
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
2011-05-24 08:23:02 +01:00
2013-03-16 20:21:51 +00:00
///////////////////////////////////////////////////////////////////////////////
2013-06-07 19:07:50 +01:00
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
2013-03-16 20:21:51 +00:00
namespace{ \
2013-06-07 19:07:50 +01:00
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
2013-03-16 20:21:51 +00:00
void test(); \
}; \
2013-06-07 19:07:50 +01:00
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
2013-03-16 20:21:51 +00:00
} \
2013-06-07 19:07:50 +01:00
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
2011-05-24 08:23:02 +01:00
2013-03-16 20:21:51 +00:00
#else
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
2013-06-07 19:07:50 +01:00
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
2013-03-16 20:21:51 +00:00
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
///////////////////////////////////////////////////////////////////////////////
2013-06-07 19:07:50 +01:00
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
2013-03-16 20:21:51 +00:00
namespace{ \
2013-06-07 19:07:50 +01:00
struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
2013-03-16 20:21:51 +00:00
void test(); \
}; \
2013-06-07 19:07:50 +01:00
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
2013-03-16 20:21:51 +00:00
} \
2013-06-07 19:07:50 +01:00
void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
2013-03-16 20:21:51 +00:00
#endif
2011-05-24 08:23:02 +01:00
// #included from: internal/catch_capture.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
2014-06-02 07:48:03 +01:00
// #included from: catch_result_builder.h
#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
2012-05-16 15:09:17 +01:00
2011-05-24 08:23:02 +01:00
// #included from: catch_result_type.h
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-05-24 08:23:02 +01:00
2012-11-13 22:04:29 +00:00
// ResultWas::OfType enum
struct ResultWas { enum OfType {
Unknown = - 1 ,
Ok = 0 ,
Info = 1 ,
Warning = 2 ,
2011-05-24 08:23:02 +01:00
2012-11-13 22:04:29 +00:00
FailureBit = 0x10 ,
2011-05-24 08:23:02 +01:00
2012-11-13 22:04:29 +00:00
ExpressionFailed = FailureBit | 1 ,
ExplicitFailure = FailureBit | 2 ,
2011-05-24 08:23:02 +01:00
2012-11-13 22:04:29 +00:00
Exception = 0x100 | FailureBit ,
2011-05-24 08:23:02 +01:00
2012-11-13 22:04:29 +00:00
ThrewException = Exception | 1 ,
2014-08-22 19:35:41 +01:00
DidntThrowException = Exception | 2 ,
FatalErrorCondition = 0x200 | FailureBit
2011-05-24 08:23:02 +01:00
2012-11-13 22:04:29 +00:00
}; };
2011-05-24 08:23:02 +01:00
2012-11-13 22:04:29 +00:00
inline bool isOk ( ResultWas :: OfType resultType ) {
return ( resultType & ResultWas :: FailureBit ) == 0 ;
}
2013-02-02 20:37:58 +00:00
inline bool isJustInfo ( int flags ) {
return flags == ResultWas :: Info ;
}
2012-10-09 11:48:55 +01:00
2012-11-13 22:04:29 +00:00
// ResultDisposition::Flags enum
struct ResultDisposition { enum Flags {
2015-05-19 18:40:00 +01:00
Normal = 0x01 ,
2012-11-13 22:04:29 +00:00
2015-05-19 18:40:00 +01:00
ContinueOnFailure = 0x02 , // Failures fail test, but execution continues
FalseTest = 0x04 , // Prefix expression with !
SuppressFail = 0x08 // Failures are reported but do not fail the test
2012-11-13 22:04:29 +00:00
}; };
inline ResultDisposition :: Flags operator | ( ResultDisposition :: Flags lhs , ResultDisposition :: Flags rhs ) {
return static_cast < ResultDisposition :: Flags > ( static_cast < int > ( lhs ) | static_cast < int > ( rhs ) );
}
2012-11-17 10:49:24 +00:00
inline bool shouldContinueOnFailure ( int flags ) { return ( flags & ResultDisposition :: ContinueOnFailure ) != 0 ; }
2014-06-02 07:48:03 +01:00
inline bool isFalseTest ( int flags ) { return ( flags & ResultDisposition :: FalseTest ) != 0 ; }
2012-11-17 10:49:24 +00:00
inline bool shouldSuppressFailure ( int flags ) { return ( flags & ResultDisposition :: SuppressFail ) != 0 ; }
2012-11-13 22:04:29 +00:00
} // end namespace Catch
2011-05-24 08:23:02 +01:00
2014-06-02 07:48:03 +01:00
// #included from: catch_assertionresult.h
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
#include <string>
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-05-24 08:23:02 +01:00
2012-11-01 08:27:09 +00:00
struct AssertionInfo
2012-10-09 11:48:55 +01:00
{
2012-11-01 08:27:09 +00:00
AssertionInfo () {}
2013-04-24 19:10:02 +01:00
AssertionInfo ( std :: string const & _macroName ,
SourceLineInfo const & _lineInfo ,
std :: string const & _capturedExpression ,
2012-11-13 22:04:29 +00:00
ResultDisposition :: Flags _resultDisposition );
2012-10-09 11:48:55 +01:00
std :: string macroName ;
SourceLineInfo lineInfo ;
std :: string capturedExpression ;
2012-11-13 22:04:29 +00:00
ResultDisposition :: Flags resultDisposition ;
2012-11-01 08:27:09 +00:00
};
struct AssertionResultData
{
AssertionResultData () : resultType ( ResultWas :: Unknown ) {}
2012-10-09 11:48:55 +01:00
std :: string reconstructedExpression ;
std :: string message ;
ResultWas :: OfType resultType ;
};
2012-11-01 08:27:09 +00:00
class AssertionResult {
2012-05-16 15:09:17 +01:00
public :
2012-11-01 08:27:09 +00:00
AssertionResult ();
2013-04-24 19:10:02 +01:00
AssertionResult ( AssertionInfo const & info , AssertionResultData const & data );
2012-11-01 08:27:09 +00:00
~ AssertionResult ();
2015-05-19 18:40:00 +01:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2014-04-18 08:49:35 +01:00
AssertionResult ( AssertionResult const & ) = default ;
AssertionResult ( AssertionResult && ) = default ;
AssertionResult & operator = ( AssertionResult const & ) = default ;
AssertionResult & operator = ( AssertionResult && ) = default ;
# endif
2011-05-24 08:23:02 +01:00
2012-11-13 22:04:29 +00:00
bool isOk () const ;
bool succeeded () const ;
2012-08-09 07:47:30 +01:00
ResultWas :: OfType getResultType () const ;
bool hasExpression () const ;
bool hasMessage () const ;
std :: string getExpression () const ;
2013-06-07 19:07:50 +01:00
std :: string getExpressionInMacro () const ;
2012-08-09 07:47:30 +01:00
bool hasExpandedExpression () const ;
std :: string getExpandedExpression () const ;
std :: string getMessage () const ;
2012-11-01 08:27:09 +00:00
SourceLineInfo getSourceInfo () const ;
2012-08-09 07:47:30 +01:00
std :: string getTestMacroName () const ;
2011-05-24 08:23:02 +01:00
protected :
2012-11-01 08:27:09 +00:00
AssertionInfo m_info ;
AssertionResultData m_resultData ;
2011-05-24 08:23:02 +01:00
};
} // end namespace Catch
2015-07-15 23:03:11 +01:00
// #included from: 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 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 :: 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
2014-06-02 07:48:03 +01:00
namespace Catch {
struct TestFailureException {};
template < typename T > class ExpressionLhs ;
struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison ;
struct CopyableStream {
CopyableStream () {}
CopyableStream ( CopyableStream const & other ) {
oss << other . oss . str ();
}
CopyableStream & operator = ( CopyableStream const & other ) {
oss . str ( "" );
oss << other . oss . str ();
return * this ;
}
std :: ostringstream oss ;
};
class ResultBuilder {
public :
ResultBuilder ( char const * macroName ,
SourceLineInfo const & lineInfo ,
char const * capturedExpression ,
2015-07-13 06:36:07 +01:00
ResultDisposition :: Flags resultDisposition ,
char const * secondArg = "" );
2014-06-02 07:48:03 +01:00
template < typename T >
2015-06-29 18:05:23 +01:00
ExpressionLhs < T const &> operator <= ( T const & operand );
ExpressionLhs < bool > operator <= ( bool value );
2014-06-02 07:48:03 +01:00
template < typename T >
ResultBuilder & operator << ( T const & value ) {
m_stream . oss << value ;
return * this ;
}
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator && ( RhsT const & );
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator || ( RhsT const & );
ResultBuilder & setResultType ( ResultWas :: OfType result );
ResultBuilder & setResultType ( bool result );
ResultBuilder & setLhs ( std :: string const & lhs );
ResultBuilder & setRhs ( std :: string const & rhs );
ResultBuilder & setOp ( std :: string const & op );
void endExpression ();
std :: string reconstructExpression () const ;
AssertionResult build () const ;
void useActiveException ( ResultDisposition :: Flags resultDisposition = ResultDisposition :: Normal );
void captureResult ( ResultWas :: OfType resultType );
void captureExpression ();
2015-07-13 06:36:07 +01:00
void captureExpectedException ( std :: string const & expectedMessage );
2015-07-15 23:03:11 +01:00
void captureExpectedException ( Matchers :: Impl :: Matcher < std :: string > const & matcher );
2015-07-13 06:36:07 +01:00
void handleResult ( AssertionResult const & result );
2014-06-02 07:48:03 +01:00
void react ();
bool shouldDebugBreak () const ;
bool allowThrows () const ;
private :
AssertionInfo m_assertionInfo ;
AssertionResultData m_data ;
struct ExprComponents {
ExprComponents () : testFalse ( false ) {}
bool testFalse ;
std :: string lhs , rhs , op ;
} m_exprComponents ;
CopyableStream m_stream ;
bool m_shouldDebugBreak ;
bool m_shouldThrow ;
};
} // namespace Catch
// Include after due to circular dependency:
// #included from: catch_expression_lhs.hpp
#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
// #included from: catch_evaluate.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
2013-03-25 09:25:31 +00:00
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
#endif
2014-04-23 18:19:49 +01:00
#include <cstddef>
2012-05-16 15:09:17 +01:00
namespace Catch {
namespace Internal {
enum Operator {
2011-05-24 08:23:02 +01:00
IsEqualTo ,
IsNotEqualTo ,
IsLessThan ,
IsGreaterThan ,
IsLessThanOrEqualTo ,
IsGreaterThanOrEqualTo
};
2012-05-21 18:52:09 +01:00
template < Operator Op > struct OperatorTraits { static const char * getName (){ return "*error*" ; } };
template <> struct OperatorTraits < IsEqualTo > { static const char * getName (){ return "==" ; } };
template <> struct OperatorTraits < IsNotEqualTo > { static const char * getName (){ return "!=" ; } };
template <> struct OperatorTraits < IsLessThan > { static const char * getName (){ return "<" ; } };
template <> struct OperatorTraits < IsGreaterThan > { static const char * getName (){ return ">" ; } };
template <> struct OperatorTraits < IsLessThanOrEqualTo > { static const char * getName (){ return "<=" ; } };
template <> struct OperatorTraits < IsGreaterThanOrEqualTo > { static const char * getName (){ return ">=" ; } };
2011-05-24 08:23:02 +01:00
2013-04-22 18:55:12 +01:00
template < typename T >
2013-04-24 19:10:02 +01:00
inline T & opCast ( T const & t ) { return const_cast < T &> ( t ); }
2013-04-22 18:55:12 +01:00
// nullptr_t support based on pull request #154 from Konstantin Baumann
#ifdef CATCH_CONFIG_CPP11_NULLPTR
inline std :: nullptr_t opCast ( std :: nullptr_t ) { return nullptr ; }
#endif // CATCH_CONFIG_CPP11_NULLPTR
2011-05-24 08:23:02 +01:00
// So the compare overloads can be operator agnostic we convey the operator as a template
// enum, which is used to specialise an Evaluator for doing the comparison.
template < typename T1 , typename T2 , Operator Op >
class Evaluator {};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsEqualTo > {
2013-04-24 19:10:02 +01:00
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2013-04-22 18:55:12 +01:00
return opCast ( lhs ) == opCast ( rhs );
2011-05-24 08:23:02 +01:00
}
};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsNotEqualTo > {
2013-04-24 19:10:02 +01:00
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2013-04-22 18:55:12 +01:00
return opCast ( lhs ) != opCast ( rhs );
2011-05-24 08:23:02 +01:00
}
};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsLessThan > {
2013-04-24 19:10:02 +01:00
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2013-04-22 18:55:12 +01:00
return opCast ( lhs ) < opCast ( rhs );
2011-05-24 08:23:02 +01:00
}
};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsGreaterThan > {
2013-04-24 19:10:02 +01:00
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2013-04-22 18:55:12 +01:00
return opCast ( lhs ) > opCast ( rhs );
2011-05-24 08:23:02 +01:00
}
};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsGreaterThanOrEqualTo > {
2013-04-24 19:10:02 +01:00
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2013-04-22 18:55:12 +01:00
return opCast ( lhs ) >= opCast ( rhs );
2011-05-24 08:23:02 +01:00
}
};
template < typename T1 , typename T2 >
2012-05-16 15:09:17 +01:00
struct Evaluator < T1 , T2 , IsLessThanOrEqualTo > {
2013-04-24 19:10:02 +01:00
static bool evaluate ( T1 const & lhs , T2 const & rhs ) {
2013-04-22 18:55:12 +01:00
return opCast ( lhs ) <= opCast ( rhs );
2011-05-24 08:23:02 +01:00
}
};
template < Operator Op , typename T1 , typename T2 >
2013-04-24 19:10:02 +01:00
bool applyEvaluator ( T1 const & lhs , T2 const & rhs ) {
2011-05-24 08:23:02 +01:00
return Evaluator < T1 , T2 , Op >:: evaluate ( lhs , rhs );
}
2012-11-13 22:04:29 +00:00
// This level of indirection allows us to specialise for integer types
// to avoid signed/ unsigned warnings
2011-05-24 08:23:02 +01:00
// "base" overload
template < Operator Op , typename T1 , typename T2 >
2013-04-24 19:10:02 +01:00
bool compare ( T1 const & lhs , T2 const & rhs ) {
2011-05-24 08:23:02 +01:00
return Evaluator < T1 , T2 , Op >:: evaluate ( lhs , rhs );
}
// unsigned X to int
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned int lhs , int rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned long lhs , int rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned char lhs , int rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned int > ( rhs ) );
}
// unsigned X to long
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned int lhs , long rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned long lhs , long rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( unsigned char lhs , long rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( lhs , static_cast < unsigned long > ( rhs ) );
}
// int to unsigned X
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( int lhs , unsigned int rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ), rhs );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( int lhs , unsigned long rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ), rhs );
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( int lhs , unsigned char rhs ) {
2011-05-24 08:23:02 +01:00
return applyEvaluator < Op > ( static_cast < unsigned int > ( lhs ), rhs );
}
// long to unsigned X
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( long lhs , unsigned int rhs ) {
2012-04-27 14:42:40 -03:00
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ), rhs );
2011-05-24 08:23:02 +01:00
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( long lhs , unsigned long rhs ) {
2012-04-27 14:42:40 -03:00
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ), rhs );
2011-05-24 08:23:02 +01:00
}
2012-05-16 15:09:17 +01:00
template < Operator Op > bool compare ( long lhs , unsigned char rhs ) {
2012-04-27 14:42:40 -03:00
return applyEvaluator < Op > ( static_cast < unsigned long > ( lhs ), rhs );
2011-05-24 08:23:02 +01:00
}
2012-05-25 08:52:05 +01:00
// pointer to long (when comparing against NULL)
2012-11-13 22:04:29 +00:00
template < Operator Op , typename T > bool compare ( long lhs , T * rhs ) {
2011-05-24 08:23:02 +01:00
return Evaluator < T * , T * , Op >:: evaluate ( reinterpret_cast < T *> ( lhs ), rhs );
2012-05-07 19:46:19 +01:00
}
2012-11-13 22:04:29 +00:00
template < Operator Op , typename T > bool compare ( T * lhs , long rhs ) {
2012-05-07 19:46:19 +01:00
return Evaluator < T * , T * , Op >:: evaluate ( lhs , reinterpret_cast < T *> ( rhs ) );
2011-05-24 08:23:02 +01:00
}
2012-05-25 08:52:05 +01:00
// pointer to int (when comparing against NULL)
2012-11-13 22:04:29 +00:00
template < Operator Op , typename T > bool compare ( int lhs , T * rhs ) {
2012-05-25 08:52:05 +01:00
return Evaluator < T * , T * , Op >:: evaluate ( reinterpret_cast < T *> ( lhs ), rhs );
}
2012-11-13 22:04:29 +00:00
template < Operator Op , typename T > bool compare ( T * lhs , int rhs ) {
2012-05-25 08:52:05 +01:00
return Evaluator < T * , T * , Op >:: evaluate ( lhs , reinterpret_cast < T *> ( rhs ) );
}
2015-07-23 23:06:26 +01:00
#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
2013-04-22 18:55:12 +01:00
#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 ) {
2015-07-23 23:06:26 +01:00
return Evaluator < T * , T * , Op >:: evaluate ( nullptr , rhs );
2013-04-22 18:55:12 +01:00
}
template < Operator Op , typename T > bool compare ( T * lhs , std :: nullptr_t ) {
2015-07-23 23:06:26 +01:00
return Evaluator < T * , T * , Op >:: evaluate ( lhs , nullptr );
2013-04-22 18:55:12 +01:00
}
#endif // CATCH_CONFIG_CPP11_NULLPTR
2011-05-24 08:23:02 +01:00
} // end of namespace Internal
} // end of namespace Catch
2013-03-25 09:25:31 +00:00
#ifdef _MSC_VER
#pragma warning(pop)
#endif
2014-06-02 07:48:03 +01:00
// #included from: catch_tostring.h
#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
#include <sstream>
#include <iomanip>
#include <limits>
#include <vector>
#include <cstddef>
#ifdef __OBJC__
// #included from: catch_objc_arc.hpp
#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
#import <Foundation/Foundation.h>
#ifdef __has_feature
#define CATCH_ARC_ENABLED __has_feature(objc_arc)
#else
#define CATCH_ARC_ENABLED 0
#endif
void arcSafeRelease ( NSObject * obj );
id performOptionalSelector ( id obj , SEL sel );
#if !CATCH_ARC_ENABLED
inline void arcSafeRelease ( NSObject * obj ) {
[ obj release ];
}
inline id performOptionalSelector ( id obj , SEL sel ) {
if ( [ obj respondsToSelector : sel ] )
return [ obj performSelector : sel ];
return nil ;
}
#define CATCH_UNSAFE_UNRETAINED
#define CATCH_ARC_STRONG
#else
inline void arcSafeRelease ( NSObject * ){}
inline id performOptionalSelector ( id obj , SEL sel ) {
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
#endif
if ( [ obj respondsToSelector : sel ] )
return [ obj performSelector : sel ];
#ifdef __clang__
#pragma clang diagnostic pop
#endif
return nil ;
}
#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
#define CATCH_ARC_STRONG __strong
#endif
#endif
2015-05-19 18:40:00 +01:00
#ifdef CATCH_CONFIG_CPP11_TUPLE
2014-12-30 18:47:29 +00:00
#include <tuple>
2015-05-19 18:40:00 +01:00
#endif
#ifdef CATCH_CONFIG_CPP11_IS_ENUM
2014-12-30 18:47:29 +00:00
#include <type_traits>
#endif
2014-06-02 07:48:03 +01:00
namespace Catch {
2014-09-03 19:23:22 +01:00
// Why we're here.
template < typename T >
std :: string toString ( T const & value );
2014-12-30 18:47:29 +00:00
// Built in overloads
std :: string toString ( std :: string const & value );
std :: string toString ( std :: wstring const & value );
std :: string toString ( const char * const value );
std :: string toString ( char * const value );
std :: string toString ( const wchar_t * const value );
std :: string toString ( wchar_t * const value );
std :: string toString ( int value );
std :: string toString ( unsigned long value );
std :: string toString ( unsigned int value );
std :: string toString ( const double value );
std :: string toString ( const float value );
std :: string toString ( bool value );
std :: string toString ( char value );
std :: string toString ( signed char value );
std :: string toString ( unsigned char value );
2015-07-23 23:06:26 +01:00
#ifdef CATCH_CONFIG_CPP11_LONG_LONG
std :: string toString ( long long value );
std :: string toString ( unsigned long long value );
#endif
2014-12-30 18:47:29 +00:00
#ifdef CATCH_CONFIG_CPP11_NULLPTR
std :: string toString ( std :: nullptr_t );
#endif
#ifdef __OBJC__
std :: string toString ( NSString const * const & nsstring );
std :: string toString ( NSString * CATCH_ARC_STRONG const & nsstring );
std :: string toString ( NSObject * const & nsObject );
#endif
2014-06-02 07:48:03 +01:00
namespace Detail {
2015-07-23 23:06:26 +01:00
extern const std :: string unprintableString ;
2014-09-15 18:40:24 +01:00
2014-06-02 07:48:03 +01:00
struct BorgType {
template < typename T > BorgType ( T const & );
};
2015-06-30 18:26:09 +01:00
struct TrueType { char sizer [ 1 ]; };
struct FalseType { char sizer [ 2 ]; };
2014-06-02 07:48:03 +01:00
TrueType & testStreamable ( std :: ostream & );
FalseType testStreamable ( FalseType );
FalseType operator << ( std :: ostream const & , BorgType const & );
template < typename T >
struct IsStreamInsertable {
static std :: ostream & s ;
static T const & t ;
enum { value = sizeof ( testStreamable ( s << t ) ) == sizeof ( TrueType ) };
};
2015-05-19 18:40:00 +01:00
#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
2014-09-03 19:23:22 +01:00
template < typename T ,
2014-09-15 18:40:24 +01:00
bool IsEnum = std :: is_enum < T >:: value
2014-09-03 19:23:22 +01:00
>
struct EnumStringMaker
{
2014-09-15 18:40:24 +01:00
static std :: string convert ( T const & ) { return unprintableString ; }
2014-09-03 19:23:22 +01:00
};
template < typename T >
struct EnumStringMaker < T , true >
{
static std :: string convert ( T const & v )
{
return :: Catch :: toString (
static_cast < typename std :: underlying_type < T >:: type > ( v )
);
}
};
#endif
2014-06-02 07:48:03 +01:00
template < bool C >
struct StringMakerBase {
2015-05-19 18:40:00 +01:00
#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
2014-09-03 19:23:22 +01:00
template < typename T >
static std :: string convert ( T const & v )
{
return EnumStringMaker < T >:: convert ( v );
}
#else
2014-06-02 07:48:03 +01:00
template < typename T >
2014-09-15 18:40:24 +01:00
static std :: string convert ( T const & ) { return unprintableString ; }
2014-09-03 19:23:22 +01:00
#endif
2014-06-02 07:48:03 +01:00
};
template <>
struct StringMakerBase < true > {
template < typename T >
static std :: string convert ( T const & _value ) {
std :: ostringstream oss ;
oss << _value ;
return oss . str ();
}
};
std :: string rawMemoryToString ( const void * object , std :: size_t size );
template < typename T >
inline std :: string rawMemoryToString ( const T & object ) {
return rawMemoryToString ( & object , sizeof ( object ) );
2012-10-09 11:48:55 +01:00
}
2014-06-02 07:48:03 +01:00
} // end namespace Detail
2012-11-01 08:27:09 +00:00
2014-06-02 07:48:03 +01:00
template < typename T >
struct StringMaker :
Detail :: StringMakerBase < Detail :: IsStreamInsertable < T >:: value > {};
2013-06-29 12:11:32 +01:00
2014-06-02 07:48:03 +01:00
template < typename T >
struct StringMaker < T *> {
template < typename U >
static std :: string convert ( U * p ) {
if ( ! p )
2015-07-02 08:21:38 +01:00
return "NULL" ;
2014-06-02 07:48:03 +01:00
else
return Detail :: rawMemoryToString ( p );
}
2011-05-24 08:23:02 +01:00
};
2014-06-02 07:48:03 +01:00
template < typename R , typename C >
struct StringMaker < R C ::*> {
static std :: string convert ( R C ::* p ) {
if ( ! p )
2015-07-02 08:21:38 +01:00
return "NULL" ;
2014-06-02 07:48:03 +01:00
else
return Detail :: rawMemoryToString ( p );
}
};
namespace Detail {
template < typename InputIterator >
std :: string rangeToString ( InputIterator first , InputIterator last );
}
2014-09-15 18:40:24 +01:00
//template<typename T, typename Allocator>
//struct StringMaker<std::vector<T, Allocator> > {
// static std::string convert( std::vector<T,Allocator> const& v ) {
// return Detail::rangeToString( v.begin(), v.end() );
// }
//};
2014-06-02 07:48:03 +01:00
template < typename T , typename Allocator >
2014-09-15 18:40:24 +01:00
std :: string toString ( std :: vector < T , Allocator > const & v ) {
return Detail :: rangeToString ( v . begin (), v . end () );
}
2014-06-02 07:48:03 +01:00
2015-05-19 18:40:00 +01:00
#ifdef CATCH_CONFIG_CPP11_TUPLE
2015-03-04 18:33:31 +00:00
// toString for tuples
2014-12-30 18:47:29 +00:00
namespace TupleDetail {
template <
typename Tuple ,
std :: size_t N = 0 ,
bool = ( N < std :: tuple_size < Tuple >:: value )
>
struct ElementPrinter {
static void print ( const Tuple & tuple , std :: ostream & os )
{
os << ( N ? ", " : " " )
<< Catch :: toString ( std :: get < N > ( tuple ));
ElementPrinter < Tuple , N + 1 >:: print ( tuple , os );
}
};
template <
typename Tuple ,
std :: size_t N
>
struct ElementPrinter < Tuple , N , false > {
static void print ( const Tuple & , std :: ostream & ) {}
};
}
template < typename ... Types >
struct StringMaker < std :: tuple < Types ... >> {
static std :: string convert ( const std :: tuple < Types ... >& tuple )
{
std :: ostringstream os ;
os << '{' ;
TupleDetail :: ElementPrinter < std :: tuple < Types ... >>:: print ( tuple , os );
os << " }" ;
return os . str ();
}
};
2015-05-19 18:40:00 +01:00
#endif // CATCH_CONFIG_CPP11_TUPLE
2014-12-30 18:47:29 +00:00
2014-06-02 07:48:03 +01:00
namespace Detail {
template < typename T >
std :: string makeString ( T const & value ) {
return StringMaker < T >:: convert ( value );
}
} // end namespace Detail
/// \brief converts any type to a string
///
/// The default template forwards on to ostringstream - except when an
/// ostringstream overload does not exist - in which case it attempts to detect
/// that and writes {?}.
/// Overload (not specialise) this template for custom typs that you don't want
/// to provide an ostream overload for.
template < typename T >
std :: string toString ( T const & value ) {
return StringMaker < T >:: convert ( value );
}
namespace Detail {
template < typename InputIterator >
std :: string rangeToString ( InputIterator first , InputIterator last ) {
std :: ostringstream oss ;
oss << "{ " ;
if ( first != last ) {
2014-12-12 08:11:18 +00:00
oss << Catch :: toString ( * first );
for ( ++ first ; first != last ; ++ first )
oss << ", " << Catch :: toString ( * first );
2014-06-02 07:48:03 +01:00
}
oss << " }" ;
return oss . str ();
}
}
2012-05-09 19:04:00 +01:00
} // end namespace Catch
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-05-11 08:17:16 +01:00
2014-04-18 08:49:35 +01:00
// Wraps the LHS of an expression and captures the operator and RHS (if any) -
2014-06-02 07:48:03 +01:00
// wrapping them all in a ResultBuilder object
2012-05-11 08:17:16 +01:00
template < typename T >
2012-11-01 08:27:09 +00:00
class ExpressionLhs {
2014-04-18 08:49:35 +01:00
ExpressionLhs & operator = ( ExpressionLhs const & );
2015-05-19 18:40:00 +01:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2014-04-18 08:49:35 +01:00
ExpressionLhs & operator = ( ExpressionLhs && ) = delete ;
# endif
2012-05-11 08:17:16 +01:00
public :
2014-06-02 07:48:03 +01:00
ExpressionLhs ( ResultBuilder & rb , T lhs ) : m_rb ( rb ), m_lhs ( lhs ) {}
2015-05-19 18:40:00 +01:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2014-04-18 08:49:35 +01:00
ExpressionLhs ( ExpressionLhs const & ) = default ;
ExpressionLhs ( ExpressionLhs && ) = default ;
# endif
2012-05-11 08:17:16 +01:00
template < typename RhsT >
2014-06-02 07:48:03 +01:00
ResultBuilder & operator == ( RhsT const & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
template < typename RhsT >
2014-06-02 07:48:03 +01:00
ResultBuilder & operator != ( RhsT const & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsNotEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
template < typename RhsT >
2014-06-02 07:48:03 +01:00
ResultBuilder & operator < ( RhsT const & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsLessThan > ( rhs );
2012-05-11 08:17:16 +01:00
}
template < typename RhsT >
2014-06-02 07:48:03 +01:00
ResultBuilder & operator > ( RhsT const & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsGreaterThan > ( rhs );
2012-05-11 08:17:16 +01:00
}
template < typename RhsT >
2014-06-02 07:48:03 +01:00
ResultBuilder & operator <= ( RhsT const & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsLessThanOrEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
template < typename RhsT >
2014-06-02 07:48:03 +01:00
ResultBuilder & operator >= ( RhsT const & rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsGreaterThanOrEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
2014-06-02 07:48:03 +01:00
ResultBuilder & operator == ( bool rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
2014-06-02 07:48:03 +01:00
ResultBuilder & operator != ( bool rhs ) {
2012-10-09 20:58:33 +01:00
return captureExpression < Internal :: IsNotEqualTo > ( rhs );
2012-05-11 08:17:16 +01:00
}
2014-06-02 07:48:03 +01:00
void endExpression () {
2012-11-01 08:27:09 +00:00
bool value = m_lhs ? true : false ;
2014-06-02 07:48:03 +01:00
m_rb
2012-11-01 08:27:09 +00:00
. setLhs ( Catch :: toString ( value ) )
. setResultType ( value )
2014-06-02 07:48:03 +01:00
. endExpression ();
2012-05-11 08:17:16 +01:00
}
2012-11-01 08:27:09 +00:00
// Only simple binary expressions are allowed on the LHS.
// If more complex compositions are required then place the sub expression in parentheses
2013-04-24 19:10:02 +01:00
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator + ( RhsT const & );
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator - ( RhsT const & );
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator / ( RhsT const & );
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator * ( RhsT const & );
2013-06-29 12:11:32 +01:00
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator && ( RhsT const & );
template < typename RhsT > STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison & operator || ( RhsT const & );
2012-05-11 08:17:16 +01:00
2012-10-09 20:58:33 +01:00
private :
template < Internal :: Operator Op , typename RhsT >
2014-06-02 07:48:03 +01:00
ResultBuilder & captureExpression ( RhsT const & rhs ) {
return m_rb
2012-11-01 08:27:09 +00:00
. setResultType ( Internal :: compare < Op > ( m_lhs , rhs ) )
. setLhs ( Catch :: toString ( m_lhs ) )
2012-10-09 20:58:33 +01:00
. setRhs ( Catch :: toString ( rhs ) )
. setOp ( Internal :: OperatorTraits < Op >:: getName () );
}
2012-05-11 08:17:16 +01:00
private :
2014-06-02 07:48:03 +01:00
ResultBuilder & m_rb ;
2012-05-11 08:17:16 +01:00
T m_lhs ;
};
} // end namespace Catch
2014-06-02 07:48:03 +01:00
2012-05-16 15:09:17 +01:00
namespace Catch {
template < typename T >
2015-06-29 18:05:23 +01:00
inline ExpressionLhs < T const &> ResultBuilder :: operator <= ( T const & operand ) {
2014-06-02 07:48:03 +01:00
return ExpressionLhs < T const &> ( * this , operand );
2012-05-16 15:09:17 +01:00
}
2015-06-29 18:05:23 +01:00
inline ExpressionLhs < bool > ResultBuilder :: operator <= ( bool value ) {
2014-06-02 07:48:03 +01:00
return ExpressionLhs < bool > ( * this , value );
2012-05-16 15:09:17 +01:00
}
2014-06-02 07:48:03 +01:00
} // namespace Catch
2012-05-16 15:09:17 +01:00
2013-02-02 20:37:58 +00:00
// #included from: catch_message.h
#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
#include <string>
namespace Catch {
struct MessageInfo {
MessageInfo ( std :: string const & _macroName ,
SourceLineInfo const & _lineInfo ,
ResultWas :: OfType _type );
std :: string macroName ;
SourceLineInfo lineInfo ;
ResultWas :: OfType type ;
std :: string message ;
unsigned int sequence ;
bool operator == ( MessageInfo const & other ) const {
return sequence == other . sequence ;
}
bool operator < ( MessageInfo const & other ) const {
return sequence < other . sequence ;
}
private :
static unsigned int globalCount ;
};
2013-06-28 17:09:57 +01:00
struct MessageBuilder {
MessageBuilder ( std :: string const & macroName ,
SourceLineInfo const & lineInfo ,
ResultWas :: OfType type )
: m_info ( macroName , lineInfo , type )
{}
2013-02-02 20:37:58 +00:00
template < typename T >
2013-06-28 17:09:57 +01:00
MessageBuilder & operator << ( T const & value ) {
m_stream << value ;
2013-02-02 20:37:58 +00:00
return * this ;
}
2013-06-28 17:09:57 +01:00
MessageInfo m_info ;
std :: ostringstream m_stream ;
2013-02-02 20:37:58 +00:00
};
2013-06-28 17:09:57 +01:00
class ScopedMessage {
2013-02-02 20:37:58 +00:00
public :
2013-06-28 17:09:57 +01:00
ScopedMessage ( MessageBuilder const & builder );
2014-05-20 18:50:59 +01:00
ScopedMessage ( ScopedMessage const & other );
2013-06-28 17:09:57 +01:00
~ ScopedMessage ();
MessageInfo m_info ;
2013-02-02 20:37:58 +00:00
};
} // end namespace Catch
2012-05-09 19:04:00 +01:00
// #included from: catch_interfaces_capture.h
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
2012-05-09 19:04:00 +01:00
#include <string>
2012-05-16 15:09:17 +01:00
namespace Catch {
2012-12-01 23:57:18 +00:00
class TestCase ;
2012-11-01 08:27:09 +00:00
class AssertionResult ;
struct AssertionInfo ;
2012-12-01 23:57:18 +00:00
struct SectionInfo ;
2013-06-28 17:09:57 +01:00
struct MessageInfo ;
2013-02-02 20:37:58 +00:00
class ScopedMessageBuilder ;
2013-12-03 18:53:55 +00:00
struct Counts ;
2012-05-09 19:04:00 +01:00
2012-05-16 15:09:17 +01:00
struct IResultCapture {
2012-05-09 19:04:00 +01:00
2012-08-13 07:46:10 +01:00
virtual ~ IResultCapture ();
2012-05-09 19:04:00 +01:00
2013-02-02 20:37:58 +00:00
virtual void assertionEnded ( AssertionResult const & result ) = 0 ;
2012-12-01 23:57:18 +00:00
virtual bool sectionStarted ( SectionInfo const & sectionInfo ,
2012-05-16 15:09:17 +01:00
Counts & assertions ) = 0 ;
2013-08-15 19:01:00 +01:00
virtual void sectionEnded ( SectionInfo const & name , Counts const & assertions , double _durationInSeconds ) = 0 ;
2013-06-28 17:09:57 +01:00
virtual void pushScopedMessage ( MessageInfo const & message ) = 0 ;
virtual void popScopedMessage ( MessageInfo const & message ) = 0 ;
2013-02-02 20:37:58 +00:00
2012-05-16 15:09:17 +01:00
virtual std :: string getCurrentTestName () const = 0 ;
2012-11-01 08:27:09 +00:00
virtual const AssertionResult * getLastResult () const = 0 ;
2014-08-22 19:35:41 +01:00
virtual void handleFatalErrorCondition ( std :: string const & message ) = 0 ;
2012-05-09 19:04:00 +01:00
};
2014-06-02 07:48:03 +01:00
IResultCapture & getResultCapture ();
2012-05-09 19:04:00 +01:00
}
2013-12-03 18:53:55 +00:00
// #included from: catch_debugger.h
#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
2012-05-09 19:04:00 +01:00
2013-08-16 19:09:09 +01:00
// #included from: catch_platform.h
#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
2012-05-09 19:04:00 +01:00
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
#define CATCH_PLATFORM_MAC
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
#define CATCH_PLATFORM_IPHONE
2013-08-16 19:09:09 +01:00
#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
2012-05-09 19:04:00 +01:00
#define CATCH_PLATFORM_WINDOWS
#endif
2013-12-03 18:53:55 +00:00
#include <string>
namespace Catch {
bool isDebuggerActive ();
void writeToDebugConsole ( std :: string const & text );
}
2012-05-09 19:04:00 +01:00
#ifdef CATCH_PLATFORM_MAC
2013-12-03 18:53:55 +00:00
// The following code snippet based on:
2012-05-09 19:04:00 +01:00
// http://cocoawithlove.com/2008/03/break-into-debugger.html
#ifdef DEBUG
#if defined(__ppc64__) || defined(__ppc__)
2013-12-03 18:53:55 +00:00
#define CATCH_BREAK_INTO_DEBUGGER() \
if( Catch::isDebuggerActive() ) { \
__asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
: : : "memory","r0","r3","r4" ); \
}
2012-05-09 19:04:00 +01:00
#else
2013-12-03 18:53:55 +00:00
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
2012-05-09 19:04:00 +01:00
#endif
#endif
#elif defined(_MSC_VER)
2013-12-03 18:53:55 +00:00
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
2012-05-11 08:17:16 +01:00
#elif defined(__MINGW32__)
extern "C" __declspec ( dllimport ) void __stdcall DebugBreak ();
2013-12-03 18:53:55 +00:00
#define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
2012-05-09 19:04:00 +01:00
#endif
2013-12-03 18:53:55 +00:00
#ifndef CATCH_BREAK_INTO_DEBUGGER
2014-06-02 07:48:03 +01:00
#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
2013-12-03 18:53:55 +00:00
#endif
2012-05-09 19:04:00 +01:00
2014-06-02 07:48:03 +01:00
// #included from: catch_interfaces_runner.h
#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
2013-03-13 12:19:30 +00:00
2012-08-31 08:10:36 +01:00
namespace Catch {
2013-12-03 18:53:55 +00:00
class TestCase ;
2012-08-31 08:10:36 +01:00
2014-06-02 07:48:03 +01:00
struct IRunner {
virtual ~ IRunner ();
virtual bool aborting () const = 0 ;
2012-08-31 08:10:36 +01:00
};
}
2012-11-01 08:27:09 +00:00
///////////////////////////////////////////////////////////////////////////////
2014-06-02 07:48:03 +01:00
// In the event of a failure works out if the debugger needs to be invoked
// and/or an exception thrown and takes appropriate action.
// This needs to be done as a macro so the debugger will stop in the user
// source code rather than in Catch library code
#define INTERNAL_CATCH_REACT( resultBuilder ) \
if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
resultBuilder.react();
2012-11-01 08:27:09 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-13 22:04:29 +00:00
#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
2012-11-01 08:27:09 +00:00
do { \
2014-06-02 07:48:03 +01:00
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2012-11-01 08:27:09 +00:00
try { \
2015-06-29 18:05:23 +01:00
( __catchResult <= expr ).endExpression(); \
2012-11-01 08:27:09 +00:00
} \
2014-06-02 07:48:03 +01:00
catch( ... ) { \
__catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
} \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
2012-11-01 08:27:09 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-13 22:04:29 +00:00
#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
if( Catch::getResultCapture().getLastResult()->succeeded() )
2012-11-01 08:27:09 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-13 22:04:29 +00:00
#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
if( !Catch::getResultCapture().getLastResult()->succeeded() )
2012-11-01 08:27:09 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-13 22:04:29 +00:00
#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
2012-11-01 08:27:09 +00:00
do { \
2014-06-02 07:48:03 +01:00
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2012-11-01 08:27:09 +00:00
try { \
expr; \
2014-06-02 07:48:03 +01:00
__catchResult.captureResult( Catch::ResultWas::Ok ); \
2012-11-01 08:27:09 +00:00
} \
catch( ... ) { \
2014-06-02 07:48:03 +01:00
__catchResult.useActiveException( resultDisposition ); \
2012-11-01 08:27:09 +00:00
} \
2014-06-02 07:48:03 +01:00
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() )
2012-11-01 08:27:09 +00:00
///////////////////////////////////////////////////////////////////////////////
2015-07-15 23:03:11 +01:00
#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
2012-11-01 08:27:09 +00:00
do { \
2015-07-15 23:03:11 +01:00
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
2014-06-30 07:35:36 +01:00
if( __catchResult.allowThrows() ) \
try { \
2014-06-02 07:48:03 +01:00
expr; \
2014-06-30 07:35:36 +01:00
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
} \
catch( ... ) { \
2015-07-15 23:03:11 +01:00
__catchResult.captureExpectedException( matcher ); \
2014-06-30 07:35:36 +01:00
} \
else \
2014-06-02 07:48:03 +01:00
__catchResult.captureResult( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() )
2012-11-01 08:27:09 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-13 22:04:29 +00:00
#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
2012-11-01 08:27:09 +00:00
do { \
2014-06-02 07:48:03 +01:00
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2014-06-30 07:35:36 +01:00
if( __catchResult.allowThrows() ) \
try { \
2014-06-02 07:48:03 +01:00
expr; \
2014-06-30 07:35:36 +01:00
__catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
} \
catch( exceptionType ) { \
__catchResult.captureResult( Catch::ResultWas::Ok ); \
} \
catch( ... ) { \
__catchResult.useActiveException( resultDisposition ); \
} \
else \
2014-06-02 07:48:03 +01:00
__catchResult.captureResult( Catch::ResultWas::Ok ); \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() )
2012-11-01 08:27:09 +00:00
2013-02-02 20:37:58 +00:00
///////////////////////////////////////////////////////////////////////////////
2013-12-14 14:34:05 +00:00
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
do { \
2014-06-02 07:48:03 +01:00
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
__catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
__catchResult.captureResult( messageType ); \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() )
2013-12-14 14:34:05 +00:00
#else
#define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
do { \
2014-06-02 07:48:03 +01:00
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
__catchResult << log + ::Catch::StreamEndStop(); \
__catchResult.captureResult( messageType ); \
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() )
2013-12-14 14:34:05 +00:00
#endif
2012-11-01 08:27:09 +00:00
///////////////////////////////////////////////////////////////////////////////
2013-06-28 17:09:57 +01:00
#define INTERNAL_CATCH_INFO( log, macroName ) \
Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
2012-11-01 08:27:09 +00:00
///////////////////////////////////////////////////////////////////////////////
2012-11-13 22:04:29 +00:00
#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
2012-11-01 08:27:09 +00:00
do { \
2014-06-02 07:48:03 +01:00
Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg " " #matcher, resultDisposition ); \
2012-11-01 08:27:09 +00:00
try { \
2014-06-02 07:48:03 +01:00
std::string matcherAsString = ::Catch::Matchers::matcher.toString(); \
__catchResult \
.setLhs( Catch::toString( arg ) ) \
2014-09-15 18:40:24 +01:00
.setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
2014-06-02 07:48:03 +01:00
.setOp( "matches" ) \
.setResultType( ::Catch::Matchers::matcher.match( arg ) ); \
__catchResult.captureExpression(); \
2012-11-01 08:27:09 +00:00
} catch( ... ) { \
2014-06-02 07:48:03 +01:00
__catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
2012-11-01 08:27:09 +00:00
} \
2014-06-02 07:48:03 +01:00
INTERNAL_CATCH_REACT( __catchResult ) \
} while( Catch::alwaysFalse() )
2012-11-01 08:27:09 +00:00
2013-12-03 18:53:55 +00:00
// #included from: internal/catch_section.h
#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
// #included from: catch_section_info.h
#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
namespace Catch {
struct SectionInfo {
2014-07-09 07:40:37 +01:00
SectionInfo
( SourceLineInfo const & _lineInfo ,
std :: string const & _name ,
std :: string const & _description = std :: string () );
2013-12-03 18:53:55 +00:00
std :: string name ;
std :: string description ;
SourceLineInfo lineInfo ;
};
} // end namespace Catch
// #included from: catch_totals.hpp
#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
#include <cstddef>
namespace Catch {
struct Counts {
2014-07-03 08:11:38 +01:00
Counts () : passed ( 0 ), failed ( 0 ), failedButOk ( 0 ) {}
2013-12-03 18:53:55 +00:00
Counts operator - ( Counts const & other ) const {
Counts diff ;
diff . passed = passed - other . passed ;
diff . failed = failed - other . failed ;
2014-07-03 08:11:38 +01:00
diff . failedButOk = failedButOk - other . failedButOk ;
2013-12-03 18:53:55 +00:00
return diff ;
}
Counts & operator += ( Counts const & other ) {
passed += other . passed ;
failed += other . failed ;
2014-07-03 08:11:38 +01:00
failedButOk += other . failedButOk ;
2013-12-03 18:53:55 +00:00
return * this ;
}
std :: size_t total () const {
2014-07-03 08:11:38 +01:00
return passed + failed + failedButOk ;
2013-12-03 18:53:55 +00:00
}
2014-07-09 19:22:49 +01:00
bool allPassed () const {
return failed == 0 && failedButOk == 0 ;
}
2014-12-30 18:26:07 +00:00
bool allOk () const {
return failed == 0 ;
}
2013-12-03 18:53:55 +00:00
std :: size_t passed ;
std :: size_t failed ;
2014-07-03 08:11:38 +01:00
std :: size_t failedButOk ;
2013-12-03 18:53:55 +00:00
};
struct Totals {
Totals operator - ( Totals const & other ) const {
Totals diff ;
diff . assertions = assertions - other . assertions ;
diff . testCases = testCases - other . testCases ;
return diff ;
}
Totals delta ( Totals const & prevTotals ) const {
Totals diff = * this - prevTotals ;
if ( diff . assertions . failed > 0 )
++ diff . testCases . failed ;
2014-07-03 08:11:38 +01:00
else if ( diff . assertions . failedButOk > 0 )
++ diff . testCases . failedButOk ;
2013-12-03 18:53:55 +00:00
else
++ diff . testCases . passed ;
return diff ;
}
Totals & operator += ( Totals const & other ) {
assertions += other . assertions ;
testCases += other . testCases ;
return * this ;
}
Counts assertions ;
Counts testCases ;
};
}
2012-11-01 08:27:09 +00:00
2013-08-15 19:01:00 +01:00
// #included from: catch_timer.h
#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2013-08-16 19:09:09 +01:00
#ifdef CATCH_PLATFORM_WINDOWS
2013-08-15 19:01:00 +01:00
typedef unsigned long long uint64_t ;
#else
#include <stdint.h>
#endif
namespace Catch {
class Timer {
public :
Timer () : m_ticks ( 0 ) {}
void start ();
2014-09-03 19:23:22 +01:00
unsigned int getElapsedMicroseconds () const ;
2013-08-15 19:01:00 +01:00
unsigned int getElapsedMilliseconds () const ;
double getElapsedSeconds () const ;
private :
uint64_t m_ticks ;
};
} // namespace Catch
2012-11-01 08:27:09 +00:00
#include <string>
namespace Catch {
2014-10-21 07:25:26 +01:00
class Section : NonCopyable {
2012-11-01 08:27:09 +00:00
public :
2014-07-09 07:40:37 +01:00
Section ( SectionInfo const & info );
2013-12-03 18:53:55 +00:00
~ Section ();
2012-11-01 08:27:09 +00:00
// This indicates whether the section should be executed or not
2014-07-09 07:40:37 +01:00
operator bool () const ;
2012-11-01 08:27:09 +00:00
private :
2012-12-01 23:57:18 +00:00
SectionInfo m_info ;
2012-11-01 08:27:09 +00:00
std :: string m_name ;
Counts m_assertions ;
bool m_sectionIncluded ;
2013-08-15 19:01:00 +01:00
Timer m_timer ;
2012-11-01 08:27:09 +00:00
};
} // end namespace Catch
2013-03-16 20:21:51 +00:00
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define INTERNAL_CATCH_SECTION( ... ) \
2014-07-09 07:40:37 +01:00
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
2013-03-16 20:21:51 +00:00
#else
#define INTERNAL_CATCH_SECTION( name, desc ) \
2014-07-09 07:40:37 +01:00
if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
2013-03-16 20:21:51 +00:00
#endif
2012-11-01 08:27:09 +00:00
// #included from: internal/catch_generators.hpp
#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
#include <iterator>
#include <vector>
#include <string>
#include <stdlib.h>
namespace Catch {
template < typename T >
struct IGenerator {
virtual ~ IGenerator () {}
virtual T getValue ( std :: size_t index ) const = 0 ;
virtual std :: size_t size () const = 0 ;
};
template < typename T >
class BetweenGenerator : public IGenerator < T > {
public :
BetweenGenerator ( T from , T to ) : m_from ( from ), m_to ( to ){}
virtual T getValue ( std :: size_t index ) const {
2013-01-16 09:44:43 +00:00
return m_from + static_cast < int > ( index );
2012-11-01 08:27:09 +00:00
}
virtual std :: size_t size () const {
return static_cast < std :: size_t > ( 1 + m_to - m_from );
}
private :
T m_from ;
T m_to ;
};
template < typename T >
class ValuesGenerator : public IGenerator < T > {
public :
ValuesGenerator (){}
void add ( T value ) {
m_values . push_back ( value );
}
virtual T getValue ( std :: size_t index ) const {
return m_values [ index ];
}
virtual std :: size_t size () const {
return m_values . size ();
}
private :
std :: vector < T > m_values ;
};
template < typename T >
class CompositeGenerator {
public :
CompositeGenerator () : m_totalSize ( 0 ) {}
2013-03-08 09:30:25 +00:00
// *** Move semantics, similar to auto_ptr ***
2012-11-01 08:27:09 +00:00
CompositeGenerator ( CompositeGenerator & other )
: m_fileInfo ( other . m_fileInfo ),
m_totalSize ( 0 )
{
2013-03-08 09:30:25 +00:00
move ( other );
2012-11-01 08:27:09 +00:00
}
CompositeGenerator & setFileInfo ( const char * fileInfo ) {
m_fileInfo = fileInfo ;
return * this ;
}
~ CompositeGenerator () {
deleteAll ( m_composed );
}
operator T () const {
size_t overallIndex = getCurrentContext (). getGeneratorIndex ( m_fileInfo , m_totalSize );
typename std :: vector < const IGenerator < T >*>:: const_iterator it = m_composed . begin ();
typename std :: vector < const IGenerator < T >*>:: const_iterator itEnd = m_composed . end ();
for ( size_t index = 0 ; it != itEnd ; ++ it )
{
const IGenerator < T >* generator = * it ;
if ( overallIndex >= index && overallIndex < index + generator -> size () )
{
return generator -> getValue ( overallIndex - index );
}
index += generator -> size ();
}
CATCH_INTERNAL_ERROR ( "Indexed past end of generated range" );
2013-03-08 09:30:25 +00:00
return T (); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so
2012-11-01 08:27:09 +00:00
}
void add ( const IGenerator < T >* generator ) {
m_totalSize += generator -> size ();
m_composed . push_back ( generator );
}
CompositeGenerator & then ( CompositeGenerator & other ) {
move ( other );
return * this ;
}
CompositeGenerator & then ( T value ) {
ValuesGenerator < T >* valuesGen = new ValuesGenerator < T > ();
valuesGen -> add ( value );
add ( valuesGen );
return * this ;
}
private :
void move ( CompositeGenerator & other ) {
std :: copy ( other . m_composed . begin (), other . m_composed . end (), std :: back_inserter ( m_composed ) );
m_totalSize += other . m_totalSize ;
other . m_composed . clear ();
}
std :: vector < const IGenerator < T >*> m_composed ;
std :: string m_fileInfo ;
size_t m_totalSize ;
};
namespace Generators
{
template < typename T >
CompositeGenerator < T > between ( T from , T to ) {
CompositeGenerator < T > generators ;
generators . add ( new BetweenGenerator < T > ( from , to ) );
return generators ;
}
template < typename T >
CompositeGenerator < T > values ( T val1 , T val2 ) {
CompositeGenerator < T > generators ;
ValuesGenerator < T >* valuesGen = new ValuesGenerator < T > ();
valuesGen -> add ( val1 );
valuesGen -> add ( val2 );
generators . add ( valuesGen );
return generators ;
}
template < typename T >
CompositeGenerator < T > values ( T val1 , T val2 , T val3 ){
CompositeGenerator < T > generators ;
ValuesGenerator < T >* valuesGen = new ValuesGenerator < T > ();
valuesGen -> add ( val1 );
valuesGen -> add ( val2 );
valuesGen -> add ( val3 );
generators . add ( valuesGen );
return generators ;
}
template < typename T >
CompositeGenerator < T > values ( T val1 , T val2 , T val3 , T val4 ) {
CompositeGenerator < T > generators ;
ValuesGenerator < T >* valuesGen = new ValuesGenerator < T > ();
valuesGen -> add ( val1 );
valuesGen -> add ( val2 );
valuesGen -> add ( val3 );
valuesGen -> add ( val4 );
generators . add ( valuesGen );
return generators ;
}
} // end namespace Generators
using namespace Generators ;
} // end namespace Catch
#define INTERNAL_CATCH_LINESTR2( line ) #line
#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
// #included from: internal/catch_interfaces_exception.h
#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
#include <string>
2014-06-02 07:48:03 +01:00
// #included from: catch_interfaces_registry_hub.h
#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
#include <string>
namespace Catch {
class TestCase ;
struct ITestCaseRegistry ;
struct IExceptionTranslatorRegistry ;
struct IExceptionTranslator ;
struct IReporterRegistry ;
struct IReporterFactory ;
struct IRegistryHub {
virtual ~ IRegistryHub ();
virtual IReporterRegistry const & getReporterRegistry () const = 0 ;
virtual ITestCaseRegistry const & getTestCaseRegistry () const = 0 ;
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry () = 0 ;
};
struct IMutableRegistryHub {
virtual ~ IMutableRegistryHub ();
2015-08-07 17:30:34 +01:00
virtual void registerReporter ( std :: string const & name , Ptr < IReporterFactory > const & factory ) = 0 ;
virtual void registerListener ( Ptr < IReporterFactory > const & factory ) = 0 ;
2014-06-02 07:48:03 +01:00
virtual void registerTest ( TestCase const & testInfo ) = 0 ;
virtual void registerTranslator ( const IExceptionTranslator * translator ) = 0 ;
};
IRegistryHub & getRegistryHub ();
IMutableRegistryHub & getMutableRegistryHub ();
void cleanUp ();
std :: string translateActiveException ();
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-05-24 08:23:02 +01:00
typedef std :: string ( * exceptionTranslateFunction )();
2012-05-16 15:09:17 +01:00
struct IExceptionTranslator {
2012-08-13 07:46:10 +01:00
virtual ~ IExceptionTranslator ();
2011-05-24 08:23:02 +01:00
virtual std :: string translate () const = 0 ;
};
2012-05-16 15:09:17 +01:00
struct IExceptionTranslatorRegistry {
2012-08-13 07:46:10 +01:00
virtual ~ IExceptionTranslatorRegistry ();
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
virtual std :: string translateActiveException () const = 0 ;
2011-05-24 08:23:02 +01:00
};
2012-05-16 15:09:17 +01:00
class ExceptionTranslatorRegistrar {
2011-05-24 08:23:02 +01:00
template < typename T >
2012-05-16 15:09:17 +01:00
class ExceptionTranslator : public IExceptionTranslator {
2011-05-24 08:23:02 +01:00
public :
2012-05-16 15:09:17 +01:00
ExceptionTranslator ( std :: string ( * translateFunction )( T & ) )
2011-05-24 08:23:02 +01:00
: m_translateFunction ( translateFunction )
{}
2012-05-16 15:09:17 +01:00
virtual std :: string translate () const {
try {
2011-05-24 08:23:02 +01:00
throw ;
}
2012-05-16 15:09:17 +01:00
catch ( T & ex ) {
2011-05-24 08:23:02 +01:00
return m_translateFunction ( ex );
}
}
protected :
std :: string ( * m_translateFunction )( T & );
};
public :
template < typename T >
2012-05-16 15:09:17 +01:00
ExceptionTranslatorRegistrar ( std :: string ( * translateFunction )( T & ) ) {
2012-08-09 07:47:30 +01:00
getMutableRegistryHub (). registerTranslator
2011-05-24 08:23:02 +01:00
( new ExceptionTranslator < T > ( translateFunction ) );
}
};
}
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
// #included from: internal/catch_approx.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
#include <cmath>
#include <limits>
2012-05-16 15:09:17 +01:00
namespace Catch {
namespace Detail {
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
class Approx {
public :
explicit Approx ( double value )
: m_epsilon ( std :: numeric_limits < float >:: epsilon () * 100 ),
m_scale ( 1.0 ),
m_value ( value )
{}
2011-06-07 14:13:57 +01:00
2013-04-24 19:10:02 +01:00
Approx ( Approx const & other )
2012-05-16 15:09:17 +01:00
: m_epsilon ( other . m_epsilon ),
m_scale ( other . m_scale ),
m_value ( other . m_value )
{}
2011-06-07 14:13:57 +01:00
2012-05-16 15:09:17 +01:00
static Approx custom () {
return Approx ( 0 );
}
2011-06-07 14:13:57 +01:00
2012-05-16 15:09:17 +01:00
Approx operator ()( double value ) {
Approx approx ( value );
approx . epsilon ( m_epsilon );
approx . scale ( m_scale );
return approx ;
}
2011-05-24 08:23:02 +01:00
2013-04-24 19:10:02 +01:00
friend bool operator == ( double lhs , Approx const & rhs ) {
2012-05-16 15:09:17 +01:00
// Thanks to Richard Harris for his help refining this formula
return fabs ( lhs - rhs . m_value ) < rhs . m_epsilon * ( rhs . m_scale + ( std :: max )( fabs ( lhs ), fabs ( rhs . m_value ) ) );
}
2011-05-24 08:23:02 +01:00
2013-04-24 19:10:02 +01:00
friend bool operator == ( Approx const & lhs , double rhs ) {
2012-05-16 15:09:17 +01:00
return operator == ( rhs , lhs );
}
2011-05-24 08:23:02 +01:00
2013-04-24 19:10:02 +01:00
friend bool operator != ( double lhs , Approx const & rhs ) {
2012-05-16 15:09:17 +01:00
return ! operator == ( lhs , rhs );
}
2011-05-24 08:23:02 +01:00
2013-04-24 19:10:02 +01:00
friend bool operator != ( Approx const & lhs , double rhs ) {
2012-05-16 15:09:17 +01:00
return ! operator == ( rhs , lhs );
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
Approx & epsilon ( double newEpsilon ) {
m_epsilon = newEpsilon ;
return * this ;
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
Approx & scale ( double newScale ) {
m_scale = newScale ;
return * this ;
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
std :: string toString () const {
std :: ostringstream oss ;
2013-12-19 18:42:25 +00:00
oss << "Approx( " << Catch :: toString ( m_value ) << " )" ;
2012-05-16 15:09:17 +01:00
return oss . str ();
}
2011-05-24 08:23:02 +01:00
2012-05-16 15:09:17 +01:00
private :
double m_epsilon ;
double m_scale ;
double m_value ;
};
}
template <>
2013-04-24 19:10:02 +01:00
inline std :: string toString < Detail :: Approx > ( Detail :: Approx const & value ) {
2012-05-16 15:09:17 +01:00
return value . toString ();
}
2011-05-24 08:23:02 +01:00
} // end namespace Catch
2014-06-30 07:35:36 +01:00
// #included from: internal/catch_interfaces_tag_alias_registry.h
#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
// #included from: catch_tag_alias.h
#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
#include <string>
namespace Catch {
struct TagAlias {
TagAlias ( std :: string _tag , SourceLineInfo _lineInfo ) : tag ( _tag ), lineInfo ( _lineInfo ) {}
std :: string tag ;
SourceLineInfo lineInfo ;
};
struct RegistrarForTagAliases {
RegistrarForTagAliases ( char const * alias , char const * tag , SourceLineInfo const & lineInfo );
};
} // end namespace Catch
#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
// #included from: catch_option.hpp
#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
namespace Catch {
// An optional type
template < typename T >
class Option {
public :
2015-07-02 08:21:38 +01:00
Option () : nullableValue ( CATCH_NULL ) {}
2014-06-30 07:35:36 +01:00
Option ( T const & _value )
: nullableValue ( new ( storage ) T ( _value ) )
{}
Option ( Option const & _other )
2015-07-02 08:21:38 +01:00
: nullableValue ( _other ? new ( storage ) T ( * _other ) : CATCH_NULL )
2014-06-30 07:35:36 +01:00
{}
~ Option () {
reset ();
}
Option & operator = ( Option const & _other ) {
if ( & _other != this ) {
reset ();
if ( _other )
nullableValue = new ( storage ) T ( * _other );
}
return * this ;
}
Option & operator = ( T const & _value ) {
reset ();
nullableValue = new ( storage ) T ( _value );
return * this ;
}
void reset () {
if ( nullableValue )
nullableValue ->~ T ();
2015-07-02 08:21:38 +01:00
nullableValue = CATCH_NULL ;
2014-06-30 07:35:36 +01:00
}
T & operator * () { return * nullableValue ; }
T const & operator * () const { return * nullableValue ; }
T * operator -> () { return nullableValue ; }
const T * operator -> () const { return nullableValue ; }
T valueOr ( T const & defaultValue ) const {
return nullableValue ? * nullableValue : defaultValue ;
}
2015-07-02 08:21:38 +01:00
bool some () const { return nullableValue != CATCH_NULL ; }
bool none () const { return nullableValue == CATCH_NULL ; }
2014-06-30 07:35:36 +01:00
2015-07-02 08:21:38 +01:00
bool operator ! () const { return nullableValue == CATCH_NULL ; }
2014-06-30 07:35:36 +01:00
operator SafeBool :: type () const {
return SafeBool :: makeSafe ( some () );
}
private :
T * nullableValue ;
char storage [ sizeof ( T )];
};
} // end namespace Catch
namespace Catch {
struct ITagAliasRegistry {
virtual ~ ITagAliasRegistry ();
virtual Option < TagAlias > find ( std :: string const & alias ) const = 0 ;
virtual std :: string expandAliases ( std :: string const & unexpandedTestSpec ) const = 0 ;
static ITagAliasRegistry const & get ();
};
} // end namespace Catch
2012-06-02 23:12:42 +01:00
// These files are included here so the single_include script doesn't put them
// in the conditionally compiled sections
2013-12-03 18:53:55 +00:00
// #included from: internal/catch_test_case_info.h
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
2012-06-02 23:12:42 +01:00
#include <string>
2013-12-03 18:53:55 +00:00
#include <set>
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
#endif
namespace Catch {
struct ITestCase ;
struct TestCaseInfo {
2014-07-03 08:11:38 +01:00
enum SpecialProperties {
None = 0 ,
IsHidden = 1 << 1 ,
ShouldFail = 1 << 2 ,
MayFail = 1 << 3 ,
Throws = 1 << 4
};
2013-12-03 18:53:55 +00:00
TestCaseInfo ( std :: string const & _name ,
std :: string const & _className ,
std :: string const & _description ,
std :: set < std :: string > const & _tags ,
SourceLineInfo const & _lineInfo );
TestCaseInfo ( TestCaseInfo const & other );
2015-07-02 08:21:38 +01:00
friend void setTags ( TestCaseInfo & testCaseInfo , std :: set < std :: string > const & tags );
2014-07-03 08:11:38 +01:00
bool isHidden () const ;
bool throws () const ;
bool okToFail () const ;
bool expectedToFail () const ;
2013-12-03 18:53:55 +00:00
std :: string name ;
std :: string className ;
std :: string description ;
std :: set < std :: string > tags ;
2014-05-20 18:50:59 +01:00
std :: set < std :: string > lcaseTags ;
2013-12-03 18:53:55 +00:00
std :: string tagsAsString ;
SourceLineInfo lineInfo ;
2014-07-03 08:11:38 +01:00
SpecialProperties properties ;
2013-12-03 18:53:55 +00:00
};
2014-05-16 18:54:48 +01:00
class TestCase : public TestCaseInfo {
2013-12-03 18:53:55 +00:00
public :
TestCase ( ITestCase * testCase , TestCaseInfo const & info );
TestCase ( TestCase const & other );
TestCase withName ( std :: string const & _newName ) const ;
void invoke () const ;
TestCaseInfo const & getTestCaseInfo () const ;
void swap ( TestCase & other );
bool operator == ( TestCase const & other ) const ;
bool operator < ( TestCase const & other ) const ;
TestCase & operator = ( TestCase const & other );
private :
Ptr < ITestCase > test ;
};
TestCase makeTestCase ( ITestCase * testCase ,
std :: string const & className ,
std :: string const & name ,
std :: string const & description ,
SourceLineInfo const & lineInfo );
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
2012-06-02 23:12:42 +01:00
2012-05-21 18:52:09 +01:00
#ifdef __OBJC__
// #included from: internal/catch_objc.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
2012-05-21 18:52:09 +01:00
#import <objc/runtime.h>
#include <string>
// NB. Any general catch headers included here must be included
// in catch.hpp first to make sure they are included by the single
// header for non obj-usage
2011-08-15 09:06:31 +01:00
2011-08-12 18:53:28 +01:00
///////////////////////////////////////////////////////////////////////////////
// This protocol is really only here for (self) documenting purposes, since
// all its methods are optional.
@ protocol OcFixture
@ optional
- ( void ) setUp ;
- ( void ) tearDown ;
@ end
2012-05-16 15:09:17 +01:00
namespace Catch {
2011-08-12 18:53:28 +01:00
2012-08-16 18:48:50 +01:00
class OcMethod : public SharedImpl < ITestCase > {
2012-05-16 15:09:17 +01:00
public :
OcMethod ( Class cls , SEL sel ) : m_cls ( cls ), m_sel ( sel ) {}
virtual void invoke () const {
2012-03-17 18:20:06 +00:00
id obj = [[ m_cls alloc ] init ];
2011-08-12 18:53:28 +01:00
2012-03-17 18:20:06 +00:00
performOptionalSelector ( obj , @ selector ( setUp ) );
performOptionalSelector ( obj , m_sel );
performOptionalSelector ( obj , @ selector ( tearDown ) );
2011-08-12 18:53:28 +01:00
2012-03-17 18:20:06 +00:00
arcSafeRelease ( obj );
2011-08-12 18:53:28 +01:00
}
private :
2012-08-16 18:48:50 +01:00
virtual ~ OcMethod () {}
2011-08-12 18:53:28 +01:00
Class m_cls ;
SEL m_sel ;
};
2012-05-16 15:09:17 +01:00
namespace Detail {
2011-08-12 18:53:28 +01:00
2012-05-16 15:09:17 +01:00
inline std :: string getAnnotation ( Class cls ,
2013-04-24 19:10:02 +01:00
std :: string const & annotationName ,
std :: string const & testCaseName ) {
2011-08-12 18:53:28 +01:00
NSString * selStr = [[ NSString alloc ] initWithFormat : @ "Catch_%s_%s" , annotationName . c_str (), testCaseName . c_str ()];
SEL sel = NSSelectorFromString ( selStr );
2012-03-17 18:20:06 +00:00
arcSafeRelease ( selStr );
id value = performOptionalSelector ( cls , sel );
if ( value )
return [( NSString * ) value UTF8String ];
2011-08-12 18:53:28 +01:00
return "" ;
}
}
2012-05-16 15:09:17 +01:00
inline size_t registerTestMethods () {
2011-08-12 18:53:28 +01:00
size_t noTestMethods = 0 ;
2015-07-02 08:21:38 +01:00
int noClasses = objc_getClassList ( CATCH_NULL , 0 );
2011-08-12 18:53:28 +01:00
2012-04-28 12:29:52 +01:00
Class * classes = ( CATCH_UNSAFE_UNRETAINED Class * ) malloc ( sizeof ( Class ) * noClasses );
2012-03-17 18:20:06 +00:00
objc_getClassList ( classes , noClasses );
2011-08-12 18:53:28 +01:00
2012-05-16 15:09:17 +01:00
for ( int c = 0 ; c < noClasses ; c ++ ) {
2011-08-12 18:53:28 +01:00
Class cls = classes [ c ];
{
u_int count ;
Method * methods = class_copyMethodList ( cls , & count );
2012-05-22 08:56:59 +01:00
for ( u_int m = 0 ; m < count ; m ++ ) {
2011-08-12 18:53:28 +01:00
SEL selector = method_getName ( methods [ m ]);
std :: string methodName = sel_getName ( selector );
2013-12-03 18:53:55 +00:00
if ( startsWith ( methodName , "Catch_TestCase_" ) ) {
2011-08-12 18:53:28 +01:00
std :: string testCaseName = methodName . substr ( 15 );
2012-03-17 18:20:06 +00:00
std :: string name = Detail :: getAnnotation ( cls , "Name" , testCaseName );
std :: string desc = Detail :: getAnnotation ( cls , "Description" , testCaseName );
2013-02-19 08:46:09 +00:00
const char * className = class_getName ( cls );
2011-08-12 18:53:28 +01:00
2013-02-19 19:47:18 +00:00
getMutableRegistryHub (). registerTest ( makeTestCase ( new OcMethod ( cls , selector ), className , name . c_str (), desc . c_str (), SourceLineInfo () ) );
2011-08-12 18:53:28 +01:00
noTestMethods ++ ;
}
}
free ( methods );
}
}
return noTestMethods ;
}
2012-03-04 21:22:36 +00:00
2012-05-16 15:09:17 +01:00
namespace Matchers {
namespace Impl {
namespace NSStringMatchers {
2013-02-19 08:46:09 +00:00
template < typename MatcherT >
struct StringHolder : MatcherImpl < MatcherT , NSString *> {
2012-03-04 21:22:36 +00:00
StringHolder ( NSString * substr ) : m_substr ( [ substr copy ] ){}
2013-02-19 08:46:09 +00:00
StringHolder ( StringHolder const & other ) : m_substr ( [ other . m_substr copy ] ){}
2012-05-16 15:09:17 +01:00
StringHolder () {
2012-03-17 18:20:06 +00:00
arcSafeRelease ( m_substr );
2012-03-04 21:22:36 +00:00
}
NSString * m_substr ;
};
2013-02-19 08:46:09 +00:00
struct Equals : StringHolder < Equals > {
2012-03-14 20:06:14 +00:00
Equals ( NSString * substr ) : StringHolder ( substr ){}
2013-02-19 08:46:09 +00:00
virtual bool match ( ExpressionType const & str ) const {
2013-07-23 08:15:34 +01:00
return ( str != nil || m_substr == nil ) &&
[ str isEqualToString : m_substr ];
2012-03-14 20:06:14 +00:00
}
2013-02-19 08:46:09 +00:00
virtual std :: string toString () const {
2014-06-30 07:35:36 +01:00
return "equals string: " + Catch :: toString ( m_substr );
2012-03-14 20:06:14 +00:00
}
};
2013-02-19 08:46:09 +00:00
struct Contains : StringHolder < Contains > {
2012-03-04 21:22:36 +00:00
Contains ( NSString * substr ) : StringHolder ( substr ){}
2013-02-19 08:46:09 +00:00
virtual bool match ( ExpressionType const & str ) const {
2013-07-23 08:15:34 +01:00
return ( str != nil || m_substr == nil ) &&
[ str rangeOfString : m_substr ]. location != NSNotFound ;
2012-03-04 21:22:36 +00:00
}
2013-02-19 08:46:09 +00:00
virtual std :: string toString () const {
2014-06-30 07:35:36 +01:00
return "contains string: " + Catch :: toString ( m_substr );
2012-03-04 21:22:36 +00:00
}
};
2013-02-19 08:46:09 +00:00
struct StartsWith : StringHolder < StartsWith > {
2012-03-04 21:22:36 +00:00
StartsWith ( NSString * substr ) : StringHolder ( substr ){}
2013-02-19 08:46:09 +00:00
virtual bool match ( ExpressionType const & str ) const {
2013-07-23 08:15:34 +01:00
return ( str != nil || m_substr == nil ) &&
[ str rangeOfString : m_substr ]. location == 0 ;
2012-03-04 21:22:36 +00:00
}
2013-02-19 08:46:09 +00:00
virtual std :: string toString () const {
2014-06-30 07:35:36 +01:00
return "starts with: " + Catch :: toString ( m_substr );
2012-03-04 21:22:36 +00:00
}
};
2013-02-19 08:46:09 +00:00
struct EndsWith : StringHolder < EndsWith > {
2012-03-04 21:22:36 +00:00
EndsWith ( NSString * substr ) : StringHolder ( substr ){}
2013-02-19 08:46:09 +00:00
virtual bool match ( ExpressionType const & str ) const {
2013-07-23 08:15:34 +01:00
return ( str != nil || m_substr == nil ) &&
[ str rangeOfString : m_substr ]. location == [ str length ] - [ m_substr length ];
2012-03-04 21:22:36 +00:00
}
2013-02-19 08:46:09 +00:00
virtual std :: string toString () const {
2014-06-30 07:35:36 +01:00
return "ends with: " + Catch :: toString ( m_substr );
2012-03-04 21:22:36 +00:00
}
};
} // namespace NSStringMatchers
} // namespace Impl
2012-03-14 20:06:14 +00:00
inline Impl :: NSStringMatchers :: Equals
Equals ( NSString * substr ){ return Impl :: NSStringMatchers :: Equals ( substr ); }
2012-03-04 21:22:36 +00:00
inline Impl :: NSStringMatchers :: Contains
Contains ( NSString * substr ){ return Impl :: NSStringMatchers :: Contains ( substr ); }
2012-03-14 20:06:14 +00:00
2012-03-04 21:22:36 +00:00
inline Impl :: NSStringMatchers :: StartsWith
StartsWith ( NSString * substr ){ return Impl :: NSStringMatchers :: StartsWith ( substr ); }
2012-03-14 20:06:14 +00:00
2012-03-04 21:22:36 +00:00
inline Impl :: NSStringMatchers :: EndsWith
EndsWith ( NSString * substr ){ return Impl :: NSStringMatchers :: EndsWith ( substr ); }
} // namespace Matchers
using namespace Matchers ;
} // namespace Catch
2011-08-12 18:53:28 +01:00
///////////////////////////////////////////////////////////////////////////////
#define OC_TEST_CASE( name, desc )\
2012-03-17 18:20:06 +00:00
+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
2011-08-12 18:53:28 +01:00
{\
2012-03-17 18:20:06 +00:00
return @ name; \
2011-08-12 18:53:28 +01:00
}\
2012-03-17 18:20:06 +00:00
+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
2011-08-12 18:53:28 +01:00
{ \
2012-03-17 18:20:06 +00:00
return @ desc; \
2011-08-12 18:53:28 +01:00
} \
-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
#endif
2014-12-21 00:21:23 +00:00
#ifdef CATCH_IMPL
2012-08-13 07:46:10 +01:00
// #included from: internal/catch_impl.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
2012-08-13 07:46:10 +01:00
// Collect all the implementation files together here
// These are the equivalent of what would usually be cpp files
2012-08-16 18:48:50 +01:00
#ifdef __clang__
2012-08-13 07:46:10 +01:00
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
2012-08-16 18:48:50 +01:00
#endif
2012-08-13 07:46:10 +01:00
2015-08-07 17:30:34 +01:00
// #included from: ../catch_session.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
2011-08-12 18:53:28 +01:00
2012-08-13 07:46:10 +01:00
// #included from: internal/catch_commandline.hpp
#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
2013-12-03 18:53:55 +00:00
// #included from: catch_config.hpp
#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
2014-05-16 18:54:48 +01:00
// #included from: catch_test_spec_parser.hpp
#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
2013-12-03 18:53:55 +00:00
#ifdef __clang__
2014-05-16 18:54:48 +01:00
#pragma clang diagnostic push
2013-12-03 18:53:55 +00:00
#pragma clang diagnostic ignored "-Wpadded"
#endif
2014-05-16 18:54:48 +01:00
// #included from: catch_test_spec.hpp
#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
2013-12-03 18:53:55 +00:00
2014-05-16 18:54:48 +01:00
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpadded"
#endif
2013-12-03 18:53:55 +00:00
2015-07-13 15:03:26 +01:00
// #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 :
2015-07-15 23:03:11 +01:00
WildcardPattern ( std :: string const & pattern , CaseSensitive :: Choice caseSensitivity )
2015-07-13 15:03:26 +01:00
: 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 {
2015-07-15 23:03:11 +01:00
return m_caseSensitivity == CaseSensitive :: No ? toLower ( str ) : str ;
2015-07-13 15:03:26 +01:00
}
2015-07-15 23:03:11 +01:00
CaseSensitive :: Choice m_caseSensitivity ;
2015-07-13 15:03:26 +01:00
WildcardPosition m_wildcard ;
std :: string m_pattern ;
};
}
2013-12-03 18:53:55 +00:00
#include <string>
#include <vector>
namespace Catch {
2014-05-16 18:54:48 +01:00
class TestSpec {
struct Pattern : SharedImpl <> {
virtual ~ Pattern ();
virtual bool matches ( TestCaseInfo const & testCase ) const = 0 ;
};
class NamePattern : public Pattern {
public :
2015-07-13 15:03:26 +01:00
NamePattern ( std :: string const & name )
2015-07-15 23:03:11 +01:00
: m_wildcardPattern ( toLower ( name ), CaseSensitive :: No )
2015-07-13 15:03:26 +01:00
{}
2014-05-16 18:54:48 +01:00
virtual ~ NamePattern ();
virtual bool matches ( TestCaseInfo const & testCase ) const {
2015-07-13 15:03:26 +01:00
return m_wildcardPattern . matches ( toLower ( testCase . name ) );
2014-05-16 18:54:48 +01:00
}
private :
2015-07-13 15:03:26 +01:00
WildcardPattern m_wildcardPattern ;
2014-05-16 18:54:48 +01:00
};
2015-07-13 15:03:26 +01:00
2014-05-16 18:54:48 +01:00
class TagPattern : public Pattern {
public :
TagPattern ( std :: string const & tag ) : m_tag ( toLower ( tag ) ) {}
virtual ~ TagPattern ();
virtual bool matches ( TestCaseInfo const & testCase ) const {
2014-05-20 18:50:59 +01:00
return testCase . lcaseTags . find ( m_tag ) != testCase . lcaseTags . end ();
2014-05-16 18:54:48 +01:00
}
private :
std :: string m_tag ;
};
2015-07-13 15:03:26 +01:00
2014-05-16 18:54:48 +01:00
class ExcludedPattern : public Pattern {
public :
ExcludedPattern ( Ptr < Pattern > const & underlyingPattern ) : m_underlyingPattern ( underlyingPattern ) {}
virtual ~ ExcludedPattern ();
virtual bool matches ( TestCaseInfo const & testCase ) const { return ! m_underlyingPattern -> matches ( testCase ); }
private :
Ptr < Pattern > m_underlyingPattern ;
};
2013-12-03 18:53:55 +00:00
2014-05-16 18:54:48 +01:00
struct Filter {
std :: vector < Ptr < Pattern > > m_patterns ;
bool matches ( TestCaseInfo const & testCase ) const {
// All patterns in a filter must match for the filter to be a match
for ( std :: vector < Ptr < Pattern > >:: const_iterator it = m_patterns . begin (), itEnd = m_patterns . end (); it != itEnd ; ++ it )
if ( ! ( * it ) -> matches ( testCase ) )
return false ;
return true ;
}
2013-12-03 18:53:55 +00:00
};
public :
2014-05-16 18:54:48 +01:00
bool hasFilters () const {
return ! m_filters . empty ();
}
bool matches ( TestCaseInfo const & testCase ) const {
// A TestSpec matches if any filter matches
for ( std :: vector < Filter >:: const_iterator it = m_filters . begin (), itEnd = m_filters . end (); it != itEnd ; ++ it )
if ( it -> matches ( testCase ) )
return true ;
return false ;
}
2013-12-03 18:53:55 +00:00
private :
2014-05-16 18:54:48 +01:00
std :: vector < Filter > m_filters ;
2013-12-03 18:53:55 +00:00
2014-05-16 18:54:48 +01:00
friend class TestSpecParser ;
2013-12-03 18:53:55 +00:00
};
}
2014-05-16 18:54:48 +01:00
#ifdef __clang__
#pragma clang diagnostic pop
#endif
namespace Catch {
class TestSpecParser {
enum Mode { None , Name , QuotedName , Tag };
Mode m_mode ;
bool m_exclusion ;
std :: size_t m_start , m_pos ;
std :: string m_arg ;
TestSpec :: Filter m_currentFilter ;
TestSpec m_testSpec ;
2014-07-03 08:11:38 +01:00
ITagAliasRegistry const * m_tagAliases ;
2014-05-16 18:54:48 +01:00
public :
2014-07-03 08:11:38 +01:00
TestSpecParser ( ITagAliasRegistry const & tagAliases ) : m_tagAliases ( & tagAliases ) {}
2014-06-30 07:35:36 +01:00
TestSpecParser & parse ( std :: string const & arg ) {
2014-05-16 18:54:48 +01:00
m_mode = None ;
m_exclusion = false ;
m_start = std :: string :: npos ;
2014-07-03 08:11:38 +01:00
m_arg = m_tagAliases -> expandAliases ( arg );
2014-05-16 18:54:48 +01:00
for ( m_pos = 0 ; m_pos < m_arg . size (); ++ m_pos )
visitChar ( m_arg [ m_pos ] );
if ( m_mode == Name )
addPattern < TestSpec :: NamePattern > ();
return * this ;
}
TestSpec testSpec () {
2014-05-20 18:50:59 +01:00
addFilter ();
2014-05-16 18:54:48 +01:00
return m_testSpec ;
}
private :
void visitChar ( char c ) {
if ( m_mode == None ) {
switch ( c ) {
case ' ' : return ;
case '~' : m_exclusion = true ; return ;
case '[' : return startNewMode ( Tag , ++ m_pos );
case '"' : return startNewMode ( QuotedName , ++ m_pos );
default : startNewMode ( Name , m_pos ); break ;
}
}
if ( m_mode == Name ) {
if ( c == ',' ) {
addPattern < TestSpec :: NamePattern > ();
addFilter ();
}
else if ( c == '[' ) {
if ( subString () == "exclude:" )
m_exclusion = true ;
else
addPattern < TestSpec :: NamePattern > ();
startNewMode ( Tag , ++ m_pos );
}
}
else if ( m_mode == QuotedName && c == '"' )
addPattern < TestSpec :: NamePattern > ();
else if ( m_mode == Tag && c == ']' )
addPattern < TestSpec :: TagPattern > ();
}
void startNewMode ( Mode mode , std :: size_t start ) {
m_mode = mode ;
m_start = start ;
}
std :: string subString () const { return m_arg . substr ( m_start , m_pos - m_start ); }
template < typename T >
void addPattern () {
std :: string token = subString ();
if ( startsWith ( token , "exclude:" ) ) {
m_exclusion = true ;
token = token . substr ( 8 );
}
if ( ! token . empty () ) {
Ptr < TestSpec :: Pattern > pattern = new T ( token );
if ( m_exclusion )
pattern = new TestSpec :: ExcludedPattern ( pattern );
m_currentFilter . m_patterns . push_back ( pattern );
}
m_exclusion = false ;
m_mode = None ;
}
void addFilter () {
if ( ! m_currentFilter . m_patterns . empty () ) {
m_testSpec . m_filters . push_back ( m_currentFilter );
m_currentFilter = TestSpec :: Filter ();
}
}
};
inline TestSpec parseTestSpec ( std :: string const & arg ) {
2014-06-30 07:35:36 +01:00
return TestSpecParser ( ITagAliasRegistry :: get () ). parse ( arg ). testSpec ();
2014-05-16 18:54:48 +01:00
}
} // namespace Catch
#ifdef __clang__
#pragma clang diagnostic pop
#endif
2014-06-02 07:48:03 +01:00
// #included from: catch_interfaces_config.h
#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
#include <iostream>
#include <string>
#include <vector>
namespace Catch {
struct Verbosity { enum Level {
NoOutput = 0 ,
Quiet ,
Normal
}; };
struct WarnAbout { enum What {
Nothing = 0x00 ,
NoAssertions = 0x01
}; };
struct ShowDurations { enum OrNot {
DefaultForReporter ,
Always ,
Never
}; };
2014-09-15 18:40:24 +01:00
struct RunTests { enum InWhatOrder {
InDeclarationOrder ,
InLexicographicalOrder ,
InRandomOrder
}; };
2014-06-02 07:48:03 +01:00
class TestSpec ;
struct IConfig : IShared {
virtual ~ IConfig ();
virtual bool allowThrows () const = 0 ;
virtual std :: ostream & stream () const = 0 ;
virtual std :: string name () const = 0 ;
virtual bool includeSuccessfulResults () const = 0 ;
virtual bool shouldDebugBreak () const = 0 ;
virtual bool warnAboutMissingAssertions () const = 0 ;
virtual int abortAfter () const = 0 ;
virtual bool showInvisibles () const = 0 ;
virtual ShowDurations :: OrNot showDurations () const = 0 ;
virtual TestSpec const & testSpec () const = 0 ;
2014-09-15 18:40:24 +01:00
virtual RunTests :: InWhatOrder runOrder () const = 0 ;
virtual unsigned int rngSeed () const = 0 ;
2015-03-04 08:23:40 +00:00
virtual bool forceColour () const = 0 ;
2014-06-02 07:48:03 +01:00
};
}
2013-12-03 18:53:55 +00:00
// #included from: catch_stream.h
#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
#include <streambuf>
#ifdef __clang__
#pragma clang diagnostic ignored "-Wpadded"
#endif
namespace Catch {
class Stream {
public :
Stream ();
Stream ( std :: streambuf * _streamBuf , bool _isOwned );
void release ();
std :: streambuf * streamBuf ;
private :
bool isOwned ;
};
2014-10-02 19:08:19 +01:00
std :: ostream & cout ();
std :: ostream & cerr ();
2013-12-03 18:53:55 +00:00
}
#include <memory>
#include <vector>
#include <string>
#include <iostream>
2014-09-15 18:40:24 +01:00
#include <ctime>
2013-12-03 18:53:55 +00:00
#ifndef CATCH_CONFIG_CONSOLE_WIDTH
#define CATCH_CONFIG_CONSOLE_WIDTH 80
#endif
namespace Catch {
struct ConfigData {
ConfigData ()
: listTests ( false ),
listTags ( false ),
listReporters ( false ),
listTestNamesOnly ( false ),
showSuccessfulTests ( false ),
shouldDebugBreak ( false ),
noThrow ( false ),
showHelp ( false ),
2014-04-23 07:10:10 +01:00
showInvisibles ( false ),
2015-03-04 08:23:40 +00:00
forceColour ( false ),
2015-07-02 08:21:38 +01:00
filenamesAsTags ( false ),
2013-12-03 18:53:55 +00:00
abortAfter ( - 1 ),
2014-09-15 18:40:24 +01:00
rngSeed ( 0 ),
2013-12-03 18:53:55 +00:00
verbosity ( Verbosity :: Normal ),
warnings ( WarnAbout :: Nothing ),
2014-09-15 18:40:24 +01:00
showDurations ( ShowDurations :: DefaultForReporter ),
runOrder ( RunTests :: InDeclarationOrder )
2013-12-03 18:53:55 +00:00
{}
bool listTests ;
bool listTags ;
bool listReporters ;
bool listTestNamesOnly ;
bool showSuccessfulTests ;
bool shouldDebugBreak ;
bool noThrow ;
bool showHelp ;
2014-04-23 07:10:10 +01:00
bool showInvisibles ;
2015-03-04 08:23:40 +00:00
bool forceColour ;
2015-07-02 08:21:38 +01:00
bool filenamesAsTags ;
2013-12-03 18:53:55 +00:00
int abortAfter ;
2014-09-15 18:40:24 +01:00
unsigned int rngSeed ;
2013-12-03 18:53:55 +00:00
Verbosity :: Level verbosity ;
WarnAbout :: What warnings ;
ShowDurations :: OrNot showDurations ;
2014-09-15 18:40:24 +01:00
RunTests :: InWhatOrder runOrder ;
2013-12-03 18:53:55 +00:00
std :: string outputFilename ;
std :: string name ;
std :: string processName ;
2015-08-07 17:30:34 +01:00
std :: vector < std :: string > reporterNames ;
2013-12-03 18:53:55 +00:00
std :: vector < std :: string > testsOrTags ;
};
class Config : public SharedImpl < IConfig > {
private :
Config ( Config const & other );
Config & operator = ( Config const & other );
virtual void dummy ();
public :
Config ()
2014-10-02 19:08:19 +01:00
: m_os ( Catch :: cout (). rdbuf () )
2013-12-03 18:53:55 +00:00
{}
Config ( ConfigData const & data )
: m_data ( data ),
2014-10-02 19:08:19 +01:00
m_os ( Catch :: cout (). rdbuf () )
2013-12-03 18:53:55 +00:00
{
if ( ! data . testsOrTags . empty () ) {
2014-06-30 07:35:36 +01:00
TestSpecParser parser ( ITagAliasRegistry :: get () );
2014-05-16 18:54:48 +01:00
for ( std :: size_t i = 0 ; i < data . testsOrTags . size (); ++ i )
parser . parse ( data . testsOrTags [ i ] );
m_testSpec = parser . testSpec ();
2013-12-03 18:53:55 +00:00
}
}
virtual ~ Config () {
2014-10-02 19:08:19 +01:00
m_os . rdbuf ( Catch :: cout (). rdbuf () );
2013-12-03 18:53:55 +00:00
m_stream . release ();
}
void setFilename ( std :: string const & filename ) {
m_data . outputFilename = filename ;
}
std :: string const & getFilename () const {
return m_data . outputFilename ;
}
bool listTests () const { return m_data . listTests ; }
bool listTestNamesOnly () const { return m_data . listTestNamesOnly ; }
bool listTags () const { return m_data . listTags ; }
bool listReporters () const { return m_data . listReporters ; }
2014-05-16 18:54:48 +01:00
std :: string getProcessName () const { return m_data . processName ; }
2013-12-03 18:53:55 +00:00
2014-05-16 18:54:48 +01:00
bool shouldDebugBreak () const { return m_data . shouldDebugBreak ; }
2013-12-03 18:53:55 +00:00
void setStreamBuf ( std :: streambuf * buf ) {
2014-10-02 19:08:19 +01:00
m_os . rdbuf ( buf ? buf : Catch :: cout (). rdbuf () );
2013-12-03 18:53:55 +00:00
}
void useStream ( std :: string const & streamName ) {
Stream stream = createStream ( streamName );
setStreamBuf ( stream . streamBuf );
m_stream . release ();
m_stream = stream ;
}
2015-08-07 17:30:34 +01:00
std :: vector < std :: string > getReporterNames () const { return m_data . reporterNames ; }
2013-12-03 18:53:55 +00:00
2014-05-16 18:54:48 +01:00
int abortAfter () const { return m_data . abortAfter ; }
2013-12-03 18:53:55 +00:00
2014-05-16 18:54:48 +01:00
TestSpec const & testSpec () const { return m_testSpec ; }
2013-12-03 18:53:55 +00:00
bool showHelp () const { return m_data . showHelp ; }
2014-04-23 07:10:10 +01:00
bool showInvisibles () const { return m_data . showInvisibles ; }
2013-12-03 18:53:55 +00:00
// IConfig interface
virtual bool allowThrows () const { return ! m_data . noThrow ; }
virtual std :: ostream & stream () const { return m_os ; }
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 ; }
virtual ShowDurations :: OrNot showDurations () const { return m_data . showDurations ; }
2014-09-15 18:40:24 +01:00
virtual RunTests :: InWhatOrder runOrder () const { return m_data . runOrder ; }
virtual unsigned int rngSeed () const { return m_data . rngSeed ; }
2015-03-04 08:23:40 +00:00
virtual bool forceColour () const { return m_data . forceColour ; }
2013-12-03 18:53:55 +00:00
private :
ConfigData m_data ;
Stream m_stream ;
mutable std :: ostream m_os ;
2014-05-16 18:54:48 +01:00
TestSpec m_testSpec ;
2013-12-03 18:53:55 +00:00
};
} // end namespace Catch
2014-02-11 18:12:41 +00:00
// #included from: catch_clara.h
#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
2014-03-06 08:16:06 +00:00
// Use Catch's value for console width (store Clara's off to the side, if present)
#ifdef CLARA_CONFIG_CONSOLE_WIDTH
#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
#undef CLARA_CONFIG_CONSOLE_WIDTH
#endif
2014-02-11 18:12:41 +00:00
#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
// Declare Clara inside the Catch namespace
2014-03-06 08:16:06 +00:00
#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
2014-03-17 18:40:58 +00:00
// #included from: ../external/clara.h
2012-08-13 07:46:10 +01:00
2014-02-11 18:12:41 +00:00
// Only use header guard if we are not using an outer namespace
2014-03-06 08:16:06 +00:00
#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
#ifndef STITCH_CLARA_OPEN_NAMESPACE
2014-03-01 10:38:14 +00:00
#define TWOBLUECUBES_CLARA_H_INCLUDED
2014-03-06 08:16:06 +00:00
#define STITCH_CLARA_OPEN_NAMESPACE
#define STITCH_CLARA_CLOSE_NAMESPACE
#else
#define STITCH_CLARA_CLOSE_NAMESPACE }
2014-02-11 18:12:41 +00:00
#endif
2013-03-29 13:44:33 +00:00
2014-03-06 08:16:06 +00:00
#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
2014-03-01 10:38:14 +00:00
// ----------- #included from tbc_text_format.h -----------
2014-02-11 18:12:41 +00:00
// Only use header guard if we are not using an outer namespace
2014-03-01 10:38:14 +00:00
#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
#define TBC_TEXT_FORMAT_H_INCLUDED
2014-02-11 18:12:41 +00:00
#endif
2014-03-01 10:38:14 +00:00
2013-03-29 13:44:33 +00:00
#include <string>
#include <vector>
2014-02-11 18:12:41 +00:00
#include <sstream>
2013-03-29 13:44:33 +00:00
2014-02-11 18:12:41 +00:00
// Use optional outer namespace
2014-03-01 10:38:14 +00:00
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
2014-02-11 18:12:41 +00:00
#endif
namespace Tbc {
#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH ;
#else
const unsigned int consoleWidth = 80 ;
#endif
2012-08-13 07:46:10 +01:00
2013-04-20 21:07:32 +01:00
struct TextAttributes {
TextAttributes ()
: initialIndent ( std :: string :: npos ),
indent ( 0 ),
2014-02-11 18:12:41 +00:00
width ( consoleWidth - 1 ),
2013-04-20 21:07:32 +01:00
tabChar ( '\t' )
2012-08-27 21:42:55 +01:00
{}
2012-08-13 07:46:10 +01:00
2013-04-20 21:07:32 +01:00
TextAttributes & setInitialIndent ( std :: size_t _value ) { initialIndent = _value ; return * this ; }
TextAttributes & setIndent ( std :: size_t _value ) { indent = _value ; return * this ; }
TextAttributes & setWidth ( std :: size_t _value ) { width = _value ; return * this ; }
TextAttributes & setTabChar ( char _value ) { tabChar = _value ; return * this ; }
2012-08-13 07:46:10 +01:00
2013-04-20 21:07:32 +01:00
std :: size_t initialIndent ; // indent of first line, or npos
std :: size_t indent ; // indent of subsequent lines, or all if initialIndent is npos
std :: size_t width ; // maximum width of text, including indent. Longer text will wrap
char tabChar ; // If this char is seen the indent is changed to current pos
2012-08-27 21:42:55 +01:00
};
2013-04-20 21:07:32 +01:00
class Text {
2012-08-27 21:42:55 +01:00
public :
2014-02-11 18:12:41 +00:00
Text ( std :: string const & _str , TextAttributes const & _attr = TextAttributes () )
: attr ( _attr )
{
std :: string wrappableChars = " [({.,/| \\ -" ;
std :: size_t indent = _attr . initialIndent != std :: string :: npos
? _attr . initialIndent
: _attr . indent ;
std :: string remainder = _str ;
while ( ! remainder . empty () ) {
if ( lines . size () >= 1000 ) {
lines . push_back ( "... message truncated due to excessive size" );
return ;
}
std :: size_t tabPos = std :: string :: npos ;
std :: size_t width = ( std :: min )( remainder . size (), _attr . width - indent );
std :: size_t pos = remainder . find_first_of ( '\n' );
if ( pos <= width ) {
width = pos ;
}
pos = remainder . find_last_of ( _attr . tabChar , width );
if ( pos != std :: string :: npos ) {
tabPos = pos ;
if ( remainder [ width ] == '\n' )
width -- ;
remainder = remainder . substr ( 0 , tabPos ) + remainder . substr ( tabPos + 1 );
}
if ( width == remainder . size () ) {
spliceLine ( indent , remainder , width );
}
else if ( remainder [ width ] == '\n' ) {
spliceLine ( indent , remainder , width );
if ( width <= 1 || remainder . size () != 1 )
remainder = remainder . substr ( 1 );
indent = _attr . indent ;
}
else {
pos = remainder . find_last_of ( wrappableChars , width );
if ( pos != std :: string :: npos && pos > 0 ) {
spliceLine ( indent , remainder , pos );
if ( remainder [ 0 ] == ' ' )
remainder = remainder . substr ( 1 );
}
else {
spliceLine ( indent , remainder , width - 1 );
lines . back () += "-" ;
}
if ( lines . size () == 1 )
indent = _attr . indent ;
if ( tabPos != std :: string :: npos )
indent += tabPos ;
}
}
}
void spliceLine ( std :: size_t _indent , std :: string & _remainder , std :: size_t _pos ) {
lines . push_back ( std :: string ( _indent , ' ' ) + _remainder . substr ( 0 , _pos ) );
_remainder = _remainder . substr ( _pos );
}
2012-08-27 21:42:55 +01:00
2013-03-29 13:44:33 +00:00
typedef std :: vector < std :: string >:: const_iterator const_iterator ;
2012-08-31 08:10:36 +01:00
2013-03-29 13:44:33 +00:00
const_iterator begin () const { return lines . begin (); }
const_iterator end () const { return lines . end (); }
std :: string const & last () const { return lines . back (); }
std :: size_t size () const { return lines . size (); }
std :: string const & operator []( std :: size_t _index ) const { return lines [ _index ]; }
2014-02-11 18:12:41 +00:00
std :: string toString () const {
std :: ostringstream oss ;
oss << * this ;
return oss . str ();
}
2012-08-31 08:10:36 +01:00
2014-02-11 18:12:41 +00:00
inline friend std :: ostream & operator << ( std :: ostream & _stream , Text const & _text ) {
for ( Text :: const_iterator it = _text . begin (), itEnd = _text . end ();
it != itEnd ; ++ it ) {
if ( it != _text . begin () )
_stream << " \n " ;
_stream << * it ;
}
return _stream ;
}
2012-08-27 21:42:55 +01:00
private :
2013-04-20 21:07:32 +01:00
std :: string str ;
TextAttributes attr ;
2013-03-29 13:44:33 +00:00
std :: vector < std :: string > lines ;
};
2014-02-11 18:12:41 +00:00
} // end namespace Tbc
2014-03-01 10:38:14 +00:00
#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
2014-02-11 18:12:41 +00:00
} // end outer namespace
#endif
2014-03-01 10:38:14 +00:00
#endif // TBC_TEXT_FORMAT_H_INCLUDED
// ----------- end of #include from tbc_text_format.h -----------
// ........... back in /Users/philnash/Dev/OSS/Clara/srcs/clara.h
2014-03-06 08:16:06 +00:00
#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
2014-02-11 18:12:41 +00:00
#include <map>
#include <algorithm>
#include <stdexcept>
#include <memory>
// Use optional outer namespace
2014-03-06 08:16:06 +00:00
#ifdef STITCH_CLARA_OPEN_NAMESPACE
STITCH_CLARA_OPEN_NAMESPACE
2014-02-11 18:12:41 +00:00
#endif
2013-03-29 13:44:33 +00:00
2013-06-07 19:07:50 +01:00
namespace Clara {
2014-03-06 08:16:06 +00:00
struct UnpositionalTag {};
extern UnpositionalTag _ ;
#ifdef CLARA_CONFIG_MAIN
UnpositionalTag _ ;
#endif
2013-06-07 19:07:50 +01:00
namespace Detail {
2014-02-11 18:12:41 +00:00
#ifdef CLARA_CONSOLE_WIDTH
const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH ;
#else
const unsigned int consoleWidth = 80 ;
#endif
2014-03-06 08:16:06 +00:00
using namespace Tbc ;
inline bool startsWith ( std :: string const & str , std :: string const & prefix ) {
return str . size () >= prefix . size () && str . substr ( 0 , prefix . size () ) == prefix ;
}
2014-02-11 18:12:41 +00:00
2013-06-07 19:07:50 +01:00
template < typename T > struct RemoveConstRef { typedef T type ; };
template < typename T > struct RemoveConstRef < T &> { typedef T type ; };
template < typename T > struct RemoveConstRef < T const &> { typedef T type ; };
template < typename T > struct RemoveConstRef < T const > { typedef T type ; };
template < typename T > struct IsBool { static const bool value = false ; };
template <> struct IsBool < bool > { static const bool value = true ; };
2012-08-27 21:42:55 +01:00
template < typename T >
2013-06-07 19:07:50 +01:00
void convertInto ( std :: string const & _source , T & _dest ) {
std :: stringstream ss ;
ss << _source ;
ss >> _dest ;
if ( ss . fail () )
throw std :: runtime_error ( "Unable to convert " + _source + " to destination type" );
}
inline void convertInto ( std :: string const & _source , std :: string & _dest ) {
_dest = _source ;
}
inline void convertInto ( std :: string const & _source , bool & _dest ) {
std :: string sourceLC = _source ;
std :: transform ( sourceLC . begin (), sourceLC . end (), sourceLC . begin (), :: tolower );
2013-08-16 19:01:32 +01:00
if ( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
2013-06-07 19:07:50 +01:00
_dest = true ;
2013-08-16 19:01:32 +01:00
else if ( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
2013-06-07 19:07:50 +01:00
_dest = false ;
else
2013-08-16 19:01:32 +01:00
throw std :: runtime_error ( "Expected a boolean value but did not recognise: \n '" + _source + "'" );
2013-06-07 19:07:50 +01:00
}
inline void convertInto ( bool _source , bool & _dest ) {
_dest = _source ;
}
template < typename T >
inline void convertInto ( bool , T & ) {
throw std :: runtime_error ( "Invalid conversion" );
2012-08-27 21:42:55 +01:00
}
2013-06-07 19:07:50 +01:00
template < typename ConfigT >
struct IArgFunction {
virtual ~ IArgFunction () {}
2015-05-19 18:40:00 +01:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2014-04-18 08:49:35 +01:00
IArgFunction () = default ;
IArgFunction ( IArgFunction const & ) = default ;
# endif
2013-06-07 19:07:50 +01:00
virtual void set ( ConfigT & config , std :: string const & value ) const = 0 ;
virtual void setFlag ( ConfigT & config ) const = 0 ;
virtual bool takesArg () const = 0 ;
virtual IArgFunction * clone () const = 0 ;
};
template < typename ConfigT >
class BoundArgFunction {
public :
2015-07-02 08:21:38 +01:00
BoundArgFunction () : functionObj ( CATCH_NULL ) {}
2013-06-07 19:07:50 +01:00
BoundArgFunction ( IArgFunction < ConfigT >* _functionObj ) : functionObj ( _functionObj ) {}
2015-07-02 08:21:38 +01:00
BoundArgFunction ( BoundArgFunction const & other ) : functionObj ( other . functionObj ? other . functionObj -> clone () : CATCH_NULL ) {}
2013-06-07 19:07:50 +01:00
BoundArgFunction & operator = ( BoundArgFunction const & other ) {
2015-07-02 08:21:38 +01:00
IArgFunction < ConfigT >* newFunctionObj = other . functionObj ? other . functionObj -> clone () : CATCH_NULL ;
2013-06-07 19:07:50 +01:00
delete functionObj ;
functionObj = newFunctionObj ;
return * this ;
}
~ BoundArgFunction () { delete functionObj ; }
void set ( ConfigT & config , std :: string const & value ) const {
functionObj -> set ( config , value );
}
void setFlag ( ConfigT & config ) const {
functionObj -> setFlag ( config );
}
bool takesArg () const { return functionObj -> takesArg (); }
2014-03-24 18:15:04 +00:00
bool isSet () const {
2015-07-02 08:21:38 +01:00
return functionObj != CATCH_NULL ;
2014-03-24 18:15:04 +00:00
}
2013-06-07 19:07:50 +01:00
private :
IArgFunction < ConfigT >* functionObj ;
};
template < typename C >
struct NullBinder : IArgFunction < C > {
virtual void set ( C & , std :: string const & ) const {}
virtual void setFlag ( C & ) const {}
virtual bool takesArg () const { return true ; }
virtual IArgFunction < C >* clone () const { return new NullBinder ( * this ); }
};
template < typename C , typename M >
struct BoundDataMember : IArgFunction < C > {
BoundDataMember ( M C ::* _member ) : member ( _member ) {}
virtual void set ( C & p , std :: string const & stringValue ) const {
convertInto ( stringValue , p . * member );
}
virtual void setFlag ( C & p ) const {
convertInto ( true , p . * member );
}
virtual bool takesArg () const { return ! IsBool < M >:: value ; }
virtual IArgFunction < C >* clone () const { return new BoundDataMember ( * this ); }
M C ::* member ;
};
template < typename C , typename M >
struct BoundUnaryMethod : IArgFunction < C > {
BoundUnaryMethod ( void ( C ::* _member )( M ) ) : member ( _member ) {}
virtual void set ( C & p , std :: string const & stringValue ) const {
typename RemoveConstRef < M >:: type value ;
convertInto ( stringValue , value );
( p . * member )( value );
}
virtual void setFlag ( C & p ) const {
typename RemoveConstRef < M >:: type value ;
convertInto ( true , value );
( p . * member )( value );
}
virtual bool takesArg () const { return ! IsBool < M >:: value ; }
virtual IArgFunction < C >* clone () const { return new BoundUnaryMethod ( * this ); }
void ( C ::* member )( M );
};
template < typename C >
struct BoundNullaryMethod : IArgFunction < C > {
BoundNullaryMethod ( void ( C ::* _member )() ) : member ( _member ) {}
virtual void set ( C & p , std :: string const & stringValue ) const {
bool value ;
convertInto ( stringValue , value );
if ( value )
( p . * member )();
}
virtual void setFlag ( C & p ) const {
( p . * member )();
}
virtual bool takesArg () const { return false ; }
virtual IArgFunction < C >* clone () const { return new BoundNullaryMethod ( * this ); }
void ( C ::* member )();
};
template < typename C >
struct BoundUnaryFunction : IArgFunction < C > {
BoundUnaryFunction ( void ( * _function )( C & ) ) : function ( _function ) {}
virtual void set ( C & obj , std :: string const & stringValue ) const {
bool value ;
convertInto ( stringValue , value );
if ( value )
function ( obj );
}
virtual void setFlag ( C & p ) const {
function ( p );
}
virtual bool takesArg () const { return false ; }
virtual IArgFunction < C >* clone () const { return new BoundUnaryFunction ( * this ); }
void ( * function )( C & );
};
template < typename C , typename T >
struct BoundBinaryFunction : IArgFunction < C > {
BoundBinaryFunction ( void ( * _function )( C & , T ) ) : function ( _function ) {}
virtual void set ( C & obj , std :: string const & stringValue ) const {
typename RemoveConstRef < T >:: type value ;
convertInto ( stringValue , value );
function ( obj , value );
}
virtual void setFlag ( C & obj ) const {
typename RemoveConstRef < T >:: type value ;
convertInto ( true , value );
function ( obj , value );
}
virtual bool takesArg () const { return ! IsBool < T >:: value ; }
virtual IArgFunction < C >* clone () const { return new BoundBinaryFunction ( * this ); }
void ( * function )( C & , T );
};
} // namespace Detail
struct Parser {
Parser () : separators ( " \t =:" ) {}
struct Token {
enum Type { Positional , ShortOpt , LongOpt };
Token ( Type _type , std :: string const & _data ) : type ( _type ), data ( _data ) {}
Type type ;
std :: string data ;
};
void parseIntoTokens ( int argc , char const * const * argv , std :: vector < Parser :: Token >& tokens ) const {
2013-12-23 10:24:06 +00:00
const std :: string doubleDash = "--" ;
for ( int i = 1 ; i < argc && argv [ i ] != doubleDash ; ++ i )
2013-06-07 19:07:50 +01:00
parseIntoTokens ( argv [ i ] , tokens );
}
void parseIntoTokens ( std :: string arg , std :: vector < Parser :: Token >& tokens ) const {
while ( ! arg . empty () ) {
Parser :: Token token ( Parser :: Token :: Positional , arg );
arg = "" ;
if ( token . data [ 0 ] == '-' ) {
if ( token . data . size () > 1 && token . data [ 1 ] == '-' ) {
token = Parser :: Token ( Parser :: Token :: LongOpt , token . data . substr ( 2 ) );
}
else {
token = Parser :: Token ( Parser :: Token :: ShortOpt , token . data . substr ( 1 ) );
if ( token . data . size () > 1 && separators . find ( token . data [ 1 ] ) == std :: string :: npos ) {
arg = "-" + token . data . substr ( 1 );
token . data = token . data . substr ( 0 , 1 );
}
}
}
if ( token . type != Parser :: Token :: Positional ) {
std :: size_t pos = token . data . find_first_of ( separators );
if ( pos != std :: string :: npos ) {
arg = token . data . substr ( pos + 1 );
token . data = token . data . substr ( 0 , pos );
}
}
tokens . push_back ( token );
}
}
std :: string separators ;
2012-08-27 21:42:55 +01:00
};
2014-03-17 18:40:58 +00:00
template < typename ConfigT >
struct CommonArgProperties {
CommonArgProperties () {}
CommonArgProperties ( Detail :: BoundArgFunction < ConfigT > const & _boundField ) : boundField ( _boundField ) {}
Detail :: BoundArgFunction < ConfigT > boundField ;
std :: string description ;
2014-03-24 18:15:04 +00:00
std :: string detail ;
2014-03-17 18:40:58 +00:00
std :: string placeholder ; // Only value if boundField takes an arg
bool takesArg () const {
return ! placeholder . empty ();
}
2014-03-24 18:15:04 +00:00
void validate () const {
if ( ! boundField . isSet () )
throw std :: logic_error ( "option not bound" );
}
2014-03-17 18:40:58 +00:00
};
struct OptionArgProperties {
std :: vector < std :: string > shortNames ;
std :: string longName ;
bool hasShortName ( std :: string const & shortName ) const {
return std :: find ( shortNames . begin (), shortNames . end (), shortName ) != shortNames . end ();
}
bool hasLongName ( std :: string const & _longName ) const {
return _longName == longName ;
}
};
struct PositionalArgProperties {
PositionalArgProperties () : position ( - 1 ) {}
int position ; // -1 means non-positional (floating)
bool isFixedPositional () const {
return position != - 1 ;
}
};
2013-06-07 19:07:50 +01:00
template < typename ConfigT >
class CommandLine {
2014-03-17 18:40:58 +00:00
struct Arg : CommonArgProperties < ConfigT > , OptionArgProperties , PositionalArgProperties {
Arg () {}
Arg ( Detail :: BoundArgFunction < ConfigT > const & _boundField ) : CommonArgProperties < ConfigT > ( _boundField ) {}
using CommonArgProperties < ConfigT >:: placeholder ; // !TBD
2013-06-07 19:07:50 +01:00
std :: string dbgName () const {
if ( ! longName . empty () )
return "--" + longName ;
if ( ! shortNames . empty () )
return "-" + shortNames [ 0 ];
return "positional args" ;
}
std :: string commands () const {
std :: ostringstream oss ;
bool first = true ;
std :: vector < std :: string >:: const_iterator it = shortNames . begin (), itEnd = shortNames . end ();
for (; it != itEnd ; ++ it ) {
if ( first )
first = false ;
else
oss << ", " ;
oss << "-" << * it ;
}
if ( ! longName . empty () ) {
if ( ! first )
oss << ", " ;
oss << "--" << longName ;
}
2014-03-06 08:16:06 +00:00
if ( ! placeholder . empty () )
oss << " <" << placeholder << ">" ;
2013-06-07 19:07:50 +01:00
return oss . str ();
}
};
2013-11-26 20:57:45 +00:00
// 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
2014-03-17 18:40:58 +00:00
friend void addOptName ( Arg & arg , std :: string const & optName )
{
if ( optName . empty () )
return ;
if ( Detail :: startsWith ( optName , "--" ) ) {
if ( ! arg . longName . empty () )
throw std :: logic_error ( "Only one long opt may be specified. '"
+ arg . longName
+ "' already specified, now attempting to add '"
+ optName + "'" );
arg . longName = optName . substr ( 2 );
}
else if ( Detail :: startsWith ( optName , "-" ) )
arg . shortNames . push_back ( optName . substr ( 1 ) );
else
throw std :: logic_error ( "option must begin with - or --. Option was: '" + optName + "'" );
}
friend void setPositionalArg ( Arg & arg , int position )
{
arg . position = position ;
}
2014-03-06 08:16:06 +00:00
class ArgBuilder {
2013-06-07 19:07:50 +01:00
public :
2014-03-24 18:15:04 +00:00
ArgBuilder ( Arg * arg ) : m_arg ( arg ) {}
2014-03-06 08:16:06 +00:00
2014-03-17 18:40:58 +00:00
// Bind a non-boolean data member (requires placeholder string)
template < typename C , typename M >
void bind ( M C ::* field , std :: string const & placeholder ) {
2014-03-24 18:15:04 +00:00
m_arg -> boundField = new Detail :: BoundDataMember < C , M > ( field );
m_arg -> placeholder = placeholder ;
2013-06-07 19:07:50 +01:00
}
2014-03-17 18:40:58 +00:00
// Bind a boolean data member (no placeholder required)
template < typename C >
void bind ( bool C ::* field ) {
2014-03-24 18:15:04 +00:00
m_arg -> boundField = new Detail :: BoundDataMember < C , bool > ( field );
2013-06-07 19:07:50 +01:00
}
2014-03-06 08:16:06 +00:00
2014-03-17 18:40:58 +00:00
// Bind a method taking a single, non-boolean argument (requires a placeholder string)
template < typename C , typename M >
2014-03-24 18:15:04 +00:00
void bind ( void ( C ::* unaryMethod )( M ), std :: string const & placeholder ) {
m_arg -> boundField = new Detail :: BoundUnaryMethod < C , M > ( unaryMethod );
m_arg -> placeholder = placeholder ;
2014-03-06 08:16:06 +00:00
}
2014-03-17 18:40:58 +00:00
// Bind a method taking a single, boolean argument (no placeholder string required)
template < typename C >
2014-03-24 18:15:04 +00:00
void bind ( void ( C ::* unaryMethod )( bool ) ) {
m_arg -> boundField = new Detail :: BoundUnaryMethod < C , bool > ( unaryMethod );
2014-03-06 08:16:06 +00:00
}
2014-03-17 18:40:58 +00:00
// Bind a method that takes no arguments (will be called if opt is present)
template < typename C >
2014-03-24 18:15:04 +00:00
void bind ( void ( C ::* nullaryMethod )() ) {
m_arg -> boundField = new Detail :: BoundNullaryMethod < C > ( nullaryMethod );
2014-03-17 18:40:58 +00:00
}
// Bind a free function taking a single argument - the object to operate on (no placeholder string required)
template < typename C >
2014-03-24 18:15:04 +00:00
void bind ( void ( * unaryFunction )( C & ) ) {
m_arg -> boundField = new Detail :: BoundUnaryFunction < C > ( unaryFunction );
2014-03-06 08:16:06 +00:00
}
2014-03-17 18:40:58 +00:00
// Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
template < typename C , typename T >
2014-03-24 18:15:04 +00:00
void bind ( void ( * binaryFunction )( C & , T ), std :: string const & placeholder ) {
m_arg -> boundField = new Detail :: BoundBinaryFunction < C , T > ( binaryFunction );
m_arg -> placeholder = placeholder ;
2013-06-07 19:07:50 +01:00
}
2014-03-06 08:16:06 +00:00
ArgBuilder & describe ( std :: string const & description ) {
2014-03-24 18:15:04 +00:00
m_arg -> description = description ;
2013-06-07 19:07:50 +01:00
return * this ;
}
2015-07-02 08:21:38 +01:00
ArgBuilder & detail ( std :: string const & _detail ) {
m_arg -> detail = _detail ;
2013-06-07 19:07:50 +01:00
return * this ;
}
2014-03-06 08:16:06 +00:00
2014-03-17 18:40:58 +00:00
protected :
2014-03-24 18:15:04 +00:00
Arg * m_arg ;
2013-06-07 19:07:50 +01:00
};
2014-03-17 18:40:58 +00:00
2014-03-06 08:16:06 +00:00
class OptBuilder : public ArgBuilder {
public :
2014-03-24 18:15:04 +00:00
OptBuilder ( Arg * arg ) : ArgBuilder ( arg ) {}
2014-03-06 08:16:06 +00:00
OptBuilder ( OptBuilder & other ) : ArgBuilder ( other ) {}
OptBuilder & operator []( std :: string const & optName ) {
2014-03-24 18:15:04 +00:00
addOptName ( * ArgBuilder :: m_arg , optName );
2014-03-06 08:16:06 +00:00
return * this ;
}
};
2013-06-07 19:07:50 +01:00
public :
CommandLine ()
: m_boundProcessName ( new Detail :: NullBinder < ConfigT > () ),
2013-12-20 19:06:26 +00:00
m_highestSpecifiedArgPosition ( 0 ),
m_throwOnUnrecognisedTokens ( false )
2013-06-07 19:07:50 +01:00
{}
CommandLine ( CommandLine const & other )
: m_boundProcessName ( other . m_boundProcessName ),
m_options ( other . m_options ),
m_positionalArgs ( other . m_positionalArgs ),
2013-12-20 19:06:26 +00:00
m_highestSpecifiedArgPosition ( other . m_highestSpecifiedArgPosition ),
m_throwOnUnrecognisedTokens ( other . m_throwOnUnrecognisedTokens )
2013-06-07 19:07:50 +01:00
{
2014-03-17 18:40:58 +00:00
if ( other . m_floatingArg . get () )
2014-10-02 18:51:05 +01:00
m_floatingArg . reset ( new Arg ( * other . m_floatingArg ) );
2013-06-07 19:07:50 +01:00
}
2013-12-20 19:06:26 +00:00
CommandLine & setThrowOnUnrecognisedTokens ( bool shouldThrow = true ) {
m_throwOnUnrecognisedTokens = shouldThrow ;
return * this ;
}
2014-03-06 08:16:06 +00:00
OptBuilder operator []( std :: string const & optName ) {
2014-03-17 18:40:58 +00:00
m_options . push_back ( Arg () );
addOptName ( m_options . back (), optName );
2014-03-24 18:15:04 +00:00
OptBuilder builder ( & m_options . back () );
2014-03-06 08:16:06 +00:00
return builder ;
2013-06-07 19:07:50 +01:00
}
2014-03-06 08:16:06 +00:00
ArgBuilder operator []( int position ) {
2014-03-17 18:40:58 +00:00
m_positionalArgs . insert ( std :: make_pair ( position , Arg () ) );
if ( position > m_highestSpecifiedArgPosition )
m_highestSpecifiedArgPosition = position ;
setPositionalArg ( m_positionalArgs [ position ], position );
2014-03-24 18:15:04 +00:00
ArgBuilder builder ( & m_positionalArgs [ position ] );
2014-03-06 08:16:06 +00:00
return builder ;
}
// Invoke this with the _ instance
ArgBuilder operator []( UnpositionalTag ) {
2014-03-17 18:40:58 +00:00
if ( m_floatingArg . get () )
throw std :: logic_error ( "Only one unpositional argument can be added" );
2014-10-02 18:51:05 +01:00
m_floatingArg . reset ( new Arg () );
2014-03-24 18:15:04 +00:00
ArgBuilder builder ( m_floatingArg . get () );
2014-03-06 08:16:06 +00:00
return builder ;
}
2014-03-17 18:40:58 +00:00
template < typename C , typename M >
void bindProcessName ( M C ::* field ) {
m_boundProcessName = new Detail :: BoundDataMember < C , M > ( field );
}
template < typename C , typename M >
void bindProcessName ( void ( C ::* _unaryMethod )( M ) ) {
m_boundProcessName = new Detail :: BoundUnaryMethod < C , M > ( _unaryMethod );
2013-06-07 19:07:50 +01:00
}
2014-02-11 18:12:41 +00:00
void optUsage ( std :: ostream & os , std :: size_t indent = 0 , std :: size_t width = Detail :: consoleWidth ) const {
2013-06-07 19:07:50 +01:00
typename std :: vector < Arg >:: const_iterator itBegin = m_options . begin (), itEnd = m_options . end (), it ;
std :: size_t maxWidth = 0 ;
for ( it = itBegin ; it != itEnd ; ++ it )
maxWidth = ( std :: max )( maxWidth , it -> commands (). size () );
for ( it = itBegin ; it != itEnd ; ++ it ) {
2015-07-02 08:21:38 +01:00
Detail :: Text usageText ( it -> commands (), Detail :: TextAttributes ()
2013-06-07 19:07:50 +01:00
. setWidth ( maxWidth + indent )
. setIndent ( indent ) );
2014-02-11 18:12:41 +00:00
Detail :: Text desc ( it -> description , Detail :: TextAttributes ()
2014-03-24 18:15:04 +00:00
. setWidth ( width - maxWidth - 3 ) );
2013-06-07 19:07:50 +01:00
2015-07-02 08:21:38 +01:00
for ( std :: size_t i = 0 ; i < ( std :: max )( usageText . size (), desc . size () ); ++ i ) {
std :: string usageCol = i < usageText . size () ? usageText [ i ] : "" ;
2013-06-07 19:07:50 +01:00
os << usageCol ;
if ( i < desc . size () && ! desc [ i ]. empty () )
os << std :: string ( indent + 2 + maxWidth - usageCol . size (), ' ' )
<< desc [ i ];
os << " \n " ;
}
}
}
std :: string optUsage () const {
std :: ostringstream oss ;
optUsage ( oss );
return oss . str ();
}
void argSynopsis ( std :: ostream & os ) const {
for ( int i = 1 ; i <= m_highestSpecifiedArgPosition ; ++ i ) {
if ( i > 1 )
os << " " ;
typename std :: map < int , Arg >:: const_iterator it = m_positionalArgs . find ( i );
if ( it != m_positionalArgs . end () )
2014-03-06 08:16:06 +00:00
os << "<" << it -> second . placeholder << ">" ;
2014-03-17 18:40:58 +00:00
else if ( m_floatingArg . get () )
os << "<" << m_floatingArg -> placeholder << ">" ;
2013-06-07 19:07:50 +01:00
else
throw std :: logic_error ( "non consecutive positional arguments with no floating args" );
}
// !TBD No indication of mandatory args
2014-03-17 18:40:58 +00:00
if ( m_floatingArg . get () ) {
2013-06-07 19:07:50 +01:00
if ( m_highestSpecifiedArgPosition > 1 )
os << " " ;
2014-03-17 18:40:58 +00:00
os << "[<" << m_floatingArg -> placeholder << "> ...]" ;
2013-06-07 19:07:50 +01:00
}
}
std :: string argSynopsis () const {
std :: ostringstream oss ;
argSynopsis ( oss );
return oss . str ();
}
void usage ( std :: ostream & os , std :: string const & procName ) const {
2014-03-24 18:15:04 +00:00
validate ();
2013-06-07 19:07:50 +01:00
os << "usage: \n " << procName << " " ;
argSynopsis ( os );
if ( ! m_options . empty () ) {
os << " [options] \n\n where options are: \n " ;
optUsage ( os , 2 );
}
os << " \n " ;
}
std :: string usage ( std :: string const & procName ) const {
std :: ostringstream oss ;
usage ( oss , procName );
return oss . str ();
}
2014-03-24 18:15:04 +00:00
ConfigT parse ( int argc , char const * const * argv ) const {
2014-03-01 10:38:14 +00:00
ConfigT config ;
parseInto ( argc , argv , config );
return config ;
}
2013-06-07 19:07:50 +01:00
std :: vector < Parser :: Token > parseInto ( int argc , char const * const * argv , ConfigT & config ) const {
std :: string processName = argv [ 0 ];
std :: size_t lastSlash = processName . find_last_of ( "/ \\ " );
if ( lastSlash != std :: string :: npos )
processName = processName . substr ( lastSlash + 1 );
m_boundProcessName . set ( config , processName );
std :: vector < Parser :: Token > tokens ;
Parser parser ;
parser . parseIntoTokens ( argc , argv , tokens );
return populate ( tokens , config );
}
std :: vector < Parser :: Token > populate ( std :: vector < Parser :: Token > const & tokens , ConfigT & config ) const {
2014-03-24 18:15:04 +00:00
validate ();
2013-06-07 19:07:50 +01:00
std :: vector < Parser :: Token > unusedTokens = populateOptions ( tokens , config );
unusedTokens = populateFixedArgs ( unusedTokens , config );
unusedTokens = populateFloatingArgs ( unusedTokens , config );
return unusedTokens ;
}
std :: vector < Parser :: Token > populateOptions ( std :: vector < Parser :: Token > const & tokens , ConfigT & config ) const {
std :: vector < Parser :: Token > unusedTokens ;
2013-12-20 19:06:26 +00:00
std :: vector < std :: string > errors ;
2013-06-07 19:07:50 +01:00
for ( std :: size_t i = 0 ; i < tokens . size (); ++ i ) {
Parser :: Token const & token = tokens [ i ];
typename std :: vector < Arg >:: const_iterator it = m_options . begin (), itEnd = m_options . end ();
for (; it != itEnd ; ++ it ) {
Arg const & arg = * it ;
try {
if ( ( token . type == Parser :: Token :: ShortOpt && arg . hasShortName ( token . data ) ) ||
( token . type == Parser :: Token :: LongOpt && arg . hasLongName ( token . data ) ) ) {
if ( arg . takesArg () ) {
if ( i == tokens . size () - 1 || tokens [ i + 1 ]. type != Parser :: Token :: Positional )
2013-12-20 19:06:26 +00:00
errors . push_back ( "Expected argument to option: " + token . data );
else
arg . boundField . set ( config , tokens [ ++ i ]. data );
2013-06-07 19:07:50 +01:00
}
else {
arg . boundField . setFlag ( config );
}
break ;
}
}
catch ( std :: exception & ex ) {
2013-12-20 19:06:26 +00:00
errors . push_back ( std :: string ( ex . what () ) + " \n - while parsing: (" + arg . commands () + ")" );
2013-06-07 19:07:50 +01:00
}
}
2013-12-20 19:06:26 +00:00
if ( it == itEnd ) {
if ( token . type == Parser :: Token :: Positional || ! m_throwOnUnrecognisedTokens )
unusedTokens . push_back ( token );
2014-09-15 18:40:24 +01:00
else if ( errors . empty () && m_throwOnUnrecognisedTokens )
2013-12-20 19:06:26 +00:00
errors . push_back ( "unrecognised option: " + token . data );
}
}
if ( ! errors . empty () ) {
std :: ostringstream oss ;
for ( std :: vector < std :: string >:: const_iterator it = errors . begin (), itEnd = errors . end ();
it != itEnd ;
++ it ) {
if ( it != errors . begin () )
oss << " \n " ;
oss << * it ;
}
throw std :: runtime_error ( oss . str () );
2013-06-07 19:07:50 +01:00
}
return unusedTokens ;
}
std :: vector < Parser :: Token > populateFixedArgs ( std :: vector < Parser :: Token > const & tokens , ConfigT & config ) const {
std :: vector < Parser :: Token > unusedTokens ;
int position = 1 ;
for ( std :: size_t i = 0 ; i < tokens . size (); ++ i ) {
Parser :: Token const & token = tokens [ i ];
typename std :: map < int , Arg >:: const_iterator it = m_positionalArgs . find ( position );
if ( it != m_positionalArgs . end () )
it -> second . boundField . set ( config , token . data );
else
unusedTokens . push_back ( token );
if ( token . type == Parser :: Token :: Positional )
position ++ ;
}
return unusedTokens ;
}
std :: vector < Parser :: Token > populateFloatingArgs ( std :: vector < Parser :: Token > const & tokens , ConfigT & config ) const {
2014-03-17 18:40:58 +00:00
if ( ! m_floatingArg . get () )
2013-06-07 19:07:50 +01:00
return tokens ;
std :: vector < Parser :: Token > unusedTokens ;
for ( std :: size_t i = 0 ; i < tokens . size (); ++ i ) {
Parser :: Token const & token = tokens [ i ];
if ( token . type == Parser :: Token :: Positional )
2014-03-17 18:40:58 +00:00
m_floatingArg -> boundField . set ( config , token . data );
2013-06-07 19:07:50 +01:00
else
unusedTokens . push_back ( token );
}
return unusedTokens ;
}
2014-03-24 18:15:04 +00:00
void validate () const
{
if ( m_options . empty () && m_positionalArgs . empty () && ! m_floatingArg . get () )
throw std :: logic_error ( "No options or arguments specified" );
for ( typename std :: vector < Arg >:: const_iterator it = m_options . begin (),
itEnd = m_options . end ();
it != itEnd ; ++ it )
it -> validate ();
}
2013-06-07 19:07:50 +01:00
private :
Detail :: BoundArgFunction < ConfigT > m_boundProcessName ;
std :: vector < Arg > m_options ;
std :: map < int , Arg > m_positionalArgs ;
2014-03-17 18:40:58 +00:00
ArgAutoPtr m_floatingArg ;
2013-06-07 19:07:50 +01:00
int m_highestSpecifiedArgPosition ;
2013-12-20 19:06:26 +00:00
bool m_throwOnUnrecognisedTokens ;
2013-06-07 19:07:50 +01:00
};
} // end namespace Clara
2014-03-06 08:16:06 +00:00
STITCH_CLARA_CLOSE_NAMESPACE
#undef STITCH_CLARA_OPEN_NAMESPACE
#undef STITCH_CLARA_CLOSE_NAMESPACE
2014-02-11 18:12:41 +00:00
2014-03-01 10:38:14 +00:00
#endif // TWOBLUECUBES_CLARA_H_INCLUDED
2014-03-06 08:16:06 +00:00
#undef STITCH_CLARA_OPEN_NAMESPACE
// Restore Clara's value for console width, if present
#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
#endif
2014-02-11 18:12:41 +00:00
2013-11-26 20:57:45 +00:00
#include <fstream>
2013-06-07 19:07:50 +01:00
namespace Catch {
inline void abortAfterFirst ( ConfigData & config ) { config . abortAfter = 1 ; }
inline void abortAfterX ( ConfigData & config , int x ) {
if ( x < 1 )
throw std :: runtime_error ( "Value after -x or --abortAfter must be greater than zero" );
config . abortAfter = x ;
}
inline void addTestOrTags ( ConfigData & config , std :: string const & _testSpec ) { config . testsOrTags . push_back ( _testSpec ); }
2015-08-07 17:30:34 +01:00
inline void addReporterName ( ConfigData & config , std :: string const & _reporterName ) { config . reporterNames . push_back ( _reporterName ); }
2013-06-07 19:07:50 +01:00
inline void addWarning ( ConfigData & config , std :: string const & _warning ) {
if ( _warning == "NoAssertions" )
2014-07-09 07:40:37 +01:00
config . warnings = static_cast < WarnAbout :: What > ( config . warnings | WarnAbout :: NoAssertions );
2013-06-07 19:07:50 +01:00
else
throw std :: runtime_error ( "Unrecognised warning: '" + _warning + "'" );
2014-09-15 18:40:24 +01:00
}
inline void setOrder ( ConfigData & config , std :: string const & order ) {
if ( startsWith ( "declared" , order ) )
config . runOrder = RunTests :: InDeclarationOrder ;
else if ( startsWith ( "lexical" , order ) )
config . runOrder = RunTests :: InLexicographicalOrder ;
else if ( startsWith ( "random" , order ) )
config . runOrder = RunTests :: InRandomOrder ;
else
throw std :: runtime_error ( "Unrecognised ordering: '" + order + "'" );
}
inline void setRngSeed ( ConfigData & config , std :: string const & seed ) {
if ( seed == "time" ) {
config . rngSeed = static_cast < unsigned int > ( std :: time ( 0 ) );
}
else {
std :: stringstream ss ;
ss << seed ;
ss >> config . rngSeed ;
if ( ss . fail () )
throw std :: runtime_error ( "Argment to --rng-seed should be the word 'time' or a number" );
}
2013-06-07 19:07:50 +01:00
}
inline void setVerbosity ( ConfigData & config , int level ) {
// !TBD: accept strings?
2014-07-09 07:40:37 +01:00
config . verbosity = static_cast < Verbosity :: Level > ( level );
2013-08-15 19:01:00 +01:00
}
inline void setShowDurations ( ConfigData & config , bool _showDurations ) {
config . showDurations = _showDurations
? ShowDurations :: Always
: ShowDurations :: Never ;
2013-06-07 19:07:50 +01:00
}
2013-11-26 20:57:45 +00:00
inline void loadTestNamesFromFile ( ConfigData & config , std :: string const & _filename ) {
std :: ifstream f ( _filename . c_str () );
if ( ! f . is_open () )
throw std :: domain_error ( "Unable to load input file: " + _filename );
std :: string line ;
while ( std :: getline ( f , line ) ) {
line = trim ( line );
if ( ! line . empty () && ! startsWith ( line , "#" ) )
2014-05-20 18:50:59 +01:00
addTestOrTags ( config , " \" " + line + " \" ," );
2013-11-26 20:57:45 +00:00
}
}
2013-06-07 19:07:50 +01:00
inline Clara :: CommandLine < ConfigData > makeCommandLineParser () {
2014-03-06 08:16:06 +00:00
using namespace Clara ;
CommandLine < ConfigData > cli ;
2013-06-07 19:07:50 +01:00
cli . bindProcessName ( & ConfigData :: processName );
2014-03-06 08:16:06 +00:00
cli [ "-?" ][ "-h" ][ "--help" ]
2013-06-07 19:07:50 +01:00
. describe ( "display usage information" )
2014-03-17 18:40:58 +00:00
. bind ( & ConfigData :: showHelp );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-l" ][ "--list-tests" ]
2013-11-26 20:57:45 +00:00
. describe ( "list all/matching test cases" )
2014-03-17 18:40:58 +00:00
. bind ( & ConfigData :: listTests );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-t" ][ "--list-tags" ]
2013-11-26 20:57:45 +00:00
. describe ( "list all/matching tags" )
2014-03-17 18:40:58 +00:00
. bind ( & ConfigData :: listTags );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-s" ][ "--success" ]
2013-06-07 19:07:50 +01:00
. describe ( "include successful tests in output" )
2014-03-17 18:40:58 +00:00
. bind ( & ConfigData :: showSuccessfulTests );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-b" ][ "--break" ]
2013-06-07 19:07:50 +01:00
. describe ( "break into debugger on failure" )
2014-03-17 18:40:58 +00:00
. bind ( & ConfigData :: shouldDebugBreak );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-e" ][ "--nothrow" ]
2013-06-07 21:15:25 +01:00
. describe ( "skip exception tests" )
2014-03-17 18:40:58 +00:00
. bind ( & ConfigData :: noThrow );
2013-06-07 19:07:50 +01:00
2014-04-23 07:10:10 +01:00
cli [ "-i" ][ "--invisibles" ]
. describe ( "show invisibles (tabs, newlines)" )
. bind ( & ConfigData :: showInvisibles );
2014-03-06 08:16:06 +00:00
cli [ "-o" ][ "--out" ]
2013-06-07 19:07:50 +01:00
. describe ( "output filename" )
2014-03-17 18:40:58 +00:00
. bind ( & ConfigData :: outputFilename , "filename" );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-r" ][ "--reporter" ]
// .placeholder( "name[:filename]" )
2013-11-26 20:57:45 +00:00
. describe ( "reporter to use (defaults to console)" )
2015-08-07 17:30:34 +01:00
. bind ( & addReporterName , "name" );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-n" ][ "--name" ]
2013-06-07 19:07:50 +01:00
. describe ( "suite name" )
2014-03-17 18:40:58 +00:00
. bind ( & ConfigData :: name , "name" );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-a" ][ "--abort" ]
2013-06-07 19:07:50 +01:00
. describe ( "abort at first failure" )
2014-03-17 18:40:58 +00:00
. bind ( & abortAfterFirst );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-x" ][ "--abortx" ]
2013-06-07 19:07:50 +01:00
. describe ( "abort after x failures" )
2014-03-17 18:40:58 +00:00
. bind ( & abortAfterX , "no. failures" );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-w" ][ "--warn" ]
2013-06-07 19:07:50 +01:00
. describe ( "enable warnings" )
2014-03-17 18:40:58 +00:00
. bind ( & addWarning , "warning name" );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
// - needs updating if reinstated
// cli.into( &setVerbosity )
2013-06-07 19:07:50 +01:00
// .describe( "level of verbosity (0=no output)" )
// .shortOpt( "v")
// .longOpt( "verbosity" )
2014-03-06 08:16:06 +00:00
// .placeholder( "level" );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ _ ]
2013-06-07 19:07:50 +01:00
. describe ( "which test or tests to use" )
2014-03-17 18:40:58 +00:00
. bind ( & addTestOrTags , "test name, pattern or tags" );
2013-06-07 19:07:50 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-d" ][ "--durations" ]
2013-08-15 19:01:00 +01:00
. describe ( "show test durations" )
2014-03-17 18:40:58 +00:00
. bind ( & setShowDurations , "yes/no" );
2013-08-15 19:01:00 +01:00
2014-03-06 08:16:06 +00:00
cli [ "-f" ][ "--input-file" ]
2013-11-26 20:57:45 +00:00
. describe ( "load test names to run from a file" )
2014-03-17 18:40:58 +00:00
. bind ( & loadTestNamesFromFile , "filename" );
2013-11-26 20:57:45 +00:00
2015-07-07 08:25:15 +01:00
cli [ "-#" ][ "--filenames-as-tags" ]
. describe ( "adds a tag for the filename" )
. bind ( & ConfigData :: filenamesAsTags );
2013-11-26 20:57:45 +00:00
// Less common commands which don't have a short form
2014-03-06 08:16:06 +00:00
cli [ "--list-test-names-only" ]
2013-11-26 20:57:45 +00:00
. describe ( "list all/matching test cases names only" )
2014-03-17 18:40:58 +00:00
. bind ( & ConfigData :: listTestNamesOnly );
2013-11-26 20:57:45 +00:00
2014-03-06 08:16:06 +00:00
cli [ "--list-reporters" ]
2013-11-26 20:57:45 +00:00
. describe ( "list all reporters" )
2014-03-17 18:40:58 +00:00
. bind ( & ConfigData :: listReporters );
2013-11-26 20:57:45 +00:00
2014-09-15 18:40:24 +01:00
cli [ "--order" ]
. describe ( "test case order (defaults to decl)" )
. bind ( & setOrder , "decl|lex|rand" );
cli [ "--rng-seed" ]
. describe ( "set a specific seed for random numbers" )
. bind ( & setRngSeed , "'time'|number" );
2015-03-04 08:23:40 +00:00
cli [ "--force-colour" ]
. describe ( "force colourised output" )
. bind ( & ConfigData :: forceColour );
2013-06-07 19:07:50 +01:00
return cli ;
}
2012-08-13 07:46:10 +01:00
} // end namespace Catch
// #included from: internal/catch_list.hpp
#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
2014-02-11 18:12:41 +00:00
// #included from: catch_text.h
#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
2014-03-17 18:40:58 +00:00
// #included from: ../external/tbc_text_format.h
2014-02-11 18:12:41 +00:00
// Only use header guard if we are not using an outer namespace
#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
# endif
# else
# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
# endif
#endif
#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
#include <string>
#include <vector>
#include <sstream>
// Use optional outer namespace
#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
#endif
namespace Tbc {
#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH ;
#else
const unsigned int consoleWidth = 80 ;
#endif
struct TextAttributes {
TextAttributes ()
: initialIndent ( std :: string :: npos ),
indent ( 0 ),
width ( consoleWidth - 1 ),
tabChar ( '\t' )
{}
TextAttributes & setInitialIndent ( std :: size_t _value ) { initialIndent = _value ; return * this ; }
TextAttributes & setIndent ( std :: size_t _value ) { indent = _value ; return * this ; }
TextAttributes & setWidth ( std :: size_t _value ) { width = _value ; return * this ; }
TextAttributes & setTabChar ( char _value ) { tabChar = _value ; return * this ; }
std :: size_t initialIndent ; // indent of first line, or npos
std :: size_t indent ; // indent of subsequent lines, or all if initialIndent is npos
std :: size_t width ; // maximum width of text, including indent. Longer text will wrap
char tabChar ; // If this char is seen the indent is changed to current pos
};
class Text {
public :
Text ( std :: string const & _str , TextAttributes const & _attr = TextAttributes () )
: attr ( _attr )
{
std :: string wrappableChars = " [({.,/| \\ -" ;
std :: size_t indent = _attr . initialIndent != std :: string :: npos
? _attr . initialIndent
: _attr . indent ;
std :: string remainder = _str ;
while ( ! remainder . empty () ) {
if ( lines . size () >= 1000 ) {
lines . push_back ( "... message truncated due to excessive size" );
return ;
}
std :: size_t tabPos = std :: string :: npos ;
std :: size_t width = ( std :: min )( remainder . size (), _attr . width - indent );
std :: size_t pos = remainder . find_first_of ( '\n' );
if ( pos <= width ) {
width = pos ;
}
pos = remainder . find_last_of ( _attr . tabChar , width );
if ( pos != std :: string :: npos ) {
tabPos = pos ;
if ( remainder [ width ] == '\n' )
width -- ;
remainder = remainder . substr ( 0 , tabPos ) + remainder . substr ( tabPos + 1 );
}
if ( width == remainder . size () ) {
spliceLine ( indent , remainder , width );
}
else if ( remainder [ width ] == '\n' ) {
spliceLine ( indent , remainder , width );
if ( width <= 1 || remainder . size () != 1 )
remainder = remainder . substr ( 1 );
indent = _attr . indent ;
}
else {
pos = remainder . find_last_of ( wrappableChars , width );
if ( pos != std :: string :: npos && pos > 0 ) {
spliceLine ( indent , remainder , pos );
if ( remainder [ 0 ] == ' ' )
remainder = remainder . substr ( 1 );
}
else {
spliceLine ( indent , remainder , width - 1 );
lines . back () += "-" ;
}
if ( lines . size () == 1 )
indent = _attr . indent ;
if ( tabPos != std :: string :: npos )
indent += tabPos ;
}
}
}
void spliceLine ( std :: size_t _indent , std :: string & _remainder , std :: size_t _pos ) {
lines . push_back ( std :: string ( _indent , ' ' ) + _remainder . substr ( 0 , _pos ) );
_remainder = _remainder . substr ( _pos );
}
typedef std :: vector < std :: string >:: const_iterator const_iterator ;
const_iterator begin () const { return lines . begin (); }
const_iterator end () const { return lines . end (); }
std :: string const & last () const { return lines . back (); }
std :: size_t size () const { return lines . size (); }
std :: string const & operator []( std :: size_t _index ) const { return lines [ _index ]; }
std :: string toString () const {
std :: ostringstream oss ;
oss << * this ;
return oss . str ();
}
inline friend std :: ostream & operator << ( std :: ostream & _stream , Text const & _text ) {
for ( Text :: const_iterator it = _text . begin (), itEnd = _text . end ();
it != itEnd ; ++ it ) {
if ( it != _text . begin () )
_stream << " \n " ;
_stream << * it ;
}
return _stream ;
}
private :
std :: string str ;
TextAttributes attr ;
std :: vector < std :: string > lines ;
};
} // end namespace Tbc
#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
} // end outer namespace
#endif
#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
namespace Catch {
using Tbc :: Text ;
using Tbc :: TextAttributes ;
}
2013-04-01 11:27:10 +01:00
// #included from: catch_console_colour.hpp
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
2012-08-13 07:46:10 +01:00
namespace Catch {
2013-04-01 11:27:10 +01:00
2013-04-05 20:58:01 +01:00
struct Colour {
enum Code {
None = 0 ,
2013-04-01 11:27:10 +01:00
2013-04-05 20:58:01 +01:00
White ,
Red ,
Green ,
Blue ,
Cyan ,
Yellow ,
Grey ,
2013-04-01 11:27:10 +01:00
2013-04-05 20:58:01 +01:00
Bright = 0x10 ,
2013-04-01 11:27:10 +01:00
2013-04-05 20:58:01 +01:00
BrightRed = Bright | Red ,
BrightGreen = Bright | Green ,
LightGrey = Bright | Grey ,
BrightWhite = Bright | White ,
// By intention
FileName = LightGrey ,
2014-07-03 08:11:38 +01:00
Warning = Yellow ,
2013-04-05 20:58:01 +01:00
ResultError = BrightRed ,
ResultSuccess = BrightGreen ,
2014-07-03 08:11:38 +01:00
ResultExpectedFailure = Warning ,
2013-04-05 20:58:01 +01:00
Error = BrightRed ,
Success = Green ,
OriginalExpression = Cyan ,
ReconstructedExpression = Yellow ,
SecondaryText = LightGrey ,
Headers = White
2013-04-01 11:27:10 +01:00
};
2013-04-05 20:58:01 +01:00
// Use constructed object for RAII guard
Colour ( Code _colourCode );
2014-07-09 07:40:37 +01:00
Colour ( Colour const & other );
2013-04-05 20:58:01 +01:00
~ Colour ();
2013-04-01 11:27:10 +01:00
2013-04-05 20:58:01 +01:00
// Use static method for one-shot changes
static void use ( Code _colourCode );
2013-04-01 11:27:10 +01:00
private :
2014-07-09 07:40:37 +01:00
bool m_moved ;
2013-04-01 11:27:10 +01:00
};
2014-07-03 08:11:38 +01:00
inline std :: ostream & operator << ( std :: ostream & os , Colour const & ) { return os ; }
2013-04-01 11:27:10 +01:00
} // end namespace Catch
2013-12-03 18:53:55 +00:00
// #included from: catch_interfaces_reporter.h
#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
#include <string>
#include <ostream>
#include <map>
#include <assert.h>
namespace Catch
{
struct ReporterConfig {
explicit ReporterConfig ( Ptr < IConfig > const & _fullConfig )
: m_stream ( & _fullConfig -> stream () ), m_fullConfig ( _fullConfig ) {}
ReporterConfig ( Ptr < IConfig > 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 ; }
private :
std :: ostream * m_stream ;
Ptr < IConfig > m_fullConfig ;
};
struct ReporterPreferences {
ReporterPreferences ()
: shouldRedirectStdOut ( false )
{}
bool shouldRedirectStdOut ;
};
template < typename T >
struct LazyStat : Option < T > {
LazyStat () : used ( false ) {}
LazyStat & operator = ( T const & _value ) {
Option < T >:: operator = ( _value );
used = false ;
return * this ;
}
void reset () {
Option < T >:: reset ();
used = false ;
}
bool used ;
};
struct TestRunInfo {
TestRunInfo ( std :: string const & _name ) : name ( _name ) {}
std :: string name ;
};
struct GroupInfo {
GroupInfo ( std :: string const & _name ,
std :: size_t _groupIndex ,
std :: size_t _groupsCount )
: name ( _name ),
groupIndex ( _groupIndex ),
groupsCounts ( _groupsCount )
{}
std :: string name ;
std :: size_t groupIndex ;
std :: size_t groupsCounts ;
};
struct AssertionStats {
AssertionStats ( AssertionResult const & _assertionResult ,
std :: vector < MessageInfo > const & _infoMessages ,
Totals const & _totals )
: assertionResult ( _assertionResult ),
infoMessages ( _infoMessages ),
totals ( _totals )
{
if ( assertionResult . hasMessage () ) {
// Copy message into messages list.
// !TBD This should have been done earlier, somewhere
MessageBuilder builder ( assertionResult . getTestMacroName (), assertionResult . getSourceInfo (), assertionResult . getResultType () );
builder << assertionResult . getMessage ();
builder . m_info . message = builder . m_stream . str ();
infoMessages . push_back ( builder . m_info );
}
}
virtual ~ AssertionStats ();
2015-05-19 18:40:00 +01:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2014-04-18 08:49:35 +01:00
AssertionStats ( AssertionStats const & ) = default ;
AssertionStats ( AssertionStats && ) = default ;
AssertionStats & operator = ( AssertionStats const & ) = default ;
AssertionStats & operator = ( AssertionStats && ) = default ;
# endif
2013-12-03 18:53:55 +00:00
AssertionResult assertionResult ;
std :: vector < MessageInfo > infoMessages ;
Totals totals ;
};
struct SectionStats {
SectionStats ( SectionInfo const & _sectionInfo ,
Counts const & _assertions ,
double _durationInSeconds ,
bool _missingAssertions )
: sectionInfo ( _sectionInfo ),
assertions ( _assertions ),
durationInSeconds ( _durationInSeconds ),
missingAssertions ( _missingAssertions )
{}
virtual ~ SectionStats ();
2015-05-19 18:40:00 +01:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2014-04-18 08:49:35 +01:00
SectionStats ( SectionStats const & ) = default ;
SectionStats ( SectionStats && ) = default ;
SectionStats & operator = ( SectionStats const & ) = default ;
SectionStats & operator = ( SectionStats && ) = default ;
# endif
2013-12-03 18:53:55 +00:00
SectionInfo sectionInfo ;
Counts assertions ;
double durationInSeconds ;
bool missingAssertions ;
};
struct TestCaseStats {
TestCaseStats ( TestCaseInfo const & _testInfo ,
Totals const & _totals ,
std :: string const & _stdOut ,
std :: string const & _stdErr ,
bool _aborting )
: testInfo ( _testInfo ),
totals ( _totals ),
stdOut ( _stdOut ),
stdErr ( _stdErr ),
aborting ( _aborting )
{}
virtual ~ TestCaseStats ();
2015-05-19 18:40:00 +01:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2014-04-18 08:49:35 +01:00
TestCaseStats ( TestCaseStats const & ) = default ;
TestCaseStats ( TestCaseStats && ) = default ;
TestCaseStats & operator = ( TestCaseStats const & ) = default ;
TestCaseStats & operator = ( TestCaseStats && ) = default ;
# endif
2013-12-03 18:53:55 +00:00
TestCaseInfo testInfo ;
Totals totals ;
std :: string stdOut ;
std :: string stdErr ;
bool aborting ;
};
struct TestGroupStats {
TestGroupStats ( GroupInfo const & _groupInfo ,
Totals const & _totals ,
bool _aborting )
: groupInfo ( _groupInfo ),
totals ( _totals ),
aborting ( _aborting )
{}
TestGroupStats ( GroupInfo const & _groupInfo )
: groupInfo ( _groupInfo ),
aborting ( false )
{}
virtual ~ TestGroupStats ();
2015-05-19 18:40:00 +01:00
# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
2014-04-18 08:49:35 +01:00
TestGroupStats ( TestGroupStats const & ) = default ;
TestGroupStats ( TestGroupStats && ) = default ;
TestGroupStats & operator = ( TestGroupStats const & ) = default ;
TestGroupStats & operator = ( TestGroupStats && ) = default ;
# endif
2013-12-03 18:53:55 +00:00
GroupInfo groupInfo ;
Totals totals ;
bool aborting ;
};
struct TestRunStats {
TestRunStats ( TestRunInfo const & _runInfo ,
Totals const & _totals ,
bool _aborting )
: runInfo ( _runInfo ),
totals ( _totals ),
aborting ( _aborting )
{}
2014-04-18 08:49:35 +01:00
virtual ~ TestRunStats ();
2015-05-19 18:40:00 +01:00
# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
2013-12-03 18:53:55 +00:00
TestRunStats ( TestRunStats const & _other )
: runInfo ( _other . runInfo ),
totals ( _other . totals ),
aborting ( _other . aborting )
{}
2014-04-18 08:49:35 +01:00
# else
TestRunStats ( TestRunStats const & ) = default ;
TestRunStats ( TestRunStats && ) = default ;
TestRunStats & operator = ( TestRunStats const & ) = default ;
TestRunStats & operator = ( TestRunStats && ) = default ;
# endif
2013-12-03 18:53:55 +00:00
TestRunInfo runInfo ;
Totals totals ;
bool aborting ;
};
struct IStreamingReporter : IShared {
virtual ~ IStreamingReporter ();
// Implementing class must also provide the following static method:
// static std::string getDescription();
virtual ReporterPreferences getPreferences () const = 0 ;
virtual void noMatchingTestCases ( std :: string const & spec ) = 0 ;
virtual void testRunStarting ( TestRunInfo const & testRunInfo ) = 0 ;
virtual void testGroupStarting ( GroupInfo const & groupInfo ) = 0 ;
virtual void testCaseStarting ( TestCaseInfo const & testInfo ) = 0 ;
virtual void sectionStarting ( SectionInfo const & sectionInfo ) = 0 ;
virtual void assertionStarting ( AssertionInfo const & assertionInfo ) = 0 ;
2014-12-21 00:21:23 +00:00
// The return value indicates if the messages buffer should be cleared:
2013-12-03 18:53:55 +00:00
virtual bool assertionEnded ( AssertionStats const & assertionStats ) = 0 ;
2015-08-07 17:30:34 +01:00
2013-12-03 18:53:55 +00:00
virtual void sectionEnded ( SectionStats const & sectionStats ) = 0 ;
virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) = 0 ;
virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) = 0 ;
virtual void testRunEnded ( TestRunStats const & testRunStats ) = 0 ;
2014-12-22 20:18:05 +00:00
virtual void skipTest ( TestCaseInfo const & testInfo ) = 0 ;
2013-12-03 18:53:55 +00:00
};
2015-08-07 17:30:34 +01:00
struct IReporterFactory : IShared {
2013-12-03 18:53:55 +00:00
virtual ~ IReporterFactory ();
virtual IStreamingReporter * create ( ReporterConfig const & config ) const = 0 ;
virtual std :: string getDescription () const = 0 ;
};
struct IReporterRegistry {
2015-08-07 17:30:34 +01:00
typedef std :: map < std :: string , Ptr < IReporterFactory > > FactoryMap ;
typedef std :: vector < Ptr < IReporterFactory > > Listeners ;
2013-12-03 18:53:55 +00:00
virtual ~ IReporterRegistry ();
virtual IStreamingReporter * create ( std :: string const & name , Ptr < IConfig > const & config ) const = 0 ;
virtual FactoryMap const & getFactories () const = 0 ;
2015-08-07 17:30:34 +01:00
virtual Listeners const & getListeners () const = 0 ;
2013-12-03 18:53:55 +00:00
};
2015-08-07 17:30:34 +01:00
Ptr < IStreamingReporter > addReporter ( Ptr < IStreamingReporter > const & existingReporter , Ptr < IStreamingReporter > const & additionalReporter );
2013-12-03 18:53:55 +00:00
}
2012-08-13 07:46:10 +01:00
#include <limits>
2013-03-29 13:44:33 +00:00
#include <algorithm>
2012-08-13 07:46:10 +01:00
namespace Catch {
2013-06-07 19:07:50 +01:00
inline std :: size_t listTests ( Config const & config ) {
2014-05-16 18:54:48 +01:00
TestSpec testSpec = config . testSpec ();
if ( config . testSpec (). hasFilters () )
2014-10-02 19:08:19 +01:00
Catch :: cout () << "Matching test cases: \n " ;
2014-05-16 18:54:48 +01:00
else {
2014-10-02 19:08:19 +01:00
Catch :: cout () << "All available test cases: \n " ;
2014-06-30 07:35:36 +01:00
testSpec = TestSpecParser ( ITagAliasRegistry :: get () ). parse ( "*" ). testSpec ();
2014-05-16 18:54:48 +01:00
}
2013-03-29 13:44:33 +00:00
std :: size_t matchedTests = 0 ;
2013-11-13 08:10:45 +00:00
TextAttributes nameAttr , tagsAttr ;
nameAttr . setInitialIndent ( 2 ). setIndent ( 4 );
tagsAttr . setIndent ( 6 );
2015-08-07 17:30:34 +01:00
std :: vector < TestCase > matchedTestCases = filterTests ( getAllTestCasesSorted ( config ), testSpec , config );
2014-04-15 18:44:37 +01:00
for ( std :: vector < TestCase >:: const_iterator it = matchedTestCases . begin (), itEnd = matchedTestCases . end ();
2013-11-13 08:10:45 +00:00
it != itEnd ;
2014-04-15 18:44:37 +01:00
++ it ) {
matchedTests ++ ;
TestCaseInfo const & testCaseInfo = it -> getTestCaseInfo ();
2014-07-03 08:11:38 +01:00
Colour :: Code colour = testCaseInfo . isHidden ()
2014-04-15 18:44:37 +01:00
? Colour :: SecondaryText
: Colour :: None ;
Colour colourGuard ( colour );
2013-03-29 13:44:33 +00:00
2014-10-02 19:08:19 +01:00
Catch :: cout () << Text ( testCaseInfo . name , nameAttr ) << std :: endl ;
2014-04-15 18:44:37 +01:00
if ( ! testCaseInfo . tags . empty () )
2014-10-02 19:08:19 +01:00
Catch :: cout () << Text ( testCaseInfo . tagsAsString , tagsAttr ) << std :: endl ;
2014-04-15 18:44:37 +01:00
}
2013-11-13 08:10:45 +00:00
2014-05-16 18:54:48 +01:00
if ( ! config . testSpec (). hasFilters () )
2014-10-02 19:08:19 +01:00
Catch :: cout () << pluralise ( matchedTests , "test case" ) << " \n " << std :: endl ;
2013-03-29 13:44:33 +00:00
else
2014-10-02 19:08:19 +01:00
Catch :: cout () << pluralise ( matchedTests , "matching test case" ) << " \n " << std :: endl ;
2013-06-07 19:07:50 +01:00
return matchedTests ;
2013-03-29 13:44:33 +00:00
}
2012-08-13 07:46:10 +01:00
2013-11-26 20:57:45 +00:00
inline std :: size_t listTestsNamesOnly ( Config const & config ) {
2014-05-16 18:54:48 +01:00
TestSpec testSpec = config . testSpec ();
if ( ! config . testSpec (). hasFilters () )
2014-06-30 07:35:36 +01:00
testSpec = TestSpecParser ( ITagAliasRegistry :: get () ). parse ( "*" ). testSpec ();
2013-11-26 20:57:45 +00:00
std :: size_t matchedTests = 0 ;
2015-08-07 17:30:34 +01:00
std :: vector < TestCase > matchedTestCases = filterTests ( getAllTestCasesSorted ( config ), testSpec , config );
2014-04-15 18:44:37 +01:00
for ( std :: vector < TestCase >:: const_iterator it = matchedTestCases . begin (), itEnd = matchedTestCases . end ();
2013-11-26 20:57:45 +00:00
it != itEnd ;
2014-04-15 18:44:37 +01:00
++ it ) {
matchedTests ++ ;
TestCaseInfo const & testCaseInfo = it -> getTestCaseInfo ();
2014-10-02 19:08:19 +01:00
Catch :: cout () << testCaseInfo . name << std :: endl ;
2014-04-15 18:44:37 +01:00
}
2013-11-26 20:57:45 +00:00
return matchedTests ;
}
2014-05-20 19:02:37 +01:00
struct TagInfo {
TagInfo () : count ( 0 ) {}
void add ( std :: string const & spelling ) {
++ count ;
spellings . insert ( spelling );
}
std :: string all () const {
std :: string out ;
for ( std :: set < std :: string >:: const_iterator it = spellings . begin (), itEnd = spellings . end ();
it != itEnd ;
++ it )
out += "[" + * it + "]" ;
return out ;
}
std :: set < std :: string > spellings ;
std :: size_t count ;
};
2013-06-07 19:07:50 +01:00
inline std :: size_t listTags ( Config const & config ) {
2014-05-16 18:54:48 +01:00
TestSpec testSpec = config . testSpec ();
if ( config . testSpec (). hasFilters () )
2014-10-02 19:08:19 +01:00
Catch :: cout () << "Tags for matching test cases: \n " ;
2014-05-16 18:54:48 +01:00
else {
2014-10-02 19:08:19 +01:00
Catch :: cout () << "All available tags: \n " ;
2014-06-30 07:35:36 +01:00
testSpec = TestSpecParser ( ITagAliasRegistry :: get () ). parse ( "*" ). testSpec ();
2014-05-16 18:54:48 +01:00
}
2013-03-29 13:44:33 +00:00
2014-05-20 18:50:59 +01:00
std :: map < std :: string , TagInfo > tagCounts ;
2013-03-29 13:44:33 +00:00
2015-08-07 17:30:34 +01:00
std :: vector < TestCase > matchedTestCases = filterTests ( getAllTestCasesSorted ( config ), testSpec , config );
2014-04-15 18:44:37 +01:00
for ( std :: vector < TestCase >:: const_iterator it = matchedTestCases . begin (), itEnd = matchedTestCases . end ();
2013-11-13 08:10:45 +00:00
it != itEnd ;
++ it ) {
2014-04-15 18:44:37 +01:00
for ( std :: set < std :: string >:: const_iterator tagIt = it -> getTestCaseInfo (). tags . begin (),
tagItEnd = it -> getTestCaseInfo (). tags . end ();
tagIt != tagItEnd ;
++ tagIt ) {
std :: string tagName = * tagIt ;
2014-05-20 18:50:59 +01:00
std :: string lcaseTagName = toLower ( tagName );
std :: map < std :: string , TagInfo >:: iterator countIt = tagCounts . find ( lcaseTagName );
2014-04-15 18:44:37 +01:00
if ( countIt == tagCounts . end () )
2014-05-20 18:50:59 +01:00
countIt = tagCounts . insert ( std :: make_pair ( lcaseTagName , TagInfo () ) ). first ;
countIt -> second . add ( tagName );
2013-03-29 13:44:33 +00:00
}
2012-08-13 07:46:10 +01:00
}
2013-03-29 13:44:33 +00:00
2014-05-20 18:50:59 +01:00
for ( std :: map < std :: string , TagInfo >:: const_iterator countIt = tagCounts . begin (),
countItEnd = tagCounts . end ();
2013-03-29 13:44:33 +00:00
countIt != countItEnd ;
++ countIt ) {
2013-11-13 08:10:45 +00:00
std :: ostringstream oss ;
2014-05-20 18:50:59 +01:00
oss << " " << std :: setw ( 2 ) << countIt -> second . count << " " ;
Text wrapper ( countIt -> second . all (), TextAttributes ()
. setInitialIndent ( 0 )
. setIndent ( oss . str (). size () )
. setWidth ( CATCH_CONFIG_CONSOLE_WIDTH - 10 ) );
2014-10-02 19:08:19 +01:00
Catch :: cout () << oss . str () << wrapper << " \n " ;
2013-03-29 13:44:33 +00:00
}
2014-10-02 19:08:19 +01:00
Catch :: cout () << pluralise ( tagCounts . size (), "tag" ) << " \n " << std :: endl ;
2013-06-07 19:07:50 +01:00
return tagCounts . size ();
2013-03-29 13:44:33 +00:00
}
2013-06-07 19:07:50 +01:00
inline std :: size_t listReporters ( Config const & /*config*/ ) {
2014-12-21 00:21:23 +00:00
Catch :: cout () << "Available reporters: \n " ;
2013-03-29 13:44:33 +00:00
IReporterRegistry :: FactoryMap const & factories = getRegistryHub (). getReporterRegistry (). getFactories ();
2013-06-07 19:07:50 +01:00
IReporterRegistry :: FactoryMap :: const_iterator itBegin = factories . begin (), itEnd = factories . end (), it ;
std :: size_t maxNameLen = 0 ;
for ( it = itBegin ; it != itEnd ; ++ it )
maxNameLen = ( std :: max )( maxNameLen , it -> first . size () );
for ( it = itBegin ; it != itEnd ; ++ it ) {
Text wrapper ( it -> second -> getDescription (), TextAttributes ()
. setInitialIndent ( 0 )
. setIndent ( 7 + maxNameLen )
. setWidth ( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen - 8 ) );
2014-10-02 19:08:19 +01:00
Catch :: cout () << " "
2013-06-07 19:07:50 +01:00
<< it -> first
<< ":"
<< std :: string ( maxNameLen - it -> first . size () + 2 , ' ' )
<< wrapper << " \n " ;
2013-03-29 13:44:33 +00:00
}
2014-10-02 19:08:19 +01:00
Catch :: cout () << std :: endl ;
2013-06-07 19:07:50 +01:00
return factories . size ();
2013-03-29 13:44:33 +00:00
}
2013-06-07 19:07:50 +01:00
inline Option < std :: size_t > list ( Config const & config ) {
Option < std :: size_t > listedCount ;
if ( config . listTests () )
listedCount = listedCount . valueOr ( 0 ) + listTests ( config );
2013-11-26 20:57:45 +00:00
if ( config . listTestNamesOnly () )
listedCount = listedCount . valueOr ( 0 ) + listTestsNamesOnly ( config );
2013-06-07 19:07:50 +01:00
if ( config . listTags () )
listedCount = listedCount . valueOr ( 0 ) + listTags ( config );
if ( config . listReporters () )
listedCount = listedCount . valueOr ( 0 ) + listReporters ( config );
return listedCount ;
2012-08-13 07:46:10 +01:00
}
} // end namespace Catch
2015-08-07 17:30:34 +01:00
// #included from: internal/catch_run_context.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
2012-08-13 07:46:10 +01:00
2013-07-25 08:12:03 +01:00
// #included from: catch_test_case_tracker.hpp
#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
2012-08-13 07:46:10 +01:00
#include <map>
#include <string>
2013-07-25 08:12:03 +01:00
#include <assert.h>
2012-08-13 07:46:10 +01:00
namespace Catch {
2013-07-25 08:12:03 +01:00
namespace SectionTracking {
class TrackedSection {
typedef std :: map < std :: string , TrackedSection > TrackedSections ;
2012-08-13 07:46:10 +01:00
public :
2013-07-25 08:12:03 +01:00
enum RunState {
NotStarted ,
Executing ,
ExecutingChildren ,
Completed
2012-08-13 07:46:10 +01:00
};
2013-07-25 08:12:03 +01:00
TrackedSection ( std :: string const & name , TrackedSection * parent )
: m_name ( name ), m_runState ( NotStarted ), m_parent ( parent )
2012-08-13 07:46:10 +01:00
{}
2013-07-25 08:12:03 +01:00
RunState runState () const { return m_runState ; }
2012-08-13 07:46:10 +01:00
2015-06-30 18:26:09 +01:00
TrackedSection * findChild ( std :: string const & childName );
TrackedSection * acquireChild ( std :: string const & childName );
2013-07-25 08:12:03 +01:00
void enter () {
if ( m_runState == NotStarted )
m_runState = Executing ;
2012-08-13 07:46:10 +01:00
}
2015-06-30 18:26:09 +01:00
void leave ();
2013-07-25 08:12:03 +01:00
TrackedSection * getParent () {
2012-08-13 07:46:10 +01:00
return m_parent ;
}
2013-07-25 08:12:03 +01:00
bool hasChildren () const {
return ! m_children . empty ();
2012-12-01 23:57:18 +00:00
}
2012-08-13 07:46:10 +01:00
private :
2012-12-01 23:57:18 +00:00
std :: string m_name ;
2013-07-25 08:12:03 +01:00
RunState m_runState ;
TrackedSections m_children ;
TrackedSection * m_parent ;
2012-08-13 07:46:10 +01:00
};
2015-06-30 18:26:09 +01:00
inline TrackedSection * TrackedSection :: findChild ( std :: string const & childName ) {
TrackedSections :: iterator it = m_children . find ( childName );
return it != m_children . end ()
? & it -> second
2015-07-02 08:21:38 +01:00
: CATCH_NULL ;
2015-06-30 18:26:09 +01:00
}
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 ;
}
m_runState = Completed ;
}
2013-07-25 08:12:03 +01:00
class TestCaseTracker {
2012-08-13 07:46:10 +01:00
public :
2013-07-25 08:12:03 +01:00
TestCaseTracker ( std :: string const & testCaseName )
2015-07-02 08:21:38 +01:00
: m_testCase ( testCaseName , CATCH_NULL ),
2013-07-25 08:12:03 +01:00
m_currentSection ( & m_testCase ),
m_completedASectionThisRun ( false )
2012-08-13 07:46:10 +01:00
{}
2013-07-25 08:12:03 +01:00
bool enterSection ( std :: string const & name ) {
2014-04-21 19:02:38 +01:00
TrackedSection * child = m_currentSection -> acquireChild ( name );
if ( m_completedASectionThisRun || child -> runState () == TrackedSection :: Completed )
2013-07-25 08:12:03 +01:00
return false ;
2014-04-21 19:02:38 +01:00
m_currentSection = child ;
m_currentSection -> enter ();
return true ;
2012-08-13 07:46:10 +01:00
}
2013-07-25 08:12:03 +01:00
void leaveSection () {
m_currentSection -> leave ();
2012-08-13 07:46:10 +01:00
m_currentSection = m_currentSection -> getParent ();
2015-07-02 08:21:38 +01:00
assert ( m_currentSection != CATCH_NULL );
2013-07-25 08:12:03 +01:00
m_completedASectionThisRun = true ;
2012-08-13 07:46:10 +01:00
}
2013-07-25 08:12:03 +01:00
bool currentSectionHasChildren () const {
return m_currentSection -> hasChildren ();
}
bool isCompleted () const {
return m_testCase . runState () == TrackedSection :: Completed ;
2012-08-13 07:46:10 +01:00
}
2013-07-25 08:12:03 +01:00
class Guard {
public :
2014-04-21 19:02:38 +01:00
Guard ( TestCaseTracker & tracker ) : m_tracker ( tracker ) {
2013-07-25 08:12:03 +01:00
m_tracker . enterTestCase ();
}
~ Guard () {
m_tracker . leaveTestCase ();
}
private :
2013-07-25 08:18:09 +01:00
Guard ( Guard const & );
void operator = ( Guard const & );
2013-07-25 08:12:03 +01:00
TestCaseTracker & m_tracker ;
};
2012-08-13 07:46:10 +01:00
private :
2013-07-25 08:12:03 +01:00
void enterTestCase () {
m_currentSection = & m_testCase ;
m_completedASectionThisRun = false ;
m_testCase . enter ();
}
void leaveTestCase () {
m_testCase . leave ();
}
2013-03-25 09:25:31 +00:00
2013-07-25 08:12:03 +01:00
TrackedSection m_testCase ;
TrackedSection * m_currentSection ;
bool m_completedASectionThisRun ;
2012-08-13 07:46:10 +01:00
};
2013-07-25 08:12:03 +01:00
} // namespace SectionTracking
using SectionTracking :: TestCaseTracker ;
} // namespace Catch
2012-08-13 07:46:10 +01:00
2014-08-22 19:35:41 +01:00
// #included from: catch_fatal_condition.hpp
#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
namespace Catch {
// Report the error condition then exit the process
inline void fatal ( std :: string const & message , int exitCode ) {
IContext & context = Catch :: getCurrentContext ();
IResultCapture * resultCapture = context . getResultCapture ();
resultCapture -> handleFatalErrorCondition ( message );
if ( Catch :: alwaysTrue () ) // avoids "no return" warnings
exit ( exitCode );
}
} // namespace Catch
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
namespace Catch {
2014-10-21 07:25:26 +01:00
struct FatalConditionHandler {
void reset () {}
};
2014-08-22 19:35:41 +01:00
} // namespace Catch
#else // Not Windows - assumed to be POSIX compatible //////////////////////////
#include <signal.h>
namespace Catch {
struct SignalDefs { int id ; const char * name ; };
extern SignalDefs signalDefs [];
SignalDefs signalDefs [] = {
{ SIGINT , "SIGINT - Terminal interrupt signal" },
{ SIGILL , "SIGILL - Illegal instruction signal" },
{ SIGFPE , "SIGFPE - Floating point error signal" },
{ SIGSEGV , "SIGSEGV - Segmentation violation signal" },
{ SIGTERM , "SIGTERM - Termination request signal" },
{ SIGABRT , "SIGABRT - Abort (abnormal termination) signal" }
};
struct FatalConditionHandler {
static void handleSignal ( int sig ) {
for ( std :: size_t i = 0 ; i < sizeof ( signalDefs ) / sizeof ( SignalDefs ); ++ i )
if ( sig == signalDefs [ i ]. id )
fatal ( signalDefs [ i ]. name , - sig );
fatal ( "<unknown signal>" , - sig );
}
2014-10-02 18:51:05 +01:00
FatalConditionHandler () : m_isSet ( true ) {
2014-08-22 19:35:41 +01:00
for ( std :: size_t i = 0 ; i < sizeof ( signalDefs ) / sizeof ( SignalDefs ); ++ i )
signal ( signalDefs [ i ]. id , handleSignal );
}
~ FatalConditionHandler () {
2014-10-02 18:51:05 +01:00
reset ();
2014-08-22 19:35:41 +01:00
}
2014-10-02 18:51:05 +01:00
void reset () {
if ( m_isSet ) {
for ( std :: size_t i = 0 ; i < sizeof ( signalDefs ) / sizeof ( SignalDefs ); ++ i )
signal ( signalDefs [ i ]. id , SIG_DFL );
m_isSet = false ;
}
}
bool m_isSet ;
2014-08-22 19:35:41 +01:00
};
} // namespace Catch
#endif // not Windows
2012-08-13 07:46:10 +01:00
#include <set>
#include <string>
namespace Catch {
class StreamRedirect {
public :
StreamRedirect ( std :: ostream & stream , std :: string & targetString )
: m_stream ( stream ),
m_prevBuf ( stream . rdbuf () ),
m_targetString ( targetString )
{
stream . rdbuf ( m_oss . rdbuf () );
}
~ StreamRedirect () {
m_targetString += m_oss . str ();
m_stream . rdbuf ( m_prevBuf );
}
private :
std :: ostream & m_stream ;
std :: streambuf * m_prevBuf ;
std :: ostringstream m_oss ;
std :: string & m_targetString ;
};
///////////////////////////////////////////////////////////////////////////
2013-06-07 19:07:50 +01:00
class RunContext : public IResultCapture , public IRunner {
2012-08-13 07:46:10 +01:00
2013-06-07 19:07:50 +01:00
RunContext ( RunContext const & );
void operator = ( RunContext const & );
2012-08-13 07:46:10 +01:00
public :
2015-07-02 08:21:38 +01:00
explicit RunContext ( Ptr < IConfig const > const & _config , Ptr < IStreamingReporter > const & reporter )
: m_runInfo ( _config -> name () ),
2012-12-01 23:57:18 +00:00
m_context ( getCurrentMutableContext () ),
2015-07-02 08:21:38 +01:00
m_activeTestCase ( CATCH_NULL ),
m_config ( _config ),
2012-08-13 07:46:10 +01:00
m_reporter ( reporter ),
2014-05-20 18:50:59 +01:00
m_prevRunner ( m_context . getRunner () ),
m_prevResultCapture ( m_context . getResultCapture () ),
2012-08-13 07:46:10 +01:00
m_prevConfig ( m_context . getConfig () )
{
m_context . setRunner ( this );
2013-06-07 19:07:50 +01:00
m_context . setConfig ( m_config );
2012-08-13 07:46:10 +01:00
m_context . setResultCapture ( this );
2012-12-01 23:57:18 +00:00
m_reporter -> testRunStarting ( m_runInfo );
2012-08-13 07:46:10 +01:00
}
2013-06-07 19:07:50 +01:00
virtual ~ RunContext () {
2013-01-16 09:44:43 +00:00
m_reporter -> testRunEnded ( TestRunStats ( m_runInfo , m_totals , aborting () ) );
2012-08-13 07:46:10 +01:00
m_context . setRunner ( m_prevRunner );
2015-07-03 18:30:25 +01:00
m_context . setConfig ( Ptr < IConfig const > () );
2012-08-13 07:46:10 +01:00
m_context . setResultCapture ( m_prevResultCapture );
m_context . setConfig ( m_prevConfig );
}
2013-01-16 09:44:43 +00:00
void testGroupStarting ( std :: string const & testSpec , std :: size_t groupIndex , std :: size_t groupsCount ) {
m_reporter -> testGroupStarting ( GroupInfo ( testSpec , groupIndex , groupsCount ) );
2012-12-01 23:57:18 +00:00
}
2013-01-16 09:44:43 +00:00
void testGroupEnded ( std :: string const & testSpec , Totals const & totals , std :: size_t groupIndex , std :: size_t groupsCount ) {
m_reporter -> testGroupEnded ( TestGroupStats ( GroupInfo ( testSpec , groupIndex , groupsCount ), totals , aborting () ) );
2012-12-01 23:57:18 +00:00
}
2012-08-13 07:46:10 +01:00
2013-04-24 19:10:02 +01:00
Totals runTest ( TestCase const & testCase ) {
2012-08-13 07:46:10 +01:00
Totals prevTotals = m_totals ;
std :: string redirectedCout ;
std :: string redirectedCerr ;
2012-12-01 23:57:18 +00:00
TestCaseInfo testInfo = testCase . getTestCaseInfo ();
2012-08-13 07:46:10 +01:00
2012-12-01 23:57:18 +00:00
m_reporter -> testCaseStarting ( testInfo );
2013-07-25 08:12:03 +01:00
m_activeTestCase = & testCase ;
m_testCaseTracker = TestCaseTracker ( testInfo . name );
2012-08-13 07:46:10 +01:00
do {
do {
runCurrentTest ( redirectedCout , redirectedCerr );
}
2013-07-25 08:12:03 +01:00
while ( ! m_testCaseTracker -> isCompleted () && ! aborting () );
2012-08-13 07:46:10 +01:00
}
while ( getCurrentContext (). advanceGeneratorsForCurrentTest () && ! aborting () );
2012-11-21 18:06:13 +00:00
Totals deltaTotals = m_totals . delta ( prevTotals );
m_totals . testCases += deltaTotals . testCases ;
2013-01-16 09:44:43 +00:00
m_reporter -> testCaseEnded ( TestCaseStats ( testInfo ,
deltaTotals ,
redirectedCout ,
redirectedCerr ,
aborting () ) );
2012-11-21 18:06:13 +00:00
2015-07-02 08:21:38 +01:00
m_activeTestCase = CATCH_NULL ;
2013-07-25 08:12:03 +01:00
m_testCaseTracker . reset ();
2012-08-13 07:46:10 +01:00
2012-08-16 18:48:50 +01:00
return deltaTotals ;
2012-08-13 07:46:10 +01:00
}
2013-06-07 19:07:50 +01:00
Ptr < IConfig const > config () const {
2012-08-13 07:46:10 +01:00
return m_config ;
}
private : // IResultCapture
2013-04-24 19:10:02 +01:00
virtual void assertionEnded ( AssertionResult const & result ) {
2012-08-13 07:46:10 +01:00
if ( result . getResultType () == ResultWas :: Ok ) {
m_totals . assertions . passed ++ ;
}
2012-11-13 22:04:29 +00:00
else if ( ! result . isOk () ) {
2012-08-13 07:46:10 +01:00
m_totals . assertions . failed ++ ;
}
2013-06-28 17:09:57 +01:00
if ( m_reporter -> assertionEnded ( AssertionStats ( result , m_messages , m_totals ) ) )
m_messages . clear ();
2012-11-19 19:59:10 +00:00
2013-02-02 20:37:58 +00:00
// Reset working state
m_lastAssertionInfo = AssertionInfo ( "" , m_lastAssertionInfo . lineInfo , "{Unknown expression after the reported line}" , m_lastAssertionInfo . resultDisposition );
2014-06-02 07:48:03 +01:00
m_lastResult = result ;
2012-08-13 07:46:10 +01:00
}
virtual bool sectionStarted (
2012-12-01 23:57:18 +00:00
SectionInfo const & sectionInfo ,
2012-08-13 07:46:10 +01:00
Counts & assertions
)
{
std :: ostringstream oss ;
2012-12-01 23:57:18 +00:00
oss << sectionInfo . name << "@" << sectionInfo . lineInfo ;
2012-08-13 07:46:10 +01:00
2013-07-25 08:12:03 +01:00
if ( ! m_testCaseTracker -> enterSection ( oss . str () ) )
2012-08-13 07:46:10 +01:00
return false ;
2012-12-01 23:57:18 +00:00
m_lastAssertionInfo . lineInfo = sectionInfo . lineInfo ;
m_reporter -> sectionStarting ( sectionInfo );
2012-11-13 22:04:29 +00:00
2012-08-13 07:46:10 +01:00
assertions = m_totals . assertions ;
return true ;
}
2013-08-15 19:01:00 +01:00
bool testForMissingAssertions ( Counts & assertions ) {
if ( assertions . total () != 0 ||
! m_config -> warnAboutMissingAssertions () ||
m_testCaseTracker -> currentSectionHasChildren () )
return false ;
m_totals . assertions . failed ++ ;
assertions . failed ++ ;
return true ;
}
2012-08-13 07:46:10 +01:00
2013-08-15 19:01:00 +01:00
virtual void sectionEnded ( SectionInfo const & info , Counts const & prevAssertions , double _durationInSeconds ) {
2013-02-19 19:47:18 +00:00
if ( std :: uncaught_exception () ) {
2013-08-15 19:01:00 +01:00
m_unfinishedSections . push_back ( UnfinishedSections ( info , prevAssertions , _durationInSeconds ) );
2013-02-19 19:47:18 +00:00
return ;
}
2012-08-31 08:10:36 +01:00
Counts assertions = m_totals . assertions - prevAssertions ;
2013-08-15 19:01:00 +01:00
bool missingAssertions = testForMissingAssertions ( assertions );
2012-12-01 23:57:18 +00:00
2013-07-25 08:12:03 +01:00
m_testCaseTracker -> leaveSection ();
2012-12-01 23:57:18 +00:00
2013-08-15 19:01:00 +01:00
m_reporter -> sectionEnded ( SectionStats ( info , assertions , _durationInSeconds , missingAssertions ) );
2013-02-02 20:37:58 +00:00
m_messages . clear ();
2012-08-13 07:46:10 +01:00
}
2013-06-28 17:09:57 +01:00
virtual void pushScopedMessage ( MessageInfo const & message ) {
m_messages . push_back ( message );
2012-08-13 07:46:10 +01:00
}
2013-06-28 17:09:57 +01:00
virtual void popScopedMessage ( MessageInfo const & message ) {
m_messages . erase ( std :: remove ( m_messages . begin (), m_messages . end (), message ), m_messages . end () );
2012-08-13 07:46:10 +01:00
}
virtual std :: string getCurrentTestName () const {
2013-07-25 08:12:03 +01:00
return m_activeTestCase
? m_activeTestCase -> getTestCaseInfo (). name
2012-08-13 07:46:10 +01:00
: "" ;
}
2012-11-01 08:27:09 +00:00
virtual const AssertionResult * getLastResult () const {
2012-08-13 07:46:10 +01:00
return & m_lastResult ;
}
2014-08-22 19:35:41 +01:00
virtual void handleFatalErrorCondition ( std :: string const & message ) {
ResultBuilder resultBuilder = makeUnexpectedResultBuilder ();
resultBuilder . setResultType ( ResultWas :: FatalErrorCondition );
resultBuilder << message ;
resultBuilder . captureExpression ();
handleUnfinishedSections ();
// Recreate section for test case (as we will lose the one that was in scope)
TestCaseInfo const & testCaseInfo = m_activeTestCase -> getTestCaseInfo ();
SectionInfo testCaseSection ( testCaseInfo . lineInfo , testCaseInfo . name , testCaseInfo . description );
Counts assertions ;
assertions . failed = 1 ;
SectionStats testCaseSectionStats ( testCaseSection , assertions , 0 , false );
m_reporter -> sectionEnded ( testCaseSectionStats );
TestCaseInfo testInfo = m_activeTestCase -> getTestCaseInfo ();
Totals deltaTotals ;
deltaTotals . testCases . failed = 1 ;
m_reporter -> testCaseEnded ( TestCaseStats ( testInfo ,
deltaTotals ,
"" ,
"" ,
false ) );
m_totals . testCases . failed ++ ;
testGroupEnded ( "" , m_totals , 1 , 1 );
m_reporter -> testRunEnded ( TestRunStats ( m_runInfo , m_totals , false ) );
}
2012-08-23 20:08:50 +01:00
public :
// !TBD We need to do this another way!
2012-08-13 07:46:10 +01:00
bool aborting () const {
2013-06-07 19:07:50 +01:00
return m_totals . assertions . failed == static_cast < std :: size_t > ( m_config -> abortAfter () );
2012-08-13 07:46:10 +01:00
}
2012-08-23 20:08:50 +01:00
private :
2012-08-13 07:46:10 +01:00
void runCurrentTest ( std :: string & redirectedCout , std :: string & redirectedCerr ) {
2013-07-25 08:12:03 +01:00
TestCaseInfo const & testCaseInfo = m_activeTestCase -> getTestCaseInfo ();
2014-07-09 07:40:37 +01:00
SectionInfo testCaseSection ( testCaseInfo . lineInfo , testCaseInfo . name , testCaseInfo . description );
2013-07-25 08:12:03 +01:00
m_reporter -> sectionStarting ( testCaseSection );
2013-08-15 19:01:00 +01:00
Counts prevAssertions = m_totals . assertions ;
double duration = 0 ;
2012-08-13 07:46:10 +01:00
try {
2013-07-25 08:12:03 +01:00
m_lastAssertionInfo = AssertionInfo ( "TEST_CASE" , testCaseInfo . lineInfo , "" , ResultDisposition :: Normal );
TestCaseTracker :: Guard guard ( * m_testCaseTracker );
2013-02-04 00:05:16 +00:00
2015-07-02 23:03:13 +01:00
seedRng ( * m_config );
2013-08-15 19:01:00 +01:00
Timer timer ;
timer . start ();
2012-12-01 23:57:18 +00:00
if ( m_reporter -> getPreferences (). shouldRedirectStdOut ) {
2014-10-02 19:08:19 +01:00
StreamRedirect coutRedir ( Catch :: cout (), redirectedCout );
StreamRedirect cerrRedir ( Catch :: cerr (), redirectedCerr );
2014-08-22 19:35:41 +01:00
invokeActiveTestCase ();
2012-08-13 07:46:10 +01:00
}
else {
2014-08-22 19:35:41 +01:00
invokeActiveTestCase ();
2012-08-31 08:10:36 +01:00
}
2013-08-15 19:01:00 +01:00
duration = timer . getElapsedSeconds ();
2012-08-13 07:46:10 +01:00
}
catch ( TestFailureException & ) {
// This just means the test was aborted due to failure
}
catch (...) {
2014-08-22 19:35:41 +01:00
makeUnexpectedResultBuilder (). useActiveException ();
2012-08-13 07:46:10 +01:00
}
2014-08-22 19:35:41 +01:00
handleUnfinishedSections ();
2013-02-04 00:05:16 +00:00
m_messages . clear ();
2013-08-15 19:01:00 +01:00
Counts assertions = m_totals . assertions - prevAssertions ;
bool missingAssertions = testForMissingAssertions ( assertions );
2014-07-03 08:11:38 +01:00
if ( testCaseInfo . okToFail () ) {
std :: swap ( assertions . failedButOk , assertions . failed );
m_totals . assertions . failed -= assertions . failedButOk ;
m_totals . assertions . failedButOk += assertions . failedButOk ;
}
2013-08-15 19:01:00 +01:00
SectionStats testCaseSectionStats ( testCaseSection , assertions , duration , missingAssertions );
2013-07-25 08:12:03 +01:00
m_reporter -> sectionEnded ( testCaseSectionStats );
2012-08-13 07:46:10 +01:00
}
2014-08-22 19:35:41 +01:00
void invokeActiveTestCase () {
FatalConditionHandler fatalConditionHandler ; // Handle signals
m_activeTestCase -> invoke ();
2014-10-02 18:51:05 +01:00
fatalConditionHandler . reset ();
2014-08-22 19:35:41 +01:00
}
2012-08-13 07:46:10 +01:00
private :
2014-08-22 19:35:41 +01:00
ResultBuilder makeUnexpectedResultBuilder () const {
return ResultBuilder ( m_lastAssertionInfo . macroName . c_str (),
m_lastAssertionInfo . lineInfo ,
m_lastAssertionInfo . capturedExpression . c_str (),
m_lastAssertionInfo . resultDisposition );
}
void handleUnfinishedSections () {
// If sections ended prematurely due to an exception we stored their
// infos here so we can tear them down outside the unwind process.
for ( std :: vector < UnfinishedSections >:: const_reverse_iterator it = m_unfinishedSections . rbegin (),
itEnd = m_unfinishedSections . rend ();
it != itEnd ;
++ it )
sectionEnded ( it -> info , it -> prevAssertions , it -> durationInSeconds );
m_unfinishedSections . clear ();
}
2013-02-19 19:47:18 +00:00
struct UnfinishedSections {
2013-08-15 19:01:00 +01:00
UnfinishedSections ( SectionInfo const & _info , Counts const & _prevAssertions , double _durationInSeconds )
: info ( _info ), prevAssertions ( _prevAssertions ), durationInSeconds ( _durationInSeconds )
2013-02-19 19:47:18 +00:00
{}
SectionInfo info ;
Counts prevAssertions ;
2013-08-15 19:01:00 +01:00
double durationInSeconds ;
2013-02-19 19:47:18 +00:00
};
2012-12-01 23:57:18 +00:00
TestRunInfo m_runInfo ;
2012-08-13 07:46:10 +01:00
IMutableContext & m_context ;
2013-07-25 08:12:03 +01:00
TestCase const * m_activeTestCase ;
Option < TestCaseTracker > m_testCaseTracker ;
2012-11-01 08:27:09 +00:00
AssertionResult m_lastResult ;
2012-08-13 07:46:10 +01:00
2013-06-07 19:07:50 +01:00
Ptr < IConfig const > m_config ;
2012-08-13 07:46:10 +01:00
Totals m_totals ;
2012-12-01 23:57:18 +00:00
Ptr < IStreamingReporter > m_reporter ;
2013-02-02 20:37:58 +00:00
std :: vector < MessageInfo > m_messages ;
2012-08-13 07:46:10 +01:00
IRunner * m_prevRunner ;
IResultCapture * m_prevResultCapture ;
2013-06-07 19:07:50 +01:00
Ptr < IConfig const > m_prevConfig ;
2012-11-13 22:04:29 +00:00
AssertionInfo m_lastAssertionInfo ;
2013-02-19 19:47:18 +00:00
std :: vector < UnfinishedSections > m_unfinishedSections ;
2012-08-13 07:46:10 +01:00
};
2014-06-02 07:48:03 +01:00
IResultCapture & getResultCapture () {
if ( IResultCapture * capture = getCurrentContext (). getResultCapture () )
return * capture ;
else
throw std :: logic_error ( "No result capture instance" );
}
2012-08-13 07:46:10 +01:00
} // end namespace Catch
2012-11-15 22:15:41 +00:00
// #included from: internal/catch_version.h
#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
namespace Catch {
// Versioning information
struct Version {
2012-12-01 23:57:18 +00:00
Version ( unsigned int _majorVersion ,
unsigned int _minorVersion ,
2015-06-29 18:05:23 +01:00
unsigned int _patchNumber ,
std :: string const & _branchName ,
unsigned int _buildNumber );
2012-12-01 23:57:18 +00:00
2014-04-18 08:30:31 +01:00
unsigned int const majorVersion ;
unsigned int const minorVersion ;
2015-06-29 18:05:23 +01:00
unsigned int const patchNumber ;
// buildNumber is only used if branchName is not null
std :: string const branchName ;
2014-04-18 08:30:31 +01:00
unsigned int const buildNumber ;
2015-06-29 18:05:23 +01:00
friend std :: ostream & operator << ( std :: ostream & os , Version const & version );
2013-03-25 09:25:31 +00:00
2013-07-03 08:25:11 +01:00
private :
void operator = ( Version const & );
2012-11-15 22:15:41 +00:00
};
extern Version libraryVersion ;
}
2011-05-24 08:23:02 +01:00
#include <fstream>
#include <stdlib.h>
#include <limits>
2012-05-16 15:09:17 +01:00
namespace Catch {
2015-08-07 17:30:34 +01:00
Ptr < IStreamingReporter > createReporter ( std :: string const & reporterName , Ptr < Config > const & config ) {
2015-08-03 07:40:52 +01:00
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 () );
2012-08-23 20:08:50 +01:00
}
2015-08-03 07:40:52 +01:00
return reporter ;
}
2012-05-25 08:52:05 +01:00
2015-08-07 17:30:34 +01:00
Ptr < IStreamingReporter > makeReporter ( Ptr < Config > const & config ) {
std :: vector < std :: string > reporters = config -> getReporterNames ();
if ( reporters . empty () )
reporters . push_back ( "console" );
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 & 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 ;
}
2015-08-03 07:40:52 +01:00
void openStreamInto ( Ptr < Config > const & config , std :: ofstream & ofs ) {
// Open output file, if specified
if ( ! config -> getFilename (). empty () ) {
ofs . open ( config -> getFilename (). c_str () );
if ( ofs . fail () ) {
2012-08-23 20:08:50 +01:00
std :: ostringstream oss ;
2015-08-03 07:40:52 +01:00
oss << "Unable to open file: '" << config -> getFilename () << "'" ;
2012-08-23 20:08:50 +01:00
throw std :: domain_error ( oss . str () );
}
2015-08-03 07:40:52 +01:00
config -> setStreamBuf ( ofs . rdbuf () );
2012-08-23 20:08:50 +01:00
}
2015-08-03 07:40:52 +01:00
}
2012-08-23 20:08:50 +01:00
2015-08-03 07:40:52 +01:00
Totals runTests ( Ptr < Config > const & config ) {
std :: ofstream ofs ;
openStreamInto ( config , ofs );
Ptr < IStreamingReporter > reporter = makeReporter ( config );
2015-08-07 17:30:34 +01:00
reporter = addListeners ( config . get (), reporter );
2015-08-03 07:40:52 +01:00
RunContext context ( config . get (), reporter );
Totals totals ;
context . testGroupStarting ( config -> name (), 1 , 1 );
TestSpec testSpec = config -> testSpec ();
if ( ! testSpec . hasFilters () )
testSpec = TestSpecParser ( ITagAliasRegistry :: get () ). parse ( "~[.]" ). testSpec (); // All not hidden tests
2015-08-07 17:30:34 +01:00
std :: vector < TestCase > const & allTestCases = getAllTestCasesSorted ( * config );
for ( std :: vector < TestCase >:: const_iterator it = allTestCases . begin (), itEnd = allTestCases . end ();
2015-08-03 07:40:52 +01:00
it != itEnd ;
++ it ) {
2015-08-07 17:30:34 +01:00
if ( ! context . aborting () && matchTest ( * it , testSpec , * config ) )
2015-08-03 07:40:52 +01:00
totals += context . runTest ( * it );
2015-08-07 17:30:34 +01:00
else
reporter -> skipTest ( * it );
2015-08-03 07:40:52 +01:00
}
context . testGroupEnded ( config -> name (), totals , 1 , 1 );
return totals ;
}
2012-08-23 20:08:50 +01:00
2015-08-07 17:30:34 +01:00
void applyFilenamesAsTags ( IConfig const & config ) {
std :: vector < TestCase > const & tests = getAllTestCasesSorted ( config );
2015-07-02 08:21:38 +01:00
for ( std :: size_t i = 0 ; i < tests . size (); ++ i ) {
TestCase & test = const_cast < TestCase &> ( tests [ i ] );
std :: set < std :: string > tags = test . tags ;
std :: string filename = test . lineInfo . file ;
2015-07-03 18:30:25 +01:00
std :: string :: size_type lastSlash = filename . find_last_of ( " \\ /" );
2015-07-02 08:21:38 +01:00
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 );
2015-07-07 08:25:15 +01:00
tags . insert ( "#" + filename );
2015-07-02 08:21:38 +01:00
setTags ( test , tags );
}
}
2014-10-21 07:25:26 +01:00
class Session : NonCopyable {
2013-06-07 19:07:50 +01:00
static bool alreadyInstantiated ;
2012-08-23 20:08:50 +01:00
2013-06-07 19:07:50 +01:00
public :
2012-08-23 20:08:50 +01:00
2013-06-07 19:07:50 +01:00
struct OnUnusedOptions { enum DoWhat { Ignore , Fail }; };
Session ()
: m_cli ( makeCommandLineParser () ) {
if ( alreadyInstantiated ) {
std :: string msg = "Only one instance of Catch::Session can ever be used" ;
2014-10-02 19:08:19 +01:00
Catch :: cerr () << msg << std :: endl ;
2013-06-07 19:07:50 +01:00
throw std :: logic_error ( msg );
2012-08-23 20:08:50 +01:00
}
2013-06-07 19:07:50 +01:00
alreadyInstantiated = true ;
2012-08-23 20:08:50 +01:00
}
2013-06-07 19:07:50 +01:00
~ Session () {
2012-08-09 07:47:30 +01:00
Catch :: cleanUp ();
2011-05-24 08:23:02 +01:00
}
2013-06-07 19:07:50 +01:00
void showHelp ( std :: string const & processName ) {
2015-06-29 18:05:23 +01:00
Catch :: cout () << " \n Catch v" << libraryVersion << " \n " ;
2011-05-24 08:23:02 +01:00
2014-10-02 19:08:19 +01:00
m_cli . usage ( Catch :: cout (), processName );
Catch :: cout () << "For more detail usage please see the project docs \n " << std :: endl ;
2012-09-07 17:52:35 +01:00
}
2011-05-24 08:23:02 +01:00
2013-06-07 19:07:50 +01:00
int applyCommandLine ( int argc , char * const argv [], OnUnusedOptions :: DoWhat unusedOptionBehaviour = OnUnusedOptions :: Fail ) {
try {
2013-12-20 19:06:26 +00:00
m_cli . setThrowOnUnrecognisedTokens ( unusedOptionBehaviour == OnUnusedOptions :: Fail );
2013-06-07 19:07:50 +01:00
m_unusedTokens = m_cli . parseInto ( argc , argv , m_configData );
if ( m_configData . showHelp )
showHelp ( m_configData . processName );
m_config . reset ();
2012-07-05 18:37:58 +01:00
}
2013-06-07 19:07:50 +01:00
catch ( std :: exception & ex ) {
2013-08-16 19:01:32 +01:00
{
Colour colourGuard ( Colour :: Red );
2015-06-29 18:05:23 +01:00
Catch :: cerr ()
<< " \n Error(s) in input: \n "
<< Text ( ex . what (), TextAttributes (). setIndent ( 2 ) )
<< " \n\n " ;
2013-08-16 19:01:32 +01:00
}
2014-10-02 19:08:19 +01:00
m_cli . usage ( Catch :: cout (), m_configData . processName );
2013-06-07 19:07:50 +01:00
return ( std :: numeric_limits < int >:: max )();
}
return 0 ;
2011-05-24 08:23:02 +01:00
}
2013-06-07 19:07:50 +01:00
void useConfigData ( ConfigData const & _configData ) {
m_configData = _configData ;
m_config . reset ();
}
2011-05-24 08:23:02 +01:00
2013-06-07 19:07:50 +01:00
int run ( int argc , char * const argv [] ) {
int returnCode = applyCommandLine ( argc , argv );
if ( returnCode == 0 )
returnCode = run ();
return returnCode ;
}
int run () {
if ( m_configData . showHelp )
return 0 ;
try
{
config (); // Force config to be constructed
2014-09-15 18:40:24 +01:00
2015-07-02 23:03:13 +01:00
seedRng ( * m_config );
2014-09-15 18:40:24 +01:00
2015-08-07 17:30:34 +01:00
if ( m_configData . filenamesAsTags )
applyFilenamesAsTags ( * m_config );
2013-06-07 19:07:50 +01:00
// Handle list request
if ( Option < std :: size_t > listed = list ( config () ) )
return static_cast < int > ( * listed );
2015-08-03 07:40:52 +01:00
return static_cast < int > ( runTests ( m_config ). assertions . failed );
2013-06-07 19:07:50 +01:00
}
catch ( std :: exception & ex ) {
2014-10-02 19:08:19 +01:00
Catch :: cerr () << ex . what () << std :: endl ;
2013-06-07 19:07:50 +01:00
return ( std :: numeric_limits < int >:: max )();
}
}
Clara :: CommandLine < ConfigData > const & cli () const {
return m_cli ;
}
std :: vector < Clara :: Parser :: Token > const & unusedTokens () const {
return m_unusedTokens ;
}
ConfigData & configData () {
return m_configData ;
}
Config & config () {
if ( ! m_config )
m_config = new Config ( m_configData );
return * m_config ;
}
private :
Clara :: CommandLine < ConfigData > m_cli ;
std :: vector < Clara :: Parser :: Token > m_unusedTokens ;
ConfigData m_configData ;
Ptr < Config > m_config ;
};
bool Session :: alreadyInstantiated = false ;
2011-05-24 08:23:02 +01:00
} // end namespace Catch
2012-08-09 07:47:30 +01:00
// #included from: catch_registry_hub.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
2012-08-09 07:47:30 +01:00
// #included from: catch_test_case_registry_impl.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
2012-08-09 07:47:30 +01:00
#include <vector>
#include <set>
#include <sstream>
#include <iostream>
2014-09-15 23:32:13 +01:00
#include <algorithm>
2012-08-09 07:47:30 +01:00
namespace Catch {
2015-08-07 17:30:34 +01:00
struct LexSort {
bool operator () ( TestCase i , TestCase j ) const { return ( i < j );}
};
struct RandomNumberGenerator {
int operator ()( int n ) const { return std :: rand () % n ; }
};
2014-09-18 18:25:10 +01:00
2015-08-07 17:30:34 +01:00
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 () );
}
struct TestMatcher {
TestMatcher ( TestSpec const & testSpec , bool allowThrows ) : m_testSpec ( testSpec ), m_allowThrows ( allowThrows ) {}
bool operator ()( TestCase const & testCase ) const {
return m_testSpec . matches ( testCase ) && ( m_allowThrows || ! testCase . throws () );
}
TestSpec m_testSpec ;
bool m_allowThrows ;
};
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 "
<< " \t First seen at " << prev . first -> getTestCaseInfo (). lineInfo << " \n "
<< " \t Redefined 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 ;
std :: copy_if ( testCases . begin (), testCases . end (), std :: back_inserter ( filtered ), TestMatcher ( testSpec , config . allowThrows () ) );
return filtered ;
}
std :: vector < TestCase > const & getAllTestCasesSorted ( IConfig const & config ) {
return getRegistryHub (). getTestCaseRegistry (). getAllTestsSorted ( config );
}
class TestRegistry : public ITestCaseRegistry {
2012-08-09 07:47:30 +01:00
public :
TestRegistry () : m_unnamedCount ( 0 ) {}
2012-08-13 07:46:10 +01:00
virtual ~ TestRegistry ();
2012-08-09 07:47:30 +01:00
2013-04-24 19:10:02 +01:00
virtual void registerTest ( TestCase const & testCase ) {
2012-12-01 23:57:18 +00:00
std :: string name = testCase . getTestCaseInfo (). name ;
if ( name == "" ) {
2012-08-09 07:47:30 +01:00
std :: ostringstream oss ;
2013-03-16 20:21:51 +00:00
oss << "Anonymous test case " << ++ m_unnamedCount ;
2012-12-01 23:57:18 +00:00
return registerTest ( testCase . withName ( oss . str () ) );
2012-08-09 07:47:30 +01:00
}
2015-08-07 17:30:34 +01:00
m_functions . push_back ( testCase );
2012-08-09 07:47:30 +01:00
}
2013-04-24 19:10:02 +01:00
virtual std :: vector < TestCase > const & getAllTests () const {
2015-08-07 17:30:34 +01:00
return m_functions ;
2012-08-09 07:47:30 +01:00
}
2015-08-07 17:30:34 +01:00
virtual std :: vector < TestCase > const & getAllTestsSorted ( IConfig const & config ) const {
if ( m_sortedFunctions . empty () )
enforceNoDuplicateTestCases ( m_functions );
2012-08-09 07:47:30 +01:00
2015-08-07 17:30:34 +01:00
if ( m_currentSortOrder != config . runOrder () || m_sortedFunctions . empty () ) {
m_sortedFunctions = sortTests ( config , m_functions );
m_currentSortOrder = config . runOrder ();
2012-08-09 07:47:30 +01:00
}
2015-08-07 17:30:34 +01:00
return m_sortedFunctions ;
2014-12-22 20:18:05 +00:00
}
private :
2015-08-07 17:30:34 +01:00
std :: vector < TestCase > m_functions ;
mutable RunTests :: InWhatOrder m_currentSortOrder ;
mutable std :: vector < TestCase > m_sortedFunctions ;
2012-08-09 07:47:30 +01:00
size_t m_unnamedCount ;
2015-07-13 06:36:07 +01:00
std :: ios_base :: Init m_ostreamInit ; // Forces cout/ cerr to be initialised
2012-08-09 07:47:30 +01:00
};
///////////////////////////////////////////////////////////////////////////
2012-08-16 18:48:50 +01:00
class FreeFunctionTestCase : public SharedImpl < ITestCase > {
2012-08-09 07:47:30 +01:00
public :
FreeFunctionTestCase ( TestFunction fun ) : m_fun ( fun ) {}
virtual void invoke () const {
m_fun ();
}
private :
2012-08-16 18:48:50 +01:00
virtual ~ FreeFunctionTestCase ();
2012-08-09 07:47:30 +01:00
TestFunction m_fun ;
};
2013-04-24 19:10:02 +01:00
inline std :: string extractClassName ( std :: string const & classOrQualifiedMethodName ) {
2012-11-13 22:04:29 +00:00
std :: string className = classOrQualifiedMethodName ;
2013-09-07 12:07:38 +01:00
if ( startsWith ( className , "&" ) )
2012-11-13 22:04:29 +00:00
{
std :: size_t lastColons = className . rfind ( "::" );
std :: size_t penultimateColons = className . rfind ( "::" , lastColons - 1 );
if ( penultimateColons == std :: string :: npos )
penultimateColons = 1 ;
className = className . substr ( penultimateColons , lastColons - penultimateColons );
}
return className ;
}
2012-08-09 07:47:30 +01:00
///////////////////////////////////////////////////////////////////////////
AutoReg :: AutoReg ( TestFunction function ,
2013-03-16 20:21:51 +00:00
SourceLineInfo const & lineInfo ,
NameAndDesc const & nameAndDesc ) {
2013-08-15 19:01:00 +01:00
registerTestCase ( new FreeFunctionTestCase ( function ), "" , nameAndDesc , lineInfo );
2012-08-09 07:47:30 +01:00
}
AutoReg ::~ AutoReg () {}
void AutoReg :: registerTestCase ( ITestCase * testCase ,
2013-03-16 20:21:51 +00:00
char const * classOrQualifiedMethodName ,
NameAndDesc const & nameAndDesc ,
SourceLineInfo const & lineInfo ) {
2012-11-13 22:04:29 +00:00
2013-03-16 20:21:51 +00:00
getMutableRegistryHub (). registerTest
( makeTestCase ( testCase ,
extractClassName ( classOrQualifiedMethodName ),
nameAndDesc . name ,
nameAndDesc . description ,
lineInfo ) );
2012-08-09 07:47:30 +01:00
}
} // end namespace Catch
// #included from: catch_reporter_registry.hpp
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
#include <map>
namespace Catch {
class ReporterRegistry : public IReporterRegistry {
public :
2015-08-07 17:30:34 +01:00
virtual ~ ReporterRegistry () override {}
2012-08-09 07:47:30 +01:00
2015-08-07 17:30:34 +01:00
virtual IStreamingReporter * create ( std :: string const & name , Ptr < IConfig > const & config ) const override {
2012-08-09 07:47:30 +01:00
FactoryMap :: const_iterator it = m_factories . find ( name );
if ( it == m_factories . end () )
2015-07-02 08:21:38 +01:00
return CATCH_NULL ;
2013-06-07 19:07:50 +01:00
return it -> second -> create ( ReporterConfig ( config ) );
2012-08-09 07:47:30 +01:00
}
2015-08-07 17:30:34 +01:00
void registerReporter ( std :: string const & name , Ptr < IReporterFactory > const & factory ) {
2012-08-09 07:47:30 +01:00
m_factories . insert ( std :: make_pair ( name , factory ) );
}
2015-08-07 17:30:34 +01:00
void registerListener ( Ptr < IReporterFactory > const & factory ) {
m_listeners . push_back ( factory );
}
2012-08-09 07:47:30 +01:00
2015-08-07 17:30:34 +01:00
virtual FactoryMap const & getFactories () const override {
2012-08-09 07:47:30 +01:00
return m_factories ;
}
2015-08-07 17:30:34 +01:00
virtual Listeners const & getListeners () const override {
return m_listeners ;
}
2012-08-09 07:47:30 +01:00
private :
FactoryMap m_factories ;
2015-08-07 17:30:34 +01:00
Listeners m_listeners ;
2012-08-09 07:47:30 +01:00
};
}
// #included from: catch_exception_translator_registry.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
2012-08-09 07:47:30 +01:00
#ifdef __OBJC__
#import "Foundation/Foundation.h"
#endif
namespace Catch {
class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
public :
~ ExceptionTranslatorRegistry () {
deleteAll ( m_translators );
}
virtual void registerTranslator ( const IExceptionTranslator * translator ) {
m_translators . push_back ( translator );
}
virtual std :: string translateActiveException () const {
try {
#ifdef __OBJC__
// In Objective-C try objective-c exceptions first
@ try {
throw ;
}
@ catch ( NSException * exception ) {
2014-12-12 08:11:18 +00:00
return Catch :: toString ( [ exception description ] );
2012-08-09 07:47:30 +01:00
}
#else
throw ;
#endif
}
2014-06-02 07:48:03 +01:00
catch ( TestFailureException & ) {
throw ;
}
2012-08-09 07:47:30 +01:00
catch ( std :: exception & ex ) {
return ex . what ();
}
catch ( std :: string & msg ) {
return msg ;
}
catch ( const char * msg ) {
return msg ;
}
catch (...) {
return tryTranslators ( m_translators . begin () );
}
}
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 );
}
}
private :
std :: vector < const IExceptionTranslator *> m_translators ;
};
}
namespace Catch {
namespace {
class RegistryHub : public IRegistryHub , public IMutableRegistryHub {
2013-04-24 19:10:02 +01:00
RegistryHub ( RegistryHub const & );
void operator = ( RegistryHub const & );
2012-08-09 07:47:30 +01:00
public : // IRegistryHub
RegistryHub () {
}
2015-08-07 17:30:34 +01:00
virtual IReporterRegistry const & getReporterRegistry () const override {
2012-08-09 07:47:30 +01:00
return m_reporterRegistry ;
}
2015-08-07 17:30:34 +01:00
virtual ITestCaseRegistry const & getTestCaseRegistry () const override {
2012-08-09 07:47:30 +01:00
return m_testCaseRegistry ;
}
2015-08-07 17:30:34 +01:00
virtual IExceptionTranslatorRegistry & getExceptionTranslatorRegistry () override {
2012-08-09 07:47:30 +01:00
return m_exceptionTranslatorRegistry ;
}
public : // IMutableRegistryHub
2015-08-07 17:30:34 +01:00
virtual void registerReporter ( std :: string const & name , Ptr < IReporterFactory > const & factory ) override {
2012-08-09 07:47:30 +01:00
m_reporterRegistry . registerReporter ( name , factory );
}
2015-08-07 17:30:34 +01:00
virtual void registerListener ( Ptr < IReporterFactory > const & factory ) override {
m_reporterRegistry . registerListener ( factory );
}
virtual void registerTest ( TestCase const & testInfo ) override {
2012-08-09 07:47:30 +01:00
m_testCaseRegistry . registerTest ( testInfo );
}
2015-08-07 17:30:34 +01:00
virtual void registerTranslator ( const IExceptionTranslator * translator ) override {
2012-08-09 07:47:30 +01:00
m_exceptionTranslatorRegistry . registerTranslator ( translator );
}
private :
TestRegistry m_testCaseRegistry ;
ReporterRegistry m_reporterRegistry ;
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry ;
};
// Single, global, instance
inline RegistryHub *& getTheRegistryHub () {
2015-07-02 08:21:38 +01:00
static RegistryHub * theRegistryHub = CATCH_NULL ;
2012-08-09 07:47:30 +01:00
if ( ! theRegistryHub )
theRegistryHub = new RegistryHub ();
return theRegistryHub ;
}
}
IRegistryHub & getRegistryHub () {
return * getTheRegistryHub ();
}
IMutableRegistryHub & getMutableRegistryHub () {
return * getTheRegistryHub ();
}
void cleanUp () {
delete getTheRegistryHub ();
2015-07-02 08:21:38 +01:00
getTheRegistryHub () = CATCH_NULL ;
2012-08-09 07:47:30 +01:00
cleanUpContext ();
}
2012-11-01 08:27:09 +00:00
std :: string translateActiveException () {
return getRegistryHub (). getExceptionTranslatorRegistry (). translateActiveException ();
}
2012-08-09 07:47:30 +01:00
} // end namespace Catch
2012-09-17 01:42:29 -04:00
2012-08-09 07:47:30 +01:00
// #included from: catch_notimplemented_exception.hpp
#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
#include <ostream>
namespace Catch {
2013-04-24 19:10:02 +01:00
NotImplementedException :: NotImplementedException ( SourceLineInfo const & lineInfo )
2012-08-09 07:47:30 +01:00
: m_lineInfo ( lineInfo ) {
std :: ostringstream oss ;
2013-01-16 09:44:43 +00:00
oss << lineInfo << ": function " ;
2012-08-09 07:47:30 +01:00
oss << "not implemented" ;
m_what = oss . str ();
}
2014-04-18 08:49:35 +01:00
const char * NotImplementedException :: what () const CATCH_NOEXCEPT {
2012-08-09 07:47:30 +01:00
return m_what . c_str ();
}
} // end namespace Catch
// #included from: catch_context_impl.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
2012-08-09 07:47:30 +01:00
2013-12-03 18:53:55 +00:00
// #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 :
2014-04-18 08:49:35 +01:00
virtual ~ StreamBufBase () CATCH_NOEXCEPT ;
2013-12-03 18:53:55 +00:00
};
}
#include <stdexcept>
#include <cstdio>
2014-10-02 19:08:19 +01:00
#include <iostream>
2013-12-03 18:53:55 +00:00
namespace Catch {
template < typename WriterF , size_t bufferSize = 256 >
class StreamBufImpl : public StreamBufBase {
char data [ bufferSize ];
WriterF m_writer ;
public :
StreamBufImpl () {
setp ( data , data + sizeof ( data ) );
}
2014-04-18 08:49:35 +01:00
~ StreamBufImpl () CATCH_NOEXCEPT {
2013-12-03 18:53:55 +00:00
sync ();
}
private :
int overflow ( int c ) {
sync ();
if ( c != EOF ) {
if ( pbase () == epptr () )
m_writer ( std :: string ( 1 , static_cast < char > ( c ) ) );
else
sputc ( static_cast < char > ( c ) );
}
return 0 ;
}
int sync () {
if ( pbase () != pptr () ) {
m_writer ( std :: string ( pbase (), static_cast < std :: string :: size_type > ( pptr () - pbase () ) ) );
setp ( pbase (), epptr () );
}
return 0 ;
}
};
///////////////////////////////////////////////////////////////////////////
struct OutputDebugWriter {
void operator ()( std :: string const & str ) {
writeToDebugConsole ( str );
}
};
Stream :: Stream ()
2015-07-02 08:21:38 +01:00
: streamBuf ( CATCH_NULL ), isOwned ( false )
2013-12-03 18:53:55 +00:00
{}
Stream :: Stream ( std :: streambuf * _streamBuf , bool _isOwned )
: streamBuf ( _streamBuf ), isOwned ( _isOwned )
{}
void Stream :: release () {
if ( isOwned ) {
delete streamBuf ;
2015-07-02 08:21:38 +01:00
streamBuf = CATCH_NULL ;
2013-12-03 18:53:55 +00:00
isOwned = false ;
}
}
2014-10-02 19:08:19 +01:00
#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement this functions
std :: ostream & cout () {
return std :: cout ;
}
std :: ostream & cerr () {
return std :: cerr ;
}
#endif
2013-12-03 18:53:55 +00:00
}
2012-08-09 07:47:30 +01:00
namespace Catch {
class Context : public IMutableContext {
2015-07-02 08:21:38 +01:00
Context () : m_config ( CATCH_NULL ), m_runner ( CATCH_NULL ), m_resultCapture ( CATCH_NULL ) {}
2013-04-24 19:10:02 +01:00
Context ( Context const & );
void operator = ( Context const & );
2012-08-09 07:47:30 +01:00
public : // IContext
2014-05-20 18:50:59 +01:00
virtual IResultCapture * getResultCapture () {
return m_resultCapture ;
2012-08-09 07:47:30 +01:00
}
2014-05-20 18:50:59 +01:00
virtual IRunner * getRunner () {
return m_runner ;
2012-08-09 07:47:30 +01:00
}
2013-04-24 19:10:02 +01:00
virtual size_t getGeneratorIndex ( std :: string const & fileInfo , size_t totalSize ) {
2012-08-09 07:47:30 +01:00
return getGeneratorsForCurrentTest ()
. getGeneratorInfo ( fileInfo , totalSize )
. getCurrentIndex ();
}
virtual bool advanceGeneratorsForCurrentTest () {
IGeneratorsForTest * generators = findGeneratorsForCurrentTest ();
return generators && generators -> moveNext ();
}
2013-06-07 19:07:50 +01:00
virtual Ptr < IConfig const > getConfig () const {
2012-08-09 07:47:30 +01:00
return m_config ;
}
public : // IMutableContext
virtual void setResultCapture ( IResultCapture * resultCapture ) {
m_resultCapture = resultCapture ;
}
virtual void setRunner ( IRunner * runner ) {
m_runner = runner ;
}
2013-06-07 19:07:50 +01:00
virtual void setConfig ( Ptr < IConfig const > const & config ) {
2012-08-09 07:47:30 +01:00
m_config = config ;
}
friend IMutableContext & getCurrentMutableContext ();
private :
IGeneratorsForTest * findGeneratorsForCurrentTest () {
2014-05-20 18:50:59 +01:00
std :: string testName = getResultCapture () -> getCurrentTestName ();
2012-08-09 07:47:30 +01:00
std :: map < std :: string , IGeneratorsForTest *>:: const_iterator it =
2015-03-04 08:23:40 +00:00
m_generatorsByTestName . find ( testName );
2012-08-09 07:47:30 +01:00
return it != m_generatorsByTestName . end ()
2013-07-25 08:12:03 +01:00
? it -> second
2015-07-02 08:21:38 +01:00
: CATCH_NULL ;
2012-08-09 07:47:30 +01:00
}
IGeneratorsForTest & getGeneratorsForCurrentTest () {
IGeneratorsForTest * generators = findGeneratorsForCurrentTest ();
if ( ! generators ) {
2014-05-20 18:50:59 +01:00
std :: string testName = getResultCapture () -> getCurrentTestName ();
2012-08-09 07:47:30 +01:00
generators = createGeneratorsForTest ();
m_generatorsByTestName . insert ( std :: make_pair ( testName , generators ) );
}
return * generators ;
}
private :
2013-10-23 15:35:07 +01:00
Ptr < IConfig const > m_config ;
2012-08-09 07:47:30 +01:00
IRunner * m_runner ;
IResultCapture * m_resultCapture ;
std :: map < std :: string , IGeneratorsForTest *> m_generatorsByTestName ;
};
namespace {
2015-07-02 08:21:38 +01:00
Context * currentContext = CATCH_NULL ;
2012-08-09 07:47:30 +01:00
}
IMutableContext & getCurrentMutableContext () {
if ( ! currentContext )
currentContext = new Context ();
return * currentContext ;
}
IContext & getCurrentContext () {
return getCurrentMutableContext ();
}
2013-04-24 19:10:02 +01:00
Stream createStream ( std :: string const & streamName ) {
2014-10-02 19:08:19 +01:00
if ( streamName == "stdout" ) return Stream ( Catch :: cout (). rdbuf (), false );
if ( streamName == "stderr" ) return Stream ( Catch :: cerr (). rdbuf (), false );
2012-09-26 18:38:26 +01:00
if ( streamName == "debug" ) return Stream ( new StreamBufImpl < OutputDebugWriter > , true );
2012-08-09 07:47:30 +01:00
throw std :: domain_error ( "Unknown stream: " + streamName );
}
void cleanUpContext () {
delete currentContext ;
2015-07-02 08:21:38 +01:00
currentContext = CATCH_NULL ;
2012-08-09 07:47:30 +01:00
}
}
2012-09-17 01:42:29 -04:00
2012-08-09 07:47:30 +01:00
// #included from: catch_console_colour_impl.hpp
#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
2014-10-21 07:25:26 +01:00
namespace Catch {
namespace {
2013-04-05 20:58:01 +01:00
2014-10-21 07:25:26 +01:00
struct IColourImpl {
virtual ~ IColourImpl () {}
virtual void use ( Colour :: Code _colourCode ) = 0 ;
};
struct NoColourImpl : IColourImpl {
void use ( Colour :: Code ) {}
static IColourImpl * instance () {
static NoColourImpl s_instance ;
return & s_instance ;
}
};
} // anon namespace
} // namespace Catch
#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
# ifdef CATCH_PLATFORM_WINDOWS
# define CATCH_CONFIG_COLOUR_WINDOWS
# else
# define CATCH_CONFIG_COLOUR_ANSI
# endif
#endif
#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
2012-08-09 07:47:30 +01:00
2013-06-29 20:31:17 +01:00
#ifndef NOMINMAX
2013-06-28 14:11:28 +01:00
#define NOMINMAX
2013-06-29 20:31:17 +01:00
#endif
2013-07-01 19:02:29 +01:00
#ifdef __AFXDLL
#include <AfxWin.h>
#else
2012-08-09 07:47:30 +01:00
#include <windows.h>
2013-07-01 19:02:29 +01:00
#endif
2012-08-23 20:08:50 +01:00
namespace Catch {
2013-03-11 18:38:29 +00:00
namespace {
2012-08-23 20:08:50 +01:00
2014-10-21 07:25:26 +01:00
class Win32ColourImpl : public IColourImpl {
2012-08-23 20:08:50 +01:00
public :
2013-04-05 20:58:01 +01:00
Win32ColourImpl () : stdoutHandle ( GetStdHandle ( STD_OUTPUT_HANDLE ) )
2012-08-09 07:47:30 +01:00
{
2013-04-05 20:58:01 +01:00
CONSOLE_SCREEN_BUFFER_INFO csbiInfo ;
GetConsoleScreenBufferInfo ( stdoutHandle , & csbiInfo );
2015-07-06 06:22:28 +01:00
originalForegroundAttributes = csbiInfo . wAttributes & ~ ( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
originalBackgroundAttributes = csbiInfo . wAttributes & ~ ( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
2012-08-09 07:47:30 +01:00
}
2012-08-23 20:08:50 +01:00
2013-04-05 20:58:01 +01:00
virtual void use ( Colour :: Code _colourCode ) {
switch ( _colourCode ) {
2015-07-06 06:22:28 +01:00
case Colour :: None : return setTextAttribute ( originalForegroundAttributes );
2013-04-05 20:58:01 +01:00
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 );
case Colour :: Blue : return setTextAttribute ( FOREGROUND_BLUE );
case Colour :: Cyan : return setTextAttribute ( FOREGROUND_BLUE | FOREGROUND_GREEN );
case Colour :: Yellow : return setTextAttribute ( FOREGROUND_RED | FOREGROUND_GREEN );
case Colour :: Grey : return setTextAttribute ( 0 );
2012-08-23 20:08:50 +01:00
2013-04-05 20:58:01 +01:00
case Colour :: LightGrey : return setTextAttribute ( FOREGROUND_INTENSITY );
case Colour :: BrightRed : return setTextAttribute ( FOREGROUND_INTENSITY | FOREGROUND_RED );
case Colour :: BrightGreen : return setTextAttribute ( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
2013-06-28 14:11:28 +01:00
case Colour :: BrightWhite : return setTextAttribute ( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
2012-08-23 20:08:50 +01:00
2013-04-05 20:58:01 +01:00
case Colour :: Bright : throw std :: logic_error ( "not a colour" );
}
2012-08-09 07:47:30 +01:00
}
2012-08-23 20:08:50 +01:00
private :
2013-04-05 20:58:01 +01:00
void setTextAttribute ( WORD _textAttribute ) {
2015-07-06 06:22:28 +01:00
SetConsoleTextAttribute ( stdoutHandle , _textAttribute | originalBackgroundAttributes );
2012-08-09 07:47:30 +01:00
}
2013-04-05 20:58:01 +01:00
HANDLE stdoutHandle ;
2015-07-06 06:22:28 +01:00
WORD originalForegroundAttributes ;
WORD originalBackgroundAttributes ;
2012-08-23 20:08:50 +01:00
};
2014-10-21 07:25:26 +01:00
IColourImpl * platformColourInstance () {
2014-04-15 18:44:37 +01:00
static Win32ColourImpl s_instance ;
return & s_instance ;
}
2013-03-11 18:38:29 +00:00
} // end anon namespace
2012-08-23 20:08:50 +01:00
} // end namespace Catch
2014-10-21 07:25:26 +01:00
#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
2012-11-01 08:27:09 +00:00
#include <unistd.h>
namespace Catch {
2013-03-11 18:38:29 +00:00
namespace {
2012-11-01 08:27:09 +00:00
// use POSIX/ ANSI console terminal codes
2013-04-05 20:58:01 +01:00
// Thanks to Adam Strzelecki for original contribution
// (http://github.com/nanoant)
2012-11-01 08:27:09 +00:00
// https://github.com/philsquared/Catch/pull/131
2014-10-21 07:25:26 +01:00
class PosixColourImpl : public IColourImpl {
2013-04-05 20:58:01 +01:00
public :
virtual void use ( Colour :: Code _colourCode ) {
switch ( _colourCode ) {
case Colour :: None :
case Colour :: White : return setColour ( "[0m" );
case Colour :: Red : return setColour ( "[0;31m" );
case Colour :: Green : return setColour ( "[0;32m" );
case Colour :: Blue : return setColour ( "[0:34m" );
case Colour :: Cyan : return setColour ( "[0;36m" );
case Colour :: Yellow : return setColour ( "[0;33m" );
case Colour :: Grey : return setColour ( "[1;30m" );
2012-11-01 08:27:09 +00:00
2013-04-05 20:58:01 +01:00
case Colour :: LightGrey : return setColour ( "[0;37m" );
case Colour :: BrightRed : return setColour ( "[1;31m" );
2013-04-12 10:43:06 +01:00
case Colour :: BrightGreen : return setColour ( "[1;32m" );
2013-04-05 20:58:01 +01:00
case Colour :: BrightWhite : return setColour ( "[1;37m" );
2012-11-01 08:27:09 +00:00
2013-04-05 20:58:01 +01:00
case Colour :: Bright : throw std :: logic_error ( "not a colour" );
2012-11-01 08:27:09 +00:00
}
}
2014-10-21 07:25:26 +01:00
static IColourImpl * instance () {
static PosixColourImpl s_instance ;
return & s_instance ;
}
2013-04-05 20:58:01 +01:00
private :
void setColour ( const char * _escapeCode ) {
2014-10-02 19:08:19 +01:00
Catch :: cout () << '\033' << _escapeCode ;
2013-03-11 18:38:29 +00:00
}
};
2014-10-21 07:25:26 +01:00
IColourImpl * platformColourInstance () {
2015-03-04 08:23:40 +00:00
Ptr < IConfig const > config = getCurrentContext (). getConfig ();
return ( config && config -> forceColour ()) || isatty ( STDOUT_FILENO )
2014-10-21 07:25:26 +01:00
? PosixColourImpl :: instance ()
: NoColourImpl :: instance ();
2014-04-15 18:44:37 +01:00
}
2012-11-01 08:27:09 +00:00
2013-04-05 20:58:01 +01:00
} // end anon namespace
} // end namespace Catch
2012-08-09 07:47:30 +01:00
2014-10-21 07:25:26 +01:00
#else // not Windows or ANSI ///////////////////////////////////////////////
2012-08-09 07:47:30 +01:00
namespace Catch {
2014-10-21 07:25:26 +01:00
static IColourImpl * platformColourInstance () { return NoColourImpl :: instance (); }
2014-04-15 18:44:37 +01:00
2014-10-21 07:25:26 +01:00
} // end namespace Catch
#endif // Windows/ ANSI/ None
namespace Catch {
2012-08-09 07:47:30 +01:00
2014-07-09 07:40:37 +01:00
Colour :: Colour ( Code _colourCode ) : m_moved ( false ) { use ( _colourCode ); }
Colour :: Colour ( Colour const & _other ) : m_moved ( false ) { const_cast < Colour &> ( _other ). m_moved = true ; }
Colour ::~ Colour (){ if ( ! m_moved ) use ( None ); }
2012-08-09 07:47:30 +01:00
2014-10-21 07:25:26 +01:00
void Colour :: use ( Code _colourCode ) {
static IColourImpl * impl = isDebuggerActive ()
? NoColourImpl :: instance ()
: platformColourInstance ();
impl -> use ( _colourCode );
2014-04-15 18:44:37 +01:00
}
2012-08-09 07:47:30 +01:00
} // end namespace Catch
// #included from: catch_generators_impl.hpp
#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
#include <vector>
#include <string>
#include <map>
namespace Catch {
struct GeneratorInfo : IGeneratorInfo {
GeneratorInfo ( std :: size_t size )
: m_size ( size ),
m_currentIndex ( 0 )
{}
bool moveNext () {
if ( ++ m_currentIndex == m_size ) {
m_currentIndex = 0 ;
return false ;
}
return true ;
}
std :: size_t getCurrentIndex () const {
return m_currentIndex ;
}
std :: size_t m_size ;
std :: size_t m_currentIndex ;
};
///////////////////////////////////////////////////////////////////////////
class GeneratorsForTest : public IGeneratorsForTest {
public :
~ GeneratorsForTest () {
deleteAll ( m_generatorsInOrder );
}
2013-04-24 19:10:02 +01:00
IGeneratorInfo & getGeneratorInfo ( std :: string const & fileInfo , std :: size_t size ) {
2012-08-09 07:47:30 +01:00
std :: map < std :: string , IGeneratorInfo *>:: const_iterator it = m_generatorsByName . find ( fileInfo );
if ( it == m_generatorsByName . end () ) {
IGeneratorInfo * info = new GeneratorInfo ( size );
m_generatorsByName . insert ( std :: make_pair ( fileInfo , info ) );
m_generatorsInOrder . push_back ( info );
return * info ;
}
return * it -> second ;
}
bool moveNext () {
std :: vector < IGeneratorInfo *>:: const_iterator it = m_generatorsInOrder . begin ();
std :: vector < IGeneratorInfo *>:: const_iterator itEnd = m_generatorsInOrder . end ();
for (; it != itEnd ; ++ it ) {
if ( ( * it ) -> moveNext () )
return true ;
}
return false ;
}
private :
std :: map < std :: string , IGeneratorInfo *> m_generatorsByName ;
std :: vector < IGeneratorInfo *> m_generatorsInOrder ;
};
IGeneratorsForTest * createGeneratorsForTest ()
{
return new GeneratorsForTest ();
}
} // end namespace Catch
2012-11-01 08:27:09 +00:00
// #included from: catch_assertionresult.hpp
#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
2012-08-09 07:47:30 +01:00
namespace Catch {
2013-04-24 19:10:02 +01:00
AssertionInfo :: AssertionInfo ( std :: string const & _macroName ,
SourceLineInfo const & _lineInfo ,
std :: string const & _capturedExpression ,
2012-11-13 22:04:29 +00:00
ResultDisposition :: Flags _resultDisposition )
: macroName ( _macroName ),
lineInfo ( _lineInfo ),
capturedExpression ( _capturedExpression ),
resultDisposition ( _resultDisposition )
2013-06-07 19:07:50 +01:00
{}
2012-11-13 22:04:29 +00:00
2012-11-01 08:27:09 +00:00
AssertionResult :: AssertionResult () {}
2012-08-09 07:47:30 +01:00
2013-04-24 19:10:02 +01:00
AssertionResult :: AssertionResult ( AssertionInfo const & info , AssertionResultData const & data )
2012-11-01 08:27:09 +00:00
: m_info ( info ),
m_resultData ( data )
{}
2012-08-09 07:47:30 +01:00
2012-11-01 08:27:09 +00:00
AssertionResult ::~ AssertionResult () {}
2012-08-09 07:47:30 +01:00
2012-11-13 22:04:29 +00:00
// Result was a success
bool AssertionResult :: succeeded () const {
return Catch :: isOk ( m_resultData . resultType );
}
// Result was a success, or failure is suppressed
bool AssertionResult :: isOk () const {
return Catch :: isOk ( m_resultData . resultType ) || shouldSuppressFailure ( m_info . resultDisposition );
2012-08-09 07:47:30 +01:00
}
2012-11-01 08:27:09 +00:00
ResultWas :: OfType AssertionResult :: getResultType () const {
return m_resultData . resultType ;
2012-08-09 07:47:30 +01:00
}
2012-11-01 08:27:09 +00:00
bool AssertionResult :: hasExpression () const {
return ! m_info . capturedExpression . empty ();
2012-08-09 07:47:30 +01:00
}
2012-11-01 08:27:09 +00:00
bool AssertionResult :: hasMessage () const {
return ! m_resultData . message . empty ();
2012-08-09 07:47:30 +01:00
}
2012-11-01 08:27:09 +00:00
std :: string AssertionResult :: getExpression () const {
2014-06-02 07:48:03 +01:00
if ( isFalseTest ( m_info . resultDisposition ) )
2013-06-07 19:07:50 +01:00
return "!" + m_info . capturedExpression ;
else
return m_info . capturedExpression ;
}
std :: string AssertionResult :: getExpressionInMacro () const {
if ( m_info . macroName . empty () )
return m_info . capturedExpression ;
else
return m_info . macroName + "( " + m_info . capturedExpression + " )" ;
2012-08-09 07:47:30 +01:00
}
2012-11-01 08:27:09 +00:00
bool AssertionResult :: hasExpandedExpression () const {
2012-10-09 11:48:55 +01:00
return hasExpression () && getExpandedExpression () != getExpression ();
2012-08-09 07:47:30 +01:00
}
2012-11-01 08:27:09 +00:00
std :: string AssertionResult :: getExpandedExpression () const {
return m_resultData . reconstructedExpression ;
2012-08-09 07:47:30 +01:00
}
2012-11-01 08:27:09 +00:00
std :: string AssertionResult :: getMessage () const {
return m_resultData . message ;
}
SourceLineInfo AssertionResult :: getSourceInfo () const {
return m_info . lineInfo ;
2012-08-09 07:47:30 +01:00
}
2012-11-01 08:27:09 +00:00
std :: string AssertionResult :: getTestMacroName () const {
return m_info . macroName ;
2012-08-09 07:47:30 +01:00
}
} // end namespace Catch
2012-08-16 18:48:50 +01:00
// #included from: catch_test_case_info.hpp
2012-09-17 01:42:29 -04:00
#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
2012-08-16 18:48:50 +01:00
namespace Catch {
2014-07-03 08:11:38 +01:00
inline TestCaseInfo :: SpecialProperties parseSpecialTag ( std :: string const & tag ) {
2014-12-15 07:26:31 +00:00
if ( startsWith ( tag , "." ) ||
2014-07-03 08:11:38 +01:00
tag == "hide" ||
tag == "!hide" )
return TestCaseInfo :: IsHidden ;
else if ( tag == "!throws" )
return TestCaseInfo :: Throws ;
else if ( tag == "!shouldfail" )
return TestCaseInfo :: ShouldFail ;
else if ( tag == "!mayfail" )
return TestCaseInfo :: MayFail ;
else
return TestCaseInfo :: None ;
2014-04-15 18:44:37 +01:00
}
inline bool isReservedTag ( std :: string const & tag ) {
2015-03-27 18:02:28 +00:00
return parseSpecialTag ( tag ) == TestCaseInfo :: None && tag . size () > 0 && ! isalnum ( tag [ 0 ] );
2014-04-15 18:44:37 +01:00
}
2014-05-16 18:54:48 +01:00
inline void enforceNotReservedTag ( std :: string const & tag , SourceLineInfo const & _lineInfo ) {
if ( isReservedTag ( tag ) ) {
{
Colour colourGuard ( Colour :: Red );
2014-10-02 19:08:19 +01:00
Catch :: cerr ()
2014-05-16 18:54:48 +01:00
<< "Tag name [" << tag << "] not allowed. \n "
<< "Tag names starting with non alpha-numeric characters are reserved \n " ;
}
{
Colour colourGuard ( Colour :: FileName );
2014-10-02 19:08:19 +01:00
Catch :: cerr () << _lineInfo << std :: endl ;
2014-05-16 18:54:48 +01:00
}
exit ( 1 );
}
}
2014-04-15 18:44:37 +01:00
2012-12-01 23:57:18 +00:00
TestCase makeTestCase ( ITestCase * _testCase ,
2013-04-24 19:10:02 +01:00
std :: string const & _className ,
std :: string const & _name ,
std :: string const & _descOrTags ,
SourceLineInfo const & _lineInfo )
2012-09-15 17:53:27 +01:00
{
2013-11-26 20:57:45 +00:00
bool isHidden ( startsWith ( _name , "./" ) ); // Legacy support
2014-05-16 18:54:48 +01:00
// Parse out tags
2012-12-01 23:57:18 +00:00
std :: set < std :: string > tags ;
2014-05-16 18:54:48 +01:00
std :: string desc , tag ;
bool inTag = false ;
for ( std :: size_t i = 0 ; i < _descOrTags . size (); ++ i ) {
char c = _descOrTags [ i ];
if ( ! inTag ) {
if ( c == '[' )
inTag = true ;
else
desc += c ;
2014-04-15 18:44:37 +01:00
}
2014-05-16 18:54:48 +01:00
else {
if ( c == ']' ) {
2014-12-15 07:26:31 +00:00
TestCaseInfo :: SpecialProperties prop = parseSpecialTag ( tag );
if ( prop == TestCaseInfo :: IsHidden )
2014-05-19 18:22:59 +01:00
isHidden = true ;
2014-12-15 07:26:31 +00:00
else if ( prop == TestCaseInfo :: None )
enforceNotReservedTag ( tag , _lineInfo );
tags . insert ( tag );
2014-05-16 18:54:48 +01:00
tag . clear ();
2014-12-15 07:26:31 +00:00
inTag = false ;
2014-05-16 18:54:48 +01:00
}
else
tag += c ;
}
2013-12-04 20:25:14 +00:00
}
2014-05-20 18:50:59 +01:00
if ( isHidden ) {
tags . insert ( "hide" );
tags . insert ( "." );
}
2014-07-03 08:11:38 +01:00
TestCaseInfo info ( _name , _className , desc , tags , _lineInfo );
2012-12-01 23:57:18 +00:00
return TestCase ( _testCase , info );
2012-09-15 17:53:27 +01:00
}
2012-08-16 18:48:50 +01:00
2015-07-02 08:21:38 +01:00
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 ();
}
2013-04-24 19:10:02 +01:00
TestCaseInfo :: TestCaseInfo ( std :: string const & _name ,
std :: string const & _className ,
std :: string const & _description ,
std :: set < std :: string > const & _tags ,
SourceLineInfo const & _lineInfo )
2012-12-01 23:57:18 +00:00
: name ( _name ),
className ( _className ),
description ( _description ),
2012-12-06 08:44:51 +00:00
lineInfo ( _lineInfo ),
2014-07-03 08:11:38 +01:00
properties ( None )
2013-03-29 13:44:33 +00:00
{
2015-07-02 08:21:38 +01:00
setTags ( * this , _tags );
2013-03-29 13:44:33 +00:00
}
2012-08-16 18:48:50 +01:00
2013-04-24 19:10:02 +01:00
TestCaseInfo :: TestCaseInfo ( TestCaseInfo const & other )
2012-12-01 23:57:18 +00:00
: name ( other . name ),
className ( other . className ),
description ( other . description ),
tags ( other . tags ),
2014-05-20 18:50:59 +01:00
lcaseTags ( other . lcaseTags ),
2013-03-29 13:44:33 +00:00
tagsAsString ( other . tagsAsString ),
2012-12-06 08:44:51 +00:00
lineInfo ( other . lineInfo ),
2014-07-03 08:11:38 +01:00
properties ( other . properties )
2012-08-16 18:48:50 +01:00
{}
2014-07-03 08:11:38 +01:00
bool TestCaseInfo :: isHidden () const {
return ( properties & IsHidden ) != 0 ;
}
bool TestCaseInfo :: throws () const {
return ( properties & Throws ) != 0 ;
}
bool TestCaseInfo :: okToFail () const {
return ( properties & ( ShouldFail | MayFail ) ) != 0 ;
}
bool TestCaseInfo :: expectedToFail () const {
return ( properties & ( ShouldFail ) ) != 0 ;
}
2013-04-24 19:10:02 +01:00
TestCase :: TestCase ( ITestCase * testCase , TestCaseInfo const & info ) : TestCaseInfo ( info ), test ( testCase ) {}
2012-12-01 23:57:18 +00:00
2013-04-24 19:10:02 +01:00
TestCase :: TestCase ( TestCase const & other )
2012-12-01 23:57:18 +00:00
: TestCaseInfo ( other ),
test ( other . test )
2012-08-16 18:48:50 +01:00
{}
2013-04-24 19:10:02 +01:00
TestCase TestCase :: withName ( std :: string const & _newName ) const {
2012-12-01 23:57:18 +00:00
TestCase other ( * this );
other . name = _newName ;
return other ;
2012-08-16 18:48:50 +01:00
}
2014-05-20 18:50:59 +01:00
void TestCase :: swap ( TestCase & other ) {
test . swap ( other . test );
name . swap ( other . name );
className . swap ( other . className );
description . swap ( other . description );
tags . swap ( other . tags );
lcaseTags . swap ( other . lcaseTags );
tagsAsString . swap ( other . tagsAsString );
2014-07-03 08:11:38 +01:00
std :: swap ( TestCaseInfo :: properties , static_cast < TestCaseInfo &> ( other ). properties );
2014-05-20 18:50:59 +01:00
std :: swap ( lineInfo , other . lineInfo );
}
2012-12-01 23:57:18 +00:00
void TestCase :: invoke () const {
test -> invoke ();
2012-08-16 18:48:50 +01:00
}
2013-04-24 19:10:02 +01:00
bool TestCase :: operator == ( TestCase const & other ) const {
2012-12-01 23:57:18 +00:00
return test . get () == other . test . get () &&
name == other . name &&
className == other . className ;
2012-08-16 18:48:50 +01:00
}
2013-04-24 19:10:02 +01:00
bool TestCase :: operator < ( TestCase const & other ) const {
2012-12-01 23:57:18 +00:00
return name < other . name ;
2012-08-16 18:48:50 +01:00
}
2013-04-24 19:10:02 +01:00
TestCase & TestCase :: operator = ( TestCase const & other ) {
2012-12-01 23:57:18 +00:00
TestCase temp ( other );
2012-08-23 19:48:57 +01:00
swap ( temp );
return * this ;
}
2012-09-24 08:30:13 +01:00
2013-04-24 19:10:02 +01:00
TestCaseInfo const & TestCase :: getTestCaseInfo () const
2012-12-01 23:57:18 +00:00
{
return * this ;
}
2012-09-24 08:30:13 +01:00
} // end namespace Catch
2012-08-16 18:48:50 +01:00
2012-11-15 22:15:41 +00:00
// #included from: catch_version.hpp
#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
namespace Catch {
2015-06-29 18:05:23 +01:00
Version :: Version
( unsigned int _majorVersion ,
unsigned int _minorVersion ,
unsigned int _patchNumber ,
std :: string const & _branchName ,
unsigned int _buildNumber )
: majorVersion ( _majorVersion ),
minorVersion ( _minorVersion ),
patchNumber ( _patchNumber ),
branchName ( _branchName ),
buildNumber ( _buildNumber )
{}
std :: ostream & operator << ( std :: ostream & os , Version const & version ) {
os << version . majorVersion << "."
<< version . minorVersion << "."
<< version . patchNumber ;
if ( ! version . branchName . empty () ) {
os << "-" << version . branchName
<< "." << version . buildNumber ;
}
return os ;
}
2015-08-07 17:30:34 +01:00
Version libraryVersion ( 1 , 2 , 1 , "develop" , 12 );
2015-06-29 18:05:23 +01:00
2012-11-15 22:15:41 +00:00
}
2013-02-02 20:37:58 +00:00
// #included from: catch_message.hpp
#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
namespace Catch {
MessageInfo :: MessageInfo ( std :: string const & _macroName ,
SourceLineInfo const & _lineInfo ,
ResultWas :: OfType _type )
: macroName ( _macroName ),
lineInfo ( _lineInfo ),
type ( _type ),
sequence ( ++ globalCount )
{}
// This may need protecting if threading support is added
unsigned int MessageInfo :: globalCount = 0 ;
////////////////////////////////////////////////////////////////////////////
2013-06-28 17:09:57 +01:00
ScopedMessage :: ScopedMessage ( MessageBuilder const & builder )
: m_info ( builder . m_info )
{
m_info . message = builder . m_stream . str ();
getResultCapture (). pushScopedMessage ( m_info );
2013-02-02 20:37:58 +00:00
}
2014-05-20 18:50:59 +01:00
ScopedMessage :: ScopedMessage ( ScopedMessage const & other )
: m_info ( other . m_info )
{}
2013-06-28 17:09:57 +01:00
ScopedMessage ::~ ScopedMessage () {
getResultCapture (). popScopedMessage ( m_info );
2013-02-02 20:37:58 +00:00
}
} // end namespace Catch
2013-04-12 10:43:06 +01:00
// #included from: catch_legacy_reporter_adapter.hpp
2013-04-08 11:50:41 +01:00
#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
// #included from: catch_legacy_reporter_adapter.h
#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
namespace Catch
{
2013-12-03 18:53:55 +00:00
// Deprecated
struct IReporter : IShared {
virtual ~ IReporter ();
virtual bool shouldRedirectStdout () const = 0 ;
virtual void StartTesting () = 0 ;
virtual void EndTesting ( Totals const & totals ) = 0 ;
virtual void StartGroup ( std :: string const & groupName ) = 0 ;
virtual void EndGroup ( std :: string const & groupName , Totals const & totals ) = 0 ;
virtual void StartTestCase ( TestCaseInfo const & testInfo ) = 0 ;
virtual void EndTestCase ( TestCaseInfo const & testInfo , Totals const & totals , std :: string const & stdOut , std :: string const & stdErr ) = 0 ;
virtual void StartSection ( std :: string const & sectionName , std :: string const & description ) = 0 ;
virtual void EndSection ( std :: string const & sectionName , Counts const & assertions ) = 0 ;
virtual void NoAssertionsInSection ( std :: string const & sectionName ) = 0 ;
virtual void NoAssertionsInTestCase ( std :: string const & testName ) = 0 ;
virtual void Aborted () = 0 ;
virtual void Result ( AssertionResult const & result ) = 0 ;
};
2013-04-08 11:50:41 +01:00
class LegacyReporterAdapter : public SharedImpl < IStreamingReporter >
{
public :
2013-06-07 19:07:50 +01:00
LegacyReporterAdapter ( Ptr < IReporter > const & legacyReporter );
2013-04-08 11:50:41 +01:00
virtual ~ LegacyReporterAdapter ();
virtual ReporterPreferences getPreferences () const ;
virtual void noMatchingTestCases ( std :: string const & );
virtual void testRunStarting ( TestRunInfo const & );
virtual void testGroupStarting ( GroupInfo const & groupInfo );
virtual void testCaseStarting ( TestCaseInfo const & testInfo );
virtual void sectionStarting ( SectionInfo const & sectionInfo );
virtual void assertionStarting ( AssertionInfo const & );
2013-06-28 17:09:57 +01:00
virtual bool assertionEnded ( AssertionStats const & assertionStats );
2013-04-08 11:50:41 +01:00
virtual void sectionEnded ( SectionStats const & sectionStats );
virtual void testCaseEnded ( TestCaseStats const & testCaseStats );
virtual void testGroupEnded ( TestGroupStats const & testGroupStats );
virtual void testRunEnded ( TestRunStats const & testRunStats );
2014-12-22 20:18:05 +00:00
virtual void skipTest ( TestCaseInfo const & );
2013-04-08 11:50:41 +01:00
private :
Ptr < IReporter > m_legacyReporter ;
};
}
namespace Catch
{
2013-06-07 19:07:50 +01:00
LegacyReporterAdapter :: LegacyReporterAdapter ( Ptr < IReporter > const & legacyReporter )
: m_legacyReporter ( legacyReporter )
2013-04-08 11:50:41 +01:00
{}
LegacyReporterAdapter ::~ LegacyReporterAdapter () {}
ReporterPreferences LegacyReporterAdapter :: getPreferences () const {
ReporterPreferences prefs ;
prefs . shouldRedirectStdOut = m_legacyReporter -> shouldRedirectStdout ();
return prefs ;
}
void LegacyReporterAdapter :: noMatchingTestCases ( std :: string const & ) {}
void LegacyReporterAdapter :: testRunStarting ( TestRunInfo const & ) {
m_legacyReporter -> StartTesting ();
}
void LegacyReporterAdapter :: testGroupStarting ( GroupInfo const & groupInfo ) {
m_legacyReporter -> StartGroup ( groupInfo . name );
}
void LegacyReporterAdapter :: testCaseStarting ( TestCaseInfo const & testInfo ) {
m_legacyReporter -> StartTestCase ( testInfo );
}
void LegacyReporterAdapter :: sectionStarting ( SectionInfo const & sectionInfo ) {
m_legacyReporter -> StartSection ( sectionInfo . name , sectionInfo . description );
}
void LegacyReporterAdapter :: assertionStarting ( AssertionInfo const & ) {
// Not on legacy interface
}
2013-06-28 17:09:57 +01:00
bool LegacyReporterAdapter :: assertionEnded ( AssertionStats const & assertionStats ) {
2013-04-08 11:50:41 +01:00
if ( assertionStats . assertionResult . getResultType () != ResultWas :: Ok ) {
for ( std :: vector < MessageInfo >:: const_iterator it = assertionStats . infoMessages . begin (), itEnd = assertionStats . infoMessages . end ();
it != itEnd ;
++ it ) {
if ( it -> type == ResultWas :: Info ) {
2014-06-02 07:48:03 +01:00
ResultBuilder rb ( it -> macroName . c_str (), it -> lineInfo , "" , ResultDisposition :: Normal );
rb << it -> message ;
rb . setResultType ( ResultWas :: Info );
AssertionResult result = rb . build ();
2013-04-08 11:50:41 +01:00
m_legacyReporter -> Result ( result );
}
}
}
m_legacyReporter -> Result ( assertionStats . assertionResult );
2013-06-28 17:09:57 +01:00
return true ;
2013-04-08 11:50:41 +01:00
}
void LegacyReporterAdapter :: sectionEnded ( SectionStats const & sectionStats ) {
if ( sectionStats . missingAssertions )
m_legacyReporter -> NoAssertionsInSection ( sectionStats . sectionInfo . name );
m_legacyReporter -> EndSection ( sectionStats . sectionInfo . name , sectionStats . assertions );
}
void LegacyReporterAdapter :: testCaseEnded ( TestCaseStats const & testCaseStats ) {
m_legacyReporter -> EndTestCase
( testCaseStats . testInfo ,
testCaseStats . totals ,
testCaseStats . stdOut ,
testCaseStats . stdErr );
}
void LegacyReporterAdapter :: testGroupEnded ( TestGroupStats const & testGroupStats ) {
if ( testGroupStats . aborting )
m_legacyReporter -> Aborted ();
m_legacyReporter -> EndGroup ( testGroupStats . groupInfo . name , testGroupStats . totals );
}
void LegacyReporterAdapter :: testRunEnded ( TestRunStats const & testRunStats ) {
m_legacyReporter -> EndTesting ( testRunStats . totals );
}
2014-12-22 20:18:05 +00:00
void LegacyReporterAdapter :: skipTest ( TestCaseInfo const & ) {
}
2013-04-08 11:50:41 +01:00
}
2013-08-15 19:01:00 +01:00
// #included from: catch_timer.hpp
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++11-long-long"
#endif
2013-08-16 19:09:09 +01:00
#ifdef CATCH_PLATFORM_WINDOWS
2013-08-15 19:01:00 +01:00
#include <windows.h>
#else
#include <sys/time.h>
#endif
namespace Catch {
namespace {
2013-08-16 19:09:09 +01:00
#ifdef CATCH_PLATFORM_WINDOWS
2013-08-15 19:01:00 +01:00
uint64_t getCurrentTicks () {
static uint64_t hz = 0 , hzo = 0 ;
if ( ! hz ) {
2015-03-27 18:02:28 +00:00
QueryPerformanceFrequency ( reinterpret_cast < LARGE_INTEGER *> ( & hz ) );
QueryPerformanceCounter ( reinterpret_cast < LARGE_INTEGER *> ( & hzo ) );
2013-08-15 19:01:00 +01:00
}
uint64_t t ;
2015-03-27 18:02:28 +00:00
QueryPerformanceCounter ( reinterpret_cast < LARGE_INTEGER *> ( & t ) );
2013-08-15 19:01:00 +01:00
return (( t - hzo ) * 1000000 ) / hz ;
}
#else
uint64_t getCurrentTicks () {
timeval t ;
2015-07-02 08:21:38 +01:00
gettimeofday ( & t , CATCH_NULL );
2014-07-09 07:40:37 +01:00
return static_cast < uint64_t > ( t . tv_sec ) * 1000000ull + static_cast < uint64_t > ( t . tv_usec );
2013-08-15 19:01:00 +01:00
}
#endif
}
void Timer :: start () {
m_ticks = getCurrentTicks ();
}
2014-09-03 19:23:22 +01:00
unsigned int Timer :: getElapsedMicroseconds () const {
2014-07-09 07:40:37 +01:00
return static_cast < unsigned int > ( getCurrentTicks () - m_ticks );
2013-08-15 19:01:00 +01:00
}
unsigned int Timer :: getElapsedMilliseconds () const {
2014-09-03 19:23:22 +01:00
return static_cast < unsigned int > ( getElapsedMicroseconds () / 1000 );
2013-08-15 19:01:00 +01:00
}
double Timer :: getElapsedSeconds () const {
2014-09-03 19:23:22 +01:00
return getElapsedMicroseconds () / 1000000.0 ;
2013-08-15 19:01:00 +01:00
}
} // namespace Catch
#ifdef __clang__
#pragma clang diagnostic pop
#endif
2013-12-03 18:53:55 +00:00
// #included from: catch_common.hpp
#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
namespace Catch {
bool startsWith ( std :: string const & s , std :: string const & prefix ) {
return s . size () >= prefix . size () && s . substr ( 0 , prefix . size () ) == prefix ;
}
bool endsWith ( std :: string const & s , std :: string const & suffix ) {
return s . size () >= suffix . size () && s . substr ( s . size () - suffix . size (), suffix . size () ) == suffix ;
}
bool contains ( std :: string const & s , std :: string const & infix ) {
return s . find ( infix ) != std :: string :: npos ;
}
void toLowerInPlace ( std :: string & s ) {
std :: transform ( s . begin (), s . end (), s . begin (), :: tolower );
}
std :: string toLower ( std :: string const & s ) {
std :: string lc = s ;
toLowerInPlace ( lc );
return lc ;
}
std :: string trim ( std :: string const & str ) {
static char const * whitespaceChars = " \n\r\t " ;
std :: string :: size_type start = str . find_first_not_of ( whitespaceChars );
std :: string :: size_type end = str . find_last_not_of ( whitespaceChars );
return start != std :: string :: npos ? str . substr ( start , 1 + end - start ) : "" ;
}
2014-12-21 00:21:23 +00:00
bool replaceInPlace ( std :: string & str , std :: string const & replaceThis , std :: string const & withThis ) {
bool replaced = false ;
std :: size_t i = str . find ( replaceThis );
while ( i != std :: string :: npos ) {
replaced = true ;
str = str . substr ( 0 , i ) + withThis + str . substr ( i + replaceThis . size () );
if ( i < str . size () - withThis . size () )
i = str . find ( replaceThis , i + withThis . size () );
else
i = std :: string :: npos ;
}
return replaced ;
}
2013-12-03 18:53:55 +00:00
pluralise :: pluralise ( std :: size_t count , std :: string const & label )
: m_count ( count ),
m_label ( label )
{}
std :: ostream & operator << ( std :: ostream & os , pluralise const & pluraliser ) {
os << pluraliser . m_count << " " << pluraliser . m_label ;
if ( pluraliser . m_count != 1 )
os << "s" ;
return os ;
}
SourceLineInfo :: SourceLineInfo () : line ( 0 ){}
2013-12-04 20:25:14 +00:00
SourceLineInfo :: SourceLineInfo ( char const * _file , std :: size_t _line )
2013-12-03 18:53:55 +00:00
: file ( _file ),
line ( _line )
{}
SourceLineInfo :: SourceLineInfo ( SourceLineInfo const & other )
: file ( other . file ),
line ( other . line )
{}
bool SourceLineInfo :: empty () const {
return file . empty ();
}
bool SourceLineInfo :: operator == ( SourceLineInfo const & other ) const {
return line == other . line && file == other . file ;
}
2015-03-04 08:23:40 +00:00
bool SourceLineInfo :: operator < ( SourceLineInfo const & other ) const {
return line < other . line || ( line == other . line && file < other . file );
}
2013-12-03 18:53:55 +00:00
2015-07-02 23:03:13 +01:00
void seedRng ( IConfig const & config ) {
if ( config . rngSeed () != 0 )
std :: srand ( config . rngSeed () );
}
unsigned int rngSeed () {
return getCurrentContext (). getConfig () -> rngSeed ();
}
2013-12-03 18:53:55 +00:00
std :: ostream & operator << ( std :: ostream & os , SourceLineInfo const & info ) {
#ifndef __GNUG__
os << info . file << "(" << info . line << ")" ;
#else
os << info . file << ":" << info . line ;
#endif
return os ;
}
void throwLogicError ( std :: string const & message , SourceLineInfo const & locationInfo ) {
std :: ostringstream oss ;
oss << locationInfo << ": Internal Catch error: '" << message << "'" ;
2014-06-02 07:48:03 +01:00
if ( alwaysTrue () )
2013-12-03 18:53:55 +00:00
throw std :: logic_error ( oss . str () );
}
}
// #included from: catch_section.hpp
#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
namespace Catch {
2014-07-09 07:40:37 +01:00
SectionInfo :: SectionInfo
( SourceLineInfo const & _lineInfo ,
std :: string const & _name ,
std :: string const & _description )
: name ( _name ),
description ( _description ),
lineInfo ( _lineInfo )
{}
Section :: Section ( SectionInfo const & info )
: m_info ( info ),
2014-05-20 18:50:59 +01:00
m_sectionIncluded ( getResultCapture (). sectionStarted ( m_info , m_assertions ) )
2013-12-03 18:53:55 +00:00
{
m_timer . start ();
}
Section ::~ Section () {
if ( m_sectionIncluded )
2014-05-20 18:50:59 +01:00
getResultCapture (). sectionEnded ( m_info , m_assertions , m_timer . getElapsedSeconds () );
2013-12-03 18:53:55 +00:00
}
// This indicates whether the section should be executed or not
2014-07-09 07:40:37 +01:00
Section :: operator bool () const {
2013-12-03 18:53:55 +00:00
return m_sectionIncluded ;
}
} // end namespace Catch
// #included from: catch_debugger.hpp
#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
#include <iostream>
#ifdef CATCH_PLATFORM_MAC
#include <assert.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>
namespace Catch {
// The following function is taken directly from the following technical note:
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
bool isDebuggerActive (){
int mib [ 4 ];
struct kinfo_proc info ;
size_t size ;
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
info . kp_proc . p_flag = 0 ;
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a specific process ID.
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_PROC ;
mib [ 2 ] = KERN_PROC_PID ;
mib [ 3 ] = getpid ();
// Call sysctl.
size = sizeof ( info );
2015-07-02 08:21:38 +01:00
if ( sysctl ( mib , sizeof ( mib ) / sizeof ( * mib ), & info , & size , CATCH_NULL , 0 ) != 0 ) {
2014-10-02 19:08:19 +01:00
Catch :: cerr () << " \n ** Call to sysctl failed - unable to determine if debugger is active ** \n " << std :: endl ;
2014-01-08 17:17:31 +00:00
return false ;
}
2013-12-03 18:53:55 +00:00
// We're being debugged if the P_TRACED flag is set.
return ( ( info . kp_proc . p_flag & P_TRACED ) != 0 );
}
} // namespace Catch
#elif defined(_MSC_VER)
extern "C" __declspec ( dllimport ) int __stdcall IsDebuggerPresent ();
namespace Catch {
bool isDebuggerActive () {
return IsDebuggerPresent () != 0 ;
}
}
#elif defined(__MINGW32__)
extern "C" __declspec ( dllimport ) int __stdcall IsDebuggerPresent ();
namespace Catch {
bool isDebuggerActive () {
return IsDebuggerPresent () != 0 ;
}
}
#else
namespace Catch {
inline bool isDebuggerActive () { return false ; }
}
#endif // Platform
#ifdef CATCH_PLATFORM_WINDOWS
extern "C" __declspec ( dllimport ) void __stdcall OutputDebugStringA ( const char * );
namespace Catch {
void writeToDebugConsole ( std :: string const & text ) {
:: OutputDebugStringA ( text . c_str () );
}
}
#else
namespace Catch {
void writeToDebugConsole ( std :: string const & text ) {
// !TBD: Need a version for Mac/ XCode and other IDEs
2014-10-02 19:08:19 +01:00
Catch :: cout () << text ;
2013-12-03 18:53:55 +00:00
}
}
#endif // Platform
2014-04-23 07:10:10 +01:00
// #included from: catch_tostring.hpp
#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
namespace Catch {
2014-06-02 07:48:03 +01:00
namespace Detail {
2015-07-23 23:06:26 +01:00
const std :: string unprintableString = "{?}" ;
2014-09-15 18:40:24 +01:00
2014-06-02 07:48:03 +01:00
namespace {
2015-07-23 23:06:26 +01:00
const int hexThreshold = 255 ;
2014-06-02 07:48:03 +01:00
struct Endianness {
enum Arch { Big , Little };
static Arch which () {
union _ {
int asInt ;
char asChar [ sizeof ( int )];
} u ;
u . asInt = 1 ;
return ( u . asChar [ sizeof ( int ) - 1 ] == 1 ) ? Big : Little ;
}
};
}
std :: string rawMemoryToString ( const void * object , std :: size_t size )
{
// Reverse order for little endian architectures
int i = 0 , end = static_cast < int > ( size ), inc = 1 ;
if ( Endianness :: which () == Endianness :: Little ) {
i = end - 1 ;
end = inc = - 1 ;
}
unsigned char const * bytes = static_cast < unsigned char const *> ( object );
std :: ostringstream os ;
os << "0x" << std :: setfill ( '0' ) << std :: hex ;
for ( ; i != end ; i += inc )
os << std :: setw ( 2 ) << static_cast < unsigned > ( bytes [ i ]);
return os . str ();
}
}
2014-04-23 07:10:10 +01:00
std :: string toString ( std :: string const & value ) {
std :: string s = value ;
if ( getCurrentContext (). getConfig () -> showInvisibles () ) {
for ( size_t i = 0 ; i < s . size (); ++ i ) {
std :: string subs ;
switch ( s [ i ] ) {
case '\n' : subs = " \\ n" ; break ;
case '\t' : subs = " \\ t" ; break ;
default : break ;
}
if ( ! subs . empty () ) {
s = s . substr ( 0 , i ) + subs + s . substr ( i + 1 );
++ i ;
}
}
}
return " \" " + s + " \" " ;
}
std :: string toString ( std :: wstring const & value ) {
std :: string s ;
s . reserve ( value . size () );
for ( size_t i = 0 ; i < value . size (); ++ i )
s += value [ i ] <= 0xff ? static_cast < char > ( value [ i ] ) : '?' ;
2014-12-12 08:11:18 +00:00
return Catch :: toString ( s );
2014-04-23 07:10:10 +01:00
}
std :: string toString ( const char * const value ) {
return value ? Catch :: toString ( std :: string ( value ) ) : std :: string ( "{null string}" );
}
std :: string toString ( char * const value ) {
return Catch :: toString ( static_cast < const char *> ( value ) );
}
2014-08-20 08:09:32 +01:00
std :: string toString ( const wchar_t * const value )
{
return value ? Catch :: toString ( std :: wstring ( value ) ) : std :: string ( "{null string}" );
}
std :: string toString ( wchar_t * const value )
{
return Catch :: toString ( static_cast < const wchar_t *> ( value ) );
}
2014-04-23 07:10:10 +01:00
std :: string toString ( int value ) {
std :: ostringstream oss ;
2015-05-21 06:16:15 +01:00
oss << value ;
2015-07-23 23:06:26 +01:00
if ( value > Detail :: hexThreshold )
2015-05-21 06:16:15 +01:00
oss << " (0x" << std :: hex << value << ")" ;
2014-04-23 07:10:10 +01:00
return oss . str ();
}
std :: string toString ( unsigned long value ) {
std :: ostringstream oss ;
2015-05-21 06:16:15 +01:00
oss << value ;
2015-07-23 23:06:26 +01:00
if ( value > Detail :: hexThreshold )
2015-05-21 06:16:15 +01:00
oss << " (0x" << std :: hex << value << ")" ;
2014-04-23 07:10:10 +01:00
return oss . str ();
}
std :: string toString ( unsigned int value ) {
2014-12-12 08:11:18 +00:00
return Catch :: toString ( static_cast < unsigned long > ( value ) );
2014-04-23 07:10:10 +01:00
}
2014-07-09 19:22:49 +01:00
template < typename T >
std :: string fpToString ( T value , int precision ) {
2014-04-23 07:10:10 +01:00
std :: ostringstream oss ;
2014-07-09 19:22:49 +01:00
oss << std :: setprecision ( precision )
2014-04-23 07:10:10 +01:00
<< std :: fixed
<< value ;
std :: string d = oss . str ();
std :: size_t i = d . find_last_not_of ( '0' );
if ( i != std :: string :: npos && i != d . size () - 1 ) {
if ( d [ i ] == '.' )
i ++ ;
d = d . substr ( 0 , i + 1 );
}
return d ;
}
2014-07-09 19:22:49 +01:00
std :: string toString ( const double value ) {
return fpToString ( value , 10 );
}
std :: string toString ( const float value ) {
return fpToString ( value , 5 ) + "f" ;
}
2014-04-23 07:10:10 +01:00
std :: string toString ( bool value ) {
return value ? "true" : "false" ;
}
std :: string toString ( char value ) {
return value < ' '
? toString ( static_cast < unsigned int > ( value ) )
: Detail :: makeString ( value );
}
std :: string toString ( signed char value ) {
return toString ( static_cast < char > ( value ) );
}
std :: string toString ( unsigned char value ) {
return toString ( static_cast < char > ( value ) );
}
2015-07-23 23:06:26 +01:00
#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
2014-04-23 07:10:10 +01:00
#ifdef CATCH_CONFIG_CPP11_NULLPTR
std :: string toString ( std :: nullptr_t ) {
return "nullptr" ;
}
#endif
#ifdef __OBJC__
std :: string toString ( NSString const * const & nsstring ) {
if ( ! nsstring )
return "nil" ;
2014-06-30 07:35:36 +01:00
return "@" + toString ([ nsstring UTF8String ]);
2014-04-23 07:10:10 +01:00
}
std :: string toString ( NSString * CATCH_ARC_STRONG const & nsstring ) {
if ( ! nsstring )
return "nil" ;
2014-06-30 07:35:36 +01:00
return "@" + toString ([ nsstring UTF8String ]);
2014-04-23 07:10:10 +01:00
}
std :: string toString ( NSObject * const & nsObject ) {
return toString ( [ nsObject description ] );
}
#endif
} // end namespace Catch
2014-06-02 07:48:03 +01:00
// #included from: catch_result_builder.hpp
#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
namespace Catch {
2015-07-13 06:36:07 +01:00
std :: string capturedExpressionWithSecondArgument ( std :: string const & capturedExpression , std :: string const & secondArg ) {
2015-07-15 23:03:11 +01:00
return secondArg . empty () || secondArg == " \"\" "
2015-07-13 06:36:07 +01:00
? capturedExpression
2015-07-15 23:03:11 +01:00
: capturedExpression + ", " + secondArg ;
2015-07-13 06:36:07 +01:00
}
2014-06-02 07:48:03 +01:00
ResultBuilder :: ResultBuilder ( char const * macroName ,
SourceLineInfo const & lineInfo ,
char const * capturedExpression ,
2015-07-13 06:36:07 +01:00
ResultDisposition :: Flags resultDisposition ,
char const * secondArg )
: m_assertionInfo ( macroName , lineInfo , capturedExpressionWithSecondArgument ( capturedExpression , secondArg ), resultDisposition ),
2014-06-02 07:48:03 +01:00
m_shouldDebugBreak ( false ),
m_shouldThrow ( false )
{}
ResultBuilder & ResultBuilder :: setResultType ( ResultWas :: OfType result ) {
m_data . resultType = result ;
return * this ;
}
ResultBuilder & ResultBuilder :: setResultType ( bool result ) {
m_data . resultType = result ? ResultWas :: Ok : ResultWas :: ExpressionFailed ;
return * this ;
}
ResultBuilder & ResultBuilder :: setLhs ( std :: string const & lhs ) {
m_exprComponents . lhs = lhs ;
return * this ;
}
ResultBuilder & ResultBuilder :: setRhs ( std :: string const & rhs ) {
m_exprComponents . rhs = rhs ;
return * this ;
}
ResultBuilder & ResultBuilder :: setOp ( std :: string const & op ) {
m_exprComponents . op = op ;
return * this ;
}
void ResultBuilder :: endExpression () {
m_exprComponents . testFalse = isFalseTest ( m_assertionInfo . resultDisposition );
captureExpression ();
}
void ResultBuilder :: useActiveException ( ResultDisposition :: Flags resultDisposition ) {
m_assertionInfo . resultDisposition = resultDisposition ;
m_stream . oss << Catch :: translateActiveException ();
captureResult ( ResultWas :: ThrewException );
}
void ResultBuilder :: captureResult ( ResultWas :: OfType resultType ) {
setResultType ( resultType );
captureExpression ();
}
2015-07-13 06:36:07 +01:00
void ResultBuilder :: captureExpectedException ( std :: string const & expectedMessage ) {
2015-07-15 23:03:11 +01:00
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 ) {
2015-07-13 06:36:07 +01:00
assert ( m_exprComponents . testFalse == false );
AssertionResultData data = m_data ;
data . resultType = ResultWas :: Ok ;
data . reconstructedExpression = m_assertionInfo . capturedExpression ;
2015-07-15 23:03:11 +01:00
std :: string actualMessage = Catch :: translateActiveException ();
if ( ! matcher . match ( actualMessage ) ) {
data . resultType = ResultWas :: ExpressionFailed ;
data . reconstructedExpression = actualMessage ;
2015-07-13 06:36:07 +01:00
}
AssertionResult result ( m_assertionInfo , data );
handleResult ( result );
}
2014-06-02 07:48:03 +01:00
void ResultBuilder :: captureExpression () {
AssertionResult result = build ();
2015-07-13 06:36:07 +01:00
handleResult ( result );
}
void ResultBuilder :: handleResult ( AssertionResult const & result )
{
2014-06-02 07:48:03 +01:00
getResultCapture (). assertionEnded ( result );
if ( ! result . isOk () ) {
if ( getCurrentContext (). getConfig () -> shouldDebugBreak () )
m_shouldDebugBreak = true ;
2015-05-19 18:40:00 +01:00
if ( getCurrentContext (). getRunner () -> aborting () || ( m_assertionInfo . resultDisposition & ResultDisposition :: Normal ) )
2014-06-02 07:48:03 +01:00
m_shouldThrow = true ;
}
}
void ResultBuilder :: react () {
if ( m_shouldThrow )
throw Catch :: TestFailureException ();
}
bool ResultBuilder :: shouldDebugBreak () const { return m_shouldDebugBreak ; }
bool ResultBuilder :: allowThrows () const { return getCurrentContext (). getConfig () -> allowThrows (); }
AssertionResult ResultBuilder :: build () const
{
assert ( m_data . resultType != ResultWas :: Unknown );
AssertionResultData data = m_data ;
// Flip bool results if testFalse is set
if ( m_exprComponents . testFalse ) {
if ( data . resultType == ResultWas :: Ok )
data . resultType = ResultWas :: ExpressionFailed ;
else if ( data . resultType == ResultWas :: ExpressionFailed )
data . resultType = ResultWas :: Ok ;
}
data . message = m_stream . oss . str ();
data . reconstructedExpression = reconstructExpression ();
if ( m_exprComponents . testFalse ) {
if ( m_exprComponents . op == "" )
data . reconstructedExpression = "!" + data . reconstructedExpression ;
else
data . reconstructedExpression = "!(" + data . reconstructedExpression + ")" ;
}
return AssertionResult ( m_assertionInfo , data );
}
std :: string ResultBuilder :: reconstructExpression () const {
if ( m_exprComponents . op == "" )
return m_exprComponents . lhs . empty () ? m_assertionInfo . capturedExpression : m_exprComponents . op + m_exprComponents . lhs ;
else if ( m_exprComponents . op == "matches" )
return m_exprComponents . lhs + " " + m_exprComponents . rhs ;
else if ( m_exprComponents . op != "!" ) {
if ( m_exprComponents . lhs . size () + m_exprComponents . rhs . size () < 40 &&
m_exprComponents . lhs . find ( " \n " ) == std :: string :: npos &&
m_exprComponents . rhs . find ( " \n " ) == std :: string :: npos )
return m_exprComponents . lhs + " " + m_exprComponents . op + " " + m_exprComponents . rhs ;
else
return m_exprComponents . lhs + " \n " + m_exprComponents . op + " \n " + m_exprComponents . rhs ;
}
else
return "{can't expand - use " + m_assertionInfo . macroName + "_FALSE( " + m_assertionInfo . capturedExpression . substr ( 1 ) + " ) instead of " + m_assertionInfo . macroName + "( " + m_assertionInfo . capturedExpression + " ) for better diagnostics}" ;
}
} // end namespace Catch
2014-06-30 07:35:36 +01:00
// #included from: catch_tag_alias_registry.hpp
#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
// #included from: catch_tag_alias_registry.h
#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
#include <map>
namespace Catch {
class TagAliasRegistry : public ITagAliasRegistry {
public :
virtual ~ TagAliasRegistry ();
virtual Option < TagAlias > find ( std :: string const & alias ) const ;
virtual std :: string expandAliases ( std :: string const & unexpandedTestSpec ) const ;
void add ( char const * alias , char const * tag , SourceLineInfo const & lineInfo );
static TagAliasRegistry & get ();
private :
std :: map < std :: string , TagAlias > m_registry ;
};
} // end namespace Catch
#include <map>
#include <iostream>
namespace Catch {
TagAliasRegistry ::~ TagAliasRegistry () {}
Option < TagAlias > TagAliasRegistry :: find ( std :: string const & alias ) const {
std :: map < std :: string , TagAlias >:: const_iterator it = m_registry . find ( alias );
if ( it != m_registry . end () )
return it -> second ;
else
return Option < TagAlias > ();
}
std :: string TagAliasRegistry :: expandAliases ( std :: string const & unexpandedTestSpec ) const {
std :: string expandedTestSpec = unexpandedTestSpec ;
for ( std :: map < std :: string , TagAlias >:: const_iterator it = m_registry . begin (), itEnd = m_registry . end ();
it != itEnd ;
++ it ) {
std :: size_t pos = expandedTestSpec . find ( it -> first );
if ( pos != std :: string :: npos ) {
expandedTestSpec = expandedTestSpec . substr ( 0 , pos ) +
it -> second . tag +
expandedTestSpec . substr ( pos + it -> first . size () );
}
}
return expandedTestSpec ;
}
void TagAliasRegistry :: add ( char const * alias , char const * tag , SourceLineInfo const & lineInfo ) {
if ( ! startsWith ( alias , "[@" ) || ! endsWith ( alias , "]" ) ) {
std :: ostringstream oss ;
oss << "error: tag alias, \" " << alias << " \" is not of the form [@alias name]. \n " << lineInfo ;
throw std :: domain_error ( oss . str (). c_str () );
}
if ( ! m_registry . insert ( std :: make_pair ( alias , TagAlias ( tag , lineInfo ) ) ). second ) {
std :: ostringstream oss ;
oss << "error: tag alias, \" " << alias << " \" already registered. \n "
<< " \t First seen at " << find ( alias ) -> lineInfo << " \n "
<< " \t Redefined at " << lineInfo ;
throw std :: domain_error ( oss . str (). c_str () );
}
}
TagAliasRegistry & TagAliasRegistry :: get () {
static TagAliasRegistry instance ;
return instance ;
}
ITagAliasRegistry ::~ ITagAliasRegistry () {}
ITagAliasRegistry const & ITagAliasRegistry :: get () { return TagAliasRegistry :: get (); }
RegistrarForTagAliases :: RegistrarForTagAliases ( char const * alias , char const * tag , SourceLineInfo const & lineInfo ) {
try {
TagAliasRegistry :: get (). add ( alias , tag , lineInfo );
}
catch ( std :: exception & ex ) {
Colour colourGuard ( Colour :: Red );
2014-10-02 19:08:19 +01:00
Catch :: cerr () << ex . what () << std :: endl ;
2014-06-30 07:35:36 +01:00
exit ( 1 );
}
}
} // end namespace Catch
2015-08-07 17:30:34 +01:00
// #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
2013-08-15 19:09:07 +01:00
// #included from: ../reporters/catch_reporter_xml.hpp
#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
2012-08-23 20:08:50 +01:00
2013-12-03 18:53:55 +00:00
// #included from: catch_reporter_bases.hpp
#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
2014-12-22 07:42:57 +00:00
#include <cstring>
2013-12-03 18:53:55 +00:00
namespace Catch {
struct StreamingReporterBase : SharedImpl < IStreamingReporter > {
StreamingReporterBase ( ReporterConfig const & _config )
: m_config ( _config . fullConfig () ),
stream ( _config . stream () )
2015-08-07 17:30:34 +01:00
{
m_reporterPrefs . shouldRedirectStdOut = false ;
}
2013-12-03 18:53:55 +00:00
2015-08-07 17:30:34 +01:00
virtual ReporterPreferences getPreferences () const CATCH_OVERRIDE {
return m_reporterPrefs ;
}
2013-12-03 18:53:55 +00:00
2015-08-07 17:30:34 +01:00
virtual ~ StreamingReporterBase () CATCH_OVERRIDE ;
2013-12-03 18:53:55 +00:00
2015-08-07 17:30:34 +01:00
virtual void noMatchingTestCases ( std :: string const & ) CATCH_OVERRIDE {}
virtual void testRunStarting ( TestRunInfo const & _testRunInfo ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
currentTestRunInfo = _testRunInfo ;
}
2015-08-07 17:30:34 +01:00
virtual void testGroupStarting ( GroupInfo const & _groupInfo ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
currentGroupInfo = _groupInfo ;
}
2015-08-07 17:30:34 +01:00
virtual void testCaseStarting ( TestCaseInfo const & _testInfo ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
currentTestCaseInfo = _testInfo ;
}
2015-08-07 17:30:34 +01:00
virtual void sectionStarting ( SectionInfo const & _sectionInfo ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
m_sectionStack . push_back ( _sectionInfo );
}
2015-08-07 17:30:34 +01:00
virtual void sectionEnded ( SectionStats const & /* _sectionStats */ ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
m_sectionStack . pop_back ();
}
2015-08-07 17:30:34 +01:00
virtual void testCaseEnded ( TestCaseStats const & /* _testCaseStats */ ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
currentTestCaseInfo . reset ();
}
2015-08-07 17:30:34 +01:00
virtual void testGroupEnded ( TestGroupStats const & /* _testGroupStats */ ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
currentGroupInfo . reset ();
}
2015-08-07 17:30:34 +01:00
virtual void testRunEnded ( TestRunStats const & /* _testRunStats */ ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
currentTestCaseInfo . reset ();
currentGroupInfo . reset ();
currentTestRunInfo . reset ();
}
2015-08-07 17:30:34 +01:00
virtual void skipTest ( TestCaseInfo const & ) CATCH_OVERRIDE {
2014-12-22 20:18:05 +00:00
// Don't do anything with this by default.
// It can optionally be overridden in the derived class.
}
2013-12-03 18:53:55 +00:00
Ptr < IConfig > m_config ;
std :: ostream & stream ;
LazyStat < TestRunInfo > currentTestRunInfo ;
LazyStat < GroupInfo > currentGroupInfo ;
LazyStat < TestCaseInfo > currentTestCaseInfo ;
std :: vector < SectionInfo > m_sectionStack ;
2015-08-07 17:30:34 +01:00
ReporterPreferences m_reporterPrefs ;
2013-12-03 18:53:55 +00:00
};
struct CumulativeReporterBase : SharedImpl < IStreamingReporter > {
template < typename T , typename ChildNodeT >
struct Node : SharedImpl <> {
explicit Node ( T const & _value ) : value ( _value ) {}
virtual ~ Node () {}
typedef std :: vector < Ptr < ChildNodeT > > ChildNodes ;
T value ;
ChildNodes children ;
};
struct SectionNode : SharedImpl <> {
explicit SectionNode ( SectionStats const & _stats ) : stats ( _stats ) {}
virtual ~ SectionNode ();
bool operator == ( SectionNode const & other ) const {
return stats . sectionInfo . lineInfo == other . stats . sectionInfo . lineInfo ;
}
bool operator == ( Ptr < SectionNode > const & other ) const {
return operator == ( * other );
}
SectionStats stats ;
typedef std :: vector < Ptr < SectionNode > > ChildSections ;
typedef std :: vector < AssertionStats > Assertions ;
ChildSections childSections ;
Assertions assertions ;
std :: string stdOut ;
std :: string stdErr ;
};
2013-12-18 08:38:33 +00:00
struct BySectionInfo {
BySectionInfo ( SectionInfo const & other ) : m_other ( other ) {}
2014-05-20 18:50:59 +01:00
BySectionInfo ( BySectionInfo const & other ) : m_other ( other . m_other ) {}
2013-12-18 08:38:33 +00:00
bool operator () ( Ptr < SectionNode > const & node ) const {
return node -> stats . sectionInfo . lineInfo == m_other . lineInfo ;
}
private :
2014-05-20 18:50:59 +01:00
void operator = ( BySectionInfo const & );
2013-12-18 08:38:33 +00:00
SectionInfo const & m_other ;
};
2013-12-03 18:53:55 +00:00
typedef Node < TestCaseStats , SectionNode > TestCaseNode ;
typedef Node < TestGroupStats , TestCaseNode > TestGroupNode ;
typedef Node < TestRunStats , TestGroupNode > TestRunNode ;
CumulativeReporterBase ( ReporterConfig const & _config )
: m_config ( _config . fullConfig () ),
stream ( _config . stream () )
2015-08-07 17:30:34 +01:00
{
m_reporterPrefs . shouldRedirectStdOut = false ;
}
2013-12-03 18:53:55 +00:00
~ CumulativeReporterBase ();
2015-08-07 17:30:34 +01:00
virtual ReporterPreferences getPreferences () const CATCH_OVERRIDE {
return m_reporterPrefs ;
}
2013-12-03 18:53:55 +00:00
2015-08-07 17:30:34 +01:00
virtual void testRunStarting ( TestRunInfo const & ) CATCH_OVERRIDE {}
virtual void testGroupStarting ( GroupInfo const & ) CATCH_OVERRIDE {}
2013-12-03 18:53:55 +00:00
2015-08-07 17:30:34 +01:00
virtual void testCaseStarting ( TestCaseInfo const & ) CATCH_OVERRIDE {}
virtual void sectionStarting ( SectionInfo const & sectionInfo ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
SectionStats incompleteStats ( sectionInfo , Counts (), 0 , false );
Ptr < SectionNode > node ;
if ( m_sectionStack . empty () ) {
if ( ! m_rootSection )
m_rootSection = new SectionNode ( incompleteStats );
node = m_rootSection ;
}
else {
SectionNode & parentNode = * m_sectionStack . back ();
SectionNode :: ChildSections :: const_iterator it =
2013-12-18 08:38:33 +00:00
std :: find_if ( parentNode . childSections . begin (),
parentNode . childSections . end (),
BySectionInfo ( sectionInfo ) );
2013-12-03 18:53:55 +00:00
if ( it == parentNode . childSections . end () ) {
node = new SectionNode ( incompleteStats );
parentNode . childSections . push_back ( node );
}
else
node = * it ;
}
m_sectionStack . push_back ( node );
m_deepestSection = node ;
}
2015-08-07 17:30:34 +01:00
virtual void assertionStarting ( AssertionInfo const & ) CATCH_OVERRIDE {}
2013-12-03 18:53:55 +00:00
virtual bool assertionEnded ( AssertionStats const & assertionStats ) {
assert ( ! m_sectionStack . empty () );
SectionNode & sectionNode = * m_sectionStack . back ();
sectionNode . assertions . push_back ( assertionStats );
return true ;
}
2015-08-07 17:30:34 +01:00
virtual void sectionEnded ( SectionStats const & sectionStats ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
assert ( ! m_sectionStack . empty () );
SectionNode & node = * m_sectionStack . back ();
node . stats = sectionStats ;
m_sectionStack . pop_back ();
}
2015-08-07 17:30:34 +01:00
virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
Ptr < TestCaseNode > node = new TestCaseNode ( testCaseStats );
assert ( m_sectionStack . size () == 0 );
node -> children . push_back ( m_rootSection );
m_testCases . push_back ( node );
m_rootSection . reset ();
assert ( m_deepestSection );
m_deepestSection -> stdOut = testCaseStats . stdOut ;
m_deepestSection -> stdErr = testCaseStats . stdErr ;
}
2015-08-07 17:30:34 +01:00
virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
Ptr < TestGroupNode > node = new TestGroupNode ( testGroupStats );
node -> children . swap ( m_testCases );
m_testGroups . push_back ( node );
}
2015-08-07 17:30:34 +01:00
virtual void testRunEnded ( TestRunStats const & testRunStats ) CATCH_OVERRIDE {
2013-12-03 18:53:55 +00:00
Ptr < TestRunNode > node = new TestRunNode ( testRunStats );
node -> children . swap ( m_testGroups );
m_testRuns . push_back ( node );
2013-12-11 08:28:15 +00:00
testRunEndedCumulative ();
2013-12-03 18:53:55 +00:00
}
2013-12-11 08:28:15 +00:00
virtual void testRunEndedCumulative () = 0 ;
2013-12-03 18:53:55 +00:00
2015-08-07 17:30:34 +01:00
virtual void skipTest ( TestCaseInfo const & ) CATCH_OVERRIDE {}
2014-12-22 20:18:05 +00:00
2013-12-03 18:53:55 +00:00
Ptr < IConfig > m_config ;
std :: ostream & stream ;
std :: vector < AssertionStats > m_assertions ;
std :: vector < std :: vector < Ptr < SectionNode > > > m_sections ;
std :: vector < Ptr < TestCaseNode > > m_testCases ;
std :: vector < Ptr < TestGroupNode > > m_testGroups ;
std :: vector < Ptr < TestRunNode > > m_testRuns ;
Ptr < SectionNode > m_rootSection ;
Ptr < SectionNode > m_deepestSection ;
std :: vector < Ptr < SectionNode > > m_sectionStack ;
2015-08-07 17:30:34 +01:00
ReporterPreferences m_reporterPrefs ;
2013-12-03 18:53:55 +00:00
};
2014-12-21 00:21:23 +00:00
template < char C >
char const * getLineOfChars () {
static char line [ CATCH_CONFIG_CONSOLE_WIDTH ] = { 0 };
if ( !* line ) {
memset ( line , C , CATCH_CONFIG_CONSOLE_WIDTH - 1 );
line [ CATCH_CONFIG_CONSOLE_WIDTH - 1 ] = 0 ;
}
return line ;
}
2015-08-07 17:30:34 +01:00
struct TestEventListenerBase : StreamingReporterBase {
TestEventListenerBase ( ReporterConfig const & _config )
: StreamingReporterBase ( _config )
{}
virtual void assertionStarting ( AssertionInfo const & ) CATCH_OVERRIDE {}
virtual bool assertionEnded ( AssertionStats const & _assertionStats ) CATCH_OVERRIDE {
return false ;
}
};
2013-12-03 18:53:55 +00:00
} // end namespace Catch
2012-08-23 20:08:50 +01:00
// #included from: ../internal/catch_reporter_registrars.hpp
#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
namespace Catch {
2012-12-01 23:57:18 +00:00
template < typename T >
class LegacyReporterRegistrar {
class ReporterFactory : public IReporterFactory {
2013-04-24 19:10:02 +01:00
virtual IStreamingReporter * create ( ReporterConfig const & config ) const {
2013-06-07 19:07:50 +01:00
return new LegacyReporterAdapter ( new T ( config ) );
2012-12-01 23:57:18 +00:00
}
virtual std :: string getDescription () const {
return T :: getDescription ();
}
};
public :
2013-04-24 19:10:02 +01:00
LegacyReporterRegistrar ( std :: string const & name ) {
2012-12-01 23:57:18 +00:00
getMutableRegistryHub (). registerReporter ( name , new ReporterFactory () );
}
};
2012-08-23 20:08:50 +01:00
template < typename T >
class ReporterRegistrar {
2015-08-07 17:30:34 +01:00
class ReporterFactory : public SharedImpl < IReporterFactory > {
2012-08-23 20:08:50 +01:00
2012-12-01 23:57:18 +00:00
// *** Please Note ***:
// - If you end up here looking at a compiler error because it's trying to register
// your custom reporter class be aware that the native reporter interface has changed
// to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
// an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
// However please consider updating to the new interface as the old one is now
// deprecated and will probably be removed quite soon!
// Please contact me via github if you have any questions at all about this.
// In fact, ideally, please contact me anyway to let me know you've hit this - as I have
// no idea who is actually using custom reporters at all (possibly no-one!).
// The new interface is designed to minimise exposure to interface changes in the future.
2013-04-24 19:10:02 +01:00
virtual IStreamingReporter * create ( ReporterConfig const & config ) const {
2012-08-23 20:08:50 +01:00
return new T ( config );
}
virtual std :: string getDescription () const {
return T :: getDescription ();
}
};
public :
2013-04-24 19:10:02 +01:00
ReporterRegistrar ( std :: string const & name ) {
2012-08-23 20:08:50 +01:00
getMutableRegistryHub (). registerReporter ( name , new ReporterFactory () );
}
};
2015-08-07 17:30:34 +01:00
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 () );
}
};
2012-08-23 20:08:50 +01:00
}
2012-12-01 23:57:18 +00:00
#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
2013-10-17 22:45:21 +01:00
namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
2015-08-07 17:30:34 +01:00
2012-08-23 20:08:50 +01:00
#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
2013-10-17 22:45:21 +01:00
namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
2012-08-23 20:08:50 +01:00
2015-08-07 17:30:34 +01:00
#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
2012-08-23 20:08:50 +01:00
// #included from: ../internal/catch_xmlwriter.hpp
#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
#include <sstream>
#include <string>
#include <vector>
2015-07-23 23:06:26 +01:00
#include <iomanip>
2012-08-23 20:08:50 +01:00
namespace Catch {
2015-07-23 23:06:26 +01:00
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 << "<" ; break ;
case '&' : os << "&" ; break ;
case '>' :
// See: http://www.w3.org/TR/xml/#syntax
if ( i > 2 && m_str [ i - 1 ] == ']' && m_str [ i - 2 ] == ']' )
os << ">" ;
else
os << c ;
break ;
case '\"' :
if ( m_forWhat == ForAttributes )
os << """ ;
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 ;
};
2012-08-23 20:08:50 +01:00
class XmlWriter {
public :
class ScopedElement {
public :
ScopedElement ( XmlWriter * writer )
: m_writer ( writer )
{}
2013-04-24 19:10:02 +01:00
ScopedElement ( ScopedElement const & other )
2012-08-23 20:08:50 +01:00
: m_writer ( other . m_writer ){
2015-07-02 08:21:38 +01:00
other . m_writer = CATCH_NULL ;
2012-08-23 20:08:50 +01:00
}
~ ScopedElement () {
if ( m_writer )
m_writer -> endElement ();
}
2013-04-24 19:10:02 +01:00
ScopedElement & writeText ( std :: string const & text , bool indent = true ) {
2012-12-01 23:57:18 +00:00
m_writer -> writeText ( text , indent );
2012-08-23 20:08:50 +01:00
return * this ;
}
template < typename T >
2013-04-24 19:10:02 +01:00
ScopedElement & writeAttribute ( std :: string const & name , T const & attribute ) {
2012-08-23 20:08:50 +01:00
m_writer -> writeAttribute ( name , attribute );
return * this ;
}
private :
mutable XmlWriter * m_writer ;
};
XmlWriter ()
: m_tagIsOpen ( false ),
m_needsNewline ( false ),
2014-10-02 19:08:19 +01:00
m_os ( & Catch :: cout () )
2012-08-23 20:08:50 +01:00
{}
XmlWriter ( std :: ostream & os )
: m_tagIsOpen ( false ),
m_needsNewline ( false ),
m_os ( & os )
{}
~ XmlWriter () {
while ( ! m_tags . empty () )
endElement ();
}
2013-04-24 19:10:02 +01:00
XmlWriter & startElement ( std :: string const & name ) {
2012-08-23 20:08:50 +01:00
ensureTagClosed ();
newlineIfNecessary ();
stream () << m_indent << "<" << name ;
m_tags . push_back ( name );
m_indent += " " ;
m_tagIsOpen = true ;
return * this ;
}
2013-04-24 19:10:02 +01:00
ScopedElement scopedElement ( std :: string const & name ) {
2012-08-23 20:08:50 +01:00
ScopedElement scoped ( this );
startElement ( name );
return scoped ;
}
XmlWriter & endElement () {
newlineIfNecessary ();
m_indent = m_indent . substr ( 0 , m_indent . size () - 2 );
if ( m_tagIsOpen ) {
stream () << "/> \n " ;
m_tagIsOpen = false ;
}
else {
stream () << m_indent << "</" << m_tags . back () << "> \n " ;
}
m_tags . pop_back ();
return * this ;
}
2013-04-24 19:10:02 +01:00
XmlWriter & writeAttribute ( std :: string const & name , std :: string const & attribute ) {
2015-07-23 23:06:26 +01:00
if ( ! name . empty () && ! attribute . empty () )
stream () << " " << name << "= \" " << XmlEncode ( attribute , XmlEncode :: ForAttributes ) << " \" " ;
2012-08-23 20:08:50 +01:00
return * this ;
}
2013-04-24 19:10:02 +01:00
XmlWriter & writeAttribute ( std :: string const & name , bool attribute ) {
2012-08-23 20:08:50 +01:00
stream () << " " << name << "= \" " << ( attribute ? "true" : "false" ) << " \" " ;
return * this ;
}
template < typename T >
2013-04-24 19:10:02 +01:00
XmlWriter & writeAttribute ( std :: string const & name , T const & attribute ) {
2015-07-23 23:06:26 +01:00
std :: ostringstream oss ;
oss << attribute ;
return writeAttribute ( name , oss . str () );
2012-08-23 20:08:50 +01:00
}
2013-04-24 19:10:02 +01:00
XmlWriter & writeText ( std :: string const & text , bool indent = true ) {
2012-08-23 20:08:50 +01:00
if ( ! text . empty () ){
bool tagWasOpen = m_tagIsOpen ;
ensureTagClosed ();
2012-12-01 23:57:18 +00:00
if ( tagWasOpen && indent )
2012-08-23 20:08:50 +01:00
stream () << m_indent ;
2015-07-23 23:06:26 +01:00
stream () << XmlEncode ( text );
2012-08-23 20:08:50 +01:00
m_needsNewline = true ;
}
return * this ;
}
2013-04-24 19:10:02 +01:00
XmlWriter & writeComment ( std :: string const & text ) {
2012-08-23 20:08:50 +01:00
ensureTagClosed ();
stream () << m_indent << "<!--" << text << "-->" ;
m_needsNewline = true ;
return * this ;
}
XmlWriter & writeBlankLine () {
ensureTagClosed ();
stream () << " \n " ;
return * this ;
}
2014-05-20 18:50:59 +01:00
void setStream ( std :: ostream & os ) {
m_os = & os ;
}
2012-08-23 20:08:50 +01:00
private :
2014-05-20 18:50:59 +01:00
XmlWriter ( XmlWriter const & );
void operator = ( XmlWriter const & );
2012-08-23 20:08:50 +01:00
std :: ostream & stream () {
return * m_os ;
}
void ensureTagClosed () {
if ( m_tagIsOpen ) {
stream () << "> \n " ;
m_tagIsOpen = false ;
}
}
void newlineIfNecessary () {
if ( m_needsNewline ) {
stream () << " \n " ;
m_needsNewline = false ;
}
}
bool m_tagIsOpen ;
bool m_needsNewline ;
std :: vector < std :: string > m_tags ;
std :: string m_indent ;
std :: ostream * m_os ;
};
}
2015-07-23 23:06:26 +01:00
// #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
2012-08-23 20:08:50 +01:00
namespace Catch {
2014-12-30 18:26:07 +00:00
class XmlReporter : public StreamingReporterBase {
2012-08-23 20:08:50 +01:00
public :
2014-12-30 18:26:07 +00:00
XmlReporter ( ReporterConfig const & _config )
: StreamingReporterBase ( _config ),
m_sectionDepth ( 0 )
2015-08-07 17:30:34 +01:00
{
m_reporterPrefs . shouldRedirectStdOut = true ;
}
2014-12-30 18:26:07 +00:00
2015-08-07 17:30:34 +01:00
virtual ~ XmlReporter () CATCH_OVERRIDE ;
2012-08-23 20:08:50 +01:00
static std :: string getDescription () {
return "Reports test results as an XML document" ;
}
2014-12-30 18:26:07 +00:00
public : // StreamingReporterBase
2012-08-23 20:08:50 +01:00
2015-08-07 17:30:34 +01:00
virtual void noMatchingTestCases ( std :: string const & s ) CATCH_OVERRIDE {
2014-12-30 18:26:07 +00:00
StreamingReporterBase :: noMatchingTestCases ( s );
}
2015-08-07 17:30:34 +01:00
virtual void testRunStarting ( TestRunInfo const & testInfo ) CATCH_OVERRIDE {
2014-12-30 18:26:07 +00:00
StreamingReporterBase :: testRunStarting ( testInfo );
m_xml . setStream ( stream );
2012-08-23 20:08:50 +01:00
m_xml . startElement ( "Catch" );
2014-12-30 18:26:07 +00:00
if ( ! m_config -> name (). empty () )
m_xml . writeAttribute ( "name" , m_config -> name () );
2012-08-23 20:08:50 +01:00
}
2015-08-07 17:30:34 +01:00
virtual void testGroupStarting ( GroupInfo const & groupInfo ) CATCH_OVERRIDE {
2014-12-30 18:26:07 +00:00
StreamingReporterBase :: testGroupStarting ( groupInfo );
2012-08-23 20:08:50 +01:00
m_xml . startElement ( "Group" )
2014-12-30 18:26:07 +00:00
. writeAttribute ( "name" , groupInfo . name );
2012-08-23 20:08:50 +01:00
}
2015-08-07 17:30:34 +01:00
virtual void testCaseStarting ( TestCaseInfo const & testInfo ) CATCH_OVERRIDE {
2014-12-30 18:26:07 +00:00
StreamingReporterBase :: testCaseStarting ( testInfo );
m_xml . startElement ( "TestCase" ). writeAttribute ( "name" , trim ( testInfo . name ) );
if ( m_config -> showDurations () == ShowDurations :: Always )
m_testCaseTimer . start ();
2012-08-23 20:08:50 +01:00
}
2015-08-07 17:30:34 +01:00
virtual void sectionStarting ( SectionInfo const & sectionInfo ) CATCH_OVERRIDE {
2014-12-30 18:26:07 +00:00
StreamingReporterBase :: sectionStarting ( sectionInfo );
2013-07-25 08:12:03 +01:00
if ( m_sectionDepth ++ > 0 ) {
m_xml . startElement ( "Section" )
2014-12-30 18:26:07 +00:00
. writeAttribute ( "name" , trim ( sectionInfo . name ) )
. writeAttribute ( "description" , sectionInfo . description );
2013-07-25 08:12:03 +01:00
}
2012-08-23 20:08:50 +01:00
}
2015-08-07 17:30:34 +01:00
virtual void assertionStarting ( AssertionInfo const & ) CATCH_OVERRIDE { }
2012-08-23 20:08:50 +01:00
2015-08-07 17:30:34 +01:00
virtual bool assertionEnded ( AssertionStats const & assertionStats ) CATCH_OVERRIDE {
2014-12-30 18:26:07 +00:00
const AssertionResult & assertionResult = assertionStats . assertionResult ;
2012-08-23 20:08:50 +01:00
2014-12-30 18:26:07 +00:00
// Print any info messages in <Info> tags.
if ( assertionStats . assertionResult . getResultType () != ResultWas :: Ok ) {
for ( std :: vector < MessageInfo >:: const_iterator it = assertionStats . infoMessages . begin (), itEnd = assertionStats . infoMessages . end ();
it != itEnd ;
++ it ) {
if ( it -> type == ResultWas :: Info ) {
m_xml . scopedElement ( "Info" )
. writeText ( it -> message );
} else if ( it -> type == ResultWas :: Warning ) {
m_xml . scopedElement ( "Warning" )
. writeText ( it -> message );
}
}
}
// Drop out if result was successful but we're not printing them.
if ( ! m_config -> includeSuccessfulResults () && isOk ( assertionResult . getResultType ()) )
return true ;
// Print the expression if there is one.
2012-11-01 08:27:09 +00:00
if ( assertionResult . hasExpression () ) {
2012-08-23 20:08:50 +01:00
m_xml . startElement ( "Expression" )
2012-11-13 22:04:29 +00:00
. writeAttribute ( "success" , assertionResult . succeeded () )
2014-12-30 18:26:07 +00:00
. writeAttribute ( "type" , assertionResult . getTestMacroName () )
2012-11-01 08:27:09 +00:00
. writeAttribute ( "filename" , assertionResult . getSourceInfo (). file )
. writeAttribute ( "line" , assertionResult . getSourceInfo (). line );
2012-08-23 20:08:50 +01:00
m_xml . scopedElement ( "Original" )
2012-11-01 08:27:09 +00:00
. writeText ( assertionResult . getExpression () );
2012-08-23 20:08:50 +01:00
m_xml . scopedElement ( "Expanded" )
2012-11-01 08:27:09 +00:00
. writeText ( assertionResult . getExpandedExpression () );
2012-08-23 20:08:50 +01:00
}
2014-12-30 18:26:07 +00:00
// And... Print a result applicable to each result type.
2012-11-01 08:27:09 +00:00
switch ( assertionResult . getResultType () ) {
2012-08-23 20:08:50 +01:00
case ResultWas :: ThrewException :
m_xml . scopedElement ( "Exception" )
2012-11-01 08:27:09 +00:00
. writeAttribute ( "filename" , assertionResult . getSourceInfo (). file )
. writeAttribute ( "line" , assertionResult . getSourceInfo (). line )
. writeText ( assertionResult . getMessage () );
2012-08-23 20:08:50 +01:00
break ;
2014-08-22 19:35:41 +01:00
case ResultWas :: FatalErrorCondition :
m_xml . scopedElement ( "Fatal Error Condition" )
. writeAttribute ( "filename" , assertionResult . getSourceInfo (). file )
. writeAttribute ( "line" , assertionResult . getSourceInfo (). line )
. writeText ( assertionResult . getMessage () );
break ;
2012-08-23 20:08:50 +01:00
case ResultWas :: Info :
m_xml . scopedElement ( "Info" )
2012-11-01 08:27:09 +00:00
. writeText ( assertionResult . getMessage () );
2012-08-23 20:08:50 +01:00
break ;
case ResultWas :: Warning :
2014-12-30 18:26:07 +00:00
// Warning will already have been written
2012-08-23 20:08:50 +01:00
break ;
case ResultWas :: ExplicitFailure :
m_xml . scopedElement ( "Failure" )
2012-11-01 08:27:09 +00:00
. writeText ( assertionResult . getMessage () );
2012-08-23 20:08:50 +01:00
break ;
2014-12-30 18:26:07 +00:00
default :
2012-08-23 20:08:50 +01:00
break ;
}
2014-12-30 18:26:07 +00:00
2012-11-01 08:27:09 +00:00
if ( assertionResult . hasExpression () )
2012-08-23 20:08:50 +01:00
m_xml . endElement ();
2014-12-30 18:26:07 +00:00
return true ;
2012-08-23 20:08:50 +01:00
}
2015-08-07 17:30:34 +01:00
virtual void sectionEnded ( SectionStats const & sectionStats ) CATCH_OVERRIDE {
2014-12-30 18:26:07 +00:00
StreamingReporterBase :: sectionEnded ( sectionStats );
if ( -- m_sectionDepth > 0 ) {
XmlWriter :: ScopedElement e = m_xml . scopedElement ( "OverallResults" );
e . writeAttribute ( "successes" , sectionStats . assertions . passed );
e . writeAttribute ( "failures" , sectionStats . assertions . failed );
e . writeAttribute ( "expectedFailures" , sectionStats . assertions . failedButOk );
if ( m_config -> showDurations () == ShowDurations :: Always )
e . writeAttribute ( "durationInSeconds" , sectionStats . durationInSeconds );
m_xml . endElement ();
}
2012-08-23 20:08:50 +01:00
}
2015-08-07 17:30:34 +01:00
virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) CATCH_OVERRIDE {
2014-12-30 18:26:07 +00:00
StreamingReporterBase :: testCaseEnded ( testCaseStats );
XmlWriter :: ScopedElement e = m_xml . scopedElement ( "OverallResult" );
e . writeAttribute ( "success" , testCaseStats . totals . assertions . allOk () );
if ( m_config -> showDurations () == ShowDurations :: Always )
e . writeAttribute ( "durationInSeconds" , m_testCaseTimer . getElapsedSeconds () );
m_xml . endElement ();
}
2015-08-07 17:30:34 +01:00
virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) CATCH_OVERRIDE {
2014-12-30 18:26:07 +00:00
StreamingReporterBase :: testGroupEnded ( testGroupStats );
// TODO: Check testGroupStats.aborting and act accordingly.
m_xml . scopedElement ( "OverallResults" )
. writeAttribute ( "successes" , testGroupStats . totals . assertions . passed )
. writeAttribute ( "failures" , testGroupStats . totals . assertions . failed )
. writeAttribute ( "expectedFailures" , testGroupStats . totals . assertions . failedButOk );
m_xml . endElement ();
}
2015-08-07 17:30:34 +01:00
virtual void testRunEnded ( TestRunStats const & testRunStats ) CATCH_OVERRIDE {
2014-12-30 18:26:07 +00:00
StreamingReporterBase :: testRunEnded ( testRunStats );
m_xml . scopedElement ( "OverallResults" )
. writeAttribute ( "successes" , testRunStats . totals . assertions . passed )
. writeAttribute ( "failures" , testRunStats . totals . assertions . failed )
. writeAttribute ( "expectedFailures" , testRunStats . totals . assertions . failedButOk );
2012-08-23 20:08:50 +01:00
m_xml . endElement ();
}
private :
2014-12-30 18:26:07 +00:00
Timer m_testCaseTimer ;
2012-08-23 20:08:50 +01:00
XmlWriter m_xml ;
2013-07-25 08:12:03 +01:00
int m_sectionDepth ;
2012-08-23 20:08:50 +01:00
};
2014-12-30 18:26:07 +00:00
INTERNAL_CATCH_REGISTER_REPORTER ( "xml" , XmlReporter )
2012-08-23 20:08:50 +01:00
} // end namespace Catch
// #included from: ../reporters/catch_reporter_junit.hpp
#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
2012-12-02 00:05:51 +00:00
#include <assert.h>
2012-08-23 20:08:50 +01:00
namespace Catch {
2013-08-15 19:01:00 +01:00
class JunitReporter : public CumulativeReporterBase {
2012-08-23 20:08:50 +01:00
public :
2013-08-15 19:01:00 +01:00
JunitReporter ( ReporterConfig const & _config )
: CumulativeReporterBase ( _config ),
xml ( _config . stream () )
2015-08-07 17:30:34 +01:00
{
m_reporterPrefs . shouldRedirectStdOut = true ;
}
2013-08-15 19:01:00 +01:00
2015-08-07 17:30:34 +01:00
virtual ~ JunitReporter () CATCH_OVERRIDE ;
2012-08-23 20:08:50 +01:00
static std :: string getDescription () {
return "Reports test results in an XML format that looks like Ant's junitreport target" ;
}
2015-08-07 17:30:34 +01:00
virtual void noMatchingTestCases ( std :: string const & /*spec*/ ) CATCH_OVERRIDE {}
2012-08-23 20:08:50 +01:00
2015-08-07 17:30:34 +01:00
virtual void testRunStarting ( TestRunInfo const & runInfo ) CATCH_OVERRIDE {
2013-08-15 19:01:00 +01:00
CumulativeReporterBase :: testRunStarting ( runInfo );
xml . startElement ( "testsuites" );
}
2012-08-23 20:08:50 +01:00
2015-08-07 17:30:34 +01:00
virtual void testGroupStarting ( GroupInfo const & groupInfo ) CATCH_OVERRIDE {
2013-08-15 19:01:00 +01:00
suiteTimer . start ();
stdOutForSuite . str ( "" );
stdErrForSuite . str ( "" );
unexpectedExceptions = 0 ;
CumulativeReporterBase :: testGroupStarting ( groupInfo );
}
2015-08-07 17:30:34 +01:00
virtual bool assertionEnded ( AssertionStats const & assertionStats ) CATCH_OVERRIDE {
2013-08-15 19:01:00 +01:00
if ( assertionStats . assertionResult . getResultType () == ResultWas :: ThrewException )
unexpectedExceptions ++ ;
return CumulativeReporterBase :: assertionEnded ( assertionStats );
}
2015-08-07 17:30:34 +01:00
virtual void testCaseEnded ( TestCaseStats const & testCaseStats ) CATCH_OVERRIDE {
2013-08-15 19:01:00 +01:00
stdOutForSuite << testCaseStats . stdOut ;
stdErrForSuite << testCaseStats . stdErr ;
CumulativeReporterBase :: testCaseEnded ( testCaseStats );
}
2015-08-07 17:30:34 +01:00
virtual void testGroupEnded ( TestGroupStats const & testGroupStats ) CATCH_OVERRIDE {
2013-08-15 19:01:00 +01:00
double suiteTime = suiteTimer . getElapsedSeconds ();
CumulativeReporterBase :: testGroupEnded ( testGroupStats );
writeGroup ( * m_testGroups . back (), suiteTime );
}
2015-08-07 17:30:34 +01:00
virtual void testRunEndedCumulative () CATCH_OVERRIDE {
2013-08-15 19:01:00 +01:00
xml . endElement ();
}
void writeGroup ( TestGroupNode const & groupNode , double suiteTime ) {
XmlWriter :: ScopedElement e = xml . scopedElement ( "testsuite" );
TestGroupStats const & stats = groupNode . value ;
xml . writeAttribute ( "name" , stats . groupInfo . name );
xml . writeAttribute ( "errors" , unexpectedExceptions );
xml . writeAttribute ( "failures" , stats . totals . assertions . failed - unexpectedExceptions );
xml . writeAttribute ( "tests" , stats . totals . assertions . total () );
xml . writeAttribute ( "hostname" , "tbd" ); // !TBD
if ( m_config -> showDurations () == ShowDurations :: Never )
xml . writeAttribute ( "time" , "" );
2012-11-16 08:47:03 +00:00
else
2013-08-15 19:01:00 +01:00
xml . writeAttribute ( "time" , suiteTime );
xml . writeAttribute ( "timestamp" , "tbd" ); // !TBD
// Write test cases
for ( TestGroupNode :: ChildNodes :: const_iterator
it = groupNode . children . begin (), itEnd = groupNode . children . end ();
it != itEnd ;
++ it )
writeTestCase ( ** it );
xml . scopedElement ( "system-out" ). writeText ( trim ( stdOutForSuite . str () ), false );
xml . scopedElement ( "system-err" ). writeText ( trim ( stdErrForSuite . str () ), false );
2012-08-23 20:08:50 +01:00
}
2013-08-15 19:01:00 +01:00
void writeTestCase ( TestCaseNode const & testCaseNode ) {
TestCaseStats const & stats = testCaseNode . value ;
// All test cases have exactly one section - which represents the
// test case itself. That section may have 0-n nested sections
assert ( testCaseNode . children . size () == 1 );
SectionNode const & rootSection = * testCaseNode . children . front ();
std :: string className = stats . testInfo . className ;
if ( className . empty () ) {
if ( rootSection . childSections . empty () )
className = "global" ;
}
writeSection ( className , "" , rootSection );
2012-08-23 20:08:50 +01:00
}
2013-08-15 19:01:00 +01:00
void writeSection ( std :: string const & className ,
std :: string const & rootName ,
SectionNode const & sectionNode ) {
std :: string name = trim ( sectionNode . stats . sectionInfo . name );
if ( ! rootName . empty () )
name = rootName + "/" + name ;
2012-08-23 20:08:50 +01:00
2013-08-15 19:01:00 +01:00
if ( ! sectionNode . assertions . empty () ||
! sectionNode . stdOut . empty () ||
! sectionNode . stdErr . empty () ) {
XmlWriter :: ScopedElement e = xml . scopedElement ( "testcase" );
if ( className . empty () ) {
xml . writeAttribute ( "classname" , name );
xml . writeAttribute ( "name" , "root" );
}
else {
xml . writeAttribute ( "classname" , className );
xml . writeAttribute ( "name" , name );
}
2014-12-12 08:11:18 +00:00
xml . writeAttribute ( "time" , Catch :: toString ( sectionNode . stats . durationInSeconds ) );
2012-08-31 08:10:36 +01:00
2013-08-15 19:01:00 +01:00
writeAssertions ( sectionNode );
2012-08-23 20:08:50 +01:00
2013-08-15 19:01:00 +01:00
if ( ! sectionNode . stdOut . empty () )
xml . scopedElement ( "system-out" ). writeText ( trim ( sectionNode . stdOut ), false );
if ( ! sectionNode . stdErr . empty () )
xml . scopedElement ( "system-err" ). writeText ( trim ( sectionNode . stdErr ), false );
}
for ( SectionNode :: ChildSections :: const_iterator
it = sectionNode . childSections . begin (),
itEnd = sectionNode . childSections . end ();
it != itEnd ;
++ it )
if ( className . empty () )
writeSection ( name , "" , ** it );
else
writeSection ( className , name , ** it );
2012-08-23 20:08:50 +01:00
}
2013-08-15 19:01:00 +01:00
void writeAssertions ( SectionNode const & sectionNode ) {
for ( SectionNode :: Assertions :: const_iterator
it = sectionNode . assertions . begin (), itEnd = sectionNode . assertions . end ();
it != itEnd ;
++ it )
writeAssertion ( * it );
}
void writeAssertion ( AssertionStats const & stats ) {
AssertionResult const & result = stats . assertionResult ;
if ( ! result . isOk () ) {
std :: string elementName ;
switch ( result . getResultType () ) {
2012-08-23 20:08:50 +01:00
case ResultWas :: ThrewException :
2014-08-22 19:35:41 +01:00
case ResultWas :: FatalErrorCondition :
2013-08-15 19:01:00 +01:00
elementName = "error" ;
2012-08-23 20:08:50 +01:00
break ;
case ResultWas :: ExplicitFailure :
2013-08-15 19:01:00 +01:00
elementName = "failure" ;
2012-08-23 20:08:50 +01:00
break ;
case ResultWas :: ExpressionFailed :
2013-08-15 19:01:00 +01:00
elementName = "failure" ;
2012-08-23 20:08:50 +01:00
break ;
2013-04-12 10:43:06 +01:00
case ResultWas :: DidntThrowException :
2013-08-15 19:01:00 +01:00
elementName = "failure" ;
2013-04-12 10:43:06 +01:00
break ;
2013-08-15 19:01:00 +01:00
// We should never see these here:
case ResultWas :: Info :
case ResultWas :: Warning :
case ResultWas :: Ok :
2012-08-23 20:08:50 +01:00
case ResultWas :: Unknown :
case ResultWas :: FailureBit :
case ResultWas :: Exception :
2013-08-15 19:01:00 +01:00
elementName = "internalError" ;
2012-08-23 20:08:50 +01:00
break ;
}
2013-08-15 19:01:00 +01:00
XmlWriter :: ScopedElement e = xml . scopedElement ( elementName );
xml . writeAttribute ( "message" , result . getExpandedExpression () );
xml . writeAttribute ( "type" , result . getTestMacroName () );
std :: ostringstream oss ;
if ( ! result . getMessage (). empty () )
oss << result . getMessage () << " \n " ;
for ( std :: vector < MessageInfo >:: const_iterator
it = stats . infoMessages . begin (),
itEnd = stats . infoMessages . end ();
it != itEnd ;
++ it )
if ( it -> type == ResultWas :: Info )
oss << it -> message << " \n " ;
oss << "at " << result . getSourceInfo ();
xml . writeText ( oss . str (), false );
2012-08-23 20:08:50 +01:00
}
}
2013-08-15 19:01:00 +01:00
XmlWriter xml ;
Timer suiteTimer ;
std :: ostringstream stdOutForSuite ;
std :: ostringstream stdErrForSuite ;
unsigned int unexpectedExceptions ;
2012-08-23 20:08:50 +01:00
};
2013-08-15 19:01:00 +01:00
INTERNAL_CATCH_REGISTER_REPORTER ( "junit" , JunitReporter )
2012-08-23 20:08:50 +01:00
} // end namespace Catch
2012-12-06 08:44:51 +00:00
// #included from: ../reporters/catch_reporter_console.hpp
#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
namespace Catch {
2013-01-16 09:44:43 +00:00
struct ConsoleReporter : StreamingReporterBase {
2012-12-06 08:44:51 +00:00
ConsoleReporter ( ReporterConfig const & _config )
2013-01-16 09:44:43 +00:00
: StreamingReporterBase ( _config ),
2014-07-03 19:08:44 +01:00
m_headerPrinted ( false )
2012-12-06 08:44:51 +00:00
{}
2015-08-07 17:30:34 +01:00
virtual ~ ConsoleReporter () CATCH_OVERRIDE ;
2012-12-06 08:44:51 +00:00
static std :: string getDescription () {
return "Reports test results as plain lines of text" ;
}
2015-08-07 17:30:34 +01:00
virtual void noMatchingTestCases ( std :: string const & spec ) CATCH_OVERRIDE {
2013-03-13 12:19:30 +00:00
stream << "No test cases matched '" << spec << "'" << std :: endl ;
}
2015-08-07 17:30:34 +01:00
virtual void assertionStarting ( AssertionInfo const & ) CATCH_OVERRIDE {
2012-12-06 08:44:51 +00:00
}
2012-12-10 08:54:57 +00:00
2015-08-07 17:30:34 +01:00
virtual bool assertionEnded ( AssertionStats const & _assertionStats ) CATCH_OVERRIDE {
2013-01-16 09:44:43 +00:00
AssertionResult const & result = _assertionStats . assertionResult ;
2012-12-10 08:54:57 +00:00
2013-11-13 08:10:45 +00:00
bool printInfoMessages = true ;
2012-12-10 08:54:57 +00:00
// Drop out if result was successful and we're not printing those
2013-11-13 08:10:45 +00:00
if ( ! m_config -> includeSuccessfulResults () && result . isOk () ) {
if ( result . getResultType () != ResultWas :: Warning )
return false ;
printInfoMessages = false ;
}
2012-12-10 08:54:57 +00:00
lazyPrint ();
2013-11-13 08:10:45 +00:00
AssertionPrinter printer ( stream , _assertionStats , printInfoMessages );
2013-01-26 20:18:30 +00:00
printer . print ();
2013-01-16 09:44:43 +00:00
stream << std :: endl ;
2013-06-28 17:09:57 +01:00
return true ;
2013-01-16 09:44:43 +00:00
}
2015-08-07 17:30:34 +01:00
virtual void sectionStarting ( SectionInfo const & _sectionInfo ) CATCH_OVERRIDE {
2013-03-08 09:30:25 +00:00
m_headerPrinted = false ;
2013-01-26 20:18:30 +00:00
StreamingReporterBase :: sectionStarting ( _sectionInfo );
2013-01-16 09:44:43 +00:00
}
2015-08-07 17:30:34 +01:00
virtual void sectionEnded ( SectionStats const & _sectionStats ) CATCH_OVERRIDE {
2013-01-16 09:44:43 +00:00
if ( _sectionStats . missingAssertions ) {
lazyPrint ();
2013-04-05 20:58:01 +01:00
Colour colour ( Colour :: ResultError );
2013-08-15 19:01:00 +01:00
if ( m_sectionStack . size () > 1 )
stream << " \n No assertions in section" ;
else
stream << " \n No assertions in test case" ;
stream << " '" << _sectionStats . sectionInfo . name << "' \n " << std :: endl ;
2013-01-16 09:44:43 +00:00
}
2013-08-16 19:01:32 +01:00
if ( m_headerPrinted ) {
if ( m_config -> showDurations () == ShowDurations :: Always )
stream << "Completed in " << _sectionStats . durationInSeconds << "s" << std :: endl ;
m_headerPrinted = false ;
}
2013-09-07 12:07:38 +01:00
else {
if ( m_config -> showDurations () == ShowDurations :: Always )
stream << _sectionStats . sectionInfo . name << " completed in " << _sectionStats . durationInSeconds << "s" << std :: endl ;
}
2013-01-16 09:44:43 +00:00
StreamingReporterBase :: sectionEnded ( _sectionStats );
}
2015-08-07 17:30:34 +01:00
virtual void testCaseEnded ( TestCaseStats const & _testCaseStats ) CATCH_OVERRIDE {
2013-01-16 09:44:43 +00:00
StreamingReporterBase :: testCaseEnded ( _testCaseStats );
2013-03-08 09:30:25 +00:00
m_headerPrinted = false ;
2013-01-16 09:44:43 +00:00
}
2015-08-07 17:30:34 +01:00
virtual void testGroupEnded ( TestGroupStats const & _testGroupStats ) CATCH_OVERRIDE {
2013-08-15 19:01:00 +01:00
if ( currentGroupInfo . used ) {
2013-01-16 09:44:43 +00:00
printSummaryDivider ();
stream << "Summary for group '" << _testGroupStats . groupInfo . name << "': \n " ;
printTotals ( _testGroupStats . totals );
stream << " \n " << std :: endl ;
}
StreamingReporterBase :: testGroupEnded ( _testGroupStats );
}
2015-08-07 17:30:34 +01:00
virtual void testRunEnded ( TestRunStats const & _testRunStats ) CATCH_OVERRIDE {
2014-07-03 08:11:38 +01:00
printTotalsDivider ( _testRunStats . totals );
2013-01-16 09:44:43 +00:00
printTotals ( _testRunStats . totals );
2014-07-03 08:11:38 +01:00
stream << std :: endl ;
2013-01-16 09:44:43 +00:00
StreamingReporterBase :: testRunEnded ( _testRunStats );
}
private :
2013-01-26 20:18:30 +00:00
class AssertionPrinter {
2013-07-03 08:25:11 +01:00
void operator = ( AssertionPrinter const & );
2013-01-26 20:18:30 +00:00
public :
2013-11-13 08:10:45 +00:00
AssertionPrinter ( std :: ostream & _stream , AssertionStats const & _stats , bool _printInfoMessages )
2013-01-26 20:18:30 +00:00
: stream ( _stream ),
stats ( _stats ),
result ( _stats . assertionResult ),
2013-04-05 20:58:01 +01:00
colour ( Colour :: None ),
2013-02-02 20:37:58 +00:00
message ( result . getMessage () ),
2013-11-13 08:10:45 +00:00
messages ( _stats . infoMessages ),
printInfoMessages ( _printInfoMessages )
2013-01-26 20:18:30 +00:00
{
switch ( result . getResultType () ) {
case ResultWas :: Ok :
2013-04-05 20:58:01 +01:00
colour = Colour :: Success ;
2013-01-26 20:18:30 +00:00
passOrFail = "PASSED" ;
2013-02-02 20:37:58 +00:00
//if( result.hasMessage() )
if ( _stats . infoMessages . size () == 1 )
2013-01-26 20:18:30 +00:00
messageLabel = "with message" ;
2013-02-02 20:37:58 +00:00
if ( _stats . infoMessages . size () > 1 )
messageLabel = "with messages" ;
2013-01-26 20:18:30 +00:00
break ;
case ResultWas :: ExpressionFailed :
if ( result . isOk () ) {
2013-04-05 20:58:01 +01:00
colour = Colour :: Success ;
2013-01-26 20:18:30 +00:00
passOrFail = "FAILED - but was ok" ;
}
else {
2013-04-05 20:58:01 +01:00
colour = Colour :: Error ;
2013-01-26 20:18:30 +00:00
passOrFail = "FAILED" ;
}
2013-02-02 20:37:58 +00:00
if ( _stats . infoMessages . size () == 1 )
2013-01-26 20:18:30 +00:00
messageLabel = "with message" ;
2013-02-02 20:37:58 +00:00
if ( _stats . infoMessages . size () > 1 )
messageLabel = "with messages" ;
2013-01-26 20:18:30 +00:00
break ;
case ResultWas :: ThrewException :
2013-04-05 20:58:01 +01:00
colour = Colour :: Error ;
2013-01-26 20:18:30 +00:00
passOrFail = "FAILED" ;
messageLabel = "due to unexpected exception with message" ;
break ;
2014-08-22 19:35:41 +01:00
case ResultWas :: FatalErrorCondition :
colour = Colour :: Error ;
passOrFail = "FAILED" ;
messageLabel = "due to a fatal error condition" ;
break ;
2013-01-26 20:18:30 +00:00
case ResultWas :: DidntThrowException :
2013-04-05 20:58:01 +01:00
colour = Colour :: Error ;
2013-01-26 20:18:30 +00:00
passOrFail = "FAILED" ;
messageLabel = "because no exception was thrown where one was expected" ;
break ;
case ResultWas :: Info :
messageLabel = "info" ;
break ;
case ResultWas :: Warning :
messageLabel = "warning" ;
break ;
case ResultWas :: ExplicitFailure :
passOrFail = "FAILED" ;
2013-04-05 20:58:01 +01:00
colour = Colour :: Error ;
2013-02-02 20:37:58 +00:00
if ( _stats . infoMessages . size () == 1 )
messageLabel = "explicitly with message" ;
if ( _stats . infoMessages . size () > 1 )
messageLabel = "explicitly with messages" ;
2013-01-26 20:18:30 +00:00
break ;
// These cases are here to prevent compiler warnings
case ResultWas :: Unknown :
case ResultWas :: FailureBit :
2013-04-12 10:43:06 +01:00
case ResultWas :: Exception :
2013-01-26 20:18:30 +00:00
passOrFail = "** internal error **" ;
2013-04-05 20:58:01 +01:00
colour = Colour :: Error ;
2013-01-26 20:18:30 +00:00
break ;
}
}
void print () const {
2013-03-04 12:19:15 +01:00
printSourceInfo ();
2013-01-26 20:18:30 +00:00
if ( stats . totals . assertions . total () > 0 ) {
2013-03-04 12:19:15 +01:00
if ( result . isOk () )
stream << " \n " ;
2013-01-26 20:18:30 +00:00
printResultType ();
printOriginalExpression ();
printReconstructedExpression ();
}
2013-03-04 12:19:15 +01:00
else {
stream << " \n " ;
}
2013-01-26 20:18:30 +00:00
printMessage ();
}
private :
void printResultType () const {
if ( ! passOrFail . empty () ) {
2013-04-05 20:58:01 +01:00
Colour colourGuard ( colour );
2013-01-26 20:18:30 +00:00
stream << passOrFail << ": \n " ;
}
}
void printOriginalExpression () const {
if ( result . hasExpression () ) {
2013-04-05 20:58:01 +01:00
Colour colourGuard ( Colour :: OriginalExpression );
2013-01-26 20:18:30 +00:00
stream << " " ;
2013-06-07 19:07:50 +01:00
stream << result . getExpressionInMacro ();
2013-01-26 20:18:30 +00:00
stream << " \n " ;
}
}
void printReconstructedExpression () const {
if ( result . hasExpandedExpression () ) {
stream << "with expansion: \n " ;
2013-04-05 20:58:01 +01:00
Colour colourGuard ( Colour :: ReconstructedExpression );
2013-04-20 21:07:32 +01:00
stream << Text ( result . getExpandedExpression (), TextAttributes (). setIndent ( 2 ) ) << " \n " ;
2013-01-26 20:18:30 +00:00
}
}
void printMessage () const {
if ( ! messageLabel . empty () )
stream << messageLabel << ":" << " \n " ;
2013-02-02 20:37:58 +00:00
for ( std :: vector < MessageInfo >:: const_iterator it = messages . begin (), itEnd = messages . end ();
it != itEnd ;
++ it ) {
2013-11-13 08:10:45 +00:00
// If this assertion is a warning ignore any INFO messages
if ( printInfoMessages || it -> type != ResultWas :: Info )
stream << Text ( it -> message , TextAttributes (). setIndent ( 2 ) ) << " \n " ;
2013-02-02 20:37:58 +00:00
}
2013-01-26 20:18:30 +00:00
}
void printSourceInfo () const {
2013-04-05 20:58:01 +01:00
Colour colourGuard ( Colour :: FileName );
2013-03-04 12:19:15 +01:00
stream << result . getSourceInfo () << ": " ;
2013-01-26 20:18:30 +00:00
}
std :: ostream & stream ;
AssertionStats const & stats ;
AssertionResult const & result ;
2013-04-05 20:58:01 +01:00
Colour :: Code colour ;
2013-01-26 20:18:30 +00:00
std :: string passOrFail ;
std :: string messageLabel ;
std :: string message ;
2013-02-02 20:37:58 +00:00
std :: vector < MessageInfo > messages ;
2013-11-13 08:10:45 +00:00
bool printInfoMessages ;
2013-01-26 20:18:30 +00:00
};
2013-01-16 09:44:43 +00:00
void lazyPrint () {
2013-08-15 19:01:00 +01:00
if ( ! currentTestRunInfo . used )
2013-01-16 09:44:43 +00:00
lazyPrintRunInfo ();
2013-08-15 19:01:00 +01:00
if ( ! currentGroupInfo . used )
2013-01-16 09:44:43 +00:00
lazyPrintGroupInfo ();
2013-03-08 09:30:25 +00:00
if ( ! m_headerPrinted ) {
printTestCaseAndSectionHeader ();
m_headerPrinted = true ;
}
2013-01-16 09:44:43 +00:00
}
void lazyPrintRunInfo () {
2014-04-23 07:10:10 +01:00
stream << " \n " << getLineOfChars < '~' > () << " \n " ;
2013-04-05 20:58:01 +01:00
Colour colour ( Colour :: SecondaryText );
2013-08-15 19:01:00 +01:00
stream << currentTestRunInfo -> name
2015-06-29 18:05:23 +01:00
<< " is a Catch v" << libraryVersion << " host application. \n "
2013-01-16 09:44:43 +00:00
<< "Run with -? for options \n\n " ;
2014-09-15 18:40:24 +01:00
if ( m_config -> rngSeed () != 0 )
stream << "Randomness seeded to: " << m_config -> rngSeed () << " \n\n " ;
2013-08-15 19:01:00 +01:00
currentTestRunInfo . used = true ;
2013-01-16 09:44:43 +00:00
}
void lazyPrintGroupInfo () {
2013-08-15 19:01:00 +01:00
if ( ! currentGroupInfo -> name . empty () && currentGroupInfo -> groupsCounts > 1 ) {
printClosedHeader ( "Group: " + currentGroupInfo -> name );
currentGroupInfo . used = true ;
2013-01-16 09:44:43 +00:00
}
}
2013-03-08 09:30:25 +00:00
void printTestCaseAndSectionHeader () {
2013-08-15 19:01:00 +01:00
assert ( ! m_sectionStack . empty () );
printOpenHeader ( currentTestCaseInfo -> name );
2013-01-16 09:44:43 +00:00
2013-08-15 19:01:00 +01:00
if ( m_sectionStack . size () > 1 ) {
Colour colourGuard ( Colour :: Headers );
std :: vector < SectionInfo >:: const_iterator
it = m_sectionStack . begin () + 1 , // Skip first section (test case)
itEnd = m_sectionStack . end ();
for ( ; it != itEnd ; ++ it )
printHeaderString ( it -> name , 2 );
2013-01-16 09:44:43 +00:00
}
2013-08-15 19:01:00 +01:00
SourceLineInfo lineInfo = m_sectionStack . front (). lineInfo ;
2013-04-20 21:07:32 +01:00
if ( ! lineInfo . empty () ){
2014-04-23 07:10:10 +01:00
stream << getLineOfChars < '-' > () << " \n " ;
2013-04-20 21:07:32 +01:00
Colour colourGuard ( Colour :: FileName );
stream << lineInfo << " \n " ;
}
2014-04-23 07:10:10 +01:00
stream << getLineOfChars < '.' > () << " \n " << std :: endl ;
2013-01-16 09:44:43 +00:00
}
2013-03-08 09:30:25 +00:00
void printClosedHeader ( std :: string const & _name ) {
printOpenHeader ( _name );
2014-04-23 07:10:10 +01:00
stream << getLineOfChars < '.' > () << " \n " ;
2013-03-08 09:30:25 +00:00
}
2013-04-20 21:07:32 +01:00
void printOpenHeader ( std :: string const & _name ) {
2014-04-23 07:10:10 +01:00
stream << getLineOfChars < '-' > () << " \n " ;
2013-04-01 11:27:10 +01:00
{
2013-04-05 20:58:01 +01:00
Colour colourGuard ( Colour :: Headers );
2013-04-20 21:07:32 +01:00
printHeaderString ( _name );
2013-04-01 11:27:10 +01:00
}
2013-01-16 09:44:43 +00:00
}
2013-04-05 20:58:01 +01:00
// if string has a : in first line will set indent to follow it on
// subsequent lines
2013-04-20 21:07:32 +01:00
void printHeaderString ( std :: string const & _string , std :: size_t indent = 0 ) {
2013-04-05 20:58:01 +01:00
std :: size_t i = _string . find ( ": " );
if ( i != std :: string :: npos )
i += 2 ;
else
i = 0 ;
2013-04-20 21:07:32 +01:00
stream << Text ( _string , TextAttributes ()
. setIndent ( indent + i )
. setInitialIndent ( indent ) ) << " \n " ;
2013-04-05 20:58:01 +01:00
}
2014-07-09 19:22:49 +01:00
struct SummaryColumn {
SummaryColumn ( std :: string const & _label , Colour :: Code _colour )
: label ( _label ),
colour ( _colour )
{}
SummaryColumn addRow ( std :: size_t count ) {
std :: ostringstream oss ;
oss << count ;
std :: string row = oss . str ();
for ( std :: vector < std :: string >:: iterator it = rows . begin (); it != rows . end (); ++ it ) {
while ( it -> size () < row . size () )
2014-07-10 09:18:50 +01:00
* it = " " + * it ;
2014-07-09 19:22:49 +01:00
while ( it -> size () > row . size () )
row = " " + row ;
}
rows . push_back ( row );
return * this ;
}
std :: string label ;
Colour :: Code colour ;
std :: vector < std :: string > rows ;
};
2014-07-03 08:11:38 +01:00
void printTotals ( Totals const & totals ) {
2013-11-13 08:10:45 +00:00
if ( totals . testCases . total () == 0 ) {
2014-07-03 08:11:38 +01:00
stream << Colour ( Colour :: Warning ) << "No tests ran \n " ;
2013-01-16 09:44:43 +00:00
}
2014-07-09 19:22:49 +01:00
else if ( totals . assertions . total () > 0 && totals . assertions . allPassed () ) {
2014-07-03 08:11:38 +01:00
stream << Colour ( Colour :: ResultSuccess ) << "All tests passed" ;
stream << " ("
2013-01-16 09:44:43 +00:00
<< pluralise ( totals . assertions . passed , "assertion" ) << " in "
2014-07-03 08:11:38 +01:00
<< pluralise ( totals . testCases . passed , "test case" ) << ")"
<< " \n " ;
2012-12-10 08:54:57 +00:00
}
2014-07-09 19:22:49 +01:00
else {
2014-07-03 08:11:38 +01:00
2014-07-09 19:22:49 +01:00
std :: vector < SummaryColumn > columns ;
columns . push_back ( SummaryColumn ( "" , Colour :: None )
. addRow ( totals . testCases . total () )
. addRow ( totals . assertions . total () ) );
columns . push_back ( SummaryColumn ( "passed" , Colour :: Success )
. addRow ( totals . testCases . passed )
. addRow ( totals . assertions . passed ) );
columns . push_back ( SummaryColumn ( "failed" , Colour :: ResultError )
. addRow ( totals . testCases . failed )
. addRow ( totals . assertions . failed ) );
columns . push_back ( SummaryColumn ( "failed as expected" , Colour :: ResultExpectedFailure )
. addRow ( totals . testCases . failedButOk )
. addRow ( totals . assertions . failedButOk ) );
2014-07-03 08:11:38 +01:00
2014-07-09 19:22:49 +01:00
printSummaryRow ( "test cases" , columns , 0 );
printSummaryRow ( "assertions" , columns , 1 );
2012-12-11 09:03:14 +00:00
}
2014-07-09 19:22:49 +01:00
}
void printSummaryRow ( std :: string const & label , std :: vector < SummaryColumn > const & cols , std :: size_t row ) {
for ( std :: vector < SummaryColumn >:: const_iterator it = cols . begin (); it != cols . end (); ++ it ) {
std :: string value = it -> rows [ row ];
if ( it -> label . empty () ) {
stream << label << ": " ;
if ( value != "0" )
stream << value ;
else
stream << Colour ( Colour :: Warning ) << "- none -" ;
}
else if ( value != "0" ) {
stream << Colour ( Colour :: LightGrey ) << " | " ;
stream << Colour ( it -> colour )
<< value << " " << it -> label ;
}
}
stream << " \n " ;
2012-12-06 08:44:51 +00:00
}
2014-07-03 08:11:38 +01:00
static std :: size_t makeRatio ( std :: size_t number , std :: size_t total ) {
std :: size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0 ;
return ( ratio == 0 && number > 0 ) ? 1 : ratio ;
}
static std :: size_t & findMax ( std :: size_t & i , std :: size_t & j , std :: size_t & k ) {
if ( i > j && i > k )
return i ;
else if ( j > k )
return j ;
else
return k ;
}
void printTotalsDivider ( Totals const & totals ) {
if ( totals . testCases . total () > 0 ) {
std :: size_t failedRatio = makeRatio ( totals . testCases . failed , totals . testCases . total () );
std :: size_t failedButOkRatio = makeRatio ( totals . testCases . failedButOk , totals . testCases . total () );
std :: size_t passedRatio = makeRatio ( totals . testCases . passed , totals . testCases . total () );
while ( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1 )
findMax ( failedRatio , failedButOkRatio , passedRatio ) ++ ;
while ( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1 )
findMax ( failedRatio , failedButOkRatio , passedRatio ) -- ;
stream << Colour ( Colour :: Error ) << std :: string ( failedRatio , '=' );
stream << Colour ( Colour :: ResultExpectedFailure ) << std :: string ( failedButOkRatio , '=' );
2014-07-09 19:22:49 +01:00
if ( totals . testCases . allPassed () )
stream << Colour ( Colour :: ResultSuccess ) << std :: string ( passedRatio , '=' );
else
stream << Colour ( Colour :: Success ) << std :: string ( passedRatio , '=' );
2014-07-03 08:11:38 +01:00
}
else {
stream << Colour ( Colour :: Warning ) << std :: string ( CATCH_CONFIG_CONSOLE_WIDTH - 1 , '=' );
}
stream << " \n " ;
2012-12-06 08:44:51 +00:00
}
2013-01-16 09:44:43 +00:00
void printSummaryDivider () {
2014-04-23 07:10:10 +01:00
stream << getLineOfChars < '-' > () << " \n " ;
2012-12-06 08:44:51 +00:00
}
2012-12-14 07:50:08 +00:00
private :
2013-03-08 09:30:25 +00:00
bool m_headerPrinted ;
2012-12-06 08:44:51 +00:00
};
INTERNAL_CATCH_REGISTER_REPORTER ( "console" , ConsoleReporter )
} // end namespace Catch
2014-05-01 19:07:02 +01:00
// #included from: ../reporters/catch_reporter_compact.hpp
#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
namespace Catch {
struct CompactReporter : StreamingReporterBase {
CompactReporter ( ReporterConfig const & _config )
: StreamingReporterBase ( _config )
{}
virtual ~ CompactReporter ();
static std :: string getDescription () {
return "Reports test results on a single line, suitable for IDEs" ;
}
virtual ReporterPreferences getPreferences () const {
ReporterPreferences prefs ;
prefs . shouldRedirectStdOut = false ;
return prefs ;
}
virtual void noMatchingTestCases ( std :: string const & spec ) {
stream << "No test cases matched '" << spec << "'" << std :: endl ;
}
virtual void assertionStarting ( AssertionInfo const & ) {
}
virtual bool assertionEnded ( AssertionStats const & _assertionStats ) {
AssertionResult const & result = _assertionStats . assertionResult ;
bool printInfoMessages = true ;
// Drop out if result was successful and we're not printing those
if ( ! m_config -> includeSuccessfulResults () && result . isOk () ) {
if ( result . getResultType () != ResultWas :: Warning )
return false ;
printInfoMessages = false ;
}
AssertionPrinter printer ( stream , _assertionStats , printInfoMessages );
printer . print ();
stream << std :: endl ;
return true ;
}
virtual void testRunEnded ( TestRunStats const & _testRunStats ) {
printTotals ( _testRunStats . totals );
stream << " \n " << std :: endl ;
StreamingReporterBase :: testRunEnded ( _testRunStats );
}
private :
class AssertionPrinter {
void operator = ( AssertionPrinter const & );
public :
AssertionPrinter ( std :: ostream & _stream , AssertionStats const & _stats , bool _printInfoMessages )
: stream ( _stream )
, stats ( _stats )
, result ( _stats . assertionResult )
, messages ( _stats . infoMessages )
, itMessage ( _stats . infoMessages . begin () )
, printInfoMessages ( _printInfoMessages )
{}
void print () {
printSourceInfo ();
itMessage = messages . begin ();
switch ( result . getResultType () ) {
case ResultWas :: Ok :
printResultType ( Colour :: ResultSuccess , passedString () );
printOriginalExpression ();
printReconstructedExpression ();
if ( ! result . hasExpression () )
printRemainingMessages ( Colour :: None );
else
printRemainingMessages ();
break ;
case ResultWas :: ExpressionFailed :
if ( result . isOk () )
printResultType ( Colour :: ResultSuccess , failedString () + std :: string ( " - but was ok" ) );
else
printResultType ( Colour :: Error , failedString () );
printOriginalExpression ();
printReconstructedExpression ();
printRemainingMessages ();
break ;
case ResultWas :: ThrewException :
printResultType ( Colour :: Error , failedString () );
printIssue ( "unexpected exception with message:" );
printMessage ();
printExpressionWas ();
printRemainingMessages ();
break ;
2014-08-22 19:35:41 +01:00
case ResultWas :: FatalErrorCondition :
printResultType ( Colour :: Error , failedString () );
printIssue ( "fatal error condition with message:" );
printMessage ();
printExpressionWas ();
printRemainingMessages ();
break ;
2014-05-01 19:07:02 +01:00
case ResultWas :: DidntThrowException :
printResultType ( Colour :: Error , failedString () );
printIssue ( "expected exception, got none" );
printExpressionWas ();
printRemainingMessages ();
break ;
case ResultWas :: Info :
printResultType ( Colour :: None , "info" );
printMessage ();
printRemainingMessages ();
break ;
case ResultWas :: Warning :
printResultType ( Colour :: None , "warning" );
printMessage ();
printRemainingMessages ();
break ;
case ResultWas :: ExplicitFailure :
printResultType ( Colour :: Error , failedString () );
printIssue ( "explicitly" );
printRemainingMessages ( Colour :: None );
break ;
// These cases are here to prevent compiler warnings
case ResultWas :: Unknown :
case ResultWas :: FailureBit :
case ResultWas :: Exception :
printResultType ( Colour :: Error , "** internal error **" );
break ;
}
}
private :
// Colour::LightGrey
2014-05-20 18:50:59 +01:00
static Colour :: Code dimColour () { return Colour :: FileName ; }
2014-05-01 19:07:02 +01:00
#ifdef CATCH_PLATFORM_MAC
static const char * failedString () { return "FAILED" ; }
static const char * passedString () { return "PASSED" ; }
#else
static const char * failedString () { return "failed" ; }
static const char * passedString () { return "passed" ; }
#endif
void printSourceInfo () const {
Colour colourGuard ( Colour :: FileName );
stream << result . getSourceInfo () << ":" ;
}
2014-05-20 18:50:59 +01:00
void printResultType ( Colour :: Code colour , std :: string passOrFail ) const {
2014-05-01 19:07:02 +01:00
if ( ! passOrFail . empty () ) {
{
Colour colourGuard ( colour );
stream << " " << passOrFail ;
}
stream << ":" ;
}
}
void printIssue ( std :: string issue ) const {
stream << " " << issue ;
}
void printExpressionWas () {
if ( result . hasExpression () ) {
stream << ";" ;
{
Colour colour ( dimColour () );
stream << " expression was:" ;
}
printOriginalExpression ();
}
}
void printOriginalExpression () const {
if ( result . hasExpression () ) {
stream << " " << result . getExpression ();
}
}
void printReconstructedExpression () const {
if ( result . hasExpandedExpression () ) {
{
Colour colour ( dimColour () );
stream << " for: " ;
}
stream << result . getExpandedExpression ();
}
}
void printMessage () {
if ( itMessage != messages . end () ) {
stream << " '" << itMessage -> message << "'" ;
++ itMessage ;
}
}
2014-05-20 18:50:59 +01:00
void printRemainingMessages ( Colour :: Code colour = dimColour () ) {
2014-05-01 19:07:02 +01:00
if ( itMessage == messages . end () )
return ;
// using messages.end() directly yields compilation error:
std :: vector < MessageInfo >:: const_iterator itEnd = messages . end ();
const std :: size_t N = static_cast < std :: size_t > ( std :: distance ( itMessage , itEnd ) );
{
Colour colourGuard ( colour );
stream << " with " << pluralise ( N , "message" ) << ":" ;
}
for (; itMessage != itEnd ; ) {
// If this assertion is a warning ignore any INFO messages
if ( printInfoMessages || itMessage -> type != ResultWas :: Info ) {
stream << " '" << itMessage -> message << "'" ;
if ( ++ itMessage != itEnd ) {
Colour colourGuard ( dimColour () );
stream << " and" ;
}
}
}
}
private :
std :: ostream & stream ;
AssertionStats const & stats ;
AssertionResult const & result ;
std :: vector < MessageInfo > messages ;
std :: vector < MessageInfo >:: const_iterator itMessage ;
bool printInfoMessages ;
};
// Colour, message variants:
// - white: No tests ran.
// - red: Failed [both/all] N test cases, failed [both/all] M assertions.
// - white: Passed [both/all] N test cases (no assertions).
// - red: Failed N tests cases, failed M assertions.
// - green: Passed [both/all] N tests cases with M assertions.
std :: string bothOrAll ( std :: size_t count ) const {
return count == 1 ? "" : count == 2 ? "both " : "all " ;
}
void printTotals ( const Totals & totals ) const {
if ( totals . testCases . total () == 0 ) {
stream << "No tests ran." ;
}
else if ( totals . testCases . failed == totals . testCases . total () ) {
Colour colour ( Colour :: ResultError );
const std :: string qualify_assertions_failed =
totals . assertions . failed == totals . assertions . total () ?
bothOrAll ( totals . assertions . failed ) : "" ;
stream <<
"Failed " << bothOrAll ( totals . testCases . failed )
<< pluralise ( totals . testCases . failed , "test case" ) << ", "
"failed " << qualify_assertions_failed <<
pluralise ( totals . assertions . failed , "assertion" ) << "." ;
}
else if ( totals . assertions . total () == 0 ) {
stream <<
"Passed " << bothOrAll ( totals . testCases . total () )
<< pluralise ( totals . testCases . total (), "test case" )
<< " (no assertions)." ;
}
else if ( totals . assertions . failed ) {
Colour colour ( Colour :: ResultError );
stream <<
"Failed " << pluralise ( totals . testCases . failed , "test case" ) << ", "
"failed " << pluralise ( totals . assertions . failed , "assertion" ) << "." ;
}
else {
Colour colour ( Colour :: ResultSuccess );
stream <<
"Passed " << bothOrAll ( totals . testCases . passed )
<< pluralise ( totals . testCases . passed , "test case" ) <<
" with " << pluralise ( totals . assertions . passed , "assertion" ) << "." ;
}
}
};
INTERNAL_CATCH_REGISTER_REPORTER ( "compact" , CompactReporter )
} // end namespace Catch
2012-08-13 07:46:10 +01:00
namespace Catch {
NonCopyable ::~ NonCopyable () {}
IShared ::~ IShared () {}
2014-04-18 08:49:35 +01:00
StreamBufBase ::~ StreamBufBase () CATCH_NOEXCEPT {}
2012-08-13 07:46:10 +01:00
IContext ::~ IContext () {}
IResultCapture ::~ IResultCapture () {}
ITestCase ::~ ITestCase () {}
ITestCaseRegistry ::~ ITestCaseRegistry () {}
IRegistryHub ::~ IRegistryHub () {}
IMutableRegistryHub ::~ IMutableRegistryHub () {}
IExceptionTranslator ::~ IExceptionTranslator () {}
IExceptionTranslatorRegistry ::~ IExceptionTranslatorRegistry () {}
IReporter ::~ IReporter () {}
IReporterFactory ::~ IReporterFactory () {}
IReporterRegistry ::~ IReporterRegistry () {}
2012-12-01 23:57:18 +00:00
IStreamingReporter ::~ IStreamingReporter () {}
AssertionStats ::~ AssertionStats () {}
SectionStats ::~ SectionStats () {}
TestCaseStats ::~ TestCaseStats () {}
TestGroupStats ::~ TestGroupStats () {}
TestRunStats ::~ TestRunStats () {}
2013-08-15 19:01:00 +01:00
CumulativeReporterBase :: SectionNode ::~ SectionNode () {}
CumulativeReporterBase ::~ CumulativeReporterBase () {}
2012-12-01 23:57:18 +00:00
2013-01-16 09:44:43 +00:00
StreamingReporterBase ::~ StreamingReporterBase () {}
2012-12-06 08:44:51 +00:00
ConsoleReporter ::~ ConsoleReporter () {}
2014-05-01 19:07:02 +01:00
CompactReporter ::~ CompactReporter () {}
2012-08-13 07:46:10 +01:00
IRunner ::~ IRunner () {}
IMutableContext ::~ IMutableContext () {}
IConfig ::~ IConfig () {}
XmlReporter ::~ XmlReporter () {}
JunitReporter ::~ JunitReporter () {}
TestRegistry ::~ TestRegistry () {}
FreeFunctionTestCase ::~ FreeFunctionTestCase () {}
IGeneratorInfo ::~ IGeneratorInfo () {}
IGeneratorsForTest ::~ IGeneratorsForTest () {}
2015-07-13 15:03:26 +01:00
WildcardPattern ::~ WildcardPattern () {}
2014-05-16 18:54:48 +01:00
TestSpec :: Pattern ::~ Pattern () {}
TestSpec :: NamePattern ::~ NamePattern () {}
TestSpec :: TagPattern ::~ TagPattern () {}
TestSpec :: ExcludedPattern ::~ ExcludedPattern () {}
2012-08-13 07:46:10 +01:00
2012-10-12 07:58:17 +01:00
Matchers :: Impl :: StdString :: Equals ::~ Equals () {}
Matchers :: Impl :: StdString :: Contains ::~ Contains () {}
Matchers :: Impl :: StdString :: StartsWith ::~ StartsWith () {}
Matchers :: Impl :: StdString :: EndsWith ::~ EndsWith () {}
2012-08-13 07:46:10 +01:00
void Config :: dummy () {}
}
2012-08-16 18:48:50 +01:00
#ifdef __clang__
2012-08-13 07:46:10 +01:00
#pragma clang diagnostic pop
2011-05-24 08:23:02 +01:00
#endif
2012-09-17 01:42:29 -04:00
2014-03-06 21:53:34 +00:00
#endif
2011-05-24 08:23:02 +01:00
2013-12-04 20:25:14 +00:00
#ifdef CATCH_CONFIG_MAIN
2011-05-24 08:23:02 +01:00
// #included from: internal/catch_default_main.hpp
2012-08-09 07:47:30 +01:00
#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
2011-05-24 08:23:02 +01:00
2012-05-11 08:17:16 +01:00
#ifndef __OBJC__
2011-05-24 08:23:02 +01:00
2012-05-11 08:17:16 +01:00
// Standard C/C++ main entry point
int main ( int argc , char * const argv []) {
2013-06-07 19:07:50 +01:00
return Catch :: Session (). run ( argc , argv );
2012-05-11 08:17:16 +01:00
}
#else // __OBJC__
// Objective-C entry point
int main ( int argc , char * const argv []) {
2012-03-17 18:20:06 +00:00
#if !CATCH_ARC_ENABLED
2011-05-24 08:23:02 +01:00
NSAutoreleasePool * pool = [[ NSAutoreleasePool alloc ] init ];
2012-03-17 18:20:06 +00:00
#endif
2011-05-24 08:23:02 +01:00
Catch :: registerTestMethods ();
2013-06-07 19:07:50 +01:00
int result = Catch :: Session (). run ( argc , ( char * const * ) argv );
2011-05-24 08:23:02 +01:00
2012-03-17 18:20:06 +00:00
#if !CATCH_ARC_ENABLED
2011-05-24 08:23:02 +01:00
[ pool drain ];
2012-03-17 18:20:06 +00:00
#endif
2011-05-24 08:23:02 +01:00
2012-02-18 09:58:30 +00:00
return result ;
2011-05-24 08:23:02 +01:00
}
2012-05-11 08:17:16 +01:00
#endif // __OBJC__
2014-03-06 21:53:34 +00:00
#endif
#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
# undef CLARA_CONFIG_MAIN
#endif
2011-05-24 08:23:02 +01:00
//////
2012-07-20 18:43:48 +01:00
// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
#ifdef CATCH_CONFIG_PREFIX_ALL
2012-11-13 22:04:29 +00:00
#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
2014-06-02 07:48:03 +01:00
#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
2012-07-20 18:43:48 +01:00
2015-07-13 06:36:07 +01:00
#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
2012-11-13 22:04:29 +00:00
#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
2015-07-15 23:03:11 +01:00
#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" )
2012-11-13 22:04:29 +00:00
#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
2012-07-20 18:43:48 +01:00
2012-11-13 22:04:29 +00:00
#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
2014-06-02 07:48:03 +01:00
#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
2012-11-13 22:04:29 +00:00
#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
2012-07-20 18:43:48 +01:00
2014-06-02 07:48:03 +01:00
#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
2012-11-13 22:04:29 +00:00
#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
2015-07-15 23:03:11 +01:00
#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
2012-11-13 22:04:29 +00:00
#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
2012-07-20 18:43:48 +01:00
2012-11-13 22:04:29 +00:00
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
2012-07-20 18:43:48 +01:00
2013-02-02 20:37:58 +00:00
#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
2013-12-14 14:34:05 +00:00
#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
2013-06-28 17:09:57 +01:00
#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
2013-02-02 20:37:58 +00:00
#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
2013-06-28 17:09:57 +01:00
#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
2012-07-20 18:43:48 +01:00
2013-03-16 20:21:51 +00:00
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
2013-06-07 19:07:50 +01:00
#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
2013-03-16 20:21:51 +00:00
#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
2013-12-14 14:34:05 +00:00
#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
2013-12-14 23:16:44 +00:00
#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
2013-03-16 20:21:51 +00:00
#else
#define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
2013-06-07 19:07:50 +01:00
#define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
2013-03-16 20:21:51 +00:00
#define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
#define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
2013-12-14 14:34:05 +00:00
#define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
2013-12-14 23:16:44 +00:00
#define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
2013-03-16 20:21:51 +00:00
#endif
#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
2012-07-20 18:43:48 +01:00
#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
2012-12-01 23:57:18 +00:00
#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
2012-07-20 18:43:48 +01:00
#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
2013-03-13 12:19:30 +00:00
// "BDD-style" convenience wrappers
2013-03-21 09:00:24 +00:00
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
2014-08-20 08:09:32 +01:00
#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
2013-03-21 09:00:24 +00:00
#else
2013-03-13 12:19:30 +00:00
#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
2014-08-20 08:09:32 +01:00
#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
2013-03-21 09:00:24 +00:00
#endif
2015-07-23 23:06:26 +01:00
#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, "" )
2013-03-13 12:19:30 +00:00
2012-07-20 18:43:48 +01:00
// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
#else
2012-11-13 22:04:29 +00:00
#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
2014-06-02 07:48:03 +01:00
#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
2011-05-24 08:23:02 +01:00
2015-07-13 06:36:07 +01:00
#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
2012-11-13 22:04:29 +00:00
#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
2015-07-15 23:03:11 +01:00
#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
2012-11-13 22:04:29 +00:00
#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
2011-05-24 08:23:02 +01:00
2012-11-13 22:04:29 +00:00
#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
2014-06-02 07:48:03 +01:00
#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
2012-11-13 22:04:29 +00:00
#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
#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" )
2011-05-24 08:23:02 +01:00
2015-07-13 06:36:07 +01:00
#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
2012-11-13 22:04:29 +00:00
#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
2015-07-15 23:03:11 +01:00
#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
2012-11-13 22:04:29 +00:00
#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
2011-05-24 08:23:02 +01:00
2012-11-13 22:04:29 +00:00
#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
2012-03-04 21:22:36 +00:00
2013-02-02 20:37:58 +00:00
#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
2013-12-14 14:34:05 +00:00
#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
2013-06-28 17:09:57 +01:00
#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
2013-02-02 20:37:58 +00:00
#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
2013-06-28 17:09:57 +01:00
#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
2011-05-24 08:23:02 +01:00
2013-03-16 20:21:51 +00:00
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
2013-06-07 19:07:50 +01:00
#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
2013-03-16 20:21:51 +00:00
#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
2013-12-14 14:34:05 +00:00
#define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
2013-12-14 23:16:44 +00:00
#define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
2013-03-16 20:21:51 +00:00
#else
#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
2013-06-07 19:07:50 +01:00
#define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
2013-03-16 20:21:51 +00:00
#define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
#define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
2013-12-14 14:34:05 +00:00
#define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
2013-12-14 23:16:44 +00:00
#define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
2013-03-16 20:21:51 +00:00
#endif
#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
2011-05-24 08:23:02 +01:00
#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
2012-12-01 23:57:18 +00:00
#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
2011-05-24 08:23:02 +01:00
#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
2012-07-20 18:43:48 +01:00
#endif
#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
2011-05-24 08:23:02 +01:00
2013-03-13 12:19:30 +00:00
// "BDD-style" convenience wrappers
2013-03-21 09:00:24 +00:00
#ifdef CATCH_CONFIG_VARIADIC_MACROS
#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
2014-08-20 08:09:32 +01:00
#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
2013-03-21 09:00:24 +00:00
#else
2013-03-13 12:19:30 +00:00
#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
2014-08-20 08:09:32 +01:00
#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
2013-03-21 09:00:24 +00:00
#endif
2015-07-23 23:06:26 +01:00
#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, "" )
2013-03-13 12:19:30 +00:00
2011-05-24 08:23:02 +01:00
using Catch :: Detail :: Approx ;
2012-05-09 19:37:51 +01:00
#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
2011-05-24 08:23:02 +01:00